pax_global_header00006660000000000000000000000064147764606440014534gustar00rootroot0000000000000052 comment=a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47 balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/000077500000000000000000000000001477646064400204225ustar00rootroot00000000000000balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/.gitignore000066400000000000000000000016451477646064400224200ustar00rootroot00000000000000*~ *.o *.lo *.la *.a *.lo *.la *.gmo *.omf *.stamp doc/*/*.mo doc/*/*.xml doc/??/*.page .deps .libs Makefile Makefile.in COPYING aclocal.m4 autom4te.cache/ balsa-mailto-handler.desktop balsa-mailto-handler.desktop.in balsa.1 balsa.appdata.xml balsa.desktop balsa.desktop.in balsa.spec compile config.guess config.h config.h.in config.log config.status config.sub configure depcomp install-sh libbalsa/imap/imap_tst libbalsa/imap/libimap-marshal.c libbalsa/imap/libimap-marshal.h libbalsa/libbalsa-marshal.c libbalsa/libbalsa-marshal.h libtool ltmain.sh m4/ missing mkinstalldirs po/Makefile.in.in po/POTFILES po/stamp-it sounds/balsa.soundlist src/balsa src/balsa-ab stamp-h1 autoscan.log configure.scan gnome-doc-utils.make libnetclient/test/start-test-env.sh org.desktop.Balsa.desktop org.desktop.Balsa.desktop.in po/Makevars.template po/Rules-quot po/balsa.pot po/*.sed po/*.header po/*.sin po/stamp-po src/balsa-*resources.c balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/.gitlab-ci.yml000066400000000000000000000002101477646064400230470ustar00rootroot00000000000000# This file is a template, and might need editing before it works on your project. include: template: Jobs/Code-Quality.gitlab-ci.yml balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/AUTHORS000066400000000000000000000071131477646064400214740ustar00rootroot00000000000000Following people contributed to versions 2.4.x and 2.5.x of balsa: Peter Bloomfield Albrecht Dreß Pawel Salek + many other contributors. Versions 2.1.x and 2.2.x: Emmanuel Allaud Peter Bloomfield Albrecht Dreß Carlos Morgado Pawel Salek Bart Visscher + many other contributors. Versions 2.0.x: Emmanuel Allaud Peter Bloomfield Carlos Morgado Pawel Salek + many other contributors. Versions 1.1.x and 1.2.0: Ian Campbell Matthew Guenther Carlos Morgado Pawel Salek patch contributors and helping souls[*]: Peter Bloomfield Albrecht Dreß Toralf Lund Berend De Schouwer Melanie Thielker Steve Wall Ali Akcaagac Stuart Parmenter Peter Williams rached ben mustapha and many others... Version 0.9.x and 1.0.0: Ian Campbell Matthew Guenther Stuart Parmenter Pawel Salek Peter Williams and others (in particular Berend De Schouwer ). Version 0.8.0: Code from: Héctor García Álvarez Ian Campbell Matthew Guenther Bruno Pires Marinho David Pickens Pawel Salek Peter Williams Special thanks to: Anthony DeRobertis for patches and ideas and bug-squashing and our bug reporters and stompers Versio 0.6.0: Code from: Héctor García Álvarez Bruno Pires Marinho David Pickens Peter Williams Special thanks to: Stuart Parmenter for letting us bring Balsa back to life. and everyone else who contributed ideas and patches Version 0.4.9 and before: Code from: Michael Lausch Jay Painter Stuart Parmenter Special thanks to: Tuomas Kuosmanen for all the beautiful icons in Balsa! They add so much to Balsa! I know I keep asking you for things and I really appreciate everything you have done! Also thanks for the awesome Balsa logo! Larry Ewing for the amazing Balsa airplane. Nat Friedman for doing the libPropList work in Balsa. Manish Singh for always looking at stuff when I need help. Especially with autoconf stuff. And everyone else I am sure I have left out here. balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/CONTRIBUTING.md000066400000000000000000000000631477646064400226520ustar00rootroot00000000000000https://wiki.gnome.org/Newcomers/SubmitContributionbalsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/COPYING000066400000000000000000000427311477646064400214640ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 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 licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. 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 convey 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 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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. balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/ChangeLog000066400000000000000000021217161477646064400222060ustar00rootroot000000000000002021-08-18 Pawel Salek * .../Makefile.am: include '*meson*' files in the distribution package. * NEWS, configure.ac, meson.build: release balsa-2.6.3 2021-03-27 Peter Bloomfield imap-handle: use a flexible array member to append data to struct ImapMsgSerialized. Thanks to @albrecht for the suggestion and reference to the C99 standard, in https://gitlab.gnome.org/GNOME/balsa/-/issues/57 * libbalsa/imap/imap-handle.c: struct ImapMsgSerialized: replace - gchar fetched_headers_first_char; with a flexible array member + gchar fetched_headers_data[]; (imap_message_serialize): adapt to the change; (imap_message_deserialize): ditto. 2021-03-25 Peter Bloomfield html: WebKit deprecation cleanup * libbalsa/html.c (lbh_web_view_new): webkit_settings_set_enable_plugins() is deprecated in 2.32 (we test for 2.31.91). 2021-03-22 Peter Bloomfield mailbox: Lock destination when copying or moving * libbalsa/mailbox.c (libbalsa_mailbox_real_messages_copy): remove guards; (messages_copy_locked): helper; (libbalsa_mailbox_messages_copy): guard and lock destination, and use helper; (libbalsa_mailbox_messages_move): ditto. 2021-03-21 Peter Bloomfield imap-handle: check for non-compliant responses * libbalsa/imap/imap-handle.c (imap_cmd_step): disconnect if a protocol error is found; (ir_exists): check that the handle is either authenticated or selected; (ir_recent): ditto; (ir_fetch_seq): check that the handle is selected; (ir_expunge): ditto; also check that the sequence number of the expunged message is valid. 2021-03-09 Peter Bloomfield Try to avoid critical messages * libbalsa/mailbox_imap.c (imap_expunge_idle): handle expunged messages in the order they are expunged; (libbalsa_mailbox_imap_fetch_headers): avoid a critical message. 2021-03-08 Peter Bloomfield Remove a scheduled idle callback at close time instead of at dispose time. * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_close): remove expunged idle source, if any; (libbalsa_mailbox_imap_dispose): comment that it should have been removed at close time. 2021-03-08 Peter Bloomfield Handle expunged IMAP messages in an idle callback * libbalsa/mailbox_imap.c: add an array of expunged messages and an idle id to LibBalsaMailboxImap; (libbalsa_mailbox_imap_init): initialize them; (libbalsa_mailbox_imap_dispose): remove any outstanding idle source; (libbalsa_mailbox_imap_finalize): free the array; (imap_expunge_cb): populate the array, and if necessary schedule the idle callback; (imap_expunge_idle): handle the expunged messages. 2020-12-21 Pawel Salek * NEWS, configure.ac, meson.build: release balsa-2.6.2 2020-12-19 Pawel Salek * libbalsa/imap/imap-auth.c: catch errors mid authentication process. * libbalsa/imap/imap-commands.c: simplify CAPABILITY handling to prevent infinite loops. 2020-12-06 Peter Bloomfield * meson.build: Define the FORTIFY_SOURCE macro only if the optimiztion level is at least 2. 2020-11-01 Peter Bloomfield main-window: Do not export balsa_window_fix_paned * src/main-window.c (bw_fix_panes): it is now local; (bw_set_panes): set the GSource for it; * src/main-window.h: do not export it; * src/main.c (balsa_activate_cb): do not use it. 2020-11-01 Peter Bloomfield main-window: Fix some geometry Use the correct GtkPaned's position to detect changes in the width of BalsaMBList and the height of BalsaIndex * src/main-window.c (Private structure): add mblist_parent and notebook_parent widgets; (bw_mblist_parent_position_cb): callback for the mblist's horizontal GtkPaned parent; (bw_notebook_parent_position_cb): callback for the notebook's vertical GtkPaned parent; (bw_set_panes): set priv->mblist_parent and priv->notebook_parent according to the layout; (balsa_window_new), (balsa_window_fix_paned), (balsa_window_refresh), (bw_show_mbtree), (balsa_change_window_layout): use the appropriate parent GtkPaneds, instead of paned_parent and paned_child. 2020-10-17 Peter Bloomfield balsa-icons: rename balsa_register_pixbufs() to balsa_register_icon_names(), and drop its now unused parameter. * src/balsa-icons.c (balsa_register_icon_names): * src/balsa-icons.h: * src/main-window.c (balsa_window_new): 2020-10-17 Peter Bloomfield balsa-index: Set the "icon-name" property of the GtkCellRendererPixbufs instead of the "pixbuf" property. * src/balsa-index.c (balsa_index_init): set the "icon-name" property; * src/balsa-icons.c (balsa_register_pixbufs): register the address-view icons by name instead of pixbuf. * libbalsa/mailbox.c (mailbox_model_init): the status and attachment columns are now strings, not pixbufs; (mailbox_model_get_value): ditto; (libbalsa_mailbox_set_unread_icon), (libbalsa_mailbox_set_trash_icon), (libbalsa_mailbox_set_flagged_icon), (libbalsa_mailbox_set_replied_icon), (libbalsa_mailbox_set_attach_icon), (libbalsa_mailbox_set_good_icon), (libbalsa_mailbox_set_notrust_icon), (libbalsa_mailbox_set_bad_icon), (libbalsa_mailbox_set_sign_icon), (libbalsa_mailbox_set_encr_icon): the parameter is a string, not a pixbuf; * libbalsa/mailbox.h: ditto. 2020-10-17 Peter Bloomfield Address-view: Set the "icon-name" property of the GtkCellRendererPixbufs instead of the "pixbuf" property. * libbalsa/address-view.c (lbav_button_activated), (libbalsa_address_view_new): the icon column is now G_TYPE_STRING instead of GDK_TYPE_PIXBUF; (libbalsa_address_view_set_book_icon), (libbalsa_address_view_set_close_icon), (libbalsa_address_view_set_drop_down_icon): the parameter is a string, not a pixbuf; * libbalsa/address-view.h: ditto; * src/balsa-icons.c (balsa_register_pixmaps), (balsa_register_pixbufs): register the address-view icons by name instead of pixbuf. 2020-09-23 Peter Bloomfield Remove LibBalsaCellRendererButton We only needed it to capture clicks, which we can do with GtkTreeView's "row-activated" signal. * libbalsa/cell-renderer-button.c: removed; * libbalsa/cell-renderer-button.h: removed; * libbalsa/address-view.c: use "row-activated" instead. 2020-09-23 Peter Bloomfield * libbalsa/address-view.c (libbalsa_address_view_new): Set "activate-on-single-click" property to TRUE, instead of doing it the hard way. 2020-09-02 Peter Bloomfield balsa-index: add a timeout to verify that the scrolled-to row is actually visible, and, if it isn't, to call scroll-to-row again * src/balsa-index.c (bndx_scroll_to_row_verify_timeout): the timeout handler; (bndx_scroll_to_row_idle): if the tree-view is realized, schedule the timeout. 2020-08-24 Peter Bloomfield * libbalsa/libbalsa-gpgme-widgets.c (create_key_label_with_warn): the warning icon is (now?) "dialog-warning", not "gtk-dialog-warning". 2020-08-22 Peter Bloomfield balsa-index: scroll to row in another idle handler * src/balsa-index.c (bndx_scroll_to_row_idle): the handler; (bndx_scroll_to_row): helper to schedule it; (bndx_scroll_on_open_idle), (bndx_select_row), (bndx_ensure_visible_idle): use the helper; (bndx_destroy): remove the source, if necessary. 2020-08-21 Peter Bloomfield balsa-index: Ensure visible in a low-priority idle callback * src/balsa-index.c (bndx_ensure_visible_idle): the callback; (balsa_index_ensure_visible): schedule it. 2020-08-20 Peter Bloomfield Fix some more mailbox-opening issues * libbalsa/mailbox.c (libbalsa_mailbox_get_has_sort_pending): new function; * libbalsa/mailbox.h: declare it; * src/balsa-index.c (bndx_scroll_on_open_idle): use it; * src/main-window.c (bw_real_open_mbnode_idle_cb): show the BalsaIndex widget here, instead of in the scroll-on-open idle handler (balsa_window_next_unread): balsa_index_select_next_unread() finds the next unread message even if it is hidden. 2020-08-17 Peter Bloomfield balsa-message: Restore text copy Edit:Copy has been broken for a while, because BalsaMimeWidgetText is now a container, not the actual text widget. * src/balsa-message.c (balsa_message_can_select): Check the mime-widget's text-widget, not the mime-widget itself. 2020-07-12 Peter Bloomfield Various: Drop libbalsa_{radio,toggle}_activated https://developer.gnome.org/gio/stable/GActionMap.html#GActionEntry: Since GLib 2.40, [activate] can be NULL for stateful actions, in which case the default handler is used. For boolean-stated actions with no parameter, this is a toggle. For other state types (and parameter type equal to the state type) this will be a function that just calls change_state… * libbalsa/application-helpers.c (libbalsa_window_add_accelerator): * libbalsa/application-helpers.h: * libbalsa/source-viewer.c (libbalsa_show_message_source): * src/ab-main.c (get_main_menu): * src/main-window.c: * src/message-window.c: * src/sendmsg-window.c: 2020-07-05 Peter Bloomfield body: If a part with content-type "message/external-body" has access-type URL, use its URL parameter as the filename, instead of g_mime_part_get_filename(), so that the previous commit can work. * libbalsa/body.c (libbalsa_message_body_set_filename): get the "access-type" parameter; if it is non-NULL and equals "URL", get the "URL" parameter and use it as the part's filename; we do not need to verify that the content-type is "message/external-body", as the "access-type" parameter is NULL for any other content-type. 2020-07-05 Peter Bloomfield compose-window: Attachments of type "message/external-body" must have a filename, because libbalsa_message_create_mime_message() uses it to distinguish access-type=URL from access-type=local-file. * src/sendmsg-window.c (attachment2message): 2020-07-04 Peter Bloomfield compose-window: Handle attachments of type "message/external-body" when continuing a draft message. * src/sendmsg-window.c (add_urlref_attachment): do not free the URL string; (attachments_add): free it here; (add_file_attachment): new helper; (continue_body): use it. 2020-07-03 Peter Bloomfield compose-window: Use gtk_selection_data_get_uris() instead of our own code. * src/sendmsg-window.c (attachments_add), (drag_data_quote): 2020-06-28 Peter Bloomfield compose-window: Make the "Open" option on the urlref-attachment context menu work. * src/sendmsg-window.cs (on_open_url_cb): Get the top-level window from the compose window; getting it from the menu-item leads to a Wayland error; (add_urlref_attachment): Populate BalsaAttachInfo:file_uri. 2020-06-24 Peter Bloomfield mime-widget-text: Actually pop up the context menu when right-clicking on an URL. * src/balsa-mime-widget-text.c (text_view_url_popup): 2020-06-16 Peter Bloomfield main: Sandbox all the webkit https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/Sandbox-all-the-WebKit! * src/main.c (balsa_startup_cb): 2020-06-13 Peter Bloomfield Various: Use GtkTreeView's "row-activated" signal instead of connecting to "button-press-event". * libbalsa/autocrypt.c (autocrypt_db_dialog_run), (row_activated_cb): * libbalsa/libbalsa-gpgme-cb.c (row_activated_cb), (lb_gpgme_select_key): 2020-06-09 Peter Bloomfield Various: restore filtering in a mailbox that is not currently being viewed. * libbalsa/mailbox.c (libbalsa_mailbox_message_match), (lbm_cache_message): make sure we cache message info when we need it for matching; * libbalsa/mailbox_local.c (message_match_real): guard against NULL threading-info; * src/filter-run-dialog.c (available_list_selection_changed), (selected_list_selection_changed): no need to disable the "Apply" buttons when the mailbox is not being viewed. 2020-06-08 Peter Bloomfield filter-run-dialog: Disable "Apply selected" and "Apply now" when the mailbox is not currently being viewed in the main window. It no longer crashes, because of the previous commit, but it does not actually carry out any filters, so the user should see the option as disabled. * src/filter-run-dialog.c (available_list_selection_changed), (selected_list_selection_changed): 2020-06-08 Peter Bloomfield Do not crash when selecting "Apply selected" when the mailbox is not being viewed in the main window. * libbalsa/mailbox_local.c (message_match_real): check for NULL values; * src/filter-run-dialog.c (balsa_filter_run_dialog_new): call prepare-threading to get ready for filtering. 2020-06-06 Peter Bloomfield balsa-message: Do not crash if the message part is changed while the find-in-message bar is active. * src/balsa-message.c (bm_find_entry_changed_cb): 2020-06-06 Peter Bloomfield toolbar-factory: Stop using direct access to GdkEvent structs Use gdk_event_get_event_type instead of directly accessing event->type. * src/toolbar-factory.c (tm_popup_context_menu_cb): 2020-06-06 Peter Bloomfield Find in message: Make it work again * src/balsa-mime-widget-text.c (balsa_mime_widget_text_get_text_widget): new getter; * src/balsa-mime-widget-text.h: ditto; * src/balsa-message.c (bm_find_entry_changed_cb), (bm_find_again), (bm_find_pass_to_entry), (balsa_message_find_in_message): use it to get the real text widget (GtkTextView, GtkSourceView). 2020-06-06 Peter Bloomfield mblist: Stop using direct access to GdkEvent structs Use GdkEvent getters instead of directly accessing fields. * src/balsa-mblist.c (bmbl_select_mailbox), (bmbl_mru_selected_cb): 2020-06-06 Peter Bloomfield compose window: Connect to the "pressed" signal of a GtkGestureMultiPress instead of the "button-press-event" widget signal. * src/sendmsg-window.c (attachment_button_press_cb), (sw_attachment_list): 2020-06-05 Peter Bloomfield mime-widget-text: Use bmwt_html_ prefix for all HTML-related functions. * src/balsa-mime-widget-text.c (bmwt_html_zoom_in), (bmwt_html_zoom_out), (bmwt_html_zoom_reset), (bmwt_html_select_all_cb), (bmwt_html_populate_popup_menu), (bmwt_html_popup_context_menu), (bmwt_html_gesture_pressed_cb), (bmwt_html_populate_popup_cb), (bm_widget_new_html): 2020-06-04 Peter Bloomfield main-window: Connect to "notify::focus" signal instead of the "focus-in" and "focus-out" widget signals. And use the focus status to block the window's accelerator keys when the search entry has the keyboard focus. * src/main-window.c (bw_check_filter), (bw_create_index_widget), (bw_add_win_action_entries), (bw_set_menus), (balsa_window_new): 2020-06-04 Peter Bloomfield application-helpers: Add the capability to block accels * libbalsa/application-helpers.c (accel_activate): check whether they are blocked; (libbalsa_window_block_accels): new function; * libbalsa/application-helpers.h: ditto. 2020-06-03 Peter Bloomfield mime-widget-text: Connect to the "pressed" signal of a GtkGestureMultiPress instead of the "button-press-event" widget signal. The HTML part context menu was the last user of an event signal. * src/balsa-mime-widget-text.c (mwt_gesture_pressed_cb), (bm_widget_new_html): 2020-06-03 Peter Bloomfield mime-widget-text: Use event-controllers instead of connecting to event signals. * src/balsa-mime-widget-text.c (mwt_controller_motion_cb), (mwt_controller_leave_cb): GtkEventControllerMotion callbacks; (balsa_mime_widget_new_text): use event-controllers instead of connecting to event signals; (store_button_coords), (check_over_url), (check_call_url): new API. 2020-06-02 Peter Bloomfield mime-widget-image: Connect to the "pressed" signal of a GtkGestureMultiPress instead of the "button-press-event" widget signal. * src/balsa-mime-widget-image.c (balsa_image_button_press_cb), (balsa_mime_widget_new_image): 2020-06-01 Peter Bloomfield balsa-message: Connect to the "pressed" signal of a GtkGestureMultiPress instead of the "button-press-event" widget signal. * src/balsa-message.c (balsa_message_init), (tree_mult_selection_popup), (tree_button_press_cb): 2020-06-01 Peter Bloomfield Various: Connect to the "focus-{in,out}" signals of a GtkEventControllerKey instead of the "focus-{in,out}-event" widget signals. This is preparation for GTK4, but will still need to be changed to use GtkEventControllerFocus in that distant future. * src/balsa-message.c (bm_header_tl_buttons), (balsa_message_init): * src/balsa-mime-widget-message.c (bm_header_widget_new): * src/balsa-mime-widget.c (balsa_mime_widget_new): * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_limit_focus), (balsa_mime_widget_unlimit_focus): new signature; * src/balsa-mime-widget-callbacks.h: ditto. 2020-06-01 Peter Bloomfield Various: Connect to the "key-pressed" signal of a GtkEventControllerKey instead of the "key-press-event" widget signal. * src/balsa-message.c (bm_header_tl_buttons), (balsa_message_init): * src/balsa-mime-widget-message.c (bm_header_widget_new): * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (bm_widget_new_html): * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_key_pressed): rename and new signature; * src/balsa-mime-widget-callbacks.h: ditto. 2020-06-01 Peter Bloomfield balsa-mblist: Connect to the "pressed" signal of a GtkGestureMultiPress instead of the "button-press-event" widget signal. * src/balsa-mblist.c (bmbl_gesture_pressed_cb), (bmbl_do_popup), (balsa_mblist_default_signal_bindings): 2020-05-31 Peter Bloomfield balsa-index: Connect to the "pressed" signal of a GtkGestureMultiPress instead of the "button-press-event" widget signal. * src/balsa-index.c (balsa_index_init), (bndx_gesture_pressed_cb), (bndx_do_popup): 2020-05-31 Peter Bloomfield ab-main: Connect to the "key-pressed" signal of a GtkEventControllerKey instead of the "key-press-event" widget signal. Also drop a pointless "delete-event" handler. * src/ab-main.c (ew_key_pressed), (bab_window_new), (main): 2020-05-29 Peter Bloomfield autocrypt: Connect to the "pressed" signal of a GtkGestureMultiPress instead of the "button_press_event" widget signal. * libbalsa/autocrypt.c (autocrypt_db_dialog_run), (gesture_pressed_cb): 2020-05-29 Peter Bloomfield address-view: Connect to "notify::has-focus" signal instead of "focus-out-event". * libbalsa/address-view.c (lbav_notify_has_focus_cb), (lbav_row_editing_cb): 2020-05-29 Peter Bloomfield compose window: Hold a reference to identity It is possible for BalsaSendmsg:ident to be unreffed by the identity configuration editor; it is only a minor inconvenience, but we can make it more robust by holding a reference. * src/sendmsg-window.c (update_bsmsg_identity), (set_identity_from_mailbox), (guess_identity_from_list), (sendmsg_window_new): manage the reference; (balsa_sendmsg_destroy_handler): ditto; also do not bother to clear members of BalsaSendmsg, as it is about to be deallocated. 2020-05-23 Peter Bloomfield autocrypt: Stop using direct access to GdkEvent structs Use GdkEvent getters instead of directly accessing fields. * libbalsa/autocrypt.c (key_button_event_press_cb): 2020-05-23 Peter Bloomfield address-view: Stop using direct access to GdkEvent structs Use GdkEvent getters instead of directly accessing fields. * libbalsa/address-view.c (lbav_key_pressed_cb), (lbav_selection_changed_cb): 2020-05-21 Peter Bloomfield address-book and subclasses: Clean up #includes * libbalsa/address-book-extern.c: * libbalsa/address-book-extern.h: * libbalsa/address-book-gpe.c: * libbalsa/address-book-gpe.h: * libbalsa/address-book-ldap.c: * libbalsa/address-book-ldap.h: * libbalsa/address-book-ldif.c: * libbalsa/address-book-osmo.c: * libbalsa/address-book-osmo.h: * libbalsa/address-book-rubrica.c: * libbalsa/address-book-text.c: * libbalsa/address-book-text.h: * libbalsa/address-book-vcard.c: * libbalsa/address-book.c: 2020-05-20 Peter Bloomfield compose window: BalsaSendmsg:ident may be destroyed while the compose window is open, and the only way we can know is if it is removed from BalsaApplication:indenties * src/sendmsg-window.c (balsa_sendmsg_destroy_handler): check if BalsaSendmsg:ident can be found in BalsaApplication:indenties. 2020-05-14 Peter Bloomfield Bump required versions as discussed in https://mail.gnome.org/archives/balsa-list/2020-May/msg00010.html and remove corresponding conditional compilation directives. * configure.ac: * libbalsa/html.c (lbh_web_process_terminated_cb), (lbh_web_view_new): * libbalsa/identity.c (help_ident_cb): * libbalsa/mime.c (is_in_url): * libbalsa/misc.c (libbalsa_font_string_to_css): * libbalsa/smtp-server.c (smtp_server_response): * meson.build: * src/address-book-config.c (help_button_cb): * src/balsa-index.c (bndx_do_popup): * src/balsa-mblist.c (bmbl_do_popup): * src/balsa-message.c (balsa_headers_attachments_popup), (tree_mult_selection_popup), (tree_button_press_cb): * src/balsa-mime-widget-image.c (balsa_image_button_press_cb): * src/balsa-mime-widget-message.c (extbody_call_url): * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (handle_url): * src/filter-edit-callbacks.c (condition_dialog_response), (fe_dialog_response): * src/filter-run-callbacks.c (fr_dialog_response): * src/folder-conf.c (folder_conf_response): * src/main-window.c (help_activated), (bw_notebook_label_new), (bw_find_real): * src/pref-manager.c (balsa_help_pbox_display), (add_menu_cb): * src/sendmsg-window.c (on_open_url_cb), (attachment_button_press_cb), (attachment_popup_cb), (create_text_area), (create_lang_menu): * src/toolbar-factory.c (tm_popup_context_menu_cb): * src/toolbar-prefs.c (tp_dialog_response_cb): 2020-05-11 Peter Bloomfield * src/balsa-message.c (display_face): Fix a scan-build report when building with compface = false. 2020-05-10 Pawel Salek * NEWS, configure.ac, meson.build: release balsa-2.6.1 2020-05-06 Peter Bloomfield * src/sendmsg-window.c (add_attachment): Insert separators between logically distinct sections of the popup menu. 2020-04-11 Pawel Salek * NEWS, configure.ac, meson.build: release balsa-2.6.0 2020-03-09 Peter Bloomfield Drop LibBalsaMailbox:is_directory It was a write-only flag. * libbalsa/mailbox.c (libbalsa_mailbox_init), (libbalsa_mailbox_set_msg_tree_changed): * libbalsa/mailbox.h: * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_new): * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_new): * libbalsa/mailbox_mh.c (libbalsa_mailbox_mh_new): 2020-03-09 Peter Bloomfield Remove libbalsa_mailbox_local_load_messages from the API, and replace it with LibBalsaMailbox::check virtual method. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_class_init), (lbml_load_messages_idle_cb), (libbalsa_mailbox_local_check), (libbalsa_mailbox_local_set_threading): * libbalsa/mailbox_local.h: * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_check): * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_check): * libbalsa/mailbox_mh.c (libbalsa_mailbox_mh_check): 2020-03-06 Peter Bloomfield mailbox: Make cache-message a class method * libbalsa/mailbox.c (libbalsa_mailbox_class_init), (lbm_cache_message), (libbalsa_mailbox_get_message), (libbalsa_mailbox_real_cache_message), (libbalsa_mailbox_cache_message): * libbalsa/mailbox.h: * libbalsa/mailbox_local.c (libbalsa_mailbox_local_class_init), (lbm_local_cache_message), (libbalsa_mailbox_local_cache_message): * libbalsa/mailbox_local.h: * libbalsa/mailbox_mbox.c (parse_mailbox): 2020-03-06 Peter Bloomfield mailbox: Guard against out-of-bounds access to a GPtrArray * libbalsa/mailbox.c (mailbox_compare_func), (libbalsa_mailbox_msgno_get_status), (libbalsa_mailbox_msgno_get_subject), (libbalsa_mailbox_get_index_entry): use a new macro LBM_GET_INDEX_ENTRY() to safely access priv->mindex. 2020-03-04 Peter Bloomfield mailbox: Do not cache message info if the mailbox is not being viewed. * libbalsa/mailbox.c (lbm_cache_message): 2020-03-03 Peter Bloomfield mailbox-local: Do not pass message to LibBalsaMailbox in a case not covered by commit d95c3a90b2478e9dcd18d50ba0bf4efd3a10f64b * libbalsa/mailbox_local.c (lbm_local_cache_message): 2020-03-03 Albrecht Dreß Move recheck crypto button to menu, toolbar * libbalsa/body.[ch]: • add new function libbalsa_message_body_has_crypto_content() which recursively checks if a LibBalsaMessageBody contains any not yet decrypted or any signed content which may be rechecked • fix comment typo * libbalsa/gmime-part-rfc2440.c: g_mime_part_check_rfc2440() make sure to lock/unlock a shared stream * libbalsa/message.[ch]: • rename libbalsa_message_is_pgp_(signed|encrypted)() to libbalsa_message_is_(signed|encrypted)(), do not export them, and detect S/MIME (RFC 8551) content • add and export libbalsa_message_has_crypto_content() to check if a message contains any not yet decrypted or any signed content which may be rechecked * src/balsa-message.[ch]: • remove recheck crypto button from bm_header_tl_buttons() • rename message_recheck_crypto_cb() to balsa_message_recheck_crypto() and export it • remove ancient code relevant for Gtk+-3.0 < 3.15.0 only * src/main-window.c, src/message-window.c: • add “recheck crypto” button to extra toolbar items • add recheck crypto callback, and connect it to the menu item • appropriately disable/enable menu item and button * src/toolbar-factory.c: register “Recheck cryptography” button * ui/main-window.ui, ui/message-window.ui: add menu item to the ui 2020-02-26 Peter Bloomfield mailbox-local: Do not pass message to LibBalsaMailbox for caching, when we're not preparing a threaded view. * libbalsa/mailbox_local.c (lbm_local_cache_message): 2020-02-26 Peter Bloomfield Use g_print() instead of g_printerr() to print network status. Fixes https://gitlab.gnome.org/GNOME/balsa/issues/29. * src/main-window.c (print_network_status): 2020-02-24 Peter Bloomfield main: Save the config files * src/main.c (balsa_shutdown_cb): the only case where Balsa must not go through the shutdown procedure is when it is called with the -s/--get-stats option; in that case, nothing has been set up, and balsa-app-destroy would cause all sorts of havoc. 2020-02-24 Peter Bloomfield main: Use non-copying GVariant formats Since https://gitlab.gnome.org/GNOME/glib/-/commit/325f1e3eb54d3969d3be104481fa1097ffa37d7b, the GApplication docs recommend using non-copying variant formats. * src/main.c (balsa_check_open_mailboxes): use g_free(), not g_strfreev(), to free cmd_line_open_mailboxes, because it is now a shallow copy; (scan_mailboxes_idle_cb): ditto; (balsa_check_open_compose_window): ditto opt_attach_list; (parse_options): ditto remaining_args; use the non-copying formats. 2020-02-23 Peter Bloomfield main: Parse command line arguments in the local instance * src/main.c (balsa_check_open_compose_window): opt_compose_email must not be free'd; coding style; (parse_options): use the GVariantDict instead of parsing the command-line arguments; (scan_mailboxes_idle_cb): coding style; (balsa_handle_local_options_cb): new function for handling command line options that do not need to be passed to the primary instance (currently just "--version"); (balsa_command_line_cb): use the GVariantDict instead of parsing the command-line arguments; (main): use g_application_add_main_option_entries() and connect to the "handle-local-options" signal. (handle_remote): coding style; 2020-02-21 Peter Bloomfield main: Behave as documented The man page says that Balsa exits immediately if given --version, --help, or --get-stats, so it should. Also, if it is given more than one of those options, it should respond to all of them. * src/main.c (config_init): is no longer called with a boolean argument; (balsa_startup_cb): do not use cmd_get_stats, it has not been set; (balsa_shutdown_cb): go through the shut-down process only if the main window has been created; it does not get created when Balsa exits immediately after responding to those options; (parse_options): respond to both --help and --version, if requested; (balsa_command_line_cb): activate Balsa only if not exiting immediately; (balsa_get_stats): coding style; (scan_mailboxes_idle_cb): ditto. 2020-02-18 Peter Bloomfield Use a GThreadPool to open mailboxes * src/balsa-index.c (balsa_index_set_mailbox_node): new function, called in a thread; (balsa_index_load_mailbox_node): mailbox-node has already been set; * src/balsa-index.h: export balsa_index_set_mailbox_node; * src/main-window.c (balsa_window_class_init): rename destroy to dispose; (balsa_window_init): create the GThreadPool, and a GPtrArray to hold the task info structures; (balsa_window_new): make priv->preview a weak pointer; (bw_real_open_mbnode_idle_cb): we no longer need to guard against being called after the main window has been destroyed; (bw_open_mbnode_info_free): a new cleanup function to be passed to g_idle_add_full(); (bw_real_open_mbnode_thread): GThreadPool manages the GThread instances, so we no longer need a GMutex; we no longer need to guard against being called after the main window has been destroyed; (balsa_window_real_open_mbnode): push the task to the thread pool instead of creating a new GThread; (balsa_window_dispose): free the thread pool and the pointer array; (bw_add_mbox_to_checklist): cosmetics. 2020-02-16 Albrecht Dreß imap-handle: Do not crash on PREAUTH greeting when it hasn't resulted in storing last-message. * libbalsa/imap/imap-handle.c (imap_mbox_connect): do not dereference NULL ImapHandle:last_msg; (ir_preauth): parse PREAUTH greeting the same as OK. Fixes https://gitlab.gnome.org/GNOME/balsa/issues/23 2020-02-07 Peter Bloomfield mailbox: Sort when new details about a message are found * libbalsa/mailbox.c (lbm_cache_message): if we get new information about the message, queue rethreading; (libbalsa_mailbox_finalize), (libbalsa_mailbox_close), (lbm_sort_idle_cb), (lbm_set_threading): rename LibBalsaMailboxPrivate:set_threading_idle_id to lbm_sort_idle_cb. 2020-02-02 Peter Bloomfield main-window: Simplify and make more robust * src/main-window.c (balsa_window_destroy): bw_idle_remove() has been removed, so remove the GSource directly; (bw_idle_replace): ditto; (bw_idle_cb): scrap some useless tests; (bw_index_changed_cb): check that priv->preview is non-NULL. 2020-02-02 Peter Bloomfield mailbox: Reset messages-threaded in the open method instead of the close method. * libbalsa/mailbox.c (libbalsa_mailbox_open), (libbalsa_mailbox_close): 2020-02-02 Peter Bloomfield Build: Do not check for getaddrinfo * .gitignore: don't ignore config.h.in; * configure.ac: do not check for getaddrinfo; * meson.build: ditto. 2020-02-02 Peter Bloomfield Add a file that's needed in the autotools build to the repository * config.h.in: 2020-02-02 Albrecht Dreß Build tools: Remove test for libresolv * configure.ac: * meson.build: 2020-02-01 Albrecht Dreß [Patch] ical improvements * README, configure.ac, meson.build: require libical >= 2.0.0 instead of 3.0.0 * libbalsa/rfc2445.c: libbalsa_vevent_reply(): add several optional fields to the “REPLY” message as to work around a M$ Exchange/Outlook bug * src/balsa-mime-widget-vcalendar.c: balsa_vevent_widget(): ref the VCal object containing the time zone data if we show the buttons for sending a reply; vevent_reply(): construct he reply as multipart/alternative, store it the the sentbox 2020-02-01 Peter Bloomfield mailbox: Remove another idle handler when closing the mailbox * libbalsa/mailbox.c (libbalsa_mailbox_close): remove the idle handler for sorting the mailbox. 2020-02-01 Peter Bloomfield mailbox: Do not sort until messages are threaded. * libbalsa/mailbox.c (lbm_set_threading_idle_cb): if threading is not complete, reschedule the handler; also drop lbm_check_and_sort()--it did not check, and sorting can be done in line. 2020-01-31 Peter Bloomfield Message threading cleanup Remove duplicate idle handler, and make libbalsa_mailbox_local_set_threading_info() private. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_init), (libbalsa_mailbox_local_finalize), (libbalsa_mailbox_local_close_mailbox): drop thread_id, and use set_threading_id instead; (message_match_real): add test for msgno > 0; (lbm_local_set_threading_info): renamed from libbalsa_mailbox_local_set_threading_info now that it is private; (libbalsa_mailbox_local_set_threading): use the new name; (lbm_local_prepare_msgno): declare it void; no gboolean return value is needed; (libbalsa_mailbox_local_prepare_threading): drop the idle handler; * libbalsa/mailbox_local.h: libbalsa_mailbox_local_set_threading_info() is now private; * libbalsa/mailbox_mbox.c (parse_mailbox): do not call it. 2020-01-31 Peter Bloomfield mailbox-local: Fetch threading info when needed Add missing_info and missing_parent members to ThreadingInfo, and use them to decide when complete rethreading is needed. * libbalsa/mailbox_local.c (lbml_info_setup): initialize them to FALSE; (lbml_thread_messages): if both are TRUE, we must fetch threading info for all messages, in case the parent is present but has not been seen; (lbml_set_parent): set missing_info if the info is missing; (lbml_find_parent): set missing_paarent if the message has references but no parent was found. 2020-01-30 Peter Bloomfield Move messages-loaded from LibBalsaMailbox to LibBalsaMailboxLocal * libbalsa/mailbox.c (libbalsa_mailbox_close), (libbalsa_mailbox_set_has_unread_messages): drop the getter and setter; * libbalsa/mailbox.h: ditto; * libbalsa/mailbox_local.c (libbalsa_mailbox_local_close_mailbox), (lbml_load_messages_idle_cb), (libbalsa_mailbox_local_load_messages), (lbml_set_threading_idle_cb), (libbalsa_mailbox_local_set_threading): add and use LibBalsaMailboxLocalPrivate:messages_loaded. 2020-01-30 Peter Bloomfield mailbox-local: Improve threading * libbalsa/mailbox_local.c (lbm_local_cache_message), (libbalsa_mailbox_local_cache_message): Add a guard to the public method, and an unguarded static version; schedule rethreading if we have new threading info; (message_match_real), (lbml_load_messages_idle_cb), (lbm_local_prepare_msgno): use the static version; (lbm_local_get_message_with_msg_info): cache the threading info; (libbalsa_mailbox_local_set_threading): pass local instead of mailbox to lbml_set_threading_idle_cb (cosmetic); (libbalsa_mailbox_local_load_messages): set messages-loaded to FALSE before loading them. 2020-01-27 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_msgno_inserted): lock the mailbox from start to finish, not just to access the private structure. 2020-01-27 Albrecht Dreß Unify wrapped label creation * libbalsa/misc.[ch]: add new helper libbalsa_create_wrap_label() for creating a label with word wrap and with or without markup; libbalsa_create_grid_label(): add missing xalign * libbalsa/html.c, libbalsa/libbalsa-gpgme-cb.c, libbalsa/libbalsa-gpgme-widgets.c, src/balsa-mime-widget-message.c, src/balsa-mime-widget-text.c, src/balsa-mime-widget-vcalendar.c, src/folder-conf.c, src/sendmsg-window.c: use libbalsa_create_wrap_label() * src/pref-manager.c: use libbalsa_create_wrap_label(); remove redundant calls to set default value * src/print-gtk.c: add_font_button(), add_margin_spinbtn(): add missing xalign, remove default justify; add_margin_spinbtn(): do not wrap the (short) units string; create_options_group(): use libbalsa_create_wrap_label() 2020-01-27 Peter Bloomfield mailbox-local: Drop a redundant auxiliary structure * libbalsa/mailbox_local.c (lbml_set_threading_idle_cb), (libbalsa_mailbox_local_set_threading): Drop LbmlSetThreadingInfo, it's redundant; just pass the mailbox. 2020-01-27 Peter Bloomfield mailbox-local: Lock the mailbox in idle callbacks * libbalsa/mailbox_local.c (libbalsa_mailbox_local_finalize): no need to clear pointers and hendler ids in a finalize() method; (lbml_set_threading_idle_cb): lock and unlock the mailbox; no need to unref the mailbox; clear the handler id; (libbalsa_mailbox_local_set_threading): store the handler id, and do not ref the mailbox. 2020-01-27 Peter Bloomfield mailbox: Lock the mailbox in idle callbacks * libbalsa/mailbox.c (lbm_msgno_filt_check_idle_cb), (lbm_set_threading_idle_cb): 2020-01-26 Peter Bloomfield mailbox: Always use the idle callback to sort after changing the threading; save the handler id, to remove the source at finalize time instead of taking a ref on the mailbox. * libbalsa/mailbox.c (libbalsa_mailbox_finalize): remove the source, if the handler id has been stored and not cleared; (lbm_set_threading_idle_cb), (lbm_set_threading): clear and store, respectively, the handler id. 2020-01-23 Peter Bloomfield Header eye candy Albrecht's suggestion! * src/balsa-mime-widget-message.c (add_header_gchar): improve xalign property of header value labels. 2020-01-23 Albrecht Dreß Crypto eye candies * libbalsa/libbalsa-gpgme-widgets.c: improve xalign and yalign properties of labels in signature and key details widgets * src/balsa-mime-widget-crypto.c: balsa_mime_widget_signature_widget: wrap/align signature status in expander label; balsa_mime_widget_crypto_frame: add tooltips to padlock icons * src/balsa-mime-widget-message.c: add_header_sigstate: wrap/align signature status in headers box 2020-01-23 Albrecht Dreß Bug fix: S/MIME cert chain broken in identity key selection * libbalsa/libbalsa-gpgme-widgets.c: libbalsa_gpgme_key(): fall back to the cert fingerprint for cb smime_show_chain() if the passed one is NULL * libbalsa/x509-cert-widget.c: x509_cert_chain_smime(): display message if the cert fingerprint is NULL, requires a litte refactoring 2020-01-19 Peter Bloomfield balsa-index: improve ensure-visible * src/balsa-index.c (balsa_index_ensure_visible): if either a message is selected or has the focus, scroll to it. 2020-01-19 Albrecht Dreß * README: fix package requirements * configure.ac, meson.build: require libical >= 3.0.0 (note: not tested for Meson builds) * libbalsa/rfc2445.[ch]: mostly re-written, using the libical parser and data types * src/balsa-mime-widget-vcalendar.c: add additional event items; use the new rfc2445.h api * src/balsa-print-object-text.c: fix two pango test layout memory leaks; add additional event items; use the new rfc2445.h api * src/print-gtk.c: fix part selection for printing text/calendar 2020-01-19 Peter Bloomfield balsa-index: Simplify managing idle handlers * src/balsa-index.c (bndx_destroy): use g_source_remove_by_user_data() instead of saving ids; (balsa_index_scroll_on_open), (bndx_scroll_on_open_idle), (bndx_mailbox_changed_idle), (bndx_queue_draw_idle): we do not save the id; (bndx_mailbox_row_inserted_cb), (bndx_mailbox_row_inserted_idle): store the msgno in the BalsaIndex, instead of allocating a new structure; (bndx_expand_to_row_and_select), (bndx_expand_to_row_and_select_idle), (bndx_update_tree_idle), (balsa_index_update_tree): we do not need to add a reference to the BalsaIndex. 2020-01-18 Peter Bloomfield balsa-index: Fix the "mostly" part of the previous commit, by using yet another idle handler to allow the tree-view's layout settle down. * src/balsa-index.c (bndx_expand_to_row_and_select_idle): new idle handler that scrolls to the desired row; (bndx_expand_to_row_and_select): use it, instead of scrolling immediately after expanding to the row. 2020-01-17 Peter Bloomfield balsa-index: improve expand and collapse If a message is being viewed, it should still be visible after View:Expand-all (Ctrl e) or View:Collapse-all (Ctrl l). This commit achieves that for Expand-all, and mostly for Collapse-all. Only mostly: if the viewed message is near the bottom of the message index, Collapse-all may leave it a few rows below the current view of the message index. Unfortunately, if the current sort order puts the latest threads at the bottom, those are the most likely to be viewed! * src/balsa-index.c (bndx_selection_changed_idle), (bndx_scroll_on_open_idle), (bndx_mailbox_row_inserted_idle), (bndx_expand_to_row_and_select), (bndx_mailbox_changed_idle): actually, gtk_tree_view_expand_to_path() doesn't do what we want: it expands to the row, and the row itself, so we use it instead on the parent of the row, using bndx_expand_to_row() again; (bndx_update_tree_idle), (balsa_index_update_tree): do the re-expansion in an idle handler, after the tree-view's layout has settled down; (bndx_expand_to_row): restore it, but using gtk_tree_view_expand_to_path() to expand to the row's parent. 2020-01-16 Peter Bloomfield balsa-index: Use gtk_tree_view_expand_to_path() instead of reimplementing it. * src/balsa-index.c (bndx_selection_changed_idle), (bndx_scroll_on_open_idle), (bndx_mailbox_row_inserted_idle), (bndx_expand_to_row_and_select), (bndx_mailbox_changed_idle): 2020-01-16 Peter Bloomfield Revert 90ee8bcc82d8ebdae0bd286212c21d1138531658 Moving code to the mailbox-opening thread resulted in calls to Gtk from the thread; moving those calls to an idle handler in the main thread got things out of order. We need a more radical refactoring to get more work done in threads. This commit reverses the changes in commit 90ee8bcc82d8ebdae0bd286212c21d1138531658, while keeping the later fixes. * src/balsa-index.c (bndx_scroll_on_open_idle), (balsa_index_load_mailbox_node): * src/main-window.c (bw_real_open_mbnode_idle_cb), (bw_real_open_mbnode_thread): 2020-01-15 Peter Bloomfield mailbox-local: Set messages-loaded * libbalsa/mailbox_local.c (libbalsa_mailbox_local_set_threading): set messages-loaded when the message tree is successfully restored from the cache. 2020-01-15 Peter Bloomfield Fix a few bugs * libbalsa/mailbox_local.c (libbalsa_mailbox_local_set_threading): thread messages only if there are some; otherwise just set messages-threaded; * src/balsa-index.c (bndx_scroll_on_open_idle): if the mailbox is empty, just show it and return; (balsa_index_scroll_on_open): do not special case an empty mailbox; * src/main-window.c (bw_real_open_mbnode_idle_cb), (balsa_window_real_open_mbnode): register open mailbox earlier, to avoid a race with an idle handler; (bw_real_open_mbnode_thread): add a warning. 2020-01-14 Peter Bloomfield Move some more code to a thread * src/balsa-index.c (bndx_scroll_on_open_idle): reschedule if the tree-view does not yet have a model; (balsa_index_scroll_on_open): do not bother scrolling if the mailbox is not showing any messages; (bndx_load_mailbox_node_idle): new idle handler for doing the Gtk-related part of the load; (balsa_index_load_mailbox_node): move the Gtk-related part of the load to the new idle handler. * src/main-window.c (bw_real_open_mbnode_idle_cb), (bw_real_open_mbnode_thread): move the call to balsa_index_load_mailbox_node() from the idle handler back to the thread. 2020-01-13 Peter Bloomfield balsa-index: Use a low priority idle handler instead of a timeout to schedule scroll-on-open. That's enough to let GtkTreeView do its layout work before the scroll-on-open handler gets called. * src/balsa-index.c (bndx_scroll_on_open_idle), (balsa_index_scroll_on_open): 2020-01-12 Peter Bloomfield Stop using gtk_main_iteration_do() Stop using gtk_main_iteration_do() to make the progress bar update. It caused all sorts of side effects by processing other events while the one needed the progress indicator was held up. Several hacky guards against bad consequences can be dropped. The progress bar is now not updated in the UI if it is used to indicate progress in a task that is executed in the main thread. A task that takes long enough to need it most likely needs to be carried out in a thread, anyway, and should be re-implemented as such. Scroll-on-open apparently depended on some of the less bad consequences, and to make it work again the order of execution of idle handlers for: • message loading; • message threading; • optional thread expansion; has to be managed. * libbalsa/mailbox.c (lbm_changed_idle_cb), (lbm_run_filters_on_reception_idle_cb): drop the guards; * libbalsa/mailbox_local.c (lbml_set_threading), (lbml_set_threading_idle_cb), (libbalsa_mailbox_local_set_threading), (lbm_local_update_view_filter), (libbalsa_mailbox_local_prepare_threading): drop guards, and manage order of execution; * src/balsa-index.c (balsa_index_init), (bndx_scroll_on_open_idle), (balsa_index_scroll_on_open): manage order of execution; * src/main-window.c (balsa_window_progress_bar_set_fraction): this was misleadingly named; * src/main-window.h: rename it; * src/main.c (balsa_progress_set_fraction): use the new name. 2020-01-10 Peter Bloomfield mailbox: Check for finalized mailbox * libbalsa/mailbox.c (lbm_changed_idle_cb): 2020-01-10 Peter Bloomfield mailbox-local: Check for error return value * libbalsa/mailbox_local.c (libbalsa_mailbox_local_set_threading): check the value returned by libbalsa_mailbox_prepare_threading(); if it is FALSE, the operation failed, perhaps because the mailbox was closed or finalized, so just quit. 2020-01-10 Peter Bloomfield Guard against mailbox being closed or finalized during a call to libbalsa_progress_set_fraction(). * libbalsa/mailbox.c (lbm_run_filters_on_reception_idle_cb): * libbalsa/mailbox_local.c (lbm_local_update_view_filter), (libbalsa_mailbox_local_prepare_threading): 2020-01-09 Peter Bloomfield mailbox: Check whether the mailbox was closed during set-fraction, while running filters on reception. * libbalsa/mailbox.c (lbm_run_filters_on_reception_idle_cb): 2020-01-09 Peter Bloomfield main-window: Really disconnect from a network monitor signal * src/main-window.c (balsa_window_init): store the network monitor's "network-changed" signal handler id; (balsa_window_destroy): use it to disconnect the handler. 2020-01-09 Peter Bloomfield mailbox: when closing a mailbox, remove the source of any pending run-filters-on-reception idle callback. * libbalsa/mailbox.c (libbalsa_mailbox_close): remove the source, if any; (libbalsa_mailbox_run_filters_on_reception): check that no callback is pending. 2020-01-09 Peter Bloomfield balsa-index: minor cleanup * src/balsa-index.c (bndx_scroll_on_open_idle): rename 'total' to 'n_children', as in: (balsa_index_ensure_visible): use gtk_tree_path_new_from_indices() instead of gtk_tree_model_iter_nth_child() and gtk_tree_model_get_path(). 2020-01-08 Peter Bloomfield libbalsa/x509-cert-widget: keep scan-build happy * libbalsa/x509-cert-widget.c (x509_cert_chain_smime): keep scan-build happy by checking for NULL chain. 2020-01-08 Peter Bloomfield balsa-index: do not scroll to first-unread message when LibBalsaMailbox::changed signal is received. It is not needed, and it blocks scroll-on-open from scrolling to the first-unread message. * src/balsa-index.c (bndx_mailbox_changed_idle): do not clear LibBalsaMailbox:first_unread; and do not scroll to it, either. 2020-01-07 Peter Bloomfield main-window: Avoid recursive entry to an idle callback. It happens because of a call to libbalsa_progress_set_fraction(), which then results in a call to gtk_main_iteration_do(); the current event is apparently still in the queue, so it gets re-entered. The progress indicator needs to be rethought! * src/main-window.c (bw_real_open_mbnode_idle_cb), (balsa_window_real_open_mbnode): 2020-01-06 Peter Bloomfield libbalsa-mailbox: Pack booleans in contiguous 1-bit fields It saves run-time storage, and also reduces binary code size (at least on x-86-64, with gcc -O2). Small differences in both cases! * libbalsa/mailbox.c (libbalsa_mailbox_set_msg_tree_changed), (libbalsa_mailbox_set_is_directory), (libbalsa_mailbox_set_readonly), (libbalsa_mailbox_set_no_reassemble), (libbalsa_mailbox_set_has_unread_messages), (libbalsa_mailbox_set_messages_loaded), (libbalsa_mailbox_set_messages_threaded): Make sure that gboolean arguments really are boolean. 2020-01-06 Peter Bloomfield Fix expand-on-open See https://mail.gnome.org/archives/balsa-list/2019-August/msg00008.html Because of a race among idle callbacks, we could call gtk_tree_view_expand_all() before the message tree was populated and threaded. So when it was populated and threaded, threads were in the default state, collapsed. * libbalsa/mailbox.c (libbalsa_mailbox_close), (lbm_set_threading), (libbalsa_mailbox_get_messages_loaded), (libbalsa_mailbox_get_messages_threaded), (libbalsa_mailbox_set_has_unread_messages), (libbalsa_mailbox_set_messages_loaded), (libbalsa_mailbox_set_messages_threaded): add messages_loaded and messages_threaded members to the private structure, and manage access to them; * libbalsa/mailbox.h: add accessors; * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_set_threading): set messages_threaded; * libbalsa/mailbox_local.c (lbml_load_messages_idle_cb): set messages_loaded; (lbml_set_threading): if messages have been loaded, set messages_threaded; * src/balsa-index.c (bndx_scroll_on_open_idle): if messages have not been loaded and threaded, reschedule the timeout; (balsa_index_scroll_on_open): use a 10 millisecond timeout instead of an idle call, to avoid a flurry of rescheduling. 2020-01-06 Peter Bloomfield main-window: Disconnect from a network monitor signal to avoid scheduling an idle callback after some objects have been finalized. * src/main-window.c (balsa_window_destroy): 2020-01-02 Peter Bloomfield balsa-index: Store idle handler ids and use them to remove the corresponding sources at dispose time, instead of taking a strong reference to the BalsaIndex and then testing whether it is the last reference. * src/balsa-index.c (bndx_destroy), (bndx_selection_changed_idle), (bndx_selection_changed), (bndx_scroll_on_open_idle), (balsa_index_scroll_on_open), (bndx_queue_draw_idle), (bndx_mailbox_changed_idle), (bndx_mailbox_changed_cb): 2019-11-26 Peter Bloomfield Address book editor: do not crash if no address books are available for editing. * src/ab-main.c (bab_set_intial_address_book), (main): check for NULL address book list. 2019-11-18 Peter Bloomfield libbalsa_message_body_get_mime_type() is guaranteed to return a lower case string, so we can safely use strcmp(). * libbalsa/body.c (libbalsa_message_body_set_parts), (libbalsa_message_body_get_pixbuf), (libbalsa_message_body_is_flowed): * libbalsa/html.c (lbh_cid_cb), (libbalsa_html_type): * src/balsa-message.c (mpart_content_name), (display_part), (part_create_menu), (libbalsa_can_display), (preferred_part), (get_crypto_content_icon), (libbalsa_msg_try_decrypt), (libbalsa_msg_perform_crypto_real): * src/balsa-mime-widget.c (balsa_mime_widget_new): * src/balsa-print-object.c (balsa_print_objects_append_from_body): * src/print-gtk.c (find_alt_part), (scan_body): 2019-11-17 Albrecht Dreß Fix handling of Multipart/Related * libbalsa/body.[ch]: implement a new helper function libbalsa_message_body_mp_related_root() returning the root object of a multipart/related; * libbalsa/html.c: pass the HTML body to the Webkit callbacks when printing; * src/balsa-message.c: use the new helper for fetching the multipart/related root object; * src/print-gtk.c: properly handle multipart/related 2019-11-14 Albrecht Dreß Display S/MIME and TLS certificate chains The patch addresses the following: S/MIME signatures: Currently, Balsa shows the certificate data and the issuer's name, serial and chain id. It is not possible to view the entire certification chain. The patch adds a button to the issuer section of a S/MIME signature, which opens a new dialogue, showing the certification tree in the upper and the details of the selected certificate in the lower part. I.e. it is now possible to inspect/verify the whole tree, up to the root certificate. If you have any S/MIME signed messages in a mailbox, you can simply test this feature. TLS: When opening an encrypted SMTP, POP3 or IMAP connection, balsa shows a dialogue with the untrusted certificate, asking whether the user accepts or rejects it. With the patch, if the untrusted certificate is not self-signed and the issuer certificate(s) can be loaded, the whole chain is displayed as above for inspection. For testing, you could temporarily disable the trust for your provider's root certificate, which should pop up the modified dialogue. * libbalsa/Makefile.am, libbalsa/meson.build: add new source and header file * libbalsa/libbalsa-gpgme-widgets.[ch]: add button to S/MIME signature widget; implement button callback for displaying the certificate chain * libbalsa/libbalsa.c: replace printf() by g_debug() calls in ask_idle() and libbalsa_ask(); use new api for creating certificate (chain) widget; delete stuff shifted to x509-cert-widget.[ch] * libbalsa/x509-cert-widget.[ch]: implement two functions for creating a certificate (chain) widget either from the S/MIME certificate fingerprint, or from a GTlsCertificate. If the passed certificate is self-signed or if the issuer cannot be determined, the function returns a widget containing the certificate information. Otherwise, the returned widget is a vertical GtkBox, containing the certificate chain tree view in the upper and a GtkStack in the lower part. The latter displays the certificate selected in the tree view. * src/save-restore.c: add certificate chain dialogue to the geometry manager 2019-11-13 Peter Bloomfield meson.build: Use dependency()'s capabilities * meson.build: dependency() can find gpgme's configuration, (it's not limited to pkg-config) so we do not need the custom code. 2019-11-13 Peter Bloomfield meson.build: Use meson's "optimization" option And avoid a warning from ninja. * meson.build: Use meson's "optimization" option instead of the "-O2" compiler flag. 2019-11-13 Peter Bloomfield meson.build: Do not enter endless loop * meson.build: With meson version 0.52, "run_command('rm', '-f', conftest_htm)" makes ninja go into an endless loop, so we'll skip it, and just leave conftest.htm in the current build dir. 2019-11-09 Peter Bloomfield Fix a mailbox-threading bug. When adding a new mailbox, we used the UI to set its threading type; unfortunately, the UI sets the threading on the currently shown mailbox instead. Spotted when the new local mailbox should have threading enabled, and the current mailbox is IMAP and does not support threading. * libbalsa/mailbox.c (libbalsa_mailbox_set_threading_type): call libbalsa_mailbox_set_threading() if the mailbox is non-NULL, instead of making the caller do it; * src/balsa-index.c (balsa_index_set_thread_messages): do not call libbalsa_mailbox_set_threading(); * src/mailbox-conf.c: drop BalsaMailboxConfView:mailbox--no one is now using it; (mailbox_conf_view_new_full): no one is now using BalsaMailboxConfView:mailbox; (mailbox_conf_view_check): set the threading type directly on the mailbox, instead of using the UI; * src/main-window.c: drop balsa_window_set_thread_messages, as it is no longer needed; (bw_enable_mailbox_menus): include the guts of balsa_window_set_thread_messages in-line; * src/main-window.h: drop balsa_window_set_thread_messages. 2019-10-19 Pawel Salek * NEWS, configure.ac, meson.build: release balsa-2.5.9 2019-10-13 Peter Bloomfield More efforts to get HTML parts to fill the pane * libbalsa/html.c (lbh_web_view_new): connect to "load-changed" signal; (lbh_load_changed_cb): call-back for it; if the load has finished, call gtk_widget_queue_resize(); * src/balsa-message.c (add_part): pack the widget with expand=FALSE, so that an HTML part's v-expand takes precedence. 2019-10-13 Peter Bloomfield Do not use archaic 200px default height; now that we set GtkWidget:vexpand to TRUE, the natural height works better. * libbalsa/html.c: for cosmetics, define LBH_NATURAL_SIZE as -1; (lbh_web_view_new): use it for the height; (libbalsa_html_print_bitmap): ditto; (libbalsa_html_new): use it for the width. 2019-10-12 Peter Bloomfield * libbalsa/html.c (lbh_web_view_new): set v-expand on the web-view to TRUE, so that HTML mail uses the whole pane. 2019-10-10 Pawel Salek * NEWS, configure.ac, meson.build: release balsa-2.5.8 2019-10-11 Peter Bloomfield libbalsa-html: Look deeper to find the WebKitWebView * libbalsa/html.c (libbalsa_html_new), (lbh_get_web_view_helper), (lbh_get_web_view): if the widget is not a WebKitWebView but is a GtkContainer, look at all its descendants for a WebKitWebView. 2019-10-01 Peter Bloomfield Build: we need -Wformat for -Wformat-security to be effective * configure.ac: * meson.build: 2019-10-01 Peter Bloomfield Build: GTimeVal, used in GtkSourceView-3, is deprecated in glib version 2.62; we will use GtkSourceView-4 if available, which doesn't use GTimeVal, or otherwise continue to use GtkSourceView-3 with -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_48 to suppress the deprecation warning. * configure.ac: * meson.build: 2019-09-18 Peter Bloomfield ab-main: Use GMenu API instead of GtkBuilder * src/ab-main.c (bab_cleanup), (set_address_book_menu_items), (file_delete_activated): * ui/ab-main.ui: no need for place-holder 2019-09-18 Peter Bloomfield address-book-config: Do not crash * src/address-book-config.c (edit_book_response): destroy the dialog as the last step; otherwise the struct is freed before we use it. 2019-09-14 Peter Bloomfield mime-widget: subclass GtkBox instead of GObject This makes BalsaMimeWidget inherit from GtkBox, so it is actually a widget. A subclass that used to create a vertical GtkBox can use the BalsaMimeWidget itself. Other subclasses can add their custom widget to the BalsaMimeWidget. * src/balsa-message.c (bm_find_scroll_to_rectangle), (bm_find_entry_changed_cb), (bm_find_again), (balsa_message_init), (balsa_message_destroy), (part_info_init), (add_part), (gtk_tree_hide_func), (balsa_message_current_part_widget), (balsa_message_can_select), (balsa_message_grab_focus), (balsa_message_can_zoom), (balsa_message_zoom), (balsa_message_find_in_message): * src/balsa-mime-widget-crypto.c (balsa_mime_widget_new_signature), (balsa_mime_widget_new_pgpkey): * src/balsa-mime-widget-image.c (img_check_size), (balsa_mime_widget_new_image): * src/balsa-mime-widget-message.c (balsa_mime_widget_new_message), (bmw_message_extbody_url), (bmw_message_extbody_mail), (balsa_mime_widget_new_message_tl): * src/balsa-mime-widget-multipart.c (balsa_mime_widget_new_multipart): * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (bm_widget_new_html), (bm_widget_new_vcard): * src/balsa-mime-widget-vcalendar.c (balsa_mime_widget_new_vcalendar): * src/balsa-mime-widget.c (balsa_mime_widget_init), (balsa_mime_widget_new), (balsa_mime_widget_new_unknown): * src/balsa-mime-widget.h: 2019-09-13 Peter Bloomfield mime-widget-text: Actually show the context menu This time, the HTML widget's context menu. * src/balsa-mime-widget-text.c (bmwt_populate_popup_menu), (bmwt_populate_popup_cb): 2019-09-12 Peter Bloomfield mime-widget-text: Actually show the context menu * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): drop an obsolete signal connection; (text_view_populate_popup): show the popup menu. 2019-09-04 Peter Bloomfield mime-widget-text: Subclass BalsaMimeWidget Make it a class with useful info in the struct, instead of extensively using GObject data. * src/balsa-mime-widget-text.c (balsa_mime_widget_text_finalize), (balsa_mime_widget_text_class_init), (balsa_mime_widget_text_init), (balsa_mime_widget_new_text), (create_text_widget), (fix_text_widget), (structured_phrases_toggle), (text_view_url_popup), (text_view_populate_popup), (store_button_coords), (check_over_url), (prepare_url_offsets), (url_found_cb), (check_call_url), (find_url), (handle_url), (free_url), (draw_cite_bar_real), (draw_cite_bars), (balsa_gtk_html_popup), (balsa_gtk_html_button_press_cb), (bm_widget_new_vcard), (check_text_encoding), (fill_text_buf_cited): * src/balsa-mime-widget-text.h: 2019-09-02 Peter Bloomfield mime-widget-image: Simplify resizing Catch the size-allocate signal only for BalsaMimeWidgetImage widgets. * src/balsa-message.c (balsa_message_init): * src/balsa-mime-widget-image.c (balsa_mime_widget_image_init), (balsa_mime_widget_image_dispose), (img_check_size), (img_size_allocate_cb), (balsa_mime_widget_new_image): * src/balsa-mime-widget-image.h: 2019-09-02 Peter Bloomfield mime-widget-image: Declare BalsaMimeWidgetImage final It was already private, so no accessors are needed. * src/balsa-mime-widget-image.h: 2019-08-31 Peter Bloomfield mime-widget: Declare BalsaMimeWidget derivable Make the struct private, and provide accessors for the widget, container, and header_widget members. * src/balsa-message.c (bm_find_scroll_to_rectangle), (bm_find_entry_changed_cb), (bm_find_again), (balsa_message_init), (add_part), (gtk_tree_hide_func), (hide_all_parts), (select_part), (balsa_message_current_part_widget), (balsa_message_can_select), (balsa_message_grab_focus), (balsa_message_can_zoom), (balsa_message_zoom), (balsa_message_find_in_message): * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_limit_focus), (balsa_mime_widget_unlimit_focus): * src/balsa-mime-widget-crypto.c (balsa_mime_widget_new_signature), (balsa_mime_widget_new_pgpkey): * src/balsa-mime-widget-image.c (balsa_mime_widget_new_image): * src/balsa-mime-widget-message.c (balsa_mime_widget_new_message), (bmw_message_extbody_url), (bmw_message_extbody_mail), (balsa_mime_widget_new_message_tl), (bmw_message_set_headers_d), (bmw_message_set_headers): * src/balsa-mime-widget-multipart.c (balsa_mime_widget_new_multipart): * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (bm_widget_new_html), (bm_widget_new_vcard): * src/balsa-mime-widget-vcalendar.c (balsa_mime_widget_new_vcalendar): * src/balsa-mime-widget.c (balsa_mime_widget_init), (balsa_mime_widget_class_init), (balsa_mime_widget_new), (balsa_mime_widget_new_unknown), (vadj_change_cb), (balsa_mime_widget_get_widget), (balsa_mime_widget_get_container), (balsa_mime_widget_get_header_widget), (balsa_mime_widget_set_widget), (balsa_mime_widget_set_container), (balsa_mime_widget_set_header_widget): * src/balsa-mime-widget.h: 2019-08-25 Peter Bloomfield * src/balsa-print-object-text.c (balsa_print_object_text_calendar): Use ngettext() for plural forms of strings. 2019-08-21 Peter Bloomfield imap-handle: Use modern macros to declare and define ImapMboxHandle * libbalsa/imap/imap-handle.c (imap_mbox_handle_init), (imap_mbox_handle_class_init), (imap_mbox_handle_new), (imap_mbox_handle_finalize): * libbalsa/imap/imap-handle.h: 2019-08-14 Peter Bloomfield balsa-message: Use "balsa_message" consistntly as its identifier, and use "bm_" consistently as the prefix for static functions. * src/balsa-message.c (balsa_headers_attachments_popup), (bm_header_tl_buttons), (bm_on_set_style), (bm_find_set_status), (bm_find_scroll_to_rectangle), (bm_find_scroll_to_selection), (bm_find_cb), (bm_find_entry_changed_cb), (bm_find_again), (bm_find_bar_new), (bm_find_pass_to_entry), (bm_disable_find_entry), (balsa_message_init), (balsa_message_destroy), (balsa_message_new), (tree_activate_row_cb), (tree_mult_selection_popup), (tree_menu_popup_key_cb), (tree_button_press_cb), (bm_clear_tree), (balsa_message_set), (balsa_message_save_current_part), (bm_set_embedded_hdr), (balsa_message_set_displayed_headers), (balsa_message_set_wrap), (display_headers), (part_info_init), (atattchments_menu_cb), (add_to_attachments_popup), (toggle_all_inline_cb), (add_toggle_inline_menu_item), (display_part), (display_parts), (display_face), (display_content), (bm_next_part_info), (balsa_message_next_part), (balsa_message_has_next_part), (bm_previous_part_info), (balsa_message_previous_part), (balsa_message_has_previous_part), (part_info_from_body), (add_body), (add_multipart_digest), (add_multipart_mixed), (add_multipart), (add_part), (hide_all_parts), (select_part), (balsa_message_current_part_widget), (balsa_message_can_select), (balsa_message_grab_focus), (balsa_message_can_zoom), (balsa_message_zoom), (bm_scan_signatures), (message_recheck_crypto_cb), (balsa_message_find_in_message), (balsa_message_get_wrap_text), (balsa_message_get_focus_state), (balsa_message_get_scroll), (balsa_message_get_bm_widget), (balsa_message_get_message), (balsa_message_get_shown_headers), (balsa_message_get_face_box), (balsa_message_get_tree_view), (balsa_message_set_focus_state), (balsa_message_set_face_box): 2019-08-14 Peter Bloomfield balsa-message: Add the attach-button to the struct instead of using GObject-data * src/balsa-message.c (bm_header_tl_buttons), (balsa_message_set_displayed_headers), (display_content): 2019-08-13 Peter Bloomfield rfc 2445: Set a struct as GObject-data instead of three separate items. * libbalsa/rfc2445.c (libbalsa_vcal_attendee_to_str), (libbalsa_vcal_attendee_rsvp), (cal_address_2445_to_lbaddress): 2019-08-12 Peter Bloomfield mailbox-imap: Store cache-manager in the object instead of using GObject-data. * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_finalize), (libbalsa_mailbox_imap_open), (libbalsa_mailbox_imap_close): 2019-08-12 Peter Bloomfield mailbox: Store message-partial ids in the object instead of using GObject-data. * libbalsa/mailbox.c (lbm_try_reassemble_idle), (libbalsa_mailbox_try_reassemble): 2019-08-12 Peter Bloomfield Drop redundant dynamic cast * src/mailbox-node.c (balsa_mailbox_node_finalize): 2019-08-12 Peter Bloomfield Unref structure members in a dispose method * libbalsa/libbalsa-vfs.c (libbalsa_vfs_class_init), (libbalsa_vfs_dispose), (libbalsa_vfs_finalize): 2019-08-12 Peter Bloomfield In calls to g_signal_connect_swapped(), do not cast data using G_OBJECT(data). The argument is a gpointer, so the cast is redundant. * src/filter-run-dialog.c (balsa_filter_run_dialog_init): 2019-08-11 Peter Bloomfield In calls to g_signal*(), do not cast object using G_OBJECT(object). The argument is a gpointer, so the cast is redundant. * libbalsa/address.c (libbalsa_address_get_edit_widget): * libbalsa/filter-funcs.c (libbalsa_filter_list_new): * libbalsa/folder-scanners.c (libbalsa_scanner_imap_dir), (imap_tree_scan): * libbalsa/identity.c (setup_ident_frame): * libbalsa/imap/imap-commands.c (imap_mbox_select_unlocked): * libbalsa/imap/imap-handle.c (imap_mbox_connect), (imap_mbox_handle_get_delim), (ir_list_lsub), (ir_exists), (ir_expunge): * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_select_key): * libbalsa/libbalsa-progress.c (libbalsa_progress_dialog_ensure_real), (create_progress_widget): * libbalsa/libbalsa-vfs.c (libbalsa_vfs_mime_button): * libbalsa/macosx-helpers.c (libbalsa_macosx_menu), (libbalsa_macosx_menu_for_parent): * libbalsa/mailbox.c (libbalsa_mailbox_progress_notify): * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_get_selected_handle), (lbm_imap_check): * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_startup): * libbalsa/send.c (lbs_process_queue_init_session): * libbalsa/server.c (libbalsa_server_set_username), (libbalsa_server_set_host), (libbalsa_server_config_changed), (lbs_get_password): * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): * libinit_balsa/assistant_helper.c (balsa_init_add_grid_entry): * libinit_balsa/assistant_init.c (balsa_initdruid_apply), (balsa_initdruid): * libinit_balsa/assistant_page_defclient.c (balsa_druid_page_defclient_init): * libinit_balsa/assistant_page_directory.c (balsa_druid_page_directory_init): * libinit_balsa/assistant_page_user.c (balsa_druid_page_user): * libnetclient/net-client.c (net_client_start_tls): * libnetclient/test/tests.c (test_basic_crypt), (test_smtp), (test_pop3): * src/ab-main.c (bab_window_list_new), (bab_get_edit_button_box), (bab_get_filter_box), (bab_window_new), (main): * src/ab-window.c (balsa_ab_window_list), (balsa_ab_window_init), (balsa_ab_window_menu_changed): * src/address-book-config.c (create_local_dialog), (create_generic_dialog), (create_osmo_dialog), (balsa_address_book_add_menu): * src/balsa-index.c (bndx_selection_changed), (bndx_row_activated), (bndx_compose_foreach), (bndx_compose_from_list), (create_stock_menu_item), (bndx_changed_find_row): * src/balsa-mblist.c (balsa_mblist_init), (balsa_mblist_default_signal_bindings), (bmbl_store_redraw_mbnode), (balsa_mblist_mru_option_menu): * src/balsa-message.c (bm_header_tl_buttons), (balsa_message_init), (tree_mult_selection_popup), (add_to_attachments_popup), (add_toggle_inline_menu_item), (part_create_menu), (select_part), (create_mdn_dialog): * src/balsa-mime-widget-crypto.c (balsa_mime_widget_signature_widget), (create_import_keys_widget): * src/balsa-mime-widget-image.c (balsa_mime_widget_new_image): * src/balsa-mime-widget-message.c (bmw_message_extbody_url), (bmw_message_extbody_mail), (bm_header_extend_popup), (bmw_message_set_headers_d): * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (text_view_url_popup), (text_view_populate_popup), (bmwt_populate_popup_menu), (fill_text_buf_cited): * src/balsa-mime-widget-vcalendar.c (balsa_vevent_widget): * src/balsa-mime-widget.c (balsa_mime_widget_new), (balsa_mime_widget_new_unknown): * src/filter-edit-callbacks.c (add_button), (add_check), (get_field_frame), (build_type_notebook), (fe_edit_condition): * src/filter-edit-dialog.c (fe_build_option_menu), (build_left_side), (build_match_page), (build_action_page), (build_right_side), (filters_edit_dialog): * src/filter-export-dialog.c (filters_export_dialog): * src/filter-run-dialog.c (selected_filters_new), (balsa_filter_run_dialog_init): * src/folder-conf.c (folder_conf_clicked_ok), (folder_conf_imap_node), (folder_conf_imap_sub_node): * src/information-dialog.c (balsa_information_list): * src/mailbox-conf.c (run_mailbox_conf), (create_local_mailbox_dialog): * src/mailbox-node.c (imap_scan_attach_mailbox), (balsa_mailbox_node_new_from_mailbox), (balsa_mailbox_node_new_from_dir), (balsa_mailbox_node_new_from_config), (balsa_mailbox_node_new_imap_node), (balsa_mailbox_node_new_imap_folder), (add_menu_entry), (balsa_mailbox_node_get_context_menu): * src/main-window.c (bw_enable_filter), (bw_disable_filter), (bw_create_index_widget), (new_message_activated), (balsa_window_new), (bw_check_mailbox_list), (bw_find_real): * src/message-window.c (destroy_message_window): * src/pref-manager.c (pm_combo_box_new), (create_pref_option_menu), (server_add_menu_widget), (pm_grid_add_remote_mailbox_servers_group), (pm_grid_add_outgoing_mail_group), (open_preferences_manager): * src/print-gtk.c (message_prefs_widget): * src/sendmsg-window.c (address_book_cb), (balsa_sendmsg_destroy_handler), (sw_get_user_codeset), (add_attachment), (add_urlref_attachment), (sw_attach_dialog), (create_info_pane), (sw_attachment_list), (create_text_area), (create_lang_menu), (sendmsg_window_set_field), (sw_include_file_activated), (sendmsg_window_new): * src/store-address.c (balsa_store_address_from_messages), (balsa_store_address): * src/toolbar-prefs.c (customize_dialog_cb), (create_toolbar_page): 2019-08-10 Peter Bloomfield In calls to g_object_unref(), do not cast object using G_OBJECT(object). The argument is a gpointer, so the cast is redundant. * libbalsa/autocrypt.c (autocrypt_db_dialog_run): * libbalsa/body.c (libbalsa_message_body_free): * libbalsa/gmime-multipart-crypt.c (g_mime_gpgme_mpe_decrypt): * libbalsa/html.c (html2text): * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_select_key): * libbalsa/libbalsa.c (ask_cert_real): * libbalsa/mailbox_imap.c (imap_exists_idle), (libbalsa_mailbox_imap_get_message): * libbalsa/mailbox_pop3.c (pop_handler_close), (libbalsa_mailbox_pop3_startup), (libbalsa_mailbox_pop3_check): * libbalsa/rfc3156.c (libbalsa_sign_mime_object), (libbalsa_encrypt_mime_object), (libbalsa_sign_encrypt_mime_object), (libbalsa_body_check_signature), (libbalsa_body_decrypt), (libbalsa_rfc2440_verify), (libbalsa_rfc2440_decrypt): * libbalsa/send.c (msg_queue_item_destroy), (send_message_info_destroy), (add_mime_body_plain), (balsa_send_message_real), (libbalsa_message_create_mime_message), (libbalsa_fill_msg_queue_item_from_queu): * libnetclient/net-client-pop.c (net_client_pop_new): * libnetclient/net-client-siobuf.c (net_client_siobuf_new): * libnetclient/net-client-smtp.c (net_client_smtp_new): * libnetclient/net-client.c (net_client_new), (net_client_shutdown), (net_client_set_cert_from_pem), (net_client_set_cert_from_file), (net_client_start_tls), (net_client_finalise): * src/ab-window.c (balsa_ab_window_get_recipients), (balsa_ab_window_swap_real), (balsa_ab_window_activate_address): * src/balsa-message.c (balsa_message_init), (balsa_message_set_embedded_hdr), (display_part), (handle_mdn_request), (mdn_dialog_response), (message_recheck_crypto_cb): * src/balsa-mime-widget-crypto.c (balsa_mime_widget_new_pgpkey): * src/balsa-mime-widget-message.c (extbody_send_mail): * src/balsa-mime-widget-vcalendar.c (vevent_reply): * src/balsa-print-object-decor.c (bpo_decor_print_frame_begin): * src/balsa-print-object-default.c (balsa_print_object_default_full): * src/balsa-print-object-header.c (balsa_print_object_header_new_real), (balsa_print_object_header_crypto), (balsa_print_object_header_draw): * src/balsa-print-object-text.c (balsa_print_object_text_plain), (balsa_print_object_text), (balsa_print_object_text_draw): * src/mailbox-conf.c (mailbox_conf_add): * src/print-gtk.c (print_header_footer), (begin_print), (message_print_page_setup), (message_print): * src/save-restore.c (config_global_load): * src/sendmsg-window.c (balsa_attach_info_finalize), (balsa_sendmsg_destroy_handler), (collect_for_quote), (sw_save_draft), (send_message_handler), (message_postpone): 2019-08-10 Peter Bloomfield In calls to g_object_ref(), do not cast object using G_OBJECT(object). The macro now casts the return value to the type of the argument, so casting away its actual type is unhelpful. * libbalsa/mailbox_imap.c (imap_exists_cb): * libbalsa/rfc3156.c (libbalsa_sign_encrypt_mime_object): * libbalsa/send.c (libbalsa_fill_msg_queue_item_from_queu): * src/balsa-message.c (message_recheck_crypto_cb): * src/balsa-print-object-header.c (balsa_print_object_header_new_real): * src/folder-conf.c (create_imap_folder_dialog): * src/print-gtk.c (message_print): * src/sendmsg-window.c (sw_buffer_swap): 2019-08-09 Peter Bloomfield In calls to g_object_[gs]et(), do not cast object using G_OBJECT(object). The argument is a gpointer, so the cast is redundant. * libbalsa/files.c (libbalsa_icon_finder): * libbalsa/libbalsa.c (libbalsa_is_cert_known), (ask_cert_real), (get_gnutls_cert): * libbalsa/mime.c (get_quote_tag): * libbalsa/server-config.c (libbalsa_server_cfg_new): * libnetclient/test/tests.c (check_cert): * src/balsa-app.c (ask_password_real): * src/balsa-mblist.c (balsa_mblist_init): * src/balsa-message.c (balsa_message_init): * src/balsa-mime-widget-message.c (balsa_mime_widget_new_message): * src/balsa-mime-widget-text.c (structured_phrases_toggle): * src/balsa-mime-widget.c (balsa_mime_widget_new): * src/main-window.c (balsa_window_new): * src/pref-manager.c (apply_prefs): * src/sendmsg-window.c (sw_attachment_list), (sw_can_undo_cb), (sw_can_redo_cb): * src/toolbar-factory.c (tm_populate): 2019-08-03 Albrecht Dreß SMTP logging See When Balsa sends a message to a local or remote SMTP server, a feedback is given only on failure. However, sometimes it is necessary to trace sent messages on the SMTP server. * libbalsa/send.c: new function balsa_send_message_syslog(), changed API of net_client_smtp_send_msg(); * libnetclient/net-client-smtp.[ch]: extend API of net_client_smtp_send_msg() for optionally passing the final SMTP server reply. 2019-08-03 Peter Bloomfield mailbox-imap: Clear search filter when mailbox is closed See * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_close): unref search filter. 2019-07-30 Peter Bloomfield folder-conf: Refactor dialog data strucures * src/folder-conf.c (folder_conf_destroy_common_data), (folder_conf_response), (validate_folder), (imap_update_subscriptions), (folder_conf_clicked_ok), (on_subscription_toggled), (create_imap_folder_dialog), (folder_conf_imap_subscriptions), (folder_data_subscribed_toggled), (folder_conf_imap_node), (validate_sub_folder), (browse_button_cb), (subfolder_conf_clicked_ok), (folder_conf_imap_sub_node), (folder_conf_delete): 2019-07-30 Peter Bloomfield mailbox-node: Scrap the "load-config" and "save-config" signals. No one needed to connect to them. * src/mailbox-node.c (balsa_mailbox_node_class_init), (balsa_mailbox_node_init), (balsa_mailbox_node_load_config), (balsa_mailbox_node_save_config): 2019-07-30 Peter Bloomfield sendmsg-window: Use modern macros to declare and define BalsaAttachInfo * src/sendmsg-window.c (balsa_attach_info_class_init), (balsa_attach_info_init), (balsa_attach_info_new), (balsa_attach_info_finalize), (sw_attachment_list): 2019-07-29 Peter Bloomfield Use parent-class set by G_DEFINE_TYPE instead of our own variable * src/mailbox-node.c (balsa_mailbox_node_class_init), (balsa_mailbox_node_dispose), (balsa_mailbox_node_finalize): 2019-07-29 Peter Bloomfield rfc2445: Use GDateTime instead of GTimeVal, which is deprecated in glib version 2.62. * libbalsa/rfc2445.c (date_time_2445_to_time_t): 2019-07-29 Peter Bloomfield main-window: declare it derivable Put the details in BalsaWindowPrivate, and provide accessors. * src/balsa-mime-widget-text.c (statusbar_pop), (handle_url), (bm_widget_on_url): * src/information-dialog.c (balsa_information_list), (status_bar_refresh), (balsa_information_bar): * src/mailbox-node.c (imap_dir_cb): * src/main-window.c (bw_network_changed_cb), (balsa_window_init), (bw_pass_to_filter), (bw_filter_entry_activate), (bw_create_index_widget), (bw_set_panes), (bw_is_active_notify), (bw_action_set_enabled), (find_in_message_activated), (zoom_in_activated), (zoom_out_activated), (zoom_normal_activated), (reset_filter_activated), (next_part_activated), (previous_part_activated), (save_part_activated), (copy_message_activated), (select_text_activated), (show_mailbox_tabs_change_state), (show_toolbar_change_state), (show_statusbar_change_state), (show_sos_bar_change_state), (wrap_change_state), (show_all_headers_change_state), (header_change_state), (threading_change_state), (bw_alt_n_cb), (balsa_window_new), (balsa_window_fix_paned), (balsa_window_update_book_menus), (bw_enable_message_menus), (bw_enable_part_menu_items), (bw_real_open_mbnode_idle_cb), (balsa_window_real_close_mbnode), (balsa_window_destroy), (balsa_window_refresh), (bw_check_mailbox_list), (bw_mailbox_check), (bw_check_messages_thread), (bw_display_new_mail_notification), (bw_change_connection_status_can_reach_cb), (bw_change_connection_status_idle), (balsa_window_find_current_index), (bw_get_view_filter), (bw_reset_filter), (bw_show_mbtree), (balsa_change_window_layout), (bw_notebook_switch_page_cb), (bw_index_changed_cb), (bw_idle_replace), (bw_idle_remove), (bw_idle_cb), (bw_progress_timeout), (bw_update_progress_bar), (balsa_window_increase_activity), (balsa_window_decrease_activity), (balsa_window_setup_progress), (balsa_window_increment_progress), (balsa_window_set_statusbar), (balsa_window_next_unread), (balsa_window_get_statusbar): * src/main-window.h: 2019-07-27 Peter Bloomfield address-book-config: Do not leak structures * src/address-book-config.c (balsa_address_book_config_new), (balsa_address_book_config_new_from_type): 2019-07-27 Peter Bloomfield mailbox-node: Do not give access to BalsaMailboxNode:scanned We can do all the checking in mailbox-node.c. * src/mailbox-node.c (balsa_mailbox_node_append_subtree): check whether the mbnode has been scanned; * src/mailbox-node.h: drop accessors; * src/balsa-mblist.c (balsa_mblist_mailbox_node_append): no need to check whether the mbnode has been scanned. 2019-07-26 Peter Bloomfield balsa-mailbox-node: Use modern macros to declare and define. * src/mailbox-node.h: declare BalsaMailboxNode final; * src/mailbox-node.c: use G_DEFINE_TYPE(); (balsa_mailbox_node_class_init), (balsa_mailbox_node_init), (get_parent_folder_name), (add_imap_entry), (handle_imap_path), (mark_imap_path), (balsa_mailbox_node_set_dir), (balsa_mailbox_node_set_name), (balsa_mailbox_node_set_config_prefix), (balsa_mailbox_node_set_last_use_time), (balsa_mailbox_node_change_style): adapt; (balsa_mailbox_node_set_list_inbox), (balsa_mailbox_node_set_subscribed), (balsa_mailbox_node_set_scanned), (balsa_mailbox_node_get_mailbox), (balsa_mailbox_node_get_name), (balsa_mailbox_node_get_config_prefix), (balsa_mailbox_node_get_last_use_time), (balsa_mailbox_node_get_server), (balsa_mailbox_node_get_style), (balsa_mailbox_node_get_subscribed), (balsa_mailbox_node_get_scanned), (balsa_mailbox_node_get_list_inbox), (balsa_mailbox_node_get_delim), (balsa_mailbox_node_get_dir), (balsa_mailbox_node_get_parent): new functions; * libbalsa/folder-scanners.h: * libinit_balsa/assistant_page_user.c (create_imap_mbx): * src/balsa-app.c (find_mailbox), (find_path), (find_url), (balsa_find_mailbox_by_url), (balsa_get_short_mailbox_name), (balsa_find_iter_by_data_func), (ba_remove_children_mailbox_nodes), (balsa_remove_children_mailbox_nodes): * src/balsa-index.c (bndx_destroy), (bndx_selection_changed_idle), (bndx_selection_changed), (bndx_find_current_msgno), (bndx_scroll_on_open_idle), (balsa_index_load_mailbox_node), (bndx_search_iter), (bndx_search_iter_and_select), (bndx_mailbox_changed_idle), (balsa_index_selected_msgnos_new), (balsa_index_selected_msgnos_free), (bndx_view_source), (bndx_compose_foreach), (bndx_compose_from_list), (bndx_do_delete), (balsa_message_move_to_trash), (balsa_find_notebook_page_num), (balsa_index_toggle_flag), (bi_toggle_deleted_cb), (mru_menu_cb), (bndx_do_popup), (balsa_index_set_thread_messages), (balsa_index_set_view_filter), (balsa_index_transfer), (balsa_index_expunge), (bndx_next_msgno), (balsa_index_pipe), (balsa_index_select_thread), (balsa_index_set_last_use_time), (balsa_index_get_last_use_time), (balsa_index_get_mailbox): * src/balsa-mblist.c (bmbl_selection_func), (bmbl_tree_expand), (bmbl_tree_collapse_helper), (bmbl_tree_collapse), (bmbl_row_compare), (bmbl_drag_cb), (bmbl_select_mailbox), (bmbl_row_activated_cb), (bmbl_find_all_unread_mboxes_func), (get_lru_descendant), (bmbl_real_disconnect_mbnode_signals), (bmbl_store_redraw_mbnode), (bmbl_node_style), (bmbl_mru_selected_cb), (bmbl_mru_activated_cb), (balsa_mblist_mailbox_node_append): * src/filter-edit-callbacks.c (update_filters_mailbox): * src/folder-conf.c (folder_conf_clicked_ok), (folder_conf_imap_subscriptions), (folder_conf_imap_node), (validate_sub_folder), (browse_button_cb), (subfolder_conf_clicked_ok), (folder_conf_imap_sub_node), (folder_conf_delete), (folder_conf_add_imap_sub_cb): * src/mailbox-conf.c (mailbox_conf_delete_cb), (mailbox_conf_delete), (run_mailbox_conf), (mailbox_conf_edit): * src/main-window.c (bw_enable_mailbox_menus), (bw_notebook_label_new), (bw_real_open_mbnode_idle_cb), (bw_real_open_mbnode_thread), (balsa_window_real_open_mbnode), (balsa_window_real_close_mbnode), (bw_check_mailbox_list), (bw_add_mbox_to_checklist), (mw_mbox_change_connection_status), (bw_change_connection_status_idle), (balsa_window_update_tab): * src/main.c (periodic_expunge_cb): * src/pref-manager.c (add_other_server), (server_del_cb), (update_mail_servers): * src/save-restore.c (folder_section_path), (migrate_imap_mailboxes), (config_folder_delete), (config_folder_init): * src/save-restore.h: use them. 2019-07-23 Peter Bloomfield filter-run: Make filter-run.h private * src/filter-run-callbacks.c: define OK_TO_INCLUDE_FILTER_RUN_H; * src/filter-run-dialog.c: ditto; * src/filter-run.h: error if it is not defined. 2019-07-23 Peter Bloomfield Cleanup after using G_DECLARE_FINAL_TYPE() * libbalsa/mailbox_imap.c: drop redundant class struct declaration; * libbalsa/mailbox_maildir.c: ditto; * libbalsa/mailbox_mbox.c: ditto; * libbalsa/mailbox_mh.c: ditto; * libbalsa/mailbox_pop3.c: ditto; * libbalsa/message.c: ditto; * src/ab-window.c: ditto; * src/balsa-cite-bar.c: ditto; drop parant_class variable; (balsa_cite_bar_class_init): no more parent_class. 2019-07-23 Peter Bloomfield * libbalsa/libbalsa-gpgme-widgets.c (create_uid_str): Do not leak an empty string. 2019-07-23 Peter Bloomfield * src/balsa-message.c (balsa_message_destroy): Do not leak BalsaMessage::face_box. 2019-07-22 Peter Bloomfield balsa-message: Use modern macros to declare and define. Make BalsaMessage opaque, and provide and use necessary accessors. * src/balsa-message.c (balsa_part_info_class_init), (balsa_message_class_init), (balsa_message_destroy), (balsa_part_info_init), (balsa_part_info_new), (balsa_part_info_dispose), (balsa_part_info_finalize), (balsa_message_get_wrap_text), (balsa_message_get_focus_state), (balsa_message_get_scroll), (balsa_message_get_bm_widget), (balsa_message_get_message), (balsa_message_get_shown_headers), (balsa_message_get_face_box), (balsa_message_get_tree_view), (balsa_message_set_focus_state), (balsa_message_set_face_box): * src/balsa-message.h: * src/balsa-mime-widget-callbacks.c (scroll_change), (balsa_mime_widget_key_press_event), (balsa_mime_widget_limit_focus), (balsa_mime_widget_unlimit_focus): * src/balsa-mime-widget-message.c (balsa_mime_widget_new_message), (bm_header_widget_new), (add_header_address_list), (bmw_message_set_headers_d), (balsa_mime_widget_message_set_headers), (balsa_mime_widget_message_set_headers_d): * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (check_text_encoding): * src/balsa-mime-widget-vcalendar.c (balsa_mime_widget_new_vcalendar): * src/main-window.c (bw_index_changed_cb), (bw_idle_replace): * src/message-window.c (mw_set_part_buttons_sensitive): 2019-07-22 Peter Bloomfield balsa-mblist: Use modern macros to declare and define. Make BalsaMBList opaque; no accessors needed. * src/balsa-mblist.c (balsa_mblist_class_init), (bmbl_drag_motion), (balsa_mblist_init): * src/balsa-mblist.h: 2019-07-22 Peter Bloomfield balsa-index: Another convenience function * src/balsa-index.c (balsa_index_get_last_use_time): another convenience function; * src/balsa-index.h: declare it; * src/main-window.c (bw_close_mailbox_on_timer): use it. 2019-07-22 Peter Bloomfield send.c: Fix the build * libbalsa/send.c (libbalsa_message_create_mime_message): LibBalsaIdentity *identity is used only in an autocrypt build. 2019-07-21 Peter Bloomfield balsa-index: Add a convenience function balsa_index_get_mailbox(). * src/balsa-index.c (balsa_index_get_mailbox): define it; * src/balsa-index.h: declare it; * src/balsa-app.c (balsa_find_index_by_mailbox): * src/balsa-mblist.c (bmbl_tree_expand), (bmbl_drag_cb), (bmbl_update_mailbox): * src/main-window.c (continue_activated), (print_activated), (mailbox_close_activated), (select_filters_activated), (remove_duplicates_activated), (threading_change_state), (bw_enable_message_menus), (balsa_window_set_thread_messages), (balsa_window_real_close_mbnode), (bw_find_real), (bw_hide_changed_set_view_filter), (bw_notebook_switch_page_cb), (bw_idle_cb), (bw_notebook_drag_received_cb), (bw_notebook_page_notify_cb), (balsa_window_next_unread): * src/message-window.c (mw_set_buttons_sensitive): * src/sendmsg-window.c (attachments_add), (drag_data_quote): use it. 2019-07-21 Peter Bloomfield balsa-index: Use modern macros to declare and define. Make BalsaIndex opaque, and provide necessary accessors. * src/balsa-index.c: use G_DEFINE_TYPE to define BalsaIndex; (balsa_index_class_init), (bndx_destroy), (balsa_index_init), (balsa_index_select_thread), (balsa_index_get_mailbox_node), (balsa_index_get_current_msgno), (balsa_index_get_filter_no), (balsa_index_get_next_message), (balsa_index_get_prev_message), (balsa_index_get_filter_string), (balsa_index_set_last_use_time): * src/balsa-index.h: use G_DECLARE_FINAL_TYPE; * src/balsa-app.c (balsa_find_index_by_mailbox): * src/balsa-mblist.c (bmbl_tree_expand), (bmbl_drag_cb), (bmbl_open_mailbox), (bmbl_update_mailbox): * src/main-window.c (continue_activated), (print_activated), (reset_filter_activated), (mailbox_close_activated), (select_filters_activated), (remove_duplicates_activated), (threading_change_state), (bw_enable_mailbox_menus), (balsa_window_update_book_menus), (bw_enable_message_menus), (balsa_window_set_thread_messages), (balsa_window_real_close_mbnode), (bw_close_mailbox_on_timer), (bw_find_real), (bw_hide_changed_set_view_filter), (bw_reset_filter), (bw_notebook_switch_page_cb), (bw_index_changed_cb), (bw_idle_cb), (bw_notebook_drag_received_cb), (bw_notebook_page_notify_cb), (balsa_window_next_unread): * src/message-window.c (mw_set_buttons_sensitive): * src/sendmsg-window.c (attachments_add), (drag_data_quote): use the accessors. 2019-07-19 Peter Bloomfield * libbalsa/filter-file.c (libbalsa_mailbox_filters_load_config): Fix loading filters. 2019-07-18 Peter Bloomfield balsa-cite-bar: Declare it final * src/balsa-cite-bar.c: Copyright update; * src/balsa-cite-bar.h: use G_DECLARE_FINAL_TYPE(). 2019-07-18 Peter Bloomfield ab-window: Use modern macros to declare and define. * src/ab-window.c: use G_DEFINE_TYPE(); * src/ab-window.h: use G_DECLARE_FINAL_TYPE(). 2019-07-17 Peter Bloomfield * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_fetch_message_structure): do not unref a NULL GMimeMessage. 2019-07-17 Peter Bloomfield * libbalsa/gmime-part-rfc2440.c (g_mime_part_check_rfc2440): use g_str_has_prefix() instead of strncmp(). 2019-07-16 Peter Bloomfield mime-stream-shared: Use modern macros to declare and define. * libbalsa/mime-stream-shared.c: Use G_DEFINE_TYPE(); (libbalsa_mime_stream_shared_class_init): do not handle parent_class; (libbalsa_mime_stream_shared_init): new stub, required by G_DEFINE_TYPE(); (lbmss_lock_new): do not ref-count locks; (lbmss_finalize): use GMimeStreamFs::owner to decide when to free the lock; (lbmss_stream_read), (lbmss_stream_write), (lbmss_stream_reset), (lbmss_stream_seek), (lbmss_stream_substream), (libbalsa_mime_stream_shared_new): parent class stuff; (libbalsa_mime_stream_shared_lock), (libbalsa_mime_stream_shared_unlock): cosmetics; * libbalsa/mime-stream-shared.h: Use G_DECLARE_FINAL_TYPE(). 2019-07-15 Peter Bloomfield Fix some Valgrind-detected issues * libbalsa/filter-file.c (libbalsa_mailbox_filters_load_config): initialize LibBalsaMailboxFilter::when; * libbalsa/mailbox.c (libbalsa_mailbox_finalize): clear the GRecMutex; * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_load_envelope): do not leak an InternetAddressList; (get_struct_from_cache): do not leak GMimeMessage; * libbalsa/send.c (lbs_message_queue_real): ref the GMimeMessage to preserve it, and then unref it. 2019-07-13 Peter Bloomfield balsa-message: Pass message headers to disposition-notify handler * src/balsa-message.c (balsa_message_set), (handle_mdn_request): 2019-07-11 Peter Bloomfield message: Declare it final Use G_DECLARE_FINAL_TYPE to declare LibBalsaMessage, make it private, and provide necessary getters and setters. * libbalsa/autocrypt.c (autocrypt_from_message): * libbalsa/body.c (libbalsa_message_body_set_text_rfc822headers), (libbalsa_message_body_get_part_stream), (libbalsa_message_body_get_message_part_stream), (libbalsa_message_body_get_stream), (libbalsa_message_body_get_content), (libbalsa_message_body_get_pixbuf), (libbalsa_message_body_save_stream): * libbalsa/filter.c (libbalsa_condition_matches), (libbalsa_condition_can_match): * libbalsa/mailbox.c (get_from_field), (lbm_index_entry_populate_from_msg), (libbalsa_mailbox_real_release_message), (libbalsa_mailbox_release_message), (libbalsa_mailbox_set_msg_headers), (libbalsa_mailbox_get_message_part), (lbm_get_mime_msg), (lbm_try_reassemble): * libbalsa/mailbox_imap.c (lbimap_update_flags), (imap_flags_cb), (imap_expunge_cb), (free_messages_info), (libbalsa_mailbox_imap_load_envelope), (libbalsa_mailbox_imap_get_message), (get_struct_from_cache), (libbalsa_mailbox_imap_fetch_structure), (libbalsa_mailbox_imap_fetch_headers), (get_section_for), (lbm_imap_get_msg_part_from_cache): * libbalsa/mailbox_local.c (lbm_local_get_message_with_msg_info), (message_match_real), (libbalsa_mailbox_local_cache_message), (libbalsa_mailbox_local_fetch_structure), (libbalsa_mailbox_local_fetch_headers), (libbalsa_mailbox_local_messages_change_flags): * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_check), (free_message_info), (libbalsa_mailbox_maildir_sync), (libbalsa_mailbox_maildir_fetch_message_structure): * libbalsa/mailbox_mbox.c (parse_mailbox), (free_message_info), (libbalsa_mailbox_mbox_sync), (libbalsa_mailbox_mbox_fetch_message_structure), (lbm_mbox_add_message): * libbalsa/mailbox_mh.c (lbm_mh_free_message_info), (libbalsa_mailbox_mh_check), (libbalsa_mailbox_mh_sync), (libbalsa_mailbox_mh_fetch_message_structure): * libbalsa/message.c (libbalsa_message_class_init), (libbalsa_message_dispose), (libbalsa_message_finalize), (lb_message_headers_extra_destroy), (libbalsa_message_headers_destroy), (libbalsa_message_body_charset), (libbalsa_message_header_get_helper), (libbalsa_message_find_user_hdr), (libbalsa_message_header_get_one), (libbalsa_message_header_get_all), (libbalsa_message_get_user_header), (libbalsa_message_set_user_header), (prepend_header_misc), (libbalsa_message_user_hdrs_from_gmime), (libbalsa_message_get_part_by_id), (libbalsa_message_save), (libbalsa_message_get_attach_icon), (libbalsa_message_reply), (libbalsa_message_body_ref), (libbalsa_message_body_unref), (libbalsa_message_is_multipart), (libbalsa_message_is_partial), (has_attached_part), (libbalsa_message_has_attachment), (libbalsa_message_get_subject), (libbalsa_message_get_lines), (libbalsa_message_get_length), (lb_message_recipients), (lb_message_headers_basic_from_gmime), (lb_message_headers_extra_from_gmime), (libbalsa_message_init_from_gmime), (libbalsa_message_refs_for_threading), (references_decode), (libbalsa_message_set_references_from_string), (libbalsa_message_set_in_reply_to_from_string), (lbmsg_set_header), (lb_message_set_headers_from_string), (libbalsa_message_load_envelope_from_stream), (libbalsa_message_load_envelope), (libbalsa_message_stream), (libbalsa_message_copy), (libbalsa_message_set_subject), (libbalsa_message_set_subject_from_header), (libbalsa_message_get_tempdir), (libbalsa_message_get_mailbox), (libbalsa_message_get_headers), (libbalsa_message_get_body_list), (libbalsa_message_get_mime_message), (libbalsa_message_get_flags), (libbalsa_message_get_message_id), (libbalsa_message_get_msgno), (libbalsa_message_get_has_all_headers), (libbalsa_message_get_sender), (libbalsa_message_get_request_dsn), (libbalsa_message_get_references), (libbalsa_message_get_identity), (libbalsa_message_get_parameters), (libbalsa_message_get_subtype), (libbalsa_message_get_gpg_mode), (libbalsa_message_get_in_reply_to), (libbalsa_message_get_attach_pubkey), (libbalsa_message_get_protect_state), (libbalsa_message_get_body_ref), (libbalsa_message_set_flags), (libbalsa_message_set_mailbox), (libbalsa_message_set_msgno), (libbalsa_message_set_has_all_headers), (libbalsa_message_set_length), (libbalsa_message_set_mime_message), (libbalsa_message_set_sender), (libbalsa_message_set_message_id), (libbalsa_message_set_protect_state), (libbalsa_message_set_request_dsn), (libbalsa_message_set_subtype), (libbalsa_message_set_body_list), (libbalsa_message_set_references), (libbalsa_message_set_in_reply_to), (libbalsa_message_set_gpg_mode), (libbalsa_message_set_attach_pubkey), (libbalsa_message_set_identity), (libbalsa_message_add_parameters): * libbalsa/message.h: * libbalsa/rfc3156.c (libbalsa_body_check_signature), (libbalsa_body_decrypt): * libbalsa/send.c (lbs_message_queue_real), (lbs_process_queue_msg), (balsa_send_message_success), (balsa_send_message_error), (balsa_send_message_real), (message_add_references), (libbalsa_message_create_mime_message), (libbalsa_message_postpone), (libbalsa_create_msg), (libbalsa_fill_msg_queue_item_from_queu), (lb_send_from), (libbalsa_create_rfc2440_buffer), (do_multipart_crypto): * libbalsa/source-viewer.c (lsv_escape_change_state), (libbalsa_show_message_source): * src/balsa-message.c (balsa_message_set), (balsa_message_set_displayed_headers), (balsa_message_set_wrap), (display_headers), (display_content), (handle_mdn_request), (create_mdn_reply), (balsa_message_scan_signatures), (libbalsa_msg_try_decrypt), (libbalsa_msg_part_2440), (balsa_message_perform_crypto), (message_recheck_crypto_cb): * src/balsa-mime-widget-message.c (extbody_send_mail): * src/balsa-mime-widget-text.c (check_text_encoding): * src/balsa-mime-widget-vcalendar.c (balsa_mime_widget_new_vcalendar), (vevent_reply): * src/balsa-mime-widget.c (balsa_mime_widget_new_unknown): * src/balsa-print-object-header.c (balsa_print_object_header_from_message): * src/main-window.c (bw_index_changed_cb): * src/message-window.c (message_window_idle_handler), (mw_set_buttons_sensitive), (mw_expunged_cb), (mw_reply_activated), (mw_reply_all_activated), (mw_reply_group_activated), (mw_forward_attached_activated), (mw_forward_inline_activated), (mw_forward_default_activated): * src/print-gtk.c (begin_print): * src/sendmsg-window.c (sw_delete_draft), (balsa_sendmsg_destroy_handler), (update_bsmsg_identity), (create_info_pane), (continue_body), (message_part_get_subject), (quote_message_body), (fill_body_from_message), (bsmsg_set_subject_from_body), (sw_save_draft), (setup_headers_from_message), (set_identity_from_mailbox), (guess_identity), (bsm_prepare_for_setup), (bsm_finish_setup), (bsmsg2message), (check_autocrypt_recommendation), (send_message_handler), (sendmsg_window_reply), (sendmsg_window_forward), (sendmsg_window_continue): * src/store-address.c (store_address_note_frame): 2019-07-11 Peter Bloomfield Rename LIBBALSA_MAILBOX_REMOTE_SERVER() to LIBBALSA_MAILBOX_REMOTE_GET_SERVER() * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_dispose), (libbalsa_mailbox_imap_update_url), (clean_cache), (libbalsa_mailbox_imap_get_handle), (libbalsa_mailbox_imap_get_selected_handle), (lbm_imap_check), (libbalsa_mailbox_imap_save_config), (libbalsa_mailbox_imap_reconnect), (libbalsa_mailbox_imap_fetch_structure), (libbalsa_mailbox_imap_messages_copy): * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_check), (libbalsa_mailbox_pop3_save_config), (libbalsa_mailbox_pop3_load_config): * libbalsa/mailbox_remote.h: * libinit_balsa/assistant_page_directory.c (unconditional_mailbox): * libinit_balsa/assistant_page_user.c (create_pop3_mbx): * src/mailbox-conf.c (update_pop_mailbox), (create_pop_mailbox_dialog): * src/save-restore.c (config_mailbox_init): 2019-07-11 Peter Bloomfield * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_messages_copy): Fix some bad logic from commit 2d54e175561c9e382701d63ed8dde4746959559b 2019-07-06 Peter Bloomfield Fix some scan-build reports * libbalsa/mailbox.c (libbalsa_mailbox_set_threading_type), (libbalsa_mailbox_set_subject_gather), (libbalsa_mailbox_set_sort_type), (libbalsa_mailbox_set_sort_field), (libbalsa_mailbox_set_show), (libbalsa_mailbox_set_subscribe), (libbalsa_mailbox_set_exposed), (libbalsa_mailbox_set_open), (libbalsa_mailbox_set_filter): remove a dead store; * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_get_selected_handle): initialize readonly to FALSE. 2019-07-06 Peter Bloomfield mailbox-{remote,imap}: Simplify dispose() methods * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_dispose): the server will be destroyed in the parent-class (LibBalsaMailboxRemote) method; * libbalsa/mailbox_remote.c (libbalsa_mailbox_remote_dispose): chain up to the parent-class (LibBalsaMailbox) method, to make sure the mailbox is closed, before destroying the server. 2019-07-05 Peter Bloomfield mailbox-pop3: Declare it final Use G_DECLARE_FINAL_TYPE to declare LibBalsaMailboxPOP3, make it private, and provide necessary getters and setters. * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_get_delete_from_server), (libbalsa_mailbox_pop3_get_check), (libbalsa_mailbox_pop3_get_filter), (libbalsa_mailbox_pop3_get_filter_cmd), (libbalsa_mailbox_pop3_get_disable_apop), (libbalsa_mailbox_pop3_get_enable_pipe), (libbalsa_mailbox_pop3_set_msg_size_limit), (libbalsa_mailbox_pop3_set_check), (libbalsa_mailbox_pop3_set_disable_apop), (libbalsa_mailbox_pop3_set_delete_from_server), (libbalsa_mailbox_pop3_set_filter), (libbalsa_mailbox_pop3_set_filter_cmd), (libbalsa_mailbox_pop3_set_enable_pipe): * libbalsa/mailbox_pop3.h: * libinit_balsa/assistant_page_user.c (create_pop3_mbx): * src/mailbox-conf.c (update_pop_mailbox), (create_pop_mailbox_dialog): 2019-07-05 Peter Bloomfield mailbox-imap: Declare it final Use G_DECLARE_FINAL_TYPE to declare LibBalsaMailboxImap No new accessors needed. * libbalsa/mailbox_imap.h: 2019-07-05 Peter Bloomfield mailbox-remote: declare it derivable Use G_DECLARE_DERIVABLE_TYPE to declare LibBalsaMailboxRemote and provide libbalsa_mailbox_remote_get_server(). * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_class_init), (libbalsa_mailbox_imap_dispose), (libbalsa_mailbox_imap_finalize), (get_header_cache_path), (get_cache_name_pair), (libbalsa_mailbox_imap_close), (libbalsa_mailbox_imap_save_config), (libbalsa_mailbox_imap_load_config), (libbalsa_mailbox_imap_add_messages), (libbalsa_mailbox_imap_messages_copy): * libbalsa/mailbox_imap.h: * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_class_init), (libbalsa_mailbox_pop3_init), (libbalsa_mailbox_pop3_finalize), (libbalsa_mailbox_pop3_new), (libbalsa_mailbox_pop3_open), (libbalsa_mailbox_pop3_startup), (update_msg_list), (libbalsa_mailbox_pop3_check), (libbalsa_mailbox_pop3_save_config), (libbalsa_mailbox_pop3_load_config), (libbalsa_mailbox_pop3_set_inbox), (libbalsa_mailbox_pop3_set_msg_size_limit): * libbalsa/mailbox_pop3.h: * libbalsa/mailbox_remote.c (libbalsa_mailbox_remote_class_init), (libbalsa_mailbox_remote_init), (libbalsa_mailbox_remote_dispose), (libbalsa_mailbox_remote_test_can_reach), (libbalsa_mailbox_remote_set_server), (libbalsa_mailbox_remote_get_server): * libbalsa/mailbox_remote.h: * libinit_balsa/assistant_page_user.c (create_pop3_mbx), (create_imap_mbx): * src/mailbox-conf.c (update_pop_mailbox), (create_pop_mailbox_dialog): * src/main-window.c (bw_check_mailbox_list): 2019-07-04 Peter Bloomfield mailbox-mh: Declare it final Use G_DECLARE_FINAL_TYPE to declare LibBalsaMailboxMh No new accessors needed. * libbalsa/mailbox_mh.c: * libbalsa/mailbox_mh.h: 2019-07-04 Peter Bloomfield mailbox-mbox: Declare it final Use G_DECLARE_FINAL_TYPE to declare LibBalsaMailboxMbox No new accessors needed. * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_class_init), (libbalsa_mailbox_mbox_dispose), (lbm_mbox_check_files), (libbalsa_mailbox_mbox_get_message_stream), (libbalsa_mailbox_mbox_remove_files), (libbalsa_mailbox_mbox_close_mailbox), (libbalsa_mailbox_mbox_fetch_message_structure): * libbalsa/mailbox_mbox.h: 2019-07-04 Peter Bloomfield mailbox-maildir: Declare it final Use G_DECLARE_FINAL_TYPE to declare LibBalsaMailboxMaildir No new accessors needed. * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_class_init), (libbalsa_mailbox_maildir_finalize), (libbalsa_mailbox_maildir_load_config), (lbm_maildir_remove_files), (libbalsa_mailbox_maildir_close_mailbox), (libbalsa_mailbox_maildir_fetch_message_structure): * libbalsa/mailbox_maildir.h: 2019-07-04 Peter Bloomfield Use G_DECLARE_DERIVABLE_TYPE to declare LibBalsaMailboxLocal No new accessors needed. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_class_init), (libbalsa_mailbox_local_init), (lbml_message_pool_take_message), (lbm_local_free_info), (libbalsa_mailbox_local_finalize), (libbalsa_mailbox_local_save_config), (libbalsa_mailbox_local_load_config), (lbm_local_save_tree_real), (lbm_local_queue_save_tree), (libbalsa_mailbox_local_close_mailbox), (message_match_real), (libbalsa_mailbox_local_cache_message), (lbml_load_messages_idle_cb), (libbalsa_mailbox_local_load_messages), (libbalsa_mailbox_local_set_threading_info), (libbalsa_mailbox_local_msgno_removed), (lbm_local_prepare_msgno), (lbm_local_thread_idle), (libbalsa_mailbox_local_prepare_threading), (lbml_get_info), (lbm_local_sync_real), (lbm_local_sync_idle), (lbm_local_sync_queue), (lbm_local_sort), (libbalsa_mailbox_local_duplicate_msgnos): * libbalsa/mailbox_local.h: 2019-07-03 Peter Bloomfield Use G_DECLARE_DERIVABLE_TYPE to declare LibBalsaMailbox and provide and use the necessary getters and setters. Also move mailbox locking to a GRecMutex in the LibBalsaMailboxPrivate structure, instead of our home-brewed lock. * libbalsa/filter-file.c (libbalsa_mailbox_filters_load_config), (libbalsa_mailbox_filters_save_config): * libbalsa/libbalsa.c: * libbalsa/mailbox-filter.c (config_mailbox_filters_load): * libbalsa/mailbox.c (libbalsa_mailbox_class_init), (libbalsa_mailbox_init), (libbalsa_mailbox_dispose), (get_from_field), (libbalsa_mailbox_index_entry_clear), (libbalsa_mailbox_index_set_flags), (libbalsa_mailbox_finalize), (libbalsa_mailbox_free_mindex), (libbalsa_mailbox_open), (libbalsa_mailbox_is_open), (libbalsa_mailbox_close), (libbalsa_mailbox_set_unread_messages_flag), (libbalsa_mailbox_check), (lbm_changed_idle_cb), (lbm_changed_schedule_idle), (libbalsa_mailbox_changed), (lbm_run_filters_on_reception_idle_cb), (libbalsa_mailbox_run_filters_on_reception), (libbalsa_mailbox_save_config), (libbalsa_mailbox_real_messages_copy), (libbalsa_mailbox_real_sort), (libbalsa_mailbox_real_save_config), (libbalsa_mailbox_real_load_config), (libbalsa_mailbox_type_from_path), (lbm_node_has_unseen_child), (lbm_msgno_changed_expunged_cb), (lbm_msgno_row_changed), (lbm_msgnos_changed_idle_cb), (lbm_msgno_changed), (libbalsa_mailbox_msgno_changed), (lbm_need_threading_idle_cb), (libbalsa_mailbox_msgno_inserted), (libbalsa_mailbox_msgno_filt_in), (libbalsa_mailbox_msgno_removed), (libbalsa_mailbox_msgno_filt_out), (lbm_msgno_filt_check), (libbalsa_mailbox_msgno_filt_check), (libbalsa_mailbox_search_iter_view), (libbalsa_mailbox_msgno_find), (libbalsa_mailbox_sync_storage), (lbm_cache_message), (libbalsa_mailbox_get_message), (libbalsa_mailbox_messages_change_flags), (libbalsa_mailbox_set_view_filter), (libbalsa_mailbox_make_view_filter_persistent), (libbalsa_mailbox_real_can_do), (lbm_check_and_sort), (lbm_set_threading), (libbalsa_mailbox_view_free), (lbm_get_view), (libbalsa_mailbox_set_identity_name), (libbalsa_mailbox_set_threading_type), (libbalsa_mailbox_set_subject_gather), (libbalsa_mailbox_set_sort_type), (libbalsa_mailbox_set_sort_field), (libbalsa_mailbox_set_show), (libbalsa_mailbox_set_subscribe), (libbalsa_mailbox_set_exposed), (libbalsa_mailbox_set_open), (libbalsa_mailbox_set_filter), (libbalsa_mailbox_set_crypto_mode), (libbalsa_mailbox_set_unread), (libbalsa_mailbox_set_total), (libbalsa_mailbox_set_mtime), (libbalsa_mailbox_set_position), (libbalsa_mailbox_get_identity_name), (libbalsa_mailbox_get_threading_type), (libbalsa_mailbox_get_subject_gather), (libbalsa_mailbox_get_sort_type), (libbalsa_mailbox_get_sort_field), (libbalsa_mailbox_get_show), (libbalsa_mailbox_get_subscribe), (libbalsa_mailbox_get_exposed), (libbalsa_mailbox_get_open), (libbalsa_mailbox_get_filter), (libbalsa_mailbox_get_crypto_mode), (libbalsa_mailbox_get_unread), (libbalsa_mailbox_get_total), (libbalsa_mailbox_get_mtime), (libbalsa_mailbox_get_position), (mailbox_model_init), (mailbox_model_get_flags), (mailbox_model_get_n_columns), (mailbox_model_get_column_type), (mailbox_model_get_iter), (mailbox_model_get_path_helper), (mailbox_model_get_path), (lbm_get_index_entry_expunged_cb), (lbm_get_index_entry_real), (lbm_get_index_entry), (mailbox_model_get_value), (mailbox_model_iter_next), (mailbox_model_iter_children), (mailbox_model_iter_has_child), (mailbox_model_iter_n_children), (mailbox_model_iter_nth_child), (mailbox_model_iter_parent), (mailbox_drag_source_init), (mailbox_row_draggable), (mailbox_drag_data_delete), (mailbox_drag_data_get), (mailbox_sortable_init), (mailbox_compare_from), (mailbox_compare_subject), (mailbox_compare_date), (mailbox_get_thread_date_traverse_func), (mailbox_get_thread_date), (mailbox_compare_thread_date), (mailbox_compare_size), (mailbox_compare_func), (lbm_has_valid_index_entry), (lbm_sort), (mailbox_get_sort_column_id), (mailbox_set_sort_column_id), (mailbox_set_sort_func), (mailbox_set_default_sort_func), (mailbox_has_default_sort_func), (libbalsa_mailbox_unlink_and_prepend), (lbm_update_msg_tree), (lbm_set_msg_tree), (libbalsa_mailbox_set_msg_tree), (lbm_try_reassemble), (libbalsa_mailbox_try_reassemble), (libbalsa_mailbox_msgno_get_status), (libbalsa_mailbox_msgno_get_subject), (libbalsa_mailbox_msgno_update_attach), (lbm_check_idle), (lbm_queue_check), (libbalsa_mailbox_search_iter_step), (libbalsa_mailbox_can_move_duplicates), (libbalsa_mailbox_move_duplicates), (libbalsa_mailbox_lock_store), (libbalsa_mailbox_unlock_store), (libbalsa_mailbox_cache_message), (lbm_set_color), (libbalsa_mailbox_set_foreground), (libbalsa_mailbox_set_background), (libbalsa_mailbox_test_can_reach), (libbalsa_mailbox_get_filters), (libbalsa_mailbox_get_name), (libbalsa_mailbox_get_url), (libbalsa_mailbox_get_unread_messages), (libbalsa_mailbox_get_first_unread), (libbalsa_mailbox_get_view_filter), (libbalsa_mailbox_get_msg_tree), (libbalsa_mailbox_get_msg_tree_changed), (libbalsa_mailbox_get_state), (libbalsa_mailbox_get_index_entry), (libbalsa_mailbox_get_view), (libbalsa_mailbox_get_stamp), (libbalsa_mailbox_get_open_ref), (libbalsa_mailbox_get_readonly), (libbalsa_mailbox_get_config_prefix), (libbalsa_mailbox_get_has_unread_messages), (libbalsa_mailbox_clear_unread_messages), (libbalsa_mailbox_set_filters), (libbalsa_mailbox_set_url), (libbalsa_mailbox_set_first_unread), (libbalsa_mailbox_set_msg_tree_changed), (libbalsa_mailbox_set_is_directory), (libbalsa_mailbox_set_readonly), (libbalsa_mailbox_set_no_reassemble), (libbalsa_mailbox_set_name), (libbalsa_mailbox_set_view), (libbalsa_mailbox_set_has_unread_messages), (libbalsa_mailbox_set_config_prefix), (libbalsa_mailbox_add_to_unread_messages), (libbalsa_lock_mailbox), (libbalsa_unlock_mailbox): * libbalsa/mailbox.h: * libbalsa/mailbox_imap.c (message_info_from_msgno), (libbalsa_mailbox_imap_init), (libbalsa_mailbox_imap_finalize), (libbalsa_mailbox_imap_update_url), (mi_get_imsg), (idle_unread_update_cb), (imap_exists_idle), (libbalsa_mailbox_imap_get_selected_handle), (lbm_imap_get_unseen), (libbalsa_mailbox_imap_open), (libbalsa_mailbox_imap_get_matchings), (libbalsa_mailbox_imap_load_config), (libbalsa_mailbox_imap_force_disconnect), (libbalsa_mailbox_imap_reconnect), (lbmi_get_imap_sort_key), (libbalsa_mailbox_imap_set_threading), (lbmi_compare_func), (libbalsa_mailbox_imap_sort): * libbalsa/mailbox_local.c (libbalsa_mailbox_local_init), (libbalsa_mailbox_local_set_path), (libbalsa_mailbox_local_load_message), (libbalsa_mailbox_local_load_config), (lbm_local_save_tree), (lbm_local_restore_tree), (lbm_local_save_tree_real), (libbalsa_mailbox_local_close_mailbox), (message_match_real), (lbml_load_messages_idle_cb), (lbml_set_threading), (libbalsa_mailbox_local_set_threading), (lbm_local_update_view_filter), (libbalsa_mailbox_local_prepare_threading), (lbml_info_setup), (lbml_thread_messages), (lbml_unthread_message), (lbml_threading_flat), (lbm_local_sync_real), (libbalsa_mailbox_local_messages_change_flags): * libbalsa/mailbox_local.h: * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_new), (lbm_maildir_remove_files), (lbm_maildir_parse), (libbalsa_mailbox_maildir_open), (libbalsa_mailbox_maildir_check), (libbalsa_mailbox_maildir_sync): * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_new), (mbox_lock), (mbox_unlock), (libbalsa_mailbox_mbox_open), (libbalsa_mailbox_mbox_check), (libbalsa_mailbox_mbox_sync): * libbalsa/mailbox_mh.c (libbalsa_mailbox_mh_new), (lbm_mh_parse_mailbox), (libbalsa_mailbox_mh_open), (libbalsa_mailbox_mh_check), (libbalsa_mailbox_mh_sync): * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_new), (message_cb), (libbalsa_mailbox_pop3_startup), (update_msg_list), (libbalsa_mailbox_pop3_check), (libbalsa_mailbox_pop3_set_inbox), (libbalsa_mailbox_pop3_set_msg_size_limit): * libbalsa/message.c (libbalsa_message_change_flags): * libbalsa/send.c (lbs_message_queue_real), (lbs_check_reachable_cb), (balsa_send_message_success): * libinit_balsa/assistant_page_directory.c (unconditional_mailbox): * libinit_balsa/assistant_page_user.c (create_pop3_mbx): * src/balsa-app.c (find_url), (balsa_get_short_mailbox_name), (ba_remove_children_mailbox_nodes): * src/balsa-index.c (bndx_scroll_on_open_idle), (bndx_mailbox_row_inserted_cb), (bndx_mailbox_changed_idle), (bndx_do_popup), (balsa_index_transfer), (balsa_index_expunge): * src/balsa-mblist.c (bmbl_mailbox_changed_cb), (bmbl_store_redraw_mbnode), (bmbl_node_style), (bmbl_mru_menu), (bmbl_mru_selected_cb), (bmbl_mru_activated_cb): * src/balsa-message.c (balsa_message_set), (balsa_message_copy_part): * src/filter-edit-callbacks.c (update_filters_mailbox): * src/filter-run-callbacks.c (save_filters), (fr_apply_selected_pressed_func), (fr_apply_selected_pressed), (fr_apply_now_pressed), (fr_add_pressed_func): * src/filter-run-dialog.c (balsa_filter_run_dialog_new), (filters_run_dialog): * src/folder-conf.c (browse_button_cb), (folder_conf_imap_sub_node): * src/mailbox-conf.c (mailbox_conf_delete), (update_pop_mailbox), (mailbox_conf_update), (mailbox_conf_add), (local_mailbox_dialog_cb), (create_local_mailbox_dialog), (create_pop_mailbox_dialog), (mailbox_conf_view_check): * src/mailbox-node.c (balsa_mailbox_node_dispose), (load_mailbox_view), (imap_scan_attach_mailbox), (balsa_mailbox_node_new_from_mailbox), (balsa_mailbox_local_append), (bmbn_scan_children_idle), (remove_special_mailbox_by_url), (add_local_mailbox): * src/main-window.c (bw_enable_mailbox_menus), (bw_enable_message_menus), (bw_notebook_label_new), (balsa_window_real_open_mbnode), (bw_check_mailbox_progress_cb), (bw_check_mailbox_list), (check_new_messages_count), (bw_mailbox_check), (bw_notebook_switch_page_cb), (balsa_window_set_statusbar), (balsa_window_next_unread): * src/main.c (initial_open_unread_mailboxes), (initial_open_inbox), (balsa_get_stats), (scan_mailboxes_idle_cb), (periodic_expunge_cb): * src/message-window.c (mw_set_buttons_sensitive), (message_window_new): * src/pref-manager.c (update_view_defaults), (add_other_server), (update_mail_servers): * src/save-restore.c (mailbox_section_path), (config_mailbox_set_as_special), (config_mailbox_delete), (config_mailbox_init), (config_mailbox_filters_save): * src/save-restore.h: * src/sendmsg-window.c (sw_delete_draft), (create_info_pane), (send_message_handler): 2019-06-30 Albrecht Dreß Small LDAP address book improvements * libbalsa/address-book-ldap.c: • implement helpers ldap_connection_get_uri(), ldap_connection_is_ldaps() and ldap_use_config_value(); • libbalsa_address_book_ldap_open_connection(): use ldap_use_config_value() for the server uri; do not attempt to run STARTTLS for a ldaps connection--print warning instead; • libbalsa_address_book_set_status(), libbalsa_address_book_ldap_alias_complete(): use ldap_use_config_value() for the base DN; • use libbalsa_information() or g_debug() & friends with log domain “ab-ldap” for messaging * src/address-book-config.c: fix misleading label in create_ldap_dialog() 2019-06-29 Albrecht Dreß Migrate print objects to new scheme Migrate the various print objects to the modern GObject scheme using G_DECLARE_*_TYPE() and G_DEFINE_TYPE(). The main difficulty was the elimination of the direct access to the internal fields of BalsaPrintObject, i.e. the surrounding rectangle of the respective object, the page number and the logical depth. I added setters/getters for this purpose, which required some refactoring in the derived classes. However, IMO the result is actually cleaner… * src/balsa-print-object-decor.c (balsa_print_object_decor_class_init), (balsa_print_object_decor_init), (balsa_print_object_decor_destroy), (decor_new_real), (balsa_print_object_frame_begin), (bpo_decor_print_separator), (bpo_decor_print_frame_end), (bpo_decor_print_frame_begin), (balsa_print_object_decor_draw): * src/balsa-print-object-decor.h: * src/balsa-print-object-default.c (balsa_print_object_default_class_init), (balsa_print_object_default_init), (balsa_print_object_default_destroy), (balsa_print_object_default), (balsa_print_object_default_full), (balsa_print_object_default_draw): * src/balsa-print-object-default.h: * src/balsa-print-object-header.c (balsa_print_object_header_class_init), (balsa_print_object_header_init), (balsa_print_object_header_destroy), (balsa_print_object_header_new_real), (balsa_print_object_header_crypto), (balsa_print_object_header_draw): * src/balsa-print-object-header.h: * src/balsa-print-object-html.c (balsa_print_object_html_class_init), (balsa_print_object_html), (balsa_print_object_html_draw): * src/balsa-print-object-html.h: * src/balsa-print-object-image.c (balsa_print_object_image_class_init), (balsa_print_object_image_init), (balsa_print_object_image_destroy), (balsa_print_object_image), (balsa_print_object_image_draw): * src/balsa-print-object-image.h: * src/balsa-print-object-text.c (balsa_print_object_text_class_init), (balsa_print_object_text_init), (balsa_print_object_text_destroy), (balsa_print_object_text_plain), (balsa_print_object_text), (get_icon), (balsa_print_object_text_vcard), (balsa_print_object_text_calendar), (balsa_print_object_text_draw): * src/balsa-print-object-text.h: * src/balsa-print-object.c (balsa_print_object_init), (balsa_print_object_class_init), (balsa_print_object_draw), (balsa_print_object_get_page), (balsa_print_object_get_rect), (balsa_print_object_set_page_depth), (balsa_print_object_set_rect), (balsa_print_object_set_height), (balsa_print_object_destroy): * src/balsa-print-object.h: * src/print-gtk.c (draw_page): 2019-06-29 Albrecht Dreß Fix build error on Buster One last pair of redundant declarations… * src/spell-check.c: Do not declare balsa_spell_check_class_init() and balsa_spell_check_init(). 2019-06-26 Peter Bloomfield * libbalsa/address-book-gpe.c: streamline. 2019-06-25 Peter Bloomfield address: rename add to append to make sure that addrs are in the same order as in the address-book, for address-books that support multiple addrs per address. * libbalsa/address-book-extern.c (lbe_load_cb): * libbalsa/address-book-gpe.c (gpe_read_attr): * libbalsa/address-book-ldap.c (libbalsa_address_book_ldap_get_address): * libbalsa/address-book-ldif.c (address_new_prefill): * libbalsa/address-book-rubrica.c (extract_net): * libbalsa/address-book-vcard.c (libbalsa_address_book_vcard_parse_address): * libbalsa/address.c (libbalsa_address_append_addr): * libbalsa/address.h: * libbalsa/rfc2445.c (cal_address_2445_to_lbaddress): * libbalsa/rfc6350.c (rfc6350_eval_line): * src/store-address.c (store_address_add_address): 2019-06-24 Peter Bloomfield address: Remove libbalsa_address_get_addr_list() Second and final step in keeping address->addr_list private. * libbalsa/address.c (libbalsa_address_get_n_addrs), (libbalsa_address_get_nth_addr): new functions to provide access to the addr-list; * libbalsa/address-book-extern.c (libbalsa_address_book_externq_add_address): * libbalsa/address-book-gpe.c (gpe_read_address): * libbalsa/address-book-ldif.c (lbab_ldif_write_addresses): * libbalsa/address-book-osmo.c (libbalsa_address_book_osmo_alias_complete): * libbalsa/address-book-rubrica.c (lbab_rubrica_load_xml), (lbab_insert_address_node), (extract_cards), (extract_net): * libbalsa/address-book-text.c (lbab_text_load_file): * libbalsa/address-book-vcard.c (lbab_vcard_write_addresses): * libbalsa/address.h: * libbalsa/rfc6350.c (rfc6350_parse_from_stream): * src/ab-main.c (bab_load_cb): * src/ab-window.c (balsa_ab_window_load_cb): Use them. 2019-06-23 Peter Bloomfield address: Remove libbalsa_address_set_addr_list() Step 1 in keeping address->addr_list private. * libbalsa/address-book-ldif.c (address_new_prefill): use libbalsa_address_add_addr() instead; * libbalsa/address-book-rubrica.c (extract_cards), (extract_net): ditto; * libbalsa/address-book-vcard.c (libbalsa_address_book_vcard_parse_address): ditto; * libbalsa/address.c: remove it; * libbalsa/address.h: ditto. 2019-06-22 Peter Bloomfield Address edit widget cosmetics * libbalsa/address.c (lba_addr_list_widget): put the GtkTreeView in a GtkFrame; (libbalsa_address_set_edit_entries), (libbalsa_address_get_edit_widget), (libbalsa_address_new_from_edit_entries): use gtk_bin_get_child() to get the GtkTreeView from the GtkFrame. 2019-06-22 Peter Bloomfield address-book-rubrica: Do not crash on bad card Do not crash if a card has multiple "Net" sections * libbalsa/address-book-rubrica.c (extract_cards): Call libbalsa_address_set_addr_list() only once, even when a card has multiple "Net" sections. 2019-06-22 Peter Bloomfield * libbalsa/address-book-rubrica.c (libbalsa_address_book_rubrica_modify_address): Fix the search for the card matching a given full-name. 2019-06-21 Peter Bloomfield Guard against null string. * libbalsa/abook-completion.c (completion_data_new): 2019-06-21 Peter Bloomfield Fix a thinko * libbalsa/address.c (libbalsa_address_new_from_edit_entries): 2019-06-21 Peter Bloomfield Allow address == NULL in libbalsa_address_set_edit_entries() and libbalsa_address_get_edit_widget() because the address book editor uses that. * libbalsa/address.c (libbalsa_address_set_edit_entries), (libbalsa_address_get_edit_widget), (libbalsa_address_new_from_edit_entries): 2019-06-18 Albrecht Dreß Fix crash using incomplete VCard items * libbalsa/address.c (vcard_strsplit): Ensure that the array contains always 5 items. 2019-06-11 Peter Bloomfield Add -Wredundant-decls -Wshadow -Wformat-security compiler warnings * configure.ac: * meson.build: 2019-06-10 Albrecht Dreß Fix format string error * src/sendmsg-window.c (sw_insert_sig_activated): fix a “format not a string literal and no format arguments” error (using gcc w/ -Werror=format-security). 2019-06-10 Albrecht Dreß Implement VCalendar stuff using G_*_TYPE() * libbalsa/rfc2445.[ch]: implement LibBalsaVCal and LibBalsaVEvent using G_DECLARE_FINAL_TYPE() and G_DEFINE_TYPE(); make the data fields private; implement private member getters required for display and printing * src/balsa-mime-widget-vcalendar.c: use new LibBalsaVCal and LibBalsaVEvent getters; add missing “Created” DTSTAMP item * src/balsa-print-object-text.c: use new LibBalsaVCal and LibBalsaVEvent getters; add missing “Created” DTSTAMP item; use same labels as for screen display 2019-06-08 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaVfs Make the object private, and move the members of LibBalsaVfsPriv into LibBalsaVfs; as a final type, it does not need a private struct. * libbalsa/files.c (libbalsa_icon_finder): * libbalsa/libbalsa-vfs.c (libbalsa_vfs_class_init), (libbalsa_vfs_init), (libbalsa_vfs_finalize), (libbalsa_vfs_new_from_uri), (libbalsa_vfs_append), (libbalsa_vfs_dir_append), (libbalsa_vfs_get_folder), (libbalsa_vfs_get_uri), (libbalsa_vfs_get_uri_utf8), (libbalsa_vfs_get_basename_utf8), (libbalsa_vfs_get_mime_type), (libbalsa_vfs_get_charset), (libbalsa_vfs_get_text_attr), (libbalsa_vfs_get_size), (libbalsa_vfs_create_stream), (libbalsa_vfs_file_exists), (libbalsa_vfs_is_regular_file), (libbalsa_vfs_file_unlink), (libbalsa_vfs_launch_app), (libbalsa_vfs_launch_app_for_body), (gio_add_vfs_menu_item), (libbalsa_vfs_fill_menu_by_content_type), (libbalsa_vfs_mime_button): * libbalsa/libbalsa-vfs.h: 2019-06-08 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaServerCfg Make the object private, and move the members of LibBalsaServerCfgPrivate into LibBalsaServerCfg; as a final type, it does not need a private struct. * libbalsa/server-config.c (libbalsa_server_cfg_new), (libbalsa_server_cfg_valid), (libbalsa_server_cfg_add_check), (libbalsa_server_cfg_add_entry), (libbalsa_server_cfg_add_item), (libbalsa_server_cfg_add_row), (libbalsa_server_cfg_get_name), (libbalsa_server_cfg_assign_server), (libbalsa_server_cfg_init), (on_server_cfg_changed): * libbalsa/server-config.h: 2019-06-08 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaSmtpServer The object was already private. * libbalsa/smtp-server.c (libbalsa_smtp_server_finalize), (libbalsa_smtp_server_class_init), (libbalsa_smtp_server_init): * libbalsa/smtp-server.h: 2019-06-08 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaImapServer The object was already private. * libbalsa/imap-server.c (libbalsa_imap_server_set_username), (libbalsa_imap_server_set_host), (libbalsa_imap_server_class_init), (libbalsa_imap_server_finalize): * libbalsa/imap-server.h: 2019-06-07 Peter Bloomfield Use G_DECLARE_DERIVABLE_TYPE to declare LibBalsaServer and provide and use the necessary getters and setters. * libbalsa/folder-scanners.c (libbalsa_scanner_imap_tree): * libbalsa/imap-server.c (libbalsa_imap_server_set_username), (libbalsa_imap_server_set_host), (libbalsa_imap_server_init), (is_info_cb), (lb_imap_server_info_new), (libbalsa_imap_server_new_from_config), (handle_connection_error), (libbalsa_imap_server_get_handle), (libbalsa_imap_server_get_handle_with_user), (libbalsa_imap_server_subscriptions): * libbalsa/mailbox_imap.c (get_header_cache_path), (get_cache_name_pair), (libbalsa_mailbox_imap_reconnect), (libbalsa_imap_url), (libbalsa_mailbox_imap_add_messages), (libbalsa_mailbox_imap_messages_copy): * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_init), (libbalsa_mailbox_pop3_startup), (update_msg_list), (libbalsa_mailbox_pop3_check): * libbalsa/send.c (lbs_check_reachable_cb), (lbs_process_queue_init_session): * libbalsa/server-config.c (libbalsa_server_cfg_new), (libbalsa_server_cfg_assign_server), (server_cfg_security_widget): * libbalsa/server.c (libbalsa_server_class_init), (libbalsa_server_init), (libbalsa_server_finalize), (libbalsa_server_set_password), (lbs_get_password), (libbalsa_server_real_set_username), (libbalsa_server_real_set_host), (libbalsa_server_load_security_config), (store_password_libsecret), (load_password_libsecret), (erase_password_libsecret), (libbalsa_server_load_config), (libbalsa_server_save_config), (libbalsa_server_get_auth), (libbalsa_server_get_cert_pass), (libbalsa_server_test_can_reach_full), (libbalsa_server_test_can_reach), (libbalsa_server_get_host), (libbalsa_server_get_user), (libbalsa_server_get_cert_file), (libbalsa_server_get_protocol), (libbalsa_server_get_password), (libbalsa_server_get_cert_passphrase), (libbalsa_server_get_security), (libbalsa_server_get_try_anonymous), (libbalsa_server_get_client_cert), (libbalsa_server_get_remember_password), (libbalsa_server_get_remember_cert_passphrase), (libbalsa_server_set_protocol), (libbalsa_server_set_cert_file), (libbalsa_server_set_security), (libbalsa_server_set_try_anonymous), (libbalsa_server_set_remember_password), (libbalsa_server_set_client_cert), (libbalsa_server_set_remember_cert_passphrase): * libbalsa/server.h: * libbalsa/smtp-server.c (libbalsa_smtp_server_init), (libbalsa_smtp_server_new): * libinit_balsa/assistant_page_user.c (create_pop3_mbx), (create_imap_mbx): * src/balsa-app.c (ask_password_real), (balsa_get_short_mailbox_name): * src/folder-conf.c (folder_conf_imap_sub_node): * src/mailbox-node.c (imap_dir_cb), (balsa_mailbox_node_new_from_config), (balsa_mailbox_node_is_imap): * src/save-restore.c (migrate_imap_mailboxes): 2019-06-04 Peter Bloomfield Remove redundant declarations and rename libbalsa_identity_new_config() to libbalsa_identity_new_from_config(). * libbalsa/identity.c (libbalsa_identity_new_from_config): * libbalsa/identity.h: * src/save-restore.c (config_identity_load), (config_identities_load): 2019-06-04 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaIdentity Make the structure private, and provide and use the necessary getters and setters. * libbalsa/autocrypt.c (autocrypt_header): * libbalsa/autocrypt.h: * libbalsa/identity.c (libbalsa_identity_finalize), (libbalsa_identity_new_with_name), (libbalsa_identity_set_address), (libbalsa_identity_set_domain), (libbalsa_identity_get_signature), (libbalsa_identity_get_sig_prepend), (libbalsa_identity_get_sig_whenreply), (libbalsa_identity_get_sig_whenforward), (libbalsa_identity_get_sig_sending), (libbalsa_identity_get_send_mp_alternative), (libbalsa_identity_get_request_mdn), (libbalsa_identity_get_request_dsn), (libbalsa_identity_get_warn_send_plain), (libbalsa_identity_get_always_trust), (libbalsa_identity_get_gpg_sign), (libbalsa_identity_get_gpg_encrypt), (libbalsa_identity_get_sig_executable), (libbalsa_identity_get_sig_separator), (libbalsa_identity_get_crypt_protocol), (libbalsa_identity_get_identity_name), (libbalsa_identity_get_force_gpg_key_id), (libbalsa_identity_get_force_smime_key_id), (libbalsa_identity_get_replyto), (libbalsa_identity_get_bcc), (libbalsa_identity_get_reply_string), (libbalsa_identity_get_forward_string), (libbalsa_identity_get_domain), (libbalsa_identity_get_face_path), (libbalsa_identity_get_x_face_path), (libbalsa_identity_get_signature_path), (libbalsa_identity_get_address), (libbalsa_identity_get_smtp_server), (libbalsa_identity_get_autocrypt_mode): * libbalsa/identity.h: * libbalsa/send.c (libbalsa_message_create_mime_message), (lb_send_from): * src/balsa-message.c (handle_mdn_request), (create_mdn_reply), (mdn_dialog_response), (autocrypt_in_use): * src/balsa-mime-widget-message.c (extbody_send_mail): * src/balsa-mime-widget-vcalendar.c (balsa_vevent_widget), (vevent_reply): * src/mailbox-conf.c (mailbox_conf_view_check): * src/save-restore.c (config_identity_load), (config_identities_save): * src/sendmsg-window.c (replace_identity_signature), (update_bsmsg_identity), (create_email_entry), (sw_insert_sig_activated), (generate_forwarded_subject), (bsmsg_set_subject_from_body), (set_identity_from_mailbox), (guess_identity_from_list), (setup_headers_from_identity), (sw_cc_add_list), (insert_initial_sig), (bsmsg2message), (check_suggest_encryption), (check_autocrypt_recommendation), (send_message_handler), (bsmsg_update_gpg_ui_on_ident_change), (sendmsg_window_new), (sendmsg_window_compose), (sendmsg_window_reply), (sendmsg_window_reply_embedded), (sendmsg_window_forward): 2019-06-04 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaCellRendererButton The object was already private. * libbalsa/cell-renderer-button.h: 2019-06-04 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddressView The object was already private. * libbalsa/address-view.h: 2019-06-03 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddress Make the structure private, and provide and use the necessary getters and setters. * libbalsa/abook-completion.c (address_compare): * libbalsa/address-book-extern.c (lbe_load_cb), (libbalsa_address_book_externq_add_address): * libbalsa/address-book-gpe.c (gpe_read_attr), (create_name), (gpe_read_address): * libbalsa/address-book-ldap.c (libbalsa_address_book_ldap_get_address), (libbalsa_address_book_ldap_add_address), (libbalsa_address_book_ldap_remove_address), (libbalsa_address_book_ldap_modify_address): * libbalsa/address-book-ldif.c (build_name), (address_new_prefill), (lbab_ldif_write_dn), (lbab_ldif_write_addresses), (lbab_ldif_write_surname), (lbab_ldif_write_givenname), (lbab_ldif_write_nickname), (lbab_ldif_write_organization): * libbalsa/address-book-osmo.c (utf8_lba_strstr), (libbalsa_address_book_osmo_alias_complete), (osmo_read_addresses): * libbalsa/address-book-rubrica.c (libbalsa_address_book_rubrica_load), (libbalsa_address_book_rubrica_add_address), (libbalsa_address_book_rubrica_modify_address), (lbab_rubrica_load_xml), (lbab_insert_address_node), (extract_cards): * libbalsa/address-book-text.c (lbab_text_item_compare), (lbab_text_load_file), (libbalsa_address_book_text_load): * libbalsa/address-book-vcard.c (lbab_vcard_write_fn), (lbab_vcard_write_n), (lbab_vcard_write_nickname), (lbab_vcard_write_org), (lbab_vcard_write_addresses), (libbalsa_address_book_vcard_parse_address): * libbalsa/address-book.c: * libbalsa/address-book.h: * libbalsa/address.c (libbalsa_address_class_init), (libbalsa_address_init), (libbalsa_address_finalize), (libbalsa_address_new_from_vcard), (libbalsa_address_set_copy), (libbalsa_address_to_gchar), (lba_get_name_or_mailbox), (libbalsa_address_get_name_from_list), (libbalsa_address_get_mailbox_from_list), (libbalsa_address_n_mailboxes_in_list), (libbalsa_address_set_edit_entries), (lba_addr_list_widget), (addrlist_drag_received_cb), (libbalsa_address_get_edit_widget), (libbalsa_address_new_from_edit_entries), (libbalsa_address_compare), (libbalsa_address_get_full_name), (libbalsa_address_get_first_name), (libbalsa_address_get_last_name), (libbalsa_address_get_nick_name), (libbalsa_address_get_organization), (libbalsa_address_get_addr), (libbalsa_address_get_addr_list), (libbalsa_address_set_full_name), (libbalsa_address_set_first_name), (libbalsa_address_set_last_name), (libbalsa_address_set_nick_name), (libbalsa_address_set_organization), (libbalsa_address_set_addr_list), (libbalsa_address_add_addr): * libbalsa/address.h: * libbalsa/rfc2445.c (libbalsa_vevent_reply), (cal_address_2445_to_lbaddress): * libbalsa/rfc6350.c (rfc6350_parse_from_stream), (rfc6350_eval_line): * src/ab-main.c (bab_load_cb): * src/ab-window.c (balsa_ab_window_load_cb): * src/balsa-mime-widget-text.c (bm_widget_new_vcard): * src/balsa-mime-widget-vcalendar.c (balsa_vevent_widget): * src/balsa-print-object-text.c (balsa_print_object_text_vcard): * src/store-address.c (store_address_add_address), (store_address_add_lbaddress): 2019-06-02 Albrecht Dreß GMimeGpgmeSigstat: use G_DECLARE_FINAL_TYPE(), G_DEFINE_TYPE() * libbalsa/gmime-gpgme-signature.ch: implement GMimeGpgmeSigstat using G_DECLARE_FINAL_TYPE() and G_DEFINE_TYPE(); implement getter/setter functions * libbalsa/body.c, libbalsa/gmime-multipart-crypt.c, libbalsa/rfc3156.c, src/balsa-message.c, src/balsa-mime-widget-crypto.c, src/balsa-mime-widget-message.c, src/balsa-print-object-header.c: use getter functions instead of accessing the object properties * libbalsa/libbalsa-gpgme.c: use setter functions instead of manipulating the object propertiy directly * libbalsa/libbalsa-gpgme-widgets.[ch]: key argument to libbalsa_gpgme_key() is const 2019-06-02 Albrecht Dreß Make GpgME/E2EE support a hard requirement * INSTALL: ancient file, add pointer to README * README: remove --with-gpgme option; add gpgme as requirement; briefly describe Balsa's E2EE support; clarify --with-libsecret * configure.ac, meson.build, meson_options.txt: remove --with-gpgme option; fail if gpgme-config is unavailable; require gpgme >= 1.6.0 * libbalsa/Makefile.am, libbalsa/meson.build: remove conditional building with/without gpgme * libbalsa/body.[ch], libbalsa/imap-server.c, libbalsa/mailbox.[ch], libbalsa/message.[ch], libbalsa/rfc3156.[ch], libbalsa/send.[ch], src/balsa-app.[ch], src/balsa-icons.[ch], src/balsa-message.[ch], src/balsa-mime-widget-crypto.[ch], src/balsa-mime-widget-message.c, src/balsa-mime-widget-multipartc, src/balsa-mime-widget.c, src/balsa-print-object-header.[ch], src/balsa-print-object.c, src/main.c, src/print-gtk.c, src/save-restore.c, src/sendmsg-window.[ch], src/toolbar-factory.c: remove conditional compilation (HAVE_GPGME) * libbalsa/identity.c: remove conditional compilation (HAVE_GPGME); simplify append_ident_notebook_page() * src/mailbox-conf.c: remove conditional compilation (HAVE_GPGME); remove useless scope in mailbox_conf_view_new_full() 2019-06-02 Albrecht Dreß libnetclient: use G_DECLARE* * libnetclient/net-client-pop.[ch]: use G_DECLARE_FINAL_TYPE(), and drop storing the private object data in a separate structure; • net_client_pop_get_capa(): enable pipelining only if included in the server's capabilities * libnetclient/net-client-siobuf.[ch], libnetclient/net-client-smtp.[ch]: use G_DECLARE_FINAL_TYPE(), and drop storing the private object data in a separate structure * libnetclient/net-client-utils.h: suppress Flexelint 9.00 false-positive * libnetclient/net-client.[hc]: use G_DECLARE_DERIVABLE_TYPE(); use net_client_get_instance_private() to access private data 2019-05-27 Peter Bloomfield * libbalsa/imap/imap-commands.h: remove redundant declaration of imap_mbox_handle_can_do(). 2019-05-27 Peter Bloomfield * libbalsa/address-book-rubrica.c (lbab_rubrica_load_xml): reduce scope of a GList* variable so that another does not shadow it. 2019-05-27 Peter Bloomfield various: remove redundant declarations Some cleanup from using G_DEFINE_TYPE{,WITH_PRIVATE} macros * libbalsa/gmime-filter-header.c: * libbalsa/server-config.c: * src/main-window.c: 2019-05-27 Peter Bloomfield address-books: remove redundant declarations Some cleanup from using G_DECLARE_{DERIVABLE,FINAL}_TYPE macros * libbalsa/address-book-ldap.c: * libbalsa/address-book-osmo.h: * libbalsa/address-book-rubrica.c: * libbalsa/address-book-text.c: * libbalsa/address-book-vcard.c: 2019-05-27 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddressBookVcard Make the structure private; no need for getters and setters. * libbalsa/address-book-vcard.c (libbalsa_address_book_vcard_init), (libbalsa_address_book_vcard_new): * libbalsa/address-book-vcard.h: 2019-05-27 Peter Bloomfield * meson.build: specify meson version >= 0.43 2019-05-27 Peter Bloomfield * meson.build: Bump default version to 2.5.7; use compiler.get_supported_arguments() to check all arguments at once, instead of looping through a list and checking them one at a time. 2019-05-26 Pawel Salek * NEWS, configure.ac: correct typos; bump version base for git builds. 2019-05-25 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddressBookRubrica Make the structure private; no need for getters and setters. * libbalsa/address-book-rubrica.c: * libbalsa/address-book-rubrica.h: 2019-05-25 Pawel Salek * NEWS, configure.ac: Release balsa-2.5.7 2019-05-22 Albrecht Dreß Mitigate “Re: What's Up Johnny?” vulnerabilities * src/balsa-app.h: add flag whether the user wants to be warned when replying to an encrypted message * src/save-restore.c: • save/restore new flag • add reply selection dialogue to geometry manager * src/sendmsg-window.c: • tree_add_quote_body(): refactoring, add information whether the part has been decrypted • scan_bodies(): use new tree_add_quote_body(), propagate information about encrypted containers • unselect_decrypted(): new function for deselecting all decrypted parts in the dialogue for selecting cited parts • quote_parts_select_dlg(): add message when replying to a fully or partially encrypted message, use geometry manager • show_decrypted_warning(): show dialogue when the user replies to a single-part decrypted message • collect_for_quote(): use new scan_bodies() api 2019-05-16 Peter Bloomfield Do not break user's config * libbalsa/address-book.c (libbalsa_address_book_new_from_config): if the type is LibBalsaAddressBookExtern, it is no longer recognized, so we use LibBalsaAddressBookExternq instead. 2019-05-15 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddressBookOsmo Make the structure private; no need for getters and setters. Adopt ab_osmo as the identifier. * libbalsa/address-book-osmo.c (osmo_read_addresses): * libbalsa/address-book-osmo.h: 2019-05-15 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddressBookLdif Make the structure private; no need for getters and setters. * libbalsa/address-book-ldif.c (libbalsa_address_book_ldif_init), (libbalsa_address_book_ldif_new): * libbalsa/address-book-ldif.h: 2019-05-15 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddressBookLdap Make the structure private, and provide and use the necessary getters and setters. Adopt ab_ldap as the identifier. * libbalsa/address-book-ldap.c (libbalsa_address_book_ldap_class_init), (libbalsa_address_book_ldap_init), (libbalsa_address_book_ldap_finalize), (libbalsa_address_book_ldap_new), (libbalsa_address_book_ldap_close_connection), (abl_interaction), (libbalsa_address_book_ldap_open_connection), (libbalsa_address_book_ldap_load), (libbalsa_address_book_ldap_get_address), (libbalsa_address_book_ldap_add_address), (libbalsa_address_book_ldap_remove_address), (libbalsa_address_book_ldap_modify_address), (libbalsa_address_book_ldap_save_config), (libbalsa_address_book_ldap_load_config), (libbalsa_address_book_ldap_alias_complete), (libbalsa_address_book_ldap_get_host), (libbalsa_address_book_ldap_get_base_dn), (libbalsa_address_book_ldap_get_bind_dn), (libbalsa_address_book_ldap_get_passwd), (libbalsa_address_book_ldap_get_book_dn), (libbalsa_address_book_ldap_get_enable_tls), (libbalsa_address_book_ldap_set_host), (libbalsa_address_book_ldap_set_base_dn), (libbalsa_address_book_ldap_set_bind_dn), (libbalsa_address_book_ldap_set_passwd), (libbalsa_address_book_ldap_set_book_dn), (libbalsa_address_book_ldap_set_enable_tls): * libbalsa/address-book-ldap.h: * src/address-book-config.c (create_ldap_dialog), (create_book), (modify_book): 2019-05-15 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddressBookGpe Make the structure private; no need for getters and setters. Adopt ab_gpe as the identifier. * libbalsa/address-book-gpe.c (libbalsa_address_book_gpe_class_init), (libbalsa_address_book_gpe_init), (libbalsa_address_book_gpe_finalize), (libbalsa_address_book_gpe_new), (libbalsa_address_book_gpe_close_db), (libbalsa_address_book_gpe_open_db), (gpe_read_address), (libbalsa_address_book_gpe_load): * libbalsa/address-book-gpe.h: 2019-05-15 Peter Bloomfield address-book: Adopt ab as the identifier * libbalsa/address-book.c (libbalsa_address_book_new_from_config): * libbalsa/address-book.h: 2019-05-15 Peter Bloomfield Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddressBookExternq Make the structure private, and provide and use the necessary getters and setters. Adopt libbalsa_address_book_externq as the namespace, and ab_externq as the identifier. * libbalsa/address-book-extern.c (libbalsa_address_book_externq_class_init), (libbalsa_address_book_externq_init), (libbalsa_address_book_externq_finalize), (libbalsa_address_book_externq_new), (lbe_load_cb), (libbalsa_address_book_externq_load), (parse_externq_file), (libbalsa_address_book_externq_add_address), (libbalsa_address_book_externq_save_config), (libbalsa_address_book_externq_load_config), (libbalsa_address_book_externq_alias_complete), (libbalsa_address_book_externq_get_load), (libbalsa_address_book_externq_get_save), (libbalsa_address_book_externq_set_load), (libbalsa_address_book_externq_set_save): * libbalsa/address-book-extern.h: * libbalsa/libbalsa.c (libbalsa_init): * src/ab-main.c (bab_window_set_title), (file_new_externq_activated), (get_main_menu), (bab_init): * src/ab-window.c (balsa_ab_window_set_title): * src/address-book-config.c (create_dialog_from_type), (create_externq_dialog), (handle_close), (create_book), (modify_book), (add_externq_cb): * src/pref-manager.c (update_address_books): 2019-05-14 Peter Bloomfield Use G_DECLARE_DERIVABLE_TYPE to declare LibBalsaAddressBookText and provide and use the necessary getters and setters. * libbalsa/address-book-ldif.c (libbalsa_address_book_ldif_new): * libbalsa/address-book-rubrica.c (libbalsa_address_book_rubrica_class_init), (libbalsa_address_book_rubrica_init), (libbalsa_address_book_rubrica_new), (libbalsa_address_book_rubrica_load), (libbalsa_address_book_rubrica_alias_complete), (libbalsa_address_book_rubrica_add_address), (libbalsa_address_book_rubrica_modify_address), (lbab_rubrica_load_xml): * libbalsa/address-book-text.c (lbab_text_item_free), (libbalsa_address_book_text_class_init), (libbalsa_address_book_text_init), (libbalsa_address_book_text_finalize), (lbab_text_address_book_need_reload), (lbab_text_load_file), (lbab_text_lock_book), (lbab_text_unlock_book), (lbab_text_open_temp), (lbab_text_close_temp), (libbalsa_address_book_text_load), (libbalsa_address_book_text_add_address), (libbalsa_address_book_text_modify_address), (libbalsa_address_book_text_save_config), (libbalsa_address_book_text_load_config), (libbalsa_address_book_text_alias_complete), (libbalsa_address_book_text_get_path), (libbalsa_address_book_text_get_item_list), (libbalsa_address_book_text_get_mtime), (libbalsa_address_book_text_get_name_complete), (libbalsa_address_book_text_set_path), (libbalsa_address_book_text_set_item_list), (libbalsa_address_book_text_set_mtime), (libbalsa_address_book_text_set_name_complete): * libbalsa/address-book-text.h: * libbalsa/address-book-vcard.c (libbalsa_address_book_vcard_new): * src/address-book-config.c (create_local_dialog), (modify_book): 2019-05-13 Peter Bloomfield Use G_DECLARE_DERIVABLE_TYPE to declare LibBalsaAddressBook The macro defines _LibBalsaAddressBook to be a bare structure with a single GObject member. The instance data must be in a _LibBalsaAddressBookPrivate structure, access to which is channeled through getters and setters. * libbalsa/address-book-extern.c (libbalsa_address_book_externq_new), (libbalsa_address_book_externq_alias_complete): * libbalsa/address-book-gpe.c (libbalsa_address_book_gpe_init), (libbalsa_address_book_gpe_new), (libbalsa_address_book_gpe_load): * libbalsa/address-book-ldap.c (libbalsa_address_book_ldap_init), (libbalsa_address_book_ldap_new), (libbalsa_address_book_ldap_open_connection), (libbalsa_address_book_ldap_add_address), (libbalsa_address_book_ldap_remove_address), (libbalsa_address_book_ldap_modify_address), (libbalsa_address_book_ldap_load_config), (libbalsa_address_book_ldap_alias_complete): * libbalsa/address-book-ldif.c (libbalsa_address_book_ldif_new): * libbalsa/address-book-osmo.c (libbalsa_address_book_osmo_init), (libbalsa_address_book_osmo_new), (libbalsa_address_book_osmo_load), (libbalsa_address_book_osmo_alias_complete): * libbalsa/address-book-rubrica.c (libbalsa_address_book_rubrica_new), (libbalsa_address_book_rubrica_alias_complete), (lbab_rubrica_load_xml): * libbalsa/address-book-text.c (lbab_text_load_file), (libbalsa_address_book_text_alias_complete): * libbalsa/address-book-vcard.c (libbalsa_address_book_vcard_new): * libbalsa/address-book.c (libbalsa_address_book_class_init), (libbalsa_address_book_init), (libbalsa_address_book_finalize), (libbalsa_address_book_set_status), (libbalsa_address_book_load_config), (libbalsa_address_is_dist_list), (libbalsa_address_book_real_save_config), (libbalsa_address_book_real_load_config), (libbalsa_address_book_strerror), (libbalsa_address_book_get_expand_aliases), (libbalsa_address_book_get_is_expensive), (libbalsa_address_book_get_dist_list_mode), (libbalsa_address_book_get_name), (libbalsa_address_book_get_config_prefix), (libbalsa_address_book_set_name), (libbalsa_address_book_set_is_expensive), (libbalsa_address_book_set_expand_aliases), (libbalsa_address_book_set_dist_list_mode): * libbalsa/address-book.h: * libbalsa/address-view.c (lbav_get_matching_addresses): * src/ab-main.c (bab_set_address_book), (bab_window_set_title), (address_book_change_state), (set_address_book_menu_items), (address_book_change), (file_delete_activated), (bab_set_intial_address_book): * src/ab-window.c (balsa_ab_window_load_books), (balsa_ab_window_init), (balsa_ab_window_set_title), (balsa_ab_window_load), (balsa_ab_window_dist_mode_toggled), (balsa_ab_window_menu_changed): * src/address-book-config.c (add_radio_buttons), (create_local_dialog), (create_osmo_dialog), (create_externq_dialog), (create_ldap_dialog), (create_gpe_dialog), (create_book), (modify_book): * src/pref-manager.c (update_address_books): * src/save-restore.c (address_book_section_path), (config_address_book_delete), (config_save): * src/store-address.c (store_address_book_frame), (store_address_add_list): 2019-05-13 Peter Bloomfield Clean up conditional compilations after bumping required versions. * libbalsa/libbalsa.c (libbalsa_dialog_flags): * libbalsa/libbalsa.h: * src/ab-main.c (libbalsa_dialog_flags): * src/ab-window.c (balsa_ab_window_new): * src/balsa-message.c (balsa_message_init): * src/balsa-mime-widget-image.c (balsa_mime_widget_image_dispose), (balsa_mime_widget_new_image): * src/filter-run-dialog.c (balsa_filter_run_dialog_new): * src/pref-manager.c (pm_grid_attach): 2019-05-13 Peter Bloomfield Bump required version of GLib to 2.48, and Gtk3 to 3.18 * configure.ac: * meson.build: 2019-05-12 Albrecht Dreß Fix “Johnny you are fired” vulnerabilities * configure.ac: require gnutls >= 3.0 * libbalsa/body.[ch]: add helper functions for detecting multipart and inline signed bodies * libbalsa/gmime-gpgme-signature.[ch]: • g_mime_gpgme_sigstat_new_from_gpgme_ctx() classify multiple signatures as possible attack, always load key if available; • add g_mime_gpgme_sigstat_info() giving the protocol, signer and signature status; • g_mime_gpgme_sigstat_to_gchar() use changed libbalsa_gpgme_sig_stat_to_gchar() interface, hide signature timestamp if it is missing; • add g_mime_gpgme_sigstat_signer() to get the OpenPGP or S/MIME signer as human-readable string; • add tokenize_subject() and cert_subject_cn_mail() for better evaluation of a certificate DN, and use them in libbalsa_cert_subject_readable() * libbalsa/html.c: fix segfault on NULL body (detected with one of the broken “Johnny” samples) * libbalsa/libbalsa-gpgme.[ch]: • add libbalsa_gpgme_protocol_name() to get consistent protocol naming (replaces gpgme_get_protocol_name() or hardcoded values); • define error code for multiple signatures * libbalsa/rfc3156.[ch]: • change libbalsa_gpgme_sig_stat_to_gchar() to return a newly allocated string, possibly including error information from gpgme; • remove duplicated #define's * src/balsa-message.c:# • get_crypto_content_icon() print extended signature info in the tree view; • libbalsa_msg_try_mp_signed() and libbalsa_msg_part_2440() use new libbalsa_gpgme_sig_stat_to_gchar() api * src/balsa-mime-widget-crypto.c: drop code to load a signature's key as this is now done in g_mime_gpgme_sigstat_new_from_gpgme_ctx() * src/balsa-mime-widget-message.c: • use new helpers for detecting signed parts; • use new libbalsa_gpgme_sig_stat_to_gchar() api * src/balsa-print-object-header.[ch]: • use new helpers for detecting signed parts and g_mime_gpgme_sigstat_info(); • remove now unused parameter from balsa_print_object_header_crypto(), and drop code to load a signature's key * src/balsa-print-object.c: use modified balsa_print_object_header_crypto() api * src/print-gtk.c: refactoring and simplification of printing signed and/or encrypted parts * src/sendmsg-window.c: use libbalsa_gpgme_protocol_name() 2019-05-11 Albrecht Dreß Fix issue #15: NULL-pointer deref in pop3 code * libnetclient/net-client-pop.c: make sure net_client_pop_read_reply() does not return a NULL server reply string on success (fix issue #15) * libnetclient/net-client-siobuf.c: silence a bunch of Flexelint warnings, no change in code behaviour * libnetclient/test/echoserver.py: add missing executable flag 2019-05-10 Peter Bloomfield * src/balsa-message.c (bm_find_bar_new): connect to GtkSearchEntry's "search-changed" signal instead of GtkEditable's "changed" signal; it provides a 150 msec delay: "To make filtering appear more reactive, it is a good idea to not react to every change in the entry text immediately, but only after a short delay. To support this, GtkSearchEntry emits the “search-changed” signal which can be used instead of the “changed” signal." 2019-05-10 Peter Bloomfield main-window: Clear the view filter when the search text is cleared. * src/main-window.c (bw_sos_icon_release): callback for the "icon-release" signal from the GtkEntry; act on it. (bw_create_index_widget): connect to the signal. 2019-05-09 Peter Bloomfield main-window: Port the subject-or-sender search bar to GtkSearchEntry * src/main-window.c (bw_create_index_widget): 2019-05-09 Peter Bloomfield balsa-message: Port the find-in-message bar to GtkSearchBar and GtkSearchEntry * src/balsa-message.c (bm_find_bar_new), (bm_disable_find_entry), (balsa_message_init), (balsa_message_find_in_message): 2019-05-01 Peter Bloomfield mailbox-local: Use g_ptr_array_new_with_free_func() to manage deallocation of threading_info structures. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_set_threading_info), (libbalsa_mailbox_local_msgno_removed) 2019-05-01 Peter Bloomfield mailbox: Use g_ptr_array_new_with_free_func() to manage deallocation of LibBalsaMailboxIndexEntry. * libbalsa/mailbox.c (lbm_index_entry_free), (libbalsa_mailbox_free_mindex), (libbalsa_mailbox_open), (libbalsa_mailbox_msgno_removed) 2019-05-01 Peter Bloomfield mailbox-mbox: Use g_ptr_array_new_with_free_func() to manage deallocation of message_info structures. * libbalsa/mailbox_mbox.c (free_message_info): refactor; (libbalsa_mailbox_mbox_open): use g_ptr_array_new_with_free_func() instead of g_ptr_array_new(); (libbalsa_mailbox_mbox_check), (libbalsa_mailbox_mbox_close_mailbox), (libbalsa_mailbox_mbox_sync): no need to manually deallocate. 2019-04-21 Peter Bloomfield address-view: drop almost duplicate code * libbalsa/address-view.c (lbav_insert_text_cb): use lbav_clean_text to replace non-printable chars by spaces, instead of using almost duplicative code. 2019-04-20 Peter Bloomfield send: Fix a compiler warning * libbalsa/send.c (libbalsa_set_message_id): strncpy() with n == sizeof(dest) generates: "error: ‘__builtin_strncpy’ specified bound 16 equals destination size [-Werror=stringop-truncation]" We now specify one fewer bytes, and explicitly nullify the last byte. 2019-04-18 Albrecht Dreß Fix the build after commit e92ec3140a1c81dbf86d90d0155cb2e08f519db2 * src/main-window.c (bw_update_progress_bar): cast with '(GSourceFunc)', not with 'G_SOURCE_FUNC()', since we do not yet require GLib 2.58! 2019-04-18 Albrecht Dreß geometry-manager: Remove a not-reached assertion * libbalsa/geometry-manager.c (geometry_manager_init): a second call with the same key is not necessarily an error. 2019-04-18 Peter Bloomfield Call Gtk only from the main thread https://mail.gnome.org/archives/balsa-list/2019-April/msg00006.html * src/main-window.c (bw_update_progress_bar_idle_cb): idle handler for calling gtk_status_bar_set_{fraction,text}; (bw_update_progress_bar): schedule the idle handler; (bw_progress_bar_set_text), (bw_progress_bar_set_fraction): convenience functions for calling bw_update_progress_bar(); (balsa_window_increase_activity), (balsa_window_decrease_activity), (balsa_window_setup_progress), (balsa_window_increment_progress): use them. 2019-04-03 Peter Bloomfield Use more precise types * libbalsa/mailbox.c (mbox_model_init), (mbox_model_get_value): Use the GTypes that are expected in gtk_cell_renderer_text_set_property(). 2019-04-01 Albrecht Dreß Improve IMAP folder parent selection, subscription management * libbalsa/folder-scanners.[ch]: implement new function libbalsa_scanner_imap_tree() for scanning an IMAP server's folder structure and subscription state into a GtkTreeStore, requires a bunch of helper functions * libbalsa/imap-server.[ch]: implement new function libbalsa_imap_server_subscriptions() for subscribing to and unsubscribing from arrays of folders using a single IMAP connection * libbalsa/mailbox_imap.[ch]: remove unused function libbalsa_mailbox_imap_subscribe() (obsoleted by libbalsa_imap_server_subscriptions()) * src/folder-conf.c: implement new style subscription and parent folder selection: • imap_apply_subscriptions() collects folders with modified subscription states from the GtkTreeView; • imap_update_subscriptions() applies changed subscription states, called from folder_conf_clicked_ok(); • on_subscription_toggled() callback for subscription state checkbox; • create_imap_folder_dialog() create the dialogue for parent folder selection and subscription management; • folder_conf_imap_subscriptions() runs the subscription management dialogue; • fcw_subscribed_toggled() callback for activating the subscription management button; • folder_conf_imap_node() add button for subscription management; • select_parent_folder() find parent of a folder in the GtkTreeModel; • on_parent_double_click() callback for double-click folder selection; • browse_button_cb() modified, runs the parent selection dialogue; • remove obsolete functions browse_button_select_row_cb(), browse_button_row_activated(), browse_button_response(), folder_selection_func(), browse_button_data_free() * src/mailbox-node.c: remove obsolete mailbox tree view entries for (un)subscribing * src/save-restore.c: add the two new dialogues to the geometry manager 2019-03-23 Albrecht Dreß Do not include a trailing period ('.') when matching an URL. Most often it's end-of-sentence punctuation rather than part of the URL. See the thread at . * libbalsa/mime.c (get_url_reg): do not match a trailing period. 2019-03-21 Albrecht Dreß I noticed that /sometimes/ closing the config dialogue of an existing maildir mailbox segfaults. It appears that this is caused by an uninitialised file chooser (I modified the particular code snippet a while ago…). I am quite sure I tested the changes, including maildir (the format I typically use), no idea why this slipped through, sorry! * src/mailbox-conf.c (create_local_mailbox_dialog): Fix maildir config crash 2019-03-12 Albrecht Dreß Broken mailbox view after moving IMAP folder sideways I noticed a bug when a folder on a IMAP server is moved sideways, e.g. from “INBOX/Folder1/Test” to “INBOX/Folder2/Test”: after moving, a partial re-scan of the mailbox tree is performed, which makes all my local folders disappear. The effect does not occur if the folder is moved up or down the tree. I could track down the source of the issue to src/folder-conf.c, function subfolder_conf_clicked_ok(). * src/folder-conf.c (subfolder_conf_clicked_ok): rescan the whole IMAP folder tree after a sideways move. 2019-03-05 Albrecht Dreß * libbalsa/send.c (libbalsa_create_rfc2440_buffer): fix confusing bcc: encryption warning in libbalsa_create_rfc2440_buffer() if no bcc: recipients are present; (do_multipart_crypto): use singular/plural form of this warning in do_multipart_crypto(). 2019-03-03 Peter Bloomfield Do not attach files in response to clicking a "mailto:" URL Only if the URL is passed to Balsa on the command line by "-m" or "--compose". Also, accept either "attach=" or "attachment=" in a "mailto:" URL. * src/sendmsg-window.c (sendmsg_window_process_url), (sw_attach_file), (sendmsg_window_set_field), (set_list_post_rfc2369): attach a file only if the request comes from the command line; * src/balsa-mime-widget-text.c (url_send_cb), (handle_url): this request is not from the command line; * src/main.c (balsa_check_open_compose_window): this request is from the command line; * src/sendmsg-window.h: new argument "gboolean from_command_line" for sendmsg_window_process_url() and sendmsg_window_set_field(). 2019-02-28 Peter Bloomfield Simplify handling "mailto:" URLs * src/sendmsg-window.c (decode_and_strdup): simplify; (sendmsg_window_process_url): drop the "field_setter func" argument; it's always "sendmsg_window_set_field"; (set_list_post_rfc2369): use new API; * src/sendmsg-window.h: export new API; * src/balsa-mime-widget-text.c (handle_url): use new API; * src/main.c (balsa_check_open_compose_window): ditto. 2019-02-24 Pawel Salek Fix some issues raised by scan-build, the clang static analyzer * libbalsa/imap/imap-commands.c (imap_mbox_store_flag): insert missing "else"; * libbalsa/imap/imap-handle.c (imap_get_flag), (imap_cmd_get_tag): always null-terminate the string; (imap_message_deserialize): omit a dead increment; (imap_cmd_exec_cmds): store the return code for return; * libbalsa/imap/imap_tst.c (test_mbox_append_common): check the return code for error. 2019-02-23 Peter Bloomfield gtk_window_present() will be deprecated in later versions of Gtk-2.24, in favor of gtk_window_present_with_time(). We never have a time-stamp readily available, so just pass gtk_get_current_event_time(). * libbalsa/identity.c (libbalsa_identity_select_dialog), (libbalsa_identity_config_dialog): * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): * src/address-book-config.c (balsa_address_book_config_new): * src/balsa-index.c (balsa_index_pipe): * src/filter-edit-dialog.c (filters_edit_dialog): * src/filter-export-dialog.c (filters_export_dialog): * src/filter-run-dialog.c (filters_run_dialog): * src/folder-conf.c (folder_conf_imap_node), (folder_conf_imap_sub_node): * src/mailbox-conf.c (mailbox_conf_new), (mailbox_conf_edit): * src/main-window.c (check_new_messages_real): * src/main.c (balsa_activate_cb), (handle_remote): * src/message-window.c (mw_set_selected), (message_window_new): * src/pref-manager.c (open_preferences_manager): * src/sendmsg-window.c (address_book_cb), (sw_spell_check_activated), (sendmsg_window_continue): * src/store-address.c (balsa_store_address_from_messages): * src/toolbar-prefs.c (customize_dialog_cb): 2019-02-23 Peter Bloomfield * libbalsa/html.c: simpler regular expression for non-cid schemes. 2018-02-23 Albrecht Dreß Error in IMAP mailbox encoding Balsa has a bug in encoding IMAP mailbox names to modified UTF-7 as defined in RFC 3501, sect. 5.1.3 [1], as the '\' (0x5c) is encoded as '\\' which is explicitly prohibited. To reproduce: activate main() in libbalsa/imap/util.c, compile it, and run e.g. (yes, the mailbox name is weird, but it includes all special cases from the RFC…) /util 'ϴä ab c&d+e/f\~ßx' orig='ϴä ab c&d+e/f\~ßx' mbx='&A,QA5A- ab c&-d+e/f\\~&AN8-x' back='ϴä ab c&d+e/f\\~ßx' WRONG CONVERSION: --------------------------------^^ * libbalsa/imap/util.c (imap_utf8_to_mailbox), (imap_mailbox_to_utf8): replace the hand-coded conversion by utilising g_convert(), and also fix the bug * libbalsa/imap/util.h: declare them with the G_GNUC_WARN_UNUSED_RESULT attribute. 2019-02-22 Peter Bloomfield * libbalsa/html.c (lbh_web_view_new): use a static location when registering 'cid:' scheme; fix the regular expression for matching non-cid schemes (it was also matching 'cid:') 2019-02-19 Peter Bloomfield * libbalsa/mailbox_imap.c (lbm_imap_get_msg_part_from_cache): plug memory leaks in error return paths; 2019-02-18 Peter Bloomfield * src/balsa-mime-widget-image.c (img_check_size): avoid scan-build false positive. 2019-02-18 Peter Bloomfield * libbalsa/imap/imap-handle.c (imap_body_from_stringi): guard against NULL pointer. 2019-02-18 Peter Bloomfield * src/balsa-print-object-text.c (collect_attrs): initialize a region by structure assignment instead of g_memdup(). 2019-02-18 Peter Bloomfield * libbalsa/send.c (libbalsa_message_create_mime_message): do not leak mime_type in error return paths; also reduce scope of mime_type. 2019-02-18 Peter Bloomfield * libbalsa/address.c (vcard_strsplit): eliminate one decrement, and add an assertion to avoid a scan-build false positive 2019-02-18 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_view_new): initialize a view by structure assignment instead of g_memdup(). 2019-02-18 Peter Bloomfield * libbalsa/address.c (libbalsa_address_new_from_vcard): do not leak a string. 2019-02-18 Peter Bloomfield Cast weak-pointer-location to (gpointer *) in calls to g_object{add,remove}_weak_pointer() * libbalsa/identity.c (libbalsa_identity_config_dialog): * libbalsa/mailbox_maildir.c (free_message_info): * libbalsa/mailbox_mbox.c (free_message_info): * libbalsa/mailbox_mh.c (lbm_mh_free_message_info): * src/balsa-index.c (bndx_clear_if_last_ref), (bndx_pipe_response): * src/balsa-mblist.c (balsa_mblist_get_store), (update_mailbox_idle), (bmbl_mailbox_changed_cb): * src/balsa-mime-widget-image.c (balsa_mime_widget_image_resize_all), (img_check_size): * src/filter-edit-callbacks.c (fe_edit_condition): * src/folder-conf.c (folder_conf_imap_node), (folder_conf_imap_sub_node): * src/information-dialog.c (balsa_information_list): * src/mailbox-conf.c (mailbox_conf_new): * src/mailbox-node.c (imap_scan_attach_mailbox), (balsa_mailbox_node_scan_children), (bmbn_scan_children_idle): * src/main-window.c (balsa_window_new), (bw_real_open_mbnode_idle_cb), (bw_real_open_mbnode_thread), (balsa_window_real_open_mbnode), (bw_focus_idle), (balsa_window_real_close_mbnode), (bw_notebook_switch_page_cb): * src/main.c (balsa_activate_cb): * src/message-window.c (destroy_message_window), (message_window_new): * src/toolbar-prefs.c (customize_dialog_cb): 2019-02-17 Peter Bloomfield * libbalsa/mailbox.c: remove an unused function; * libbalsa/mailbox.h: do not export it. 2019-02-16 Peter Bloomfield mailbox-local: Do not leak LibBalsaMessage * libbalsa/mailbox_local.c (lbml_message_pool_take_message): new name for 'lbml_add_message_to_pool', emphasizing that it takes over the reference count; (lbm_local_get_message_with_msg_info): use the new name; (libbalsa_mailbox_local_get_message): always return a reference to the LibBalsaMessage. 2019-02-16 Peter Bloomfield imap-mbox-handle: Do not leak a GNode tree * libbalsa/imap/imap-handle.c (imap_mbox_handle_finalize): destroy the thread-root GNode tree. 2018-02-15 Albrecht Dreß Relax secret key selection Currently, the user can only select a key with a uid which matches the account's email address. However, there are use-cases where this is not sufficient. At work, we have an isolated network with “internal” email addresses. Outgoing messages are re-written to public addresses, but the internal ones shall not be exposed to the outside world (see e.g. [1]), i.e. the key /must not/ carry a user-id for the internal address. Thus, neither auto-selection nor defining the key id in the gui works (it would be possible to run gpg[sm] on the console to print the id, and then copy it into the input field, though). The patch enables selecting any valid private key in the identity dialogue, but /not/ when a message shall be sent and the private key cannot be determined. Note that the vast majority of users will probably never use this feature, i.e. use automatic key selection (id is empty in the identity setup). * libbalsa/libbalsa-gpgme.c (libbalsa_gpgme_get_seckey): relax the selection of the private key in the identity setup dialogue 2018-02-15 Albrecht Dreß Fix broken decryption of s/mime messages loaded from imap * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_fetch_structure): fetch part if it is not multipart/*, instead of only fetching text/*. 2018-02-15 Albrecht Dreß Printing of HTML message parts * libbalsa/html.[ch]: implement function for rendering to a Cairo surface; refactor for extracting common code * src/balsa-print-object-html.[ch]: implement printing the HTML Cairo surface (new module) * src/Makefile.am, src/meson.build: add new module * src/balsa-print-object.c: use the new module for HTML (falls back to default if built w/o HTML support) * src/balsa-print-object.h: add the “volatile” HTML printing options to BalsaPrintSetup * src/print-gtk.c: refactor print dialogue to use GtkGrid; add new options; add function for selecting the proper part from multipart/alternative * src/balsa-print-object-html.[ch]: new files 2019-02-15 Peter Bloomfield * src/mailbox-node.c (balsa_mailbox_node_dispose): now that we unref POP3 mailboxes, which do not need to be saved in the config file, we must not try to save them. 2019-02-14 Peter Bloomfield Plug some memory leaks * src/balsa-mime-widget.[ch]: No need for a 'finalize' method * src/balsa-message.c: Unref the BalsaMimeWidget * src/balsa-app.c: Unref the POP3 mailboxes and free the list * libbalsa/mailbox_pop3.c: Do not leak the filter-cmd * libbalsa/address-book-rubrica.c: Do not leak the completion 2019-02-07 Peter Bloomfield Preserve tab order of open mailboxes across instances (#12) * libbalsa/mailbox.c (libbalsa_mailbox_set_position), (libbalsa_mailbox_get_position): manage the mailbox's position in the notebook; (libbalsa_mailbox_set_open): unset the position when the mailbox is closed; * libbalsa/mailbox.h: new member 'position'; * libbalsa/mailbox_local.c (lbml_set_threading): guard against NULL msg_tree; * src/balsa-app.c (position_compare_func), (balsa_add_open_mailbox_urls): sort the mailboxes to be opened by their position in the last instance; * src/balsa-app.h: new member 'gboolean in_destruction'; * src/balsa-index.c (bndx_destroy), (bndx_selection_changed), (balsa_index_load_mailbox_node): take a strong ref on the BalsaMailboxNode instead of a weak ref; * src/mailbox-node.c (balsa_mailbox_node_dispose): do not bother to close the mbnode; * src/main-window.c (bw_notebook_page_notify_cb): callback for the "child-notify::position" signal; (bw_real_open_mbnode_idle_cb): connect to it; (balsa_window_destroy): set 'in_destruction'; * src/save-restore.c (config_load_mailbox_view), (config_save_mailbox_view): save and restore positions; (config_mailbox_get_int_property), (config_mailbox_get_position): new functions to get position; * src/save-restore.h: new API. 2019-02-04 Peter Bloomfield * meson_options.txt: make 'autocrypt' a boolean option, default false; * meson.build: rename 'autocryptcfg' to 'autocrypt', since it is now boolean. 2019-02-03 Peter Bloomfield Restore running the address book editor * src/meson.build: build the editor with the correct name: "balsa-ab", not "balsa_ab"; * ui/balsa-ab.gresource.xml: use the correct prefix: "/org/desktop/BalsaAb", not "/org/desktop/Balsa". 2018-01-30 Albrecht Dreß LDAP address book: use all email attributes * libbalsa_address_book_ldap_get_address(): assign the GList of all mail attribute strings to LibBalsaAddress instead of the first one only; * lbabl_get_internet_address(): append separate InternetAddress to a GList instead on returning the first one only. 2018-01-24 Albrecht Dreß * libbalsa/html.c (lbh_web_process_terminated_cb): new signal in webkit version 2.20; (libbalsa_html_new): do not auto-load images if any are external (that is, not cid: data) 2019-01-22 Peter Bloomfield More menu shuffling * ui/main-window.ui: move "File → New → Message" to "Message → New…"; move "Mailbox → Close" to the foot of the "Mailbox" menu, and group "Remove Duplicates" and "Expunge Deleted Messages" immediately above it; move "Message → Next Message" and three friends to a new "Go" top-level menu. 2019-01-21 Peter Bloomfield * ui/main-window.ui: Shuffle some menu items; see https://gitlab.gnome.org/GNOME/balsa/issues/14 2019-01-21 Peter Bloomfield * ui/main-window.ui: Restore 'm' shortcut for "New message" 2019-01-20 Peter Bloomfield Remove application menu GNOME has decided that application menus, shown in the top bar of the GNOME desktop, are a bad idea. It was kind of a stretch for Balsa to implement one, so it shouldn't be too hard to drop it. * src/main-window.c (settings_activated), (bw_add_win_action_entries), (balsa_window_add_action_entries), (bw_set_menus): move the appmenu items that are not already duplicate in the File: menu back there; * ui/main-window.ui: ditto. 2018-01-20 Albrecht Dreß Do not trigger a CRITICAL message when request for a Message Disposition Notification is activated Fixes https://mail.gnome.org/archives/balsa-list/2019-January/msg00018.html * libbalsa/message.c (libbalsa_message_set_dispnotify): test whether message->headers->dispnotify_to is NULL before unreffing it. 2018-01-13 Albrecht Dreß Get the Autocrypt headers from Balsa's user-headers instead of from a GMimeMessage, which doesn't always exist. * libbalsa/autocrypt.c (scan_autocrypt_headers): new function for scanning Balsa's user-headers; (autocrypt_from_message): use it, instead of g_mime_object_get_header_list() and friends; (parse_autocrypt_header): extend the (debug) output when checking the key data from an Autocrypt header fails. 2019-01-11 Peter Bloomfield Check for NULL message * libbalsa/imap/imap-commands.c (imap_mbox_sort_msgno_client): check for NULL message and for a message with a NULL envelope, to avoid dereferencing NULL pointers. 2018-01-10 Albrecht Dreß Minor autocrypt fixes * libbalsa/autocrypt.c: set a proper error message if no fingerprint of a usable private key can be identified for a mailbox; fix memory leak; attach Autocrypt database window to geometry manager * libbalsa/send.c: do not add Autocrypt header when postponing; propagate error from creating Autocrypt header * src/save-restore.c: restore Autocrypt database window geometry 2018-01-05 Albrecht Dreß make IMAP messages translatable * libbalsa/imap/auth-cram.c, libbalsa/imap/auth-gssapi.c, libbalsa/imap/imap-commands.c, libbalsa/imap/imap-handle.c: make message strings translatable * libbalsa/imap/imap-handle.c, libbalsa/imap/imap_private.h: implement imap_mbox_handle_set_msg() as function * libbalsa/imap/imap-commands.h, libbalsa/imap/imap-tls.c: add GError to imap_handle_starttls() api 2019-01-05 Peter Bloomfield Fix the meson build * libbalsa/meson.build: add geometry manager module 2018-01-05 Albrecht Dreß Simplify window geometry management * libbalsa/Makefile.am: add geometry manager module * libbalsa/geometry-manager.[hc]: geometry manager module implementation * libbalsa/libbalsa-gpgme-cb.c: use geometry manager for the key list dialogue * libbalsa/libbalsa-gpgme-widgets.c: use geometry manager for the key dialogue * libbalsa/libbalsa.h: simplify libbalsa_show_message_source() api, remove unimplemented function prototype * libbalsa/source-viewer.c: use geometry manager, simplify libbalsa_show_message_source() api * src/balsa-app.c: remove initialisation of obsolete balsa_app items * src/balsa-app.h: remove obsolete balsa_app items * src/balsa-index.c: use new libbalsa_show_message_source() api * src/folder-conf.c, src/main-window.c, src/main.c, src/message-window.c, src/sendmsg-window.c: use geometry manager and new libbalsa_show_message_source() api * src/save-restore.c: use geometry manager to load and save values 2018-01-05 Albrecht Dreß minor Autocrypt fixes * libbalsa/autocrypt.c: * add missing include, required on Debian stretch * make sure the ~/.balsa folder exists before initialising the autocrypt sub-system (otherwise an error is thrown when balsa is started for the first time) * clarify debug messages, indicating if a database entry has actually been changed 2018-12-18 Peter Bloomfield * src/mailbox-conf.c (create_local_mailbox_dialog): avoid possibly dereferencing a NULL pointer. 2018-12-18 Albrecht Dreß Fix broken display of expired application/pgp-keys parts * libbalsa/libbalsa-gpgme-keys.[hc]: add flag to libbalsa_gpgme_list_keys() for listing expired etc. keys, use the new api w/o allowing expired etc. keys * libbalsa/libbalsa-gpgme.c, libbalsa/rfc3156.c: use the new api w/o allowing expired etc. keys * src/balsa-mime-widget-crypto.c: use the new api, allowing expired etc. keys 2018-12-18 Albrecht Dreß Fix buffer overflow and missing include * libbalsa/folder-scanners.c: fix missing include on old systems which do not indirectly import string.h, remove obsolete macro * libbalsa/libbalsa.c: fix one-byte buffer overflow in x509_fingerprint() 2018-12-18 Albrecht Dreß SMTP, POP: fall back to auth w/ password if GSS failed * libnetclient/net-client-pop.c, libnetclient/net-client-smtp.c: retry auth with password if GSS auth failed; small performance improvement checking the various auth methods * libnetclient/net-client-utils.c: print more (internal) debug info about failed GSS operations, fix nit-picks 2018-12-14 Peter Bloomfield Stop using GSlice; it may go away * libbalsa/mailbox.c (libbalsa_mailbox_search_iter_new): use g_new(), not g_slice_new(); (libbalsa_mailbox_search_iter_unref): use g_free(), not g_slice_free(). 2018-12-13 Albrecht Dreß Replace readdir() by g_dir_read_name() * libbalsa/folder-scanners.c: replace opendir/readdir/closedir by g_dir_*, and refactor functions libbalsa_scanner_mdir() and libbalsa_scanner_local_dir_helper * libbalsa/mailbox_imap.c: replace opendir/readdir/closedir by g_dir_* 2018-12-09 Albrecht Dreß Clean up deadwood * src/mailbox-conf.c (run_mailbox_conf), (create_local_mailbox_dialog): remove the “deadwood”, and a stray debug message… 2018-12-08 Albrecht Dreß Fix some issues detected by cppcheck * libbalsa/imap/auth-gssapi.c: fix (unlikely) uninitialised use of rc * libbalsa/imap/imap-auth.c: do not dereference NULL pointer if an error occurred * libbalsa/libbalsa.c: fix signed/unsigned mismatch, and use g_debug instead of printf * libbalsa/mailbox_imap.c: fix signed/unsigned mismatch * libinit_balsa/assistant_page_directory.c: fix different parameters names in function prototype and implementation * src/balsa-message.c, src/save-restore.c: do no dereference pointer before checking it it is not NULL * src/sendmsg-window.c: fix false-positive about NULL pointer dereference * src/store-address.c: fix false-positive by splitting an over-complex construct 2018-12-04 Peter Bloomfield Deprecation cleanup * libbalsa/mime.c (libbalsa_text_to_html): pango_unichar_direction() is deprecated in Pango 1.44; a commit message suggests using fribidi directly. * configure.ac: add direct fribidi dependency; it is already an indirect dependency through Pango. * meson.build: ditto. 2018-12-03 Peter Bloomfield Do not include no-longer-existing libbalsa/libbalsa-marshal.h * src/main-window.c: 2018-11-30 Albrecht Dreß Replace custom ELEMENTS macro with Glib G_N_ELEMENTS * libbalsa/filter-funcs.c (libbalsa_condition_new_from_string), (append_header_names), (append_flag_names): * libbalsa/identity.c (md_sig_path_changed): * libbalsa/imap/imap-commands.c (need_fetch), (imap_mbox_status), (enum_flag_to_str): * libbalsa/imap/imap-handle.c (ir_capability_data), (ir_resp_text_code), (ir_list_lsub), (ir_status), (ir_msg_att_flags), (ir_fetch_seq), (ir_handle_response): * libbalsa/libbalsa.h: * libbalsa/mailbox.c (mbox_model_get_value): * src/balsa-index.c (bndx_instance_init), (bndx_popup_menu_create): * src/balsa-mblist.c (balsa_mblist_default_signal_bindings): * src/filter-edit-callbacks.c (build_condition_dialog): * src/filter-edit-dialog.c (build_match_page), (build_action_page): * src/main-window.c (bw_create_index_widget): * src/sendmsg-window.c (find_locale_index_by_locale), (create_email_entry), (sw_attachment_list), (create_text_area), (create_lang_menu): * src/toolbar-factory.c: 2018-11-30 Albrecht Dreß Fix confusing signature info * libbalsa/gmime-gpgme-signature.c: hide unavailable data if a signature is bad, the public key missing, or without signature data at all * libbalsa/libbalsa-gpgme-widgets.c: find proper subkey even if only the end of the fingerprint is given * src/balsa-mime-widget-crypto.c: remove useless debug message 2018-11-28 Peter Bloomfield Pass NULL instead of a stock marshaller to g_signal_new(). * libbalsa/address-view.c (libbalsa_address_view_class_init): * libbalsa/cell-renderer-button.c (libbalsa_cell_renderer_button_class_init): * libbalsa/imap/imap-handle.c (imap_mbox_handle_class_init): * libbalsa/mailbox.c (libbalsa_mailbox_class_init): * src/balsa-index.c (bndx_class_init): * src/balsa-mblist.c (bmbl_class_init): * src/balsa-message.c (balsa_message_class_init): * src/filter-run-dialog.c (balsa_filter_run_dialog_class_init): * src/mailbox-node.c (balsa_mailbox_node_class_init): * src/main-window.c (balsa_window_class_init): * src/toolbar-factory.c (balsa_toolbar_model_class_init): 2018-11-28 Peter Bloomfield Remove marshal lists * libbalsa/imap/libimap-marshal.list: * libbalsa/libbalsa-marshal.list: 2018-11-27 Peter Bloomfield GNotification does not use HTML markup * libbalsa/information.c (libbalsa_information_varg): so do not escape markup characters in the text 2018-11-27 Albrecht Dreß Clear passwords if authentication fails * libbalsa/mailbox_pop3.c, libbalsa/send.c: clear appropriate password when libnetclient reports an authentication failure (SMTP, POP), or could not decrypt a user certificate's private key * libnetclient/net-client-pop.[ch]: report auth failure if the server reports any error in the authentication phase (AUTH, APOP, USER/PASS); fix nagging by Flexelint * libnetclient/net-client-smtp.[ch]: report auth failure if the server replies with status codes 534 or 535; fix nagging by Flexelint * libnetclient/net-client.[ch]: report a certificate key decryption error if the passphrase is wrong 2018-11-27 Albrecht Dreß Fix broken IMAP special folders & other migration issues * libbalsa/mailbox.[ch]: tell libbalsa_mailbox_new_from_config() if a folder is special, so it is processed even if it is an IMAP one * libbalsa/mailbox_imap.c: always set the "Migrated" flag for LibBalsaMailboxImap mailboxes * src/save-restore.c: in the migration process, track "user@host" folder ids in a hash table to avoid duplicates; keep special IMAP folders; load folders before mailboxes so special IMAP mailboxes do not overwrite the folder's IMAP configs (the server config originates from the first server seen) 2018-11-27 Albrecht Dreß Password dialogue improvements * libbalsa/imap-server.c, libbalsa/server-config.c, libinit_balsa/assistant_page_user.c, src/save-restore.c: use changed libbalsa_server_set_password() api * libbalsa/libbalsa.[c]: implement GTK_DIALOG_USE_HEADER_BAR detection as boolean for GCR dialogue * libbalsa/server.[ch]: clean up signal definitions (remove obsolete marshallers); remove unused class method; adjust api's for libbalsa_server_set_password(), libbalsa_server_get_password() and libbalsa_server_get_cert_pass() * libnetclient/net-client.[ch]: pass cert subject only instead of full binary data in the passphrase signal * src/balsa-app.[ch]: use GCR password dialogue if available; drop set_passwd_from_matching_server() which is never used 2018-11-04 Albrecht Dreß Unified server configuration GUI * libbalsa/Makefile.am, libbalsa/meson.build: add new server-config module * libbalsa/imap-server.c: use common config class; ensure server hash key required by changed folder conf approach * libbalsa/libbalsa-conf.[ch]: add option for obfuscated private string, so libbalsa_rot() is used only locally * libbalsa/address-book-ldap.c: use changed libbalsa-conf api * libbalsa/libbalsa.[ch]: libbalsa_rot() moved to libbalsa/libbalsa-conf.c * libbalsa/mailbox_pop3.c: properly initialise procmail command * libbalsa/send.c: fix broken signal connections if a user certificate is used * libbalsa/server-config.[ch]: implement new server config gui class * libbalsa/server.[ch]: use new config gui; refactor libsecret stuff; store user cert passphrase using libsecret if requested; clean up exported types * libbalsa/smtp-server.c: use new config gui * src/folder-conf.c: use new config gui; Note: slightly changed approach for adding an IMAP folder * src/mailbox-conf.[ch]: use new config gui, removes loads of obsolete exported code * src/mailbox-node.c: use g_debug() for debug messages * src/save-restore.c: use changed libbalsa-conf api 2018-10-17 Peter Bloomfield * src/main-window.c (bw_create_index_widget): gtk_container_*_focus_chain functions are deprecated. 2018-10-17 Peter Bloomfield * src/balsa-mime-widget-callbacks.c (bmw_set_can_focus), (balsa_mime_widget_limit_focus), (balsa_mime_widget_unlimit_focus): gtk_container_*_focus_chain functions are deprecated. 2018-09-14 Peter Bloomfield * libbalsa/information.c (libbalsa_information_varg): use g_markup_escape_text to entity-escape the body of a GNotification, instead of our home-brewed non-UTF8-safe version. 2018-09-05 Albrecht Dreß Fix crash listing S/MIME certificates * libbalsa/gmime-gpgme-signature.c (libbalsa_cert_subject_readable): restore a missing termination check. 2018-08-29 Albrecht Dreß Move single IMAP mailboxes to folders * libbalsa/mailbox.c: print paranoid warning if libbalsa_mailbox_new_from_config() is called for an IMAP mailbox * src/mailbox-conf.[ch]: remove obsolete mailbox_conf_add_imap_cb(), create_imap_mailbox_dialog() and dependent functions * src/mailbox-node.[ch]: make sure BalsaMailboxNode::dir is properly initialised; remove obsolete balsa_mailbox_node_new_imap() * src/pref-manager.c: clean up menu * src/save-restore.c: migrate IMAP mailboxes to IMAP folders 2018-08-27 Peter Bloomfield Apply threading changes on 'Update' * src/mailbox-conf.c (thread_messages_toggled), (mailbox_conf_view_new_full), (mailbox_conf_view_check): apply threading changes on 'Update' instead of instantly on checking the boxes. 2018-08-27 Peter Bloomfield Check for valid msgno * libbalsa/mailbox.c (mbox_get_thread_date_traverse_func): check that the msgno that we get from the GNode is in the valid range 1 <= msgno <= mindex->len. 2018-08-27 Peter Bloomfield Clear timeout source id in handler * libbalsa/mailbox_local.c (lbm_local_sync_real), (lbm_local_sync_idle): clear LibBalsaMailboxLocal::sync_id in the timeout handler, not in the thread that it creates. 2018-08-25 Peter Bloomfield Add UI for 'merge threads by subject' * libbalsa/mailbox.c (libbalsa_mailbox_set_subject_gather), (libbalsa_mailbox_get_subject_gather): new methods. * libbalsa/mailbox.h: add LibBalsaMailboxView::subject_gather and declare the getter/setter. * src/balsa-index.c (balsa_index_set_thread_messages): use thread-messages and subject-gather to decide whether threading is flat, simple, or JWZ. * src/mailbox-conf.c (thread_messages_toggled), (subject_gather_toggled), (mailbox_conf_view_new_full), (mailbox_conf_view_check): add the UI to the mailbox config dialog. * src/main-window.c (bw_enable_mailbox_menus), (balsa_window_set_thread_messages): export -set-thread-messages. * src/main-window.h: ditto. 2018-08-20 Peter Bloomfield Limit use of LibBalsaMailboxThreadingType in src/ to balsa-index.c * src/main-window.c (threading_change_state): pass gboolean thread_messages to balsa-index, instead of LibBalsaMailboxThreadingType threading_type; * src/balsa-index.c (balsa_index_set_thread_messages): ditto; * src/balsa-index.h: change API. 2018-08-19 Peter Bloomfield Simplify threading Change THREADING_SIMPLE to mean JWZ without the 'subject gather' phase, and change the UI to enable or disable threading instead of offering the choice of threading algorithms. Still to do: add UI for choosing JWZ instead of SIMPLE. * libbalsa/mailbox.c (lbm_need_threading_idle_cb), (libbalsa_mailbox_set_view_filter), (lbm_set_threading_idle_cb), (lbm_set_threading), (libbalsa_mailbox_set_threading): do not pass threading type to _set_threading, just get it from the view. * libbalsa/mailbox.h: ditto. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_close_mailbox), (lbml_set_threading), (lbml_set_threading_idle_cb), (libbalsa_mailbox_local_set_threading), (lbm_local_thread_idle), (lbml_thread_messages), (lbml_unthread_message), (lbml_threading_flat): change THREADING_SIMPLE to mean JWZ without the 'subject gather' phase, and simplify THREADING_FLAT. * src/balsa-index.c (balsa_index_set_threading_type): do nothing if the type has not changed. * src/balsa-index.h: the threading type is LibBalsaMailboxThreadingType. * src/main-window.c (threading_change_state), (bw_add_win_action_entries), (balsa_window_new), (bw_enable_expand_collapse), (bw_enable_mailbox_menus), (bw_set_thread_messages), (bw_real_open_mbnode_idle_cb): remove the threading type radio buttons, and replace them with a 'Thread messages' check-box. * src/main.c (balsa_get_stats): new API for libbalsa_mailbox_set_threading. * src/pref-manager.c (update_view_defaults), (apply_prefs), (set_prefs), (pm_grid_add_threading_group), (open_preferences_manager): remove the threading type combo box, and replace it with a 'Thread messages by default' check-box. * ui/main-window.ui: remove the threading type radio buttons, and replace them with a 'Thread messages' check-box. 2018-08-11 Albrecht Dreß Improve IMAP folder configuration Commit b821fb65cec529f52fee7757c870fb9ef131d653 was erased from the git log by a later merge--oops! * src/folder-conf.c: simplify folder_conf_imap_sub_node() which is now used only for modifying an existing folder, not for creating a new one; put the logic for the latter into folder_conf_add_imap_sub_cb(). Note that folder_conf_imap_sub_node() still needs some refactoring… * src/mailbox-node.[ch]: replace empty items by separators in add_menu_entry(); export helper balsa_mailbox_node_is_imap() indicating if a BalsaMailboxNode is on an IMAP server; in balsa_mailbox_node_get_context_menu() remove the “Remote IMAP folder” and show “Remote IMAP subfolder” for IMAP BalsaMailboxNodes only * src/main-window.c: “Remote IMAP folder”, activate “Remote IMAP subfolder” for selected IMAP BalsaMailboxNodes only * ui/main-window.ui: remove “Remote IMAP folder” from the ui 2018-07-24 Peter Bloomfield * meson.build: Change the pkg-config test for enchant from "<= 1.6.0" to "!= 1.6.1"; Gentoo provides enchant versions 2.x.x with enchant.pc, not enchant-2.pc. 2018-07-24 Peter Bloomfield * configure.ac: Change the pkg-config test for enchant from "<= 1.6.0" to "!= 1.6.1"; Gentoo provides enchant versions 2.x.x with enchant.pc, not enchant-2.pc. 2018-07-21 Peter Bloomfield Oops, forgot this in the previous commit. * src/sendmsg-window.c (create_text_area): MR gtk!236 has been merged; the fix will be in Gtk 3.24 when it is released, but for building against unstable versions the test is GTK_CHECK_VERSION(3, 23, 1). 2018-07-20 Peter Bloomfield * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): MR gtk!236 has been merged; the fix will be in Gtk 3.24 when it is released, but for building against unstable versions the test is GTK_CHECK_VERSION(3, 23, 1). 2018-07-19 Peter Bloomfield * libbalsa/html.c: Handle the deprecation of GtkAction more cleanly. 2018-07-18 Peter Bloomfield More work around MR gtk!236 * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): set the GtkTextView margins to zero; * src/sendmsg-window.c (create_text_area): ditto. 2018-07-18 Peter Bloomfield Work around MR gtk!236 * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): use GtkWidget margins instead of GtkTextView margins, to make the window shrinkable and to avoid button creep; * src/sendmsg-window.c (create_text_area): ditto, to make the window shrinkable (does not fix the problem when GtkSourceView is used). 2018-07-07 Albrecht Dreß Fix HTML rendering with webkit2gtk-4.0 < 2.20 * README: document use of G_MESSAGES_DEBUG=… * libbalsa/html.c (lbh_navigation_policy_decision): allow the rendering of “about:blank”. 2018-07-07 Peter Bloomfield Use g_debug() instead of conditionally compiled printing * libbalsa/html.c (lbh_navigation_policy_decision), (lbh_new_window_policy_decision), (lbh_response_policy_decision), (lbh_resource_notify_response_cb), (lbh_web_process_crashed_cb), (lbh_cid_cb), (libbalsa_html_new): 2018-07-05 Peter Bloomfield * src/balsa-mime-widget.c (balsa_mime_widget_new): Do not leak the GtkAdjustment. 2018-07-05 Peter Bloomfield * src/balsa-message.c (bm_find_scroll_to_rectangle), (select_part): Use gtk_scrolled_window_get_{h,v}adjustment() instead of GObject properties (and consequently, do not leak the adjustments). 2018-07-03 Albrecht Dreß libnetclient private data fixes * libnetclient/net-client-pop.c, libnetclient/net-client-siobuf.c, libnetclient/net-client-smtp.c: properly access and destroy the private data * libnetclient/test/Makefile.am: fix lcov cleaning the test app from the coverage data * libnetclient/test/cert.pem, libnetclient/test/cert_u.pem: replace expired snakeoil certs for testing 2018-06-28 Peter Bloomfield * src/mailbox-conf.c: Really build with gpgme desabled. 2018-06-28 Peter Bloomfield * libnetclient/net-client.c (net_client_class_init), (net_client_init): g_type_class_add_private() is soon to be deprecated; use G_DEFINE_TYPE_WITH_PRIVATE intead; also use net_client_get_instance_private() instead of G_TYPE_INSTANCE_GET_PRIVATE(). 2018-06-26 Peter Bloomfield * src/main-window.c (about_activated): Update the 'about' dialog. 2018-06-26 Peter Bloomfield * src/main-window.c (bw_real_open_mbnode_idle_cb), (bw_real_open_mbnode_thread), (balsa_window_real_open_mbnode), (bw_mailbox_check): Use g_application_{hold,release} to keep the GApplication alive while mailboxes are being opened. 2018-06-26 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_finalize), (lbm_changed_idle_cb), (lbm_changed_schedule_idle), (lbm_run_filters_on_reception_idle_cb), (libbalsa_mailbox_run_filters_on_reception): manage idle ids. * libbalsa/mailbox.h: new idle id for run-filters-on-reception idle handler. 2018-06-26 Peter Bloomfield * libbalsa/libbalsa-conf.c (libbalsa_conf_foreach_group): check that the key-file has not been dropped. 2018-06-26 Peter Bloomfield * libbalsa/imap/imap_search.c (imap_search_exec): keep the handle alive while searching. 2018-06-24 Peter Bloomfield Make the 'Balsa closes…' notification outlive the main window, and close it when shut-down is complete. * src/main-window.c (quit_activated): NULL parent makes the notification outlive the window. * src/main.c (balsa_shutdown_cb): send an empty notification string to withdraw the notification. 2018-06-24 Peter Bloomfield * libbalsa/information.c (libbalsa_information_varg): if message is an empty string, withdraw the notification. 2018-06-24 Peter Bloomfield * libbalsa/imap-server.c (lb_imap_server_info_free), (lb_imap_server_cleanup): Check for NULL 'struct handle_info *'. 2018-06-24 Peter Bloomfield * src/main.c (balsa_activate_cb): Present the main-window, if we already have one. 2018-06-23 Peter Bloomfield Migrate from libnotify to GNotification * README: Remove reference to libnotify. * configure.ac: Do not configure it. * meson.build: Ditto. * meson_options.txt: Ditto. * libbalsa/information.c (lbi_notification_parent_weak_notify), (libbalsa_information_varg), (libbalsa_notification_new): Use GNotification instead, and we do not need to drop through to balsa-information. * libbalsa/information.h: New function libbalsa_notification_new. * libbalsa/libbalsa.c (libbalsa_init): Clean up initialization. * libbalsa/libbalsa.h: Ditto. * src/main.c (balsa_notification_notify_cb), (balsa_setup_libbalsa_notification), (balsa_startup_cb): Get a GNotification, and use its "notify" signal to show or withdraw it. * src/ab-main.c (balsa_ab_notification_notify_cb), (balsa_ab_notification_shutdown_cb), (balsa_ab_setup_libbalsa_notification), (main): Ditto. 2018-06-23 Peter Bloomfield * src/balsa-icons.c (balsa_icon_id): Return NULL if the icon-table has been destroyed; (balsa_register_pixbufs): cope with it; * src/toolbar-prefs.c (tp_store_set): ditto. 2018-06-23 Peter Bloomfield * libbalsa/mailbox_imap.c (lbm_imap_check): Object-ref handle while we check for a list-response. 2018-06-22 Peter Bloomfield * src/main-window.c (bw_is_active_notify), (bw_display_new_mail_notification): get the application from the window, not using g_object_get(); 2018-06-21 Peter Bloomfield * configure.ac, Makefile.am, meson.build: Rename balsa.desktop to org.desktop.Balsa.desktop. 2018-06-21 Peter Bloomfield * src/main-window.c (view_source_activated), (bw_set_menus): get the application from the window, not using g_object_get(); (balsa_window_new): do not leak adjustments. 2018-06-20 Peter Bloomfield Migrate new mail notification from NotifyNotification to GNotification. * src/main-window.c (bw_is_active_notify), (check_new_messages_count), (bw_display_new_mail_notification): Migrate new mail notification from NotifyNotification to GNotification. * src/main-window.h: Use a boolean to remember when a notification is being shown. 2018-06-20 Peter Bloomfield * src/main-window.c (view_source_activated), (bw_set_menus): Do not leak application. 2018-06-20 Peter Bloomfield * src/main-window.c (balsa_window_new): Pass the GtkApplication as an argument to balsa_window_new(); (view_source_activated), (bw_set_menus): Get the GtkApplication as a property of BalsaWindow, instead of from the balsa-app structure; * src/main-window.h: New API for balsa_window_new(). 2018-06-20 Peter Bloomfield * src/main.c (balsa_startup_cb), (balsa_shutdown_cb), (balsa_activate_cb), (balsa_command_line_cb), (main): Use all the GApplication signals, instead of doing it all in the command-line handler. 2018-06-15 Peter Bloomfield * src/mailbox-conf.c: Build with gpgme desabled. 2018-06-15 Peter Bloomfield * libinit_balsa/assistant_page_directory.c (unconditional_mailbox): adapt to new libbalsa_server_set_host() API. 2018-06-07 Peter Bloomfield * libbalsa/imap/meson.build: Edit libimap_a_sources to reflect the previous commit, and add libnetclient_include to the include_directories for imap_tst. 2018-06-05 Albrecht Dreß IMAP goes GIO Changes to libnetclient/*: As I mentioned above, in the libnetclient library I added a module which “simulates” the character-buffering methods of libbalsa/imap/siobuf.[hc]. Other improvements include: - transparent compression (RFC 4978) support – which revealed a bug in GIO sending crap when finalising the connection. This is not really harmful, but may confuse a network-based IDS (see ); - helper function for wiping auth data with random chars before freeing the string; - improved unit tests. Changes to libbalsa/imap/*: - siobuf.[hc] are removed, siobuf-nc.h providing a “glue layer” for libnetclient is added - auth-cram.c, imap-auth.[ch]: partly re-written; uses libnetclient signals; replace fixed-length strings by dynamically allocated glib strings which is safer; simplifications by using libnetclient functions - auth-gssapi.c: simplified by using libnetclient helpers; glib strings as above - imap-commands.c, imap-handle.[ch], imap_search.c, imap_tst.c: simplifications by using libnetclient functions, removed some unused functions - imap-tls.c, imap_compress.[ch]: massive simplification as all “real” work is implemented in GIO via libnetclient - imap_private.h: modification of struct _ImapMboxHandle to use libnetclient stuff, and remove obsolete fields - util.c: simplified quoting function, removed unused unquoting In all modules, I replaced the mixture of debugging functions ([f]printf) by g_debug etc. Changes to libbalsa/*: - imap-server.c: cleaned up unused monitor cb, use unified security (from libnetclient) instead of separate ssl/tls settings - libbalsa.c: replace OpenSSL-based certificate functions by GTlsCertificate and GnuTLS (if GCR is not available, remember that GIO is based on GnuTLS) - misc.c: tiny improvement for assuring ~/.balsa - server.[ch]: use NetClientCryptMode instead of use_ssl and tls_mode; remove obsolete libbalsa_server_user_cb (replaced by libnetclient's signals); simplify libbalsa_server_check_cert - smtp-server.c: use changed server api Changes to libinit_balsa/*: - assistant_page_user.c: use changed server api Changes to src/*: - folder-conf.c: configure IMAP according to changed server api (note: widget (de)activation logic not yet fully functional) - src/mailbox-conf.[ch]: ditto, but with a working (de)activation logic (I think) - mailbox-node.c: use g_debug instead of printf - main.c: remove IMAP debug option (use G_MESSAGES_DEBUG, as always) - save-restore.c: remove obsolete item On the top-level: - the configure/meson checks for OpenSSL and ZLib have been removed 2018-06-05 Peter Bloomfield * libbalsa/address-book-rubrica.c (extract_net): Fix a typo that broke the build. 2018-06-05 Peter Bloomfield Do not seg fault on delayed exit * libbalsa/mailbox.c (lbm_changed_schedule_idle): ref the mailbox (lbm_changed_idle_cb): and unref it; * src/main-window.c (check_new_messages_real): check for balsa_app.mblist_tree_store == NULL, and do not dereference it. 2018-06-01 Pawel Salek * NEWS, configure.ac: release balsa-2.5.6 * src/Makefile.am: add missing xml files 2018-06-01 Pawel Salek * src/balsa-icons.c: don't let missing icons stop balsa. 2018-05-31 Peter Bloomfield Use g_strcmp0() for NULL-safe comparisons * libbalsa/address-book-rubrica.c (extract_net): * libbalsa/gmime-gpgme-signature.c (libbalsa_cert_subject_readable): * libbalsa/html.c (lbh_mouse_target_changed_cb), (libbalsa_html_search): * libbalsa/identity.c (libbalsa_identity_combo_box): * libbalsa/mailbox.c (libbalsa_mailbox_set_identity_name), (lbm_try_reassemble): * libbalsa/mailbox_mbox.c (lbm_mbox_message_new): * libbalsa/smtp-server.c (smtp_server_compare): * src/ab-main.c (bab_config_init): * src/balsa-app.c (find_path), (balsa_quote_regex_new): * src/balsa-icons.c (load_balsa_pixmap): * src/filter-edit-callbacks.c (change_filter_name): * src/folder-conf.c (subfolder_conf_clicked_ok), (folder_conf_imap_sub_node): * src/mailbox-node.c (remove_special_mailbox_by_url): * src/pref-manager.c (open_preferences_manager_idle): * src/save-restore.c (config_address_book_load): * src/sendmsg-window.c (sw_preferred_charset), (find_locale_index_by_locale), (has_file_attached): 2018-05-31 Peter Bloomfield * src/filter-edit-callbacks.c (fe_new_pressed): Do not leak new_item. 2018-05-31 Peter Bloomfield * src/balsa-index.c (bndx_pipe_queue_last): Do not leak PipeData. 2018-05-31 Peter Bloomfield * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_get_matchings): Do not leak ImapSearchData. 2018-05-31 Peter Bloomfield * libbalsa/imap/imap-handle.c (ir_body_type_1part): Do not leak ImapEnvelope. 2018-05-31 Albrecht Dreß Mitigate EFail vulnerability for Webkit2 * libbalsa/html.c (lbh_navigation_policy_decision): ignore all decisions except WEBKIT_NAVIGATION_TYPE_LINK_CLICKED; (libbalsa_html_new): disable Java and JavaScript. 2018-05-31 Peter Bloomfield * src/balsa-index.c (bndx_compose_foreach): Count skipped messages only when replying to group. 2018-05-30 Peter Bloomfield * src/balsa-index.c (bndx_compose_foreach): When replying to group, count how many messages were skipped for not having the "list-post" header, and report them. 2018-05-30 Peter Bloomfield * src/message-window.c (message_window_new): Disable "reply to group" when the message is not from an RFC-2369-compliant mailing list. 2018-05-29 Peter Bloomfield * src/balsa-index.c (bndx_selection_changed): Emit "index-changed" even if the preview does not need to be updated, so that the main window menus can be enabled/disabled appropriately. 2018-05-29 Peter Bloomfield * src/sendmsg-window.c (sendmsg_window_reply): If the message is a reply to a mailing list, check that the message we are replying to actually came from a mailing list; if not, return NULL. 2018-05-29 Peter Bloomfield * src/main-window.c (bw_enable_message_menus): Disable "reply to group" when the message is not from an RFC-2369-compliant mail list. 2018-05-10 Peter Bloomfield New files for migrating to GResource * ui/balsa-ab.gresource.xml: * ui/balsa.gresource.xml: 2018-05-01 Albrecht Dreß Display time stamps of date-only RFC 5545 iCalendar events I noticed that “VALUE=DATE” time stamps (date only, without time) in RFC 5545 iCalendar parts (MIME type text/calendar) are not displayed. The attached trivial patch add parsing, displaying and printing such values As to simplify life, the date-only values are printed using the “%x” conversion specification, instead of extracting the date part from balsa_app.date_string. * libbalsa/rfc2445.c (libbalsa_vcal_new_from_body), (date_time_2445_to_time_t): * libbalsa/rfc2445.h: * src/balsa-mime-widget-vcalendar.c (balsa_vevent_widget): * src/balsa-print-object-text.c (balsa_print_object_text_calendar): 2018-04-11 Peter Bloomfield Fix the "scroll on click" issue (https://bugzilla.gnome.org/show_bug.cgi?id=795085) * src/balsa-message.c (balsa_message_init): wrap the BalsaMimeWidget::widget in a GtkViewport; if we do not, GtkContainer does it for us, but also sets it up to scroll when first clicked, which leaves the wrong text under the pointer. 2018-03-19 Peter Bloomfield * libbalsa/imap/imap-commands.c (imap_mbox_handle_fetch_body): silence a gcc gripe about snprintf. 2018-03-19 Peter Bloomfield * libbalsa/imap/imap-commands.c (imap_mbox_handle_fetch_body): silence a gcc gripe about strncpy. 2018-02-27 Pawel Salek * src/main-window.c: update a date. * meson.build, configure.ac: update version strings. * NEWS: balsa-2.5.5 release notes 2018-02-12 Albrecht Dreß Crypto performance improvements * libbalsa/body.c: calculate protection state without the key * libbalsa/gmime-gpgme-signature.[ch]: do not try to load the key when creating the signature object, add and rename some signature-only related functions from rfc3156.[hc], set 'crypto' log domain * libbalsa/libbalsa-gpgme-keys.[ch]: add function to load a public key, properly restore the context attributes when listing keys, set 'crypto' log domain * libbalsa/libbalsa-gpgme-widgets.[ch]: improved function for creating a string from the key data (shifted from rfc3156.[hc]), set 'crypto' log domain * libbalsa/rfc3156.[ch]: refoctoring; shift some signature-only related functions to gmime-gpgme-signature.[ch], set 'crypto' log domain * src/balsa-message.c: use renamed signature info functions, calculate protection state without the key * src/balsa-mime-widget-crypto.c: add callback to load the key when the user wants to show it, drop condition which cannot be TRUE, use renamed signature info functions * src/balsa-mime-widget-message.c: use renamed signature info functions * src/balsa-print-object-header.c: try to load the key before printing, use renamed signature info functions * README, configure.ac, meson.build: require gpgme ≥ 1.5.0 * libbalsa/libbalsa-gpgme.c: set 'crypto' log domain, adjust debug messages * libbalsa/gmime-application-pkcs7.c, libbalsa/gmime-multipart-crypt.c, libbalsa/gmime-part-rfc2440.c, libbalsa/libbalsa-gpgme-cb.c: set 'crypto' log domain 2018-02-10 Peter Bloomfield Clean up generated marshalling files * libbalsa/Makefile.am: create a CLEANFILES variable to arrange for libbalsa-marshal.[ch] to be removed with "make clean". 2018-02-09 Peter Bloomfield In glib-2.56, g_object_ref() propagates the type from its argument to its return type, which can raise incompatible-pointer-type warnings; previously it returned a gpointer, which could conceal a coding error. * src/main-window.c (bw_check_mailbox_done), (bw_check_mailbox_list): make the mailbox member of bw_pop_mbox_t a LibBalsaMailbox, so that it can accept the value of g_object_ref(mailbox) without a warning; rename it from 'object' to 'mailbox' because, well, that's what it is. 2018-02-07 Peter Bloomfield * libbalsa/mailbox.c (lbm_sort): check for zero-length array. 2018-02-07 Peter Bloomfield Fix two use-after-free false positives * src/filter-edit-callbacks.c (change_filter_name): Use g_list_delete_link() with a valid link instead of g_list_remove() with the address of freed data. 2018-02-07 Peter Bloomfield Fix a use-after-free bug * src/sendmsg-window.c (edit_with_gnome_check): unlink the file before freeing its name. 2018-01-26 Peter Bloomfield * meson.build: use Unicode quotation marks. 2018-01-26 Peter Bloomfield * meson.build: fix the definition of HAVE_CTIME_R. 2018-01-26 Peter Bloomfield * meson.build: test for and set HAVE_LOCALE_H if found. 2018-01-21 Peter Bloomfield Meson build system changes to mirror the autotools changes in the previous commit * meson.build: check if the selected conversion tool accepts “--unicode-snob”. 2018-01-20 Albrecht Dreß Improve replying to html-only messages * configure.ac: check if the selected conversion tool accepts “--unicode-snob”. * libbalsa/html.c (html2text): run the conversion tool with “--unicode-snob” if supported. 2018-01-20 Peter Bloomfield Meson build system changes to mirror the autotools changes in the previous commit * libnetclient/meson.build: add c_args: '-DG_LOG_DOMAIN="libnetclient"' to static_library arguments. * meson.build: drop sed and ncat prerequisites. 2018-01-20 Albrecht Dreß Improve low-level network library, POP3 responsiveness on error * configure.ac: add missing flags and libs for libnetclient unit tests, drop sed and ncat prerequisites * libbalsa/mailbox_pop3.c: shut down the connection on error, so un'refing it does not wait for the QUIT command * libnetclient/Makefile.am: fix log domain * libnetclient/README: update documentation * libnetclient/net-client-pop.c: execute QUIT only if the connection exists * libnetclient/net-client-smtp.c: fix FlexeLint warnings about ignored function return values, execute QUIT only if the connection exists * libnetclient/net-client.[ch]: implement new methods for shutting down the network connection and for checking the connection status * libnetclient/test/Makefile.am: drop sed and ncat requirements, fix test application build error * libnetclient/test/echoserver.py: (new file) trivial echo server in Python * libnetclient/test/start-test-env.sh.in: control the echo server for testing * libnetclient/test/tests.c: improve unit tests 2018-01-11 Albrecht Dreß Fix progress dialogue on error * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_check): send the “finalise” notification to the dialogue even if opening the connection fails. 2018-01-06 Albrecht Dreß Fix the meson build * src/meson.build: threads.h is no more. 2018-01-05 Albrecht Dreß Enable multi-threaded POP3 retrieval * libbalsa/libbalsa-marshal.list, libbalsa/mailbox.[ch]: new simplified signature for the mailbox '' signal and the related helper libbalsa_mailbox_progress_notify() * libbalsa/libbalsa-progress.[ch]: heavy re-factoring of the progress dialogue, including a fully thread-safe interface, simplified access functions, and a new activity mode * libbalsa/mailbox_pop3.c, libbalsa/send.[ch]: use new progress dialogue interface, pass option to disable send progress dialogue * src/balsa-app.[ch]: define and initialise enable progress dialogue settings, use changed send function signature * src/balsa-message.c, src/balsa-mime-widget-message.c, src/balsa-mime-widget-vcalendar.c, src/sendmsg-window.c: use changed send function signature * src/main-window.[ch]: implement multi-threaded POP3 retrieval, remove old progress implementation, use changed send function signature, replace two-state enum by bool * src/main.c: remove old progress implementation stuff * src/pref-manager.c: replace progress dialogue settings by two new bool values and related check boxes * src/save-restore.c: save/restore new progress dialogue bool values * src/threads.h: completely remove the file 2018-01-04 Peter Bloomfield Fix a use-after-free bug * libbalsa/mailbox.c (mbox_model_get_value): get the date format string indirectly through balsa_app.date_string. * libbalsa/mailbox.h: declare libbalsa_mailbox_date_format as gchar **. * src/main.c (real_main): initialize it here * src/save-restore.c (config_global_load): ...not here. 2017-12-11 Peter Bloomfield Avoid possible repeated dynamic cast * src/main-window.c (balsa_window_setup_progress): cast the result of g_object_ref() instead of its argument. 2017-12-10 Peter Bloomfield Revise configuration of enchant spell-checking lib Version 2.1.3 of enchant is parallel-installable with version 1.6, so we first check for enchant-2. If that fails, check for enchant; we want version <= 1.6.0, to avoid issues with 1.6.1. * configure.ac: do it. * meson.build: ditto. 2017-12-08 Peter Bloomfield In glib-2.56, g_object_ref() propagates the type from its argument to its return type, which can raise incompatible-pointer-type warnings; previously it returned a gpointer, which could conceal a coding error. * libbalsa/send.c (send_message_info_new): do not cast arguments to GObject. * src/main-window.c (balsa_window_setup_progress): cast argument window->progress_bar to GtkProgressBar. 2017-12-03 Peter Bloomfield Remove a webkitgtk workaround * src/main.c (main): do not set the WEBKIT_DISABLE_COMPOSITING_MODE environment variable to "1"--it doesn't seem to be needed any more. 2017-12-03 Albrecht Dreß Fix documentation * README: remove description of two configure options (--with-gpg-app, --enable-smime) that have gone away. 2017-12-02 Albrecht Dreß Expand lists in address book window * src/ab-window.c (balsa_ab_window_init): use GtkWidget's hexpand and vexpand functions to properly expand the address lists in the address book window when the dialogue is enlarged. 2017-11-26 Peter Bloomfield Do not crash if no spell-checker dictionaries are found * src/sendmsg-window.c (create_text_area): do not set up spell checker if no dictionary is found; (create_lang_menu): return value is now the current locale; first check whether any dictionaries can be found, and return NULL if none; (set_locale): check whether spell-checking is disabled; (sendmsg_window_new): set up language menu early, so that we can find out whether any dictionaries are found. 2017-11-16 Peter Bloomfield * src/toolbar-prefs.c (tp_store_set): map the pixmap id. 2017-11-08 Peter Bloomfield Fix some icon issues * images/meson.build: remove pointless comment. * meson.build: install desktop icon. 2017-11-08 Peter Bloomfield Install appstream metadata to non-deprecated location Fixes bgo 790076, thanks to Jeremy Bicha * Makefile.am: install balsa.appdata.xml in $(datarootdir)/metainfo. * meson.build: ditto. 2017-11-05 Peter Bloomfield Old glib-genmarshal has no --output option Thanks to Jack for the report * libbalsa/imap/meson.build: use the 'capture' option of customtarget, because the old glib-genmarshal has no --output option. * libbalsa/meson.build: ditto. 2017-09-30 Peter Bloomfield Remove unused make_gradient function, and build with quote-color.[ch] only if spell-checker == internal * src/Makefile.am: move quote-color.[ch] to balsa_spell_extra[,_dist] * src/meson.build: move quote-color.[ch] to balsa_spell_extra * src/quote-color.c: remove unused make_gradient function. * src/quote-color.h: ditto. 2017-09-28 Peter Bloomfield * libbalsa/imap/meson.build: fix prefix in marshal files. * libbalsa/meson.build: ditto. 2017-09-28 Peter Bloomfield * libbalsa/imap/meson.build: fix basename of marshal files. * libbalsa/meson.build: ditto. 2017-09-27 Peter Bloomfield * meson.build: .split() strings returned by custom config commands. 2017-09-26 Peter Bloomfield Use gnome.genmarshal if glib is new enough * meson.build: check whether glib version >= 2.53.4. * libbalsa/imap/meson.build: use gnome.genmarshal if glib is new enough; otherwise, use glib-genmarshal directly instead of in a sh command. * libbalsa/meson.build: ditto. 2017-09-26 Peter Bloomfield Use --output option of glib-genmarshal * libbalsa/imap/meson.build: * libbalsa/meson.build: 2017-09-25 Peter Bloomfield Use include_directories instead of explicit -I… * libbalsa/imap/meson.build: * libbalsa/meson.build: * libinit_balsa/meson.build: * libnetclient/meson.build: * libnetclient/test/meson.build: * meson.build: * src/meson.build: 2017-09-25 Peter Bloomfield * src/filter-run-dialog.c: include filter-funcs.h instead of libbalsa/filter-funcs.h, same as elsewhere. 2017-09-23 Peter Bloomfield * src/balsa-app.c (balsa_find_iter_by_data): we no longer ever define BALSA_DEBUG_THREADS. 2017-09-23 Peter Bloomfield Remove 'debug-threads' option * meson.build: do not use it. * meson_options.txt: do not define it. 2017-09-23 Albrecht Dreß Remove deprecated gdk_threads_* stuff In an attempt to clean up the code and to simplify the configure file, this patch: * removes gdk_threads_(enter|leave) calls from the code, * removes the related “--enable-debug-threads” configure option and * replaces the calls to gdk_threads_add_idle() by g_idle_add(). * configure.ac: * libbalsa/address-view.c (lbav_ensure_blank_line): * libbalsa/identity.c (sd_response_ok): * libbalsa/information.c (libbalsa_information_idle_handler): * libbalsa/libbalsa-gpgme-cb.c (get_passphrase_idle): * libbalsa/libbalsa.c (ask_idle), (libbalsa_ask): * libbalsa/libbalsa.h: * libbalsa/mailbox.c (libbalsa_mailbox_close), (libbalsa_mailbox_msgno_inserted), (libbalsa_mailbox_msgno_filt_in), (libbalsa_mailbox_msgno_removed), (libbalsa_mailbox_msgno_filt_out), (lbm_set_threading), (mbox_set_sort_column_id), (libbalsa_mailbox_unlink_and_prepend), (lbm_set_msg_tree), (libbalsa_mailbox_set_msg_tree): * libbalsa/mailbox_imap.c (idle_unread_update_cb), (imap_exists_idle): * libbalsa/mailbox_local.c (lbm_local_restore_tree), (lbml_load_messages_idle_cb), (libbalsa_mailbox_local_set_threading): * libbalsa/send.c: * libinit_balsa/assistant_init.c (balsa_init_begin): * src/balsa-app.c (ask_passwd_idle), (balsa_open_mailbox_list), (balsa_find_mailbox), (balsa_find_dir): * src/balsa-index.c (bndx_destroy), (bndx_mailbox_row_inserted_idle), (balsa_index_load_mailbox_node), (balsa_index_expunge): * src/balsa-mblist.c (bmbl_set_property_node_style), (balsa_mblist_close_lru_peer_mbx), (bmbl_sort_idle), (balsa_mblist_mailbox_node_append): * src/balsa-mime-widget-image.c (img_check_size): * src/balsa-mime-widget-text.c (statusbar_pop): * src/balsa-mime-widget.c (resize_idle): * src/information-dialog.c (status_bar_refresh): * src/mailbox-node.c (bmbn_scan_children_idle): * src/main-window.c (bw_focus_idle), (mail_progress_notify_cb), (bw_idle_replace), (bw_progress_timeout): * src/main.c (initial_open_unread_mailboxes), (initial_open_inbox), (balsa_get_stats), (scan_mailboxes_idle_cb), (periodic_expunge_cb), (balsa_progress_set_fraction), (balsa_progress_set_activity), (real_main), (handle_remote): * src/message-window.c (message_window_idle_handler): * src/pref-manager.c (open_preferences_manager_idle): * src/save-restore.c (config_warning_idle): * src/sendmsg-window.c (edit_with_gnome_check), (sw_autosave_timeout_cb), (sw_grab_focus_to_text): * src/spell-check.c (highlight_idle): 2017-09-22 Peter Bloomfield Drop 'enable-' and 'with-', inherited from autotools, from option names. * libnetclient/meson.build: * libnetclient/test/meson.build: * meson.build: * meson_options.txt: 2017-09-22 Peter Bloomfield * sounds/meson.build: use documented option syntax for msgfmt. 2017-09-21 Peter Bloomfield Replace 'yes'|'no' option values inherited from autotools with 'true'|'false' string values. * libbalsa/meson.build: * meson.build: * meson_options.txt: 2017-09-21 Peter Bloomfield * sounds/meson.build: make an absolute path to the po dir. 2017-09-20 Peter Bloomfield Pass '-lz' link argument as a dependency of libimap instead of through add_global_link_arguments * libbalsa/imap/meson.build: add the dependency. * meson.build: do not use add_global_link_arguments. 2017-09-20 Peter Bloomfield Use 'glib-genmarshal --header --body' to generate marshal.c files, instead of catting a header line to the file * libbalsa/imap/meson.build: * libbalsa/meson.build: 2017-09-20 Peter Bloomfield Do not include internal dependencies in declare_dependency() * libbalsa/imap/meson.build: * libbalsa/meson.build: * libinit_balsa/meson.build: * libnetclient/meson.build: * libnetclient/test/meson.build: * src/meson.build: 2017-09-19 Peter Bloomfield * meson.build: adapt the meson build to reflect the GNOME option changes. * meson_options.txt: ditto. 2017-09-19 Peter Bloomfield Remove obsolete option to build with deprecated GnomeKeyring * configure.ac: do not check for the lib and do not define HAVE_GNOME_KEYRING and friends. * libbalsa/imap-server.c (libbalsa_imap_server_new_from_config): do not use it. * libbalsa/server.c (libbalsa_server_load_config), (libbalsa_server_save_config): ditto. * libbalsa/server.h: ditto. * src/balsa-app.c (ask_password_real): ditto. * src/folder-conf.c (folder_conf_imap_node): ditto. * src/mailbox-conf.c (create_imap_mailbox_dialog): ditto. 2017-09-19 Peter Bloomfield HAVE_GNOME is redundant * configure.ac: do not define it. * libbalsa/filter-file.c (libbalsa_condition_new_2_0): do not refer to it. * src/toolbar-factory.c (balsa_toolbar_model_finalize), (tm_gsettings_change_cb), (balsa_toolbar_model_new), (tm_default_style): use GSettings without checking it. 2017-09-14 Peter Bloomfield Allow installing the help files * meson.build: * src/meson.build: 2017-09-13 Peter Bloomfield Meson uses msgfmt rather than intltool-merge, so we do not use underscore prefixes to mark strings for translation. * balsa-mailto-handler.desktop.meson: new file * balsa.desktop.meson: ditto * sounds/balsa.soundlist.meson: ditto 2017-09-13 Peter Bloomfield * src/meson.build: make balsa and balsa_ab installable. 2017-09-13 Peter Bloomfield * meson.build: fix install directory. * ui/meson.build: ditto. 2017-08-29 Peter Bloomfield * libbalsa/misc.c (libbalsa_get_domainname): use utsname.domainname if it is available. 2017-08-29 Peter Bloomfield * libbalsa/libbalsa.c (libbalsa_init): drop unused call to uname. 2017-08-22 Tony Nelson Fix https://bugzilla.redhat.com/show_bug.cgi?id=1483354, balsa message window Queue toolbar button sends immediately * src/sendmsg-window.c: respect balsa_app.always_queue_sent_mail. 2017-08-20 Peter Bloomfield Do not crash if DSN header is absent Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1483355 * libbalsa/send.c (lbs_process_queue_msg): check for missing X-Balsa-DSN header, and do not pass NULL to atoi. 2017-08-11 Peter Bloomfield * libbalsa/imap/imap-handle.c (idle_start): assert that the handle is not NULL, to avoid the appearance of dereferencing a NULL pointer. 2017-08-10 Albrecht Dreß Crypto-related (mostly) fixes and improvements * libbalsa/gmime-multipart-crypt.c: do not qp-encode 7-bit parts for encryption * libbalsa/identity.[ch]: implement separate forced signing key id's for gpg and s/mime including selection from the key list; clarify option text * libbalsa/libbalsa-gpgme-cb.c: simplify key list, show key details on double-click * libbalsa/libbalsa-gpgme-keys.[ch]: add functions for exporting and importing ascii-armoured keys; re-factor import result evaluation * libbalsa/libbalsa-gpgme-widgets.c: extend subkey details * libbalsa/libbalsa-gpgme.[ch]: fix context creation for s/mime; add helpers for configuring the gpgme context's home folder, for exporting a key to ASCII and for identifying the proper key id of a secret key; fix confusing comment * libbalsa/message.[ch]: use a reference to the sending identity instead of copying the key id * libbalsa/misc.c: re-factor deleting a folder and creating a temp folder (re-sent from last week's patch) * libbalsa/rfc3156.c: fix mem leak when encrypting a message (re-sent from last week's patch) * libbalsa/send.c: add helper for creating a gpg public key attachment and attach the key on request; fix mem leak in encryption * libbalsa/smtp-server.c: remove misleading/confusing comment (re-sent from last week's patch) * src/balsa-mime-widget-crypto.[ch]: implement display of application/pgp-keys parts and the import of the keys within them * src/balsa-mime-widget.c: call handler for application/pgp-keys parts * src/information-dialog.c: add missing dialogue flags * src/sendmsg-window.[ch], ui/sendmsg-window.ui: add user interface for attaching the GnuPG public key 2017-08-05 Peter Bloomfield * libbalsa/imap/imap-tls.c (imap_create_ssl): unlock global_tls_lock and print the SSL error stack before returning. 2017-08-05 Zhouyang Jia * libbalsa/imap/imap-tls.c (imap_create_ssl): check for NULL value from SSL_CTX_new. 2017-08-03 Peter Bloomfield Save and restore the spell checking language when built with the internal checker * src/balsa-app.h: include the spell_check_lang member in all builds. * src/save-restore.c (config_global_load), (config_save): save and restore it in all builds. * src/sendmsg-window.c (create_lang_menu), (lang_set_cb): use it in all builds. 2017-07-17 Peter Bloomfield * libbalsa/libbalsa-gpgme.c (get_key_from_name): do not dereference a NULL pointer. 2017-07-17 Peter Bloomfield Avoid some whining from the clang static analyzer * libbalsa/libbalsa-gpgme-keys.c (gpgme_import_key): value stored to 'gpgme_err' is never read. * libbalsa/libbalsa-gpgme-widgets.c (create_subkey_widget): value stored to 'subkey_row' is never read. 2017-07-17 Peter Bloomfield * src/balsa-mime-widget-message.c (foreach_label): the only children that have a "populate-popup" signal are GtkLabels. 2017-07-16 Peter Bloomfield * libbalsa/server.c (libbalsa_server_load_config): dereference server->cert_passphrase. 2017-07-15 Peter Bloomfield Do not use local variables that shadow other variables * libbalsa/address-book-text.c (lbab_text_load_file): * libbalsa/address-view.c (lbav_set_text): * libbalsa/gmime-part-rfc2440.c (g_mime_part_rfc2440_verify), (g_mime_part_rfc2440_decrypt): * libbalsa/imap/imap-tls.c (imap_check_server_identity): * libbalsa/libbalsa-conf.c (lbc_init): * libbalsa/libbalsa.c (libbalsa_is_cert_known): * libbalsa/mailbox.c (libbalsa_mailbox_add_messages): * libbalsa/mailbox_imap.c (imap_expunge_cb), (internet_address_new_list_from_imap_address), (libbalsa_mailbox_imap_add_messages), (icm_restore_from_cache): * libbalsa/mailbox_local.c (libbalsa_mailbox_local_prepare_threading): * libbalsa/mailbox_mh.c (libbalsa_mailbox_mh_get_message_stream), (libbalsa_mailbox_mh_check), (libbalsa_mailbox_mh_sync), (libbalsa_mailbox_mh_fetch_message_structure), (lbm_mh_add_message): * libbalsa/mime.c (libbalsa_text_to_html): * libbalsa/send.c (libbalsa_message_create_mime_message): * src/balsa-mblist.c (bmbl_select_mailbox): * src/balsa-message.c (balsa_part_info_free): * src/filter-run-dialog.c (filters_run_dialog): * src/main-window.c: * src/save-restore.c (config_global_load): * src/sendmsg-window.c (sw_edit_activated), (update_bsmsg_identity), (scan_bodies), (create_lang_menu), (send_message_handler), (sendmsg_window_new_from_list), (sendmsg_window_continue): 2017-07-15 Peter Bloomfield * src/balsa-app.c (balsa_find_dir): put braces around empty "if" block. 2017-07-15 Peter Bloomfield * libbalsa/address.c (libbalsa_address_get_edit_widget): do not use old style declaration. 2017-07-15 Albrecht Dreß * libbalsa/libbalsa-progress.c (revealer_destroy_notify), (libbalsa_progress_dialog_update), (remove_progress_widget): save a time-out id and remove the source if the progress dialog is closed before the time-out expires. 2017-07-02 Albrecht Dreß Gpgme-related improvements * libbalsa/libbalsa-gpgme-keys.[ch]: (new) implement key listing and key server operations * libbalsa/libbalsa-gpgme-widgets.[ch]: (new) implement key widget and dialogue * configure.ac: drop otions "--with-gpg-app" and "--enable-smime" * libbalsa/Makefile.am: remove option for building without s/mime support * libbalsa/gmime-multipart-crypt.c, libbalsa/identity.c, libbalsa/send.c, src/balsa-print-object.c, src/sendmsg-window.c: remove conditionals for s/mime support * libbalsa/libbalsa-gpgme-cb.[ch]: use new key dialogue, fix prototype indent * libbalsa/libbalsa-gpgme.[ch]: export functions for setting a gpgme error and creating a context, do not set gpg application, remove conditionals for s/mime support, fix loading a key for a name or fingerprint, use new key listing function * libbalsa/rfc3156.[ch}: remove conditionals for s/mime support, use convenience functions exported by libbalsa-gpgme.c, export new function creating a short signature status, remove functions talking to the keyserver through gpg directly, use GLib functions to check to the trust db update lock, check for public key availibility by using the new key list function * src/balsa-mime-widget-crypto.c: use new key widget, drop GPG-related conditionals 2017-06-30 Peter Bloomfield Add assertions to remove some clang-static-analyzer false positives * libbalsa/imap-server.c (lb_imap_server_info_free): assert that info is non-NULL. * libbalsa/mailbox_imap.c (imap_expunge_cb): assert that msg_info is non-NULL; (get_struct_from_cache): assert that message->headers is non-NULL. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_set_path): assert that klass is non-NULL. 2017-06-28 Peter Bloomfield Assert that a child widget is non-NULL * src/balsa-mime-widget-message.c (foreach_label): assert that the widget is non-NULL. 2017-06-28 Peter Bloomfield Assert that the BalsaWindow is not NULL * src/main-window.c (bw_action_set_enabled): assert that the BalsaWindow is not NULL. 2017-06-28 Peter Bloomfield Handle GError pointer more carefully * libbalsa/body.c (libbalsa_message_body_set_text_rfc822headers): do not create a GError and then ignore it; (libbalsa_message_body_get_stream): allow NULL GError pointer, and take more care in setting errors when it is non-NULL. 2017-06-28 Peter Bloomfield Assert that a node is not NULL * libbalsa/mailbox.c (lbm_next): assert that node is not NULL before testing whether it is the root node 2017-06-28 Peter Bloomfield Check for NULL pointer * libbalsa/mailbox.c (lbm_sort): check for NULL prev. 2017-06-28 Peter Bloomfield Handle broken pipe and other errors before writing to pipe * src/balsa-index.c (pipe_in_watch): handle G_IO_HUP or G_IO_ERR and return, before writing to the pipe. 2017-06-26 Peter Bloomfield Remove dead assignment * libbalsa/rfc6350.c (rfc6350_eval_line): 2017-06-26 Peter Bloomfield Assert that getpwuid returns a valid passwd structure * libbalsa/rfc3156.c (gpg_updates_trustdb): Assert that getpwuid returns a valid passwd structure. 2017-06-26 Peter Bloomfield Assert that a mailbox is either IMAP or local * src/main-window.c (bw_mailbox_check): assert that a mailbox is either IMAP or local. 2017-06-25 Peter Bloomfield Do not store label values that are never read * src/folder-conf.c (folder_conf_imap_sub_node): 2017-06-25 Peter Bloomfield Remove unused initializer * src/toolbar-prefs.c (tp_page_swap_rows): 2017-06-25 Peter Bloomfield Decode all RFC-2047-encoded headers * libbalsa/message.c (prepend_header_misc): decode header value; (libbalsa_message_user_hdrs_from_gmime): streamline code. 2017-06-19 Peter Bloomfield Possible fix for Red Hat Bugzilla #1462546, reported by jamesbdonovan@rambler.ru * src/balsa-mime-widget-text.c (statusbar_pop): check that the main window and the status bar are still valid. 2017-06-18 Albrecht Dreß Implement automatic sending in background * libbalsa/libbalsa-progress.[ch]: new files, implementing the progress dialogue. Its update operation shall be called using idle callbacks. For the time being, it is used for SMTP only, but it might also be useful for receiving messages. * libbalsa/Makefile.am: add the aforementioned new files * libbalsa/send.c: implement the core of the patch, and do some re-factoring to make the source better readable. Add functions for the auto-send timer stuff. Remove the old send message dialogue implementation. * libbalsa/send.h: export functions for controlling the auto-send feature, and remove the old progress dialogue stuff * libbalsa/smtp-server.[ch]: extend the smtp server class by a lock flag, implemented as atomic variable * src/balsa-app.c: implement auto-send callback, and initialise the feature * src/balsa-app.h: add auto-send application variables * src/main-window.c: remove old progress dialogue callback * src/main.c, src/threads.h: remove old progress dialogue globals and initialisation * src/pref-manager.c: configuration of the auto-send feature * src/save-restore.c: load and save the configuration of the auto-send feature 2017-06-16 Albrecht Dreß Build with Gtk version < 3.22 * src/toolbar-factory.c (tm_popup_context_menu_cb): GdkEvent has no member "time"; use gtk_get_current_event_time. 2017-06-15 Peter Bloomfield Use gdk_event_triggers_context_menu instead of checking event type and button * src/balsa-index.c (bndx_button_event_press_cb): * src/balsa-mblist.c (bmbl_button_press_cb): * src/balsa-message.c (tree_button_press_cb): * src/balsa-mime-widget-image.c (balsa_image_button_press_cb): * src/balsa-mime-widget-text.c (balsa_gtk_html_button_press_cb): * src/sendmsg-window.c (attachment_button_press_cb): 2017-06-15 Peter Bloomfield Simplify popping up a toolbar's context menu, and make icons visible after changing style * src/toolbar-factory.c (tm_populate): set the toolbar style before showing-all; (tm_changed_cb): tm_set_style is redundant and has been removed; (tm_popup_context_menu_cb): new callback for "popup-context-menu" signal; (balsa_toolbar_new): no need to connect to "realized" signal; connect to GtkToolbar's "popup-context-menu" signal instead of GtkWidget's "button-press-event" and "popup-menu" signals. 2017-06-14 Albrecht Dreß Use John Jack's new icons for "mail-queue" and "balsa-send-queued" actions * images/16x16/Makefile.am: add the file names. * images/24x24/Makefile.am: ditto. * src/balsa-icons.c (balsa_register_pixmaps): use them. * src/balsa-icons.h: ditto. * src/main-window.c: ditto. * src/sendmsg-window.c: ditto. * src/toolbar-factory.c: ditto. 2017-06-13 Peter Bloomfield * src/filter-run-dialog.c (balsa_filter_run_dialog_new): build with gtk version < 3.12. 2017-06-12 Peter Bloomfield Use a wrapper for an environment variable * src/filter-run-dialog.c (balsa_filter_run_dialog_new): use libbalsa_dialog_flags() instead of directly checking the BALSA_DIALOG_HEADERBAR environment variable. 2017-06-01 Peter Bloomfield Remove obsolete reference in configure summary * configure.ac: $install_mimeicons was removed in commit 4400b65d2325e0446cbc45bcf0c250476c8caea7. 2017-06-01 Peter Bloomfield Recent pref-manager changes break display * src/pref-manager.c (open_preferences_manager): put a horizontal box in the dialog's content area, instead of making the content area horizontal. 2017-05-31 Peter Bloomfield Code cleanup * src/pref-manager.c (option_menu_cb), (pgdown_modified_cb): simplify callback placement. 2017-05-31 Peter Bloomfield Port preferences window from GtkNotebook to GtkStack * src/pref-manager.c (pm_combo_box_info_free), (pm_combo_box_new), (pm_combo_box_set_level), (pm_combo_box_get_level), (pm_selection_changed), (destroy_pref_window_cb), (update_view_defaults), (check_font_button), (apply_prefs), (set_prefs), (update_address_books), (add_other_server), (add_button_to_box), (add_show_menu), (create_pref_option_menu), (create_layout_types_menu), (create_action_after_move_menu), (balsa_help_pbox_display), (create_information_message_menu), (create_mdn_reply_menu), (update_smtp_servers), (pm_grid_new), (pm_grid_attach), (pm_group_label), (pm_grid_attach_check), (pm_grid_attach_label), (pm_grid_attach_pref_menu), (pm_grid_attach_entry), (pm_grid_attach_color_box), (font_button_check_font_size), (pm_grid_attach_font_button), (pm_grid_attach_information_menu), (properties_modified_cb), (server_edit_cb), (smtp_server_update), (smtp_server_add_cb), (smtp_server_edit_cb), (smtp_server_del_cb), (smtp_server_changed), (address_book_change), (address_book_edit_cb), (address_book_set_default_cb), (add_menu_cb), (address_book_delete_cb), (pop3_add_cb), (server_add_menu_widget), (server_del_cb), (timer_modified_cb), (browse_modified_cb), (mark_quoted_modified_cb), (wrap_modified_cb), (pgdown_modified_cb), (option_menu_cb), (mailbox_close_timer_modified_cb), (filter_modified_cb), (expunge_on_close_cb), (expunge_auto_cb), (imap_toggled_cb), (convert_8bit_cb), (use_system_fonts_cb), (font_modified_cb), (default_font_size_cb), (response_cb), (pm_grid_add_main_window_group), (pm_grid_add_threading_group), (pm_grid_add_progress_group), (pm_append_page), (pm_mailserver_page), (pm_incoming_page), (pm_outgoing_page), (pm_display_page), (pm_threading_page), (pm_message_page), (pm_colors_page), (pm_format_page), (pm_status_messages_page), (create_address_book_page), (pm_spelling_page), (pm_startup_page), (pm_misc_page), (create_mail_options_section), (create_display_section), (open_preferences_manager_idle), (open_preferences_manager), (update_mail_servers): replace mutiple notebooks by a single stack; refactor code into groups of options, pages of one or more groups, and sections where multiple pages are related. 2017-05-30 Peter Bloomfield Port preferences window to GtkGrid * src/pref-manager.c (add_button_to_box), (pm_grid_new), (pm_grid_attach), (pm_group_label), (pm_grid_attach_check), (pm_grid_attach_label), (pm_grid_attach_pref_menu), (pm_grid_attach_entry), (pm_grid_attach_color_box), (font_button_check_font_size), (pm_grid_attach_font_button), (pm_grid_attach_information_menu), (pm_grid_add_remote_mailbox_servers_group), (pm_grid_add_local_mail_group), (pm_grid_add_outgoing_mail_group), (mailserver_subpage), (pm_grid_add_checking_group), (pm_grid_add_mdn_group), (incoming_subpage), (pm_grid_add_word_wrap_group), (pm_grid_add_other_options_group), (outgoing_subpage), (create_mail_options_page), (pm_grid_add_main_window_group), (pm_grid_add_message_window_group), (display_subpage), (pm_grid_add_threading_group), (threading_subpage), (pm_grid_add_preview_font_group), (pm_grid_add_quoted_group), (pm_grid_add_alternative_group), (message_subpage), (pm_grid_add_message_colors_group), (pm_grid_add_link_color_group), (colors_subpage), (pm_grid_add_display_formats_group), (pm_grid_add_broken_8bit_codeset_group), (format_subpage), (pm_grid_add_information_messages_group), (pm_grid_add_progress_group), (status_messages_subpage), (create_display_page), (pm_grid_add_address_books_group), (create_address_book_page), (pm_grid_add_misc_spelling_group), (create_spelling_page), (pm_grid_add_startup_options_group), (pm_grid_add_folder_scanning_group), (create_startup_page), (pm_grid_add_misc_group), (pm_grid_add_deleting_messages_group), (create_misc_page): make each page a single GtkGrid and use fewer nested GtkBoxes. 2017-05-28 Peter Bloomfield Use widget alignment instead of label alignment * src/pref-manager.c (attach_entry_full), (attach_label), (checking_group), (quoted_group), (mdn_group), (main_window_group), (add_pref_menu), (deleting_messages_group), (folder_scanning_group), (pm_group_new): scrap set_align, and use gtk_widget_set_[hv]align instead of gtk_label_set_[xy]align or deprecated gtk_misc_set_alignment. 2017-05-28 Peter Bloomfield Use widget alignment instead of label alignment * src/balsa-mime-widget-message.c (add_header_gchar): use gtk_widget_set_halign instead of gtk_label_set_xalign or deprecated gtk_misc_set_alignment. 2017-05-28 Albrecht Dreß Adjust SMTP timeouts * libnetclient/net-client-smtp.c (net_client_smtp_connect), (net_client_smtp_send_msg): adjust all SMTP client transaction timeouts to the minimum values (which are *very* long imho!) required by RFC 5321, sect. 4.5.3.2.1. - 4.5.3.2.6. 2017-05-27 Peter Bloomfield Increase a timeout interval * src/main.c (real_main): increase the fix-panes timeout again, from 700 to 800 msec. 2017-05-27 Peter Bloomfield Remove unused code * libbalsa/misc.c: libbalsa_guess_pop_server and libbalsa_guess_ldif_file are not used. * libbalsa/misc.h: do not export libbalsa_guess_ldif_file. * libbalsa/libbalsa.h: do not export libbalsa_guess_pop_server. 2017-05-27 Peter Bloomfield Clean up file finder code * libbalsa/files.c (balsa_file_finder): remove unused arguments. * libbalsa/files.h: ditto. 2017-05-27 Peter Bloomfield Remove unused code * libinit_balsa/assistant_helper.c: remove balsa_init_get_png, as it is not used. * libinit_balsa/assistant_helper.h: do not export it. 2017-05-27 Peter Bloomfield Use Balsa's main window as parent of a dialog * src/sendmsg-window.c (send_message_handler): use balsa_app.main_window as the parent for the sending progress dialog, to allow the compose window to close before sending is finished. 2017-05-27 Peter Bloomfield After a transient error, leave messages ready to resend * libbalsa/send.c (balsa_send_message_real): clear FLAGGED flag if sending failed because of a transient error, so that the messages can be resent just using send-queued-mail. 2017-05-27 Peter Bloomfield Keep a parent window alive * libbalsa/send.c (lbs_process_queue): object-ref the parent window... (lbs_check_reachable_cb): and unref it. 2017-05-27 Peter Bloomfield Plug leak * libbalsa/libbalsa.c (libbalsa_source_view_new): use the default GtkSourceStyleSchemeManager instead of leaking a new one. 2017-05-26 Peter Bloomfield Plug leak * src/sendmsg-window.c (sendmsg_window_new): free ui_file string. 2017-05-26 Albrecht Dreß Test whether we can reach an SMTP server * libbalsa/send.c: use atomic operations for the sending state; check if the smtp server is reachable before sending; simplify some API's; replace the term "MTA" in user dialogues by "SMTP server" which is more common * libbalsa/send.h: export simplified API * libbalsa/server.c: ignore port in server host string * src/balsa-message.c, src/balsa-mime-widget-message.c, balsa-mime-widget-vcalendar.c, src/main-window.c, src/sendmsg-window.c: use simplified API 2017-05-25 Peter Bloomfield Use is-maximized property instead of window-state-event signal * src/main-window.c (bw_notify_is_maximized_cb), (balsa_window_new): connect to "notify::is-maximized" signal instead of "window-state-event" to avoid irrelevant state changes. * src/main.c (real_main): increase the fix-panes timeout again, from 600 to 700 msec. 2017-05-25 Peter Bloomfield Revert 45b7ce83a56690beb40c37f911f7c61b553d8828, and just increase the timeout from 500 to 600 msec. * src/main-window.c (bw_window_state_event_cb), (balsa_window_new), (balsa_window_fix_paned): revert 45b7ce83a56690beb40c37f911f7c61b553d8828. * src/main.c (real_main): increase the fix-panes timeout from 500 to 600 msec. 2017-05-23 Peter Bloomfield Try to avoid geometry creep * src/main-window.c (balsa_window_new): connect to "notify::is-maximized" instead of "window-state-event"; set the GtkPaned positions in a timeout, to let the window geometry settle down. (bw_notify_is_maximized_cb): new version of bw_window_state_event_cb. (bw_window_new_idle_cb): the timeout handler. (balsa_window_fix_paned): move connecting to "notify::position" to the timeout handler. 2017-05-22 Peter Bloomfield Use the LibBalsaMailbox method to test whether we can reach IMAP mailboxes and POP3 hosts * src/main-window.c (bw_network_changed_cb): add a timeout whenever we get the "network-changed" signal, because the reachability of hosts may have changed even when the network is still "available"; save the timeout source id; (balsa_window_destroy): remove the GSource, if any; (mw_mbox_can_reach_cb): new callback for testing whether we can reach an IMAP mailbox; (mw_mbox_change_connection_status): use the new LibBalsaMailbox method for testing reachability; (bw_change_connection_status_can_reach_cb): new callback for testing whether we can reach a POP3 host; (bw_change_connection_status_idle): use the new LibBalsaMailbox method for testing reachability. * src/main-window.h: New member guint BalsaWindow::network_changed_source_id. 2017-05-22 Peter Bloomfield Test whether a LibBalsaMailbox can be reached by testing its server * libbalsa/mailbox.c (libbalsa_mailbox_class_init), (libbalsa_mailbox_set_background), (libbalsa_mailbox_test_can_reach): LibBalsaMailbox support. * libbalsa/mailbox.h: ditto. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_class_init), (libbalsa_mailbox_local_test_can_reach): LibBalsaMailboxLocal support. * libbalsa/mailbox_remote.c (libbalsa_mailbox_remote_class_init), (libbalsa_mailbox_remote_test_can_reach): LibBalsaMailboxRemote support. 2017-05-22 Peter Bloomfield Needed for previous LibBalsaServer commit * libbalsa/libbalsa.h: typedef the callback for testing whether a server can be reached. 2017-05-22 Peter Bloomfield Implement testing reachability of a server * libbalsa/server.c (libbalsa_server_can_reach_cb), (libbalsa_server_test_can_reach_full), (libbalsa_server_test_can_reach): new methods for testing whether a server's host can be reached over the network; * libbalsa/server.h: declare them. 2017-05-14 Peter Bloomfield * libbalsa/imap/imap-handle.c (idle_start): clear ImapMboxHandle::enable_idle_id before returning FALSE. 2017-05-04 Peter Bloomfield * libbalsa/mailbox_mbox.c (parse_mailbox): try to recover when the GMimeParser returns a NULL GMimeMessage. 2017-05-04 Peter Bloomfield * libbalsa/mailbox_pop3.c (message_cb): reset the GMimeStream before passing it to libbalsa_mailbox_add_message. 2017-05-02 Peter Bloomfield Do not dereference NULL GError pointer * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_check): check for err == NULL. 2017-05-01 Peter Bloomfield Assistant improvements * libbalsa/libbalsa.c (libbalsa_guess_email_address): read /etc/mailname using glib, and remove everything starting with the 1st newline. * libinit_balsa/assistant_page_user.[ch]: replace the "SSL" checkbox by a combo asking for the requested security mode. 2017-04-27 Peter Bloomfield Restore support for $(DESTDIR) installations * images/Makefile.am: 2017-04-27 Peter Bloomfield Restore updating the icon cache, and remove a redundant action * configure.ac: find the path to gtk-update-icon-cache. * images/Makefile.am: re-enable updating the cache. * libbalsa/files.c (libbalsa_icon_finder): do not redundantly append BALSA_DATA_PREFIX "/hicolor/48x48/mimetypes" to the default icon theme search path. 2017-04-26 Peter Bloomfield * src/balsa-icons.c: disable debug output, left enabled by mistake. 2017-04-26 Peter Bloomfield Do not define an unused path * configure.ac: do not define BALSA_STD_PREFIX, it is not used. * libbalsa/files.c: do not put it in a search path. * src/balsa-icons.c (balsa_register_pixmaps), (balsa_register_pixbufs): do not append it to the icon-theme-search-path. 2017-04-24 Peter Bloomfield * libbalsa/files.c (libbalsa_icon_finder): more carefully check names of extra mime icons. 2017-04-24 Peter Bloomfield * configure.ac: pass install directories on the compile command line instead of in config.h; * libbalsa/files.c: use the directories. 2017-04-23 Peter Bloomfield * configure.ac: fix a warning about changing the permissions of a generated file * libbalsa/imap/Makefile.am: fix building outside the source directory. 2017-04-22 Peter Bloomfield Fix access to local POP3 server * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_startup): allow all auth methods, in order to allow connections to localhost; * libnetclient/net-client-pop.c (net_client_pop_get_capa): cosmetics 2017-04-20 Peter Bloomfield * configure.ac: replace --with-spell-checker=no with --with-spell-checker=internal. 2017-04-20 Peter Bloomfield Fix a bug in the SMTP code, and generally clean up; https://mail.gnome.org/archives/balsa-list/2017-April/msg00040.html * libnetclient/net-client-smtp.c (net_client_smtp_send_msg): do not set SMTP DSN parameters for a server not supporting it; (net_client_smtp_finalise): fix long delay when sending a message fails in the callback; * libnetclient/test/inetsim.conf: * libnetclient/test/start-test-env.sh.in: * libnetclient/test/tests.c (msg_data_cb), (test_smtp): improve SMTP unit tests; improve the test environment script as to place the results readable in the cwd. 2017-04-18 Peter Bloomfield Remove unused code * libbalsa/misc.c: remove unused function libbalsa_truncate_string; * libbalsa/misc.h: remove obsolete declarations. 2017-04-17 Peter Bloomfield Clean up identity code * libbalsa/identity.c (libbalsa_identity_get_signature): use g_spawn_async instead of popen and libbalsa_readfile_nostat. * libbalsa/misc.c: libbalsa_readfile_nostat is no longer needed. * libbalsa/misc.h: ditto. 2017-04-15 Peter Bloomfield Fix some more conversion specifier mismatches * libnetclient/net-client-pop.c (net_client_pop_list): cast gsize to unsigned long, to print portably with %lu. * libnetclient/net-client.c (net_client_read_line): use G_GSIZE_FORMAT to scan portably a POP3 message list. 2017-04-14 Peter Bloomfield * libbalsa/misc.h: define libbalsa_urlencode and libbalsa_decode to use g_uri_escape_string and g_uri_unescape_string, instead of declaring the custom functions; * libbalsa/misc.c: remove the custom functions. 2017-04-14 Peter Bloomfield * libbalsa/mailbox_pop3.c (notify_progress), (libbalsa_mailbox_pop3_check): cast gsize to unsigned long, to print portably with %lu. 2017-04-13 Peter Bloomfield * libbalsa/address-book-ldif.c (string_to_value_spec), (value_spec_to_string): remove custom base64 encode and decode stuff. 2017-04-12 Peter Bloomfield * libbalsa/libbalsa-vfs.c (libbalsa_vfs_create_stream): retain ownership of priv->gio_gfile. 2017-04-12 Peter Bloomfield * libbalsa/imap/auth-gssapi.c (ag_get_token), (ag_parse_request), (ag_negotiate_parameters): use existing buffers for base-64 conversions. 2017-04-09 Albrecht Dreß * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_check): do not unref NULL NetClientPop object. 2017-04-09 Albrecht Dreß * libnetclient/net-client.c (net_client_new): do not return pointer to finalized object. 2017-04-08 Peter Bloomfield Streamline code * src/spell-check.c: remove redundant gboolean quoted_rex_compiled; (balsa_spell_check_start): do not use it; (next_word): ditto; (balsa_spell_check_destroy): ditto; also use g_clear_pointer. 2017-04-07 Peter Bloomfield * src/balsa-message.c (select_part): reset adjustments only when displaying a real message part. 2017-04-07 Albrecht Dreß Do not emit a critical warning * src/balsa-mime-widget.c (balsa_mime_widget_new_unknown): Do not emit a critical warning on the console, e.g. when I select an encrypted message, but cancel the decryption: 2017-04-02 Peter Bloomfield Deprecation cleanup * libbalsa/gmime-filter-header.c (g_mime_filter_header_new): use g_object_new instead of g_object_newv, because the latter is deprecated in glib-2.54. 2017-03-15 Peter Bloomfield Use GMime's native GIO Stream module * libbalsa/gmime-stream-gio.h: removed. * libbalsa/libbalsa-vfs.c: do not include it. * libbalsa/gmime-stream-gio.c: removed. * libbalsa/Makefile.am: remove references to them. 2017-03-13 Peter Bloomfield * libbalsa/identity.c (libbalsa_identity_combo_box): compare active name with the identity name, not the parenthesized version 2017-03-10 Peter Bloomfield * libbalsa/mailbox_local.c (lbml_load_messages_idle_cb): clear load_messages_id even when returning early. 2017-03-10 Peter Bloomfield Lock mailbox while accessing an idle callback id * libbalsa/mailbox.c (lbm_need_threading_idle_cb), (libbalsa_mailbox_msgno_inserted), (libbalsa_mailbox_msgno_removed): lock mailbox while accessing need_threading_idle_id. 2017-03-04 Peter Bloomfield * src/main-window.c (bw_master_position_cb), (bw_slave_position_cb), (bw_size_allocate_cb): remember the new position even if maximized. 2017-03-03 Peter Bloomfield Use dialog buttons more consistently * src/mailbox-conf.c (create_generic_dialog): use GTK_RESPONSE_CANCEL instead of CLOSE (run_mailbox_conf): ditto. 2017-03-01 Peter Bloomfield Use an idle callback to rethread the mailbox display. * libbalsa/mailbox.c (libbalsa_mailbox_finalize): remove an outstanding idle source; (lbm_need_threading_idle_cb): the idle callback; (libbalsa_mailbox_check): schedule the idle callback; (libbalsa_mailbox_msgno_inserted): ditto; (libbalsa_mailbox_msgno_removed): ditto; (libbalsa_mailbox_sync_storage): just signal mailbox changed; (lbm_check_idle): ref the mailbox here... (lbm_queue_check): not here. * libbalsa/mailbox.h: add guint LibBalsaMailbox::need_threading_idle_id; we no longer need LIBBALSA_MAILBOX_UNTHREADED. * libbalsa/mailbox_local.c (lbml_info_setup): LIBBALSA_MAILBOX_UNTHREADED is now irrelevant. 2017-02-21 Peter Bloomfield gtk_show_uri is deprecated in favor of gtk_show_uri_on_window * libbalsa/identity.c (help_ident_cb): fix it. * libbalsa/smtp-server.c (smtp_server_response): fix it, and correct the help file URI. * src/address-book-config.c (create_local_dialog): fix it, and move the Cancel button to the left; (help_button_cb): fix it. * src/balsa-mime-widget-message.c (extbody_call_url): fix it. * src/balsa-mime-widget-text.c (handle_url): ditto. * src/filter-edit-callbacks.c (condition_dialog_response), (fe_dialog_response): ditto. * src/filter-run-callbacks.c (fr_dialog_response): ditto. * src/folder-conf.c (folder_conf_response): ditto. * src/main-window.c (help_activated), (bw_find_real): ditto. * src/pref-manager.c (balsa_help_pbox_display): ditto. * src/sendmsg-window.c (on_open_url_cb): ditto. * src/toolbar-prefs.c (tp_dialog_response_cb): ditto. 2017-02-21 Peter Bloomfield * libbalsa/imap/imap-tls.c: fix OPENSSL_VERSION_NUMBER check 2017-02-20 Peter Bloomfield Give the user the option to ignore PIPELINING capability in a POP3 server * libbalsa/imap/pop3.c (pop_connect): respect PopHandle::enable_pipe. * libbalsa/mailbox_pop3.c (libbalsa_mailbox_pop3_check): set the option in PopHandle; (libbalsa_mailbox_pop3_save_config): save it; (libbalsa_mailbox_pop3_load_config): load it; * libbalsa/mailbox_pop3.h: new member LibBalsaMailboxPop3::enable_pipe; * src/mailbox-conf.c (mailbox_conf_set_values), (update_pop_mailbox), (create_pop_mailbox_dialog): new check-box in the UI. 2017-02-19 Peter Bloomfield SMTP extensions: TLS client cert; rework config dialog * README: make it not quite so out of date. * libbalsa/send.c (get_auth), (get_cert_pass), (lbs_process_queue): use client cert if required. * libbalsa/smtp-server.c (libbalsa_smtp_server_finalize), (libbalsa_smtp_server_new_from_config), (libbalsa_smtp_server_save_config), (libbalsa_smtp_server_require_client_cert), (libbalsa_smtp_server_get_cert_file), (smtp_server_response), (smtp_server_changed), (libbalsa_smtp_server_dialog): add cert-related entries to LibBalsaSmtpServer, and set and use them. * libbalsa/smtp-server.h: add cert-related API. 2017-02-19 Albrecht Dreß Make "Select Filters..." dialogue respect the headerbars config * src/filter-run-dialog.c (balsa_filter_run_dialog_new): check the BALSA_DIALOG_HEADERBAR environment variable. 2017-02-19 Albrecht Dreß Fix unsafe permissions for config-private * libbalsa/libbalsa-conf.c (lbc_init), (lbc_lock), (lbc_sync): ensure that permissons on $HOME/.balsa/config-private are 0600 after saving it. 2017-02-08 Peter Bloomfield Do not access a stale pointer * src/main-window.c (balsa_window_destroy): nullify window->preview; (bw_action_set_enabled): check for NULL window->preview; (bw_idle_replace): ditto. 2017-01-24 Peter Bloomfield Fix some conditional compilation code so that uncrustify does not break the build. * src/balsa-message.c (balsa_headers_attachments_popup), (tree_button_press_cb): fix it. * src/balsa-mime-widget-text.c (prepare_url_offsets): ditto. * src/sendmsg-window.c (attachment_button_press_cb), (attachment_popup_cb): ditto. 2017-01-03 Albrecht Dreß Use glib for digest calculations * libbalsa/imap/auth-cram.c (imap_auth_cram): * libbalsa/imap/pop3.c (compute_auth_hash): 2016-12-28 Pawel Salek * libbalsa/imap/imap-tls.c: avoid warnings with openssl-1.1.x 2016-12-20 Peter Bloomfield Get notifications about GtkPaned's position to save the new position, instead of the size-allocate signal for the child. * src/main-window.c (bw_master_position_cb): callback for changes in the paned-master's position; (bw_slave_position_cb): ditto paned-slave; (balsa_window_fix_paned): change signal connections. 2016-12-20 Peter Bloomfield Avoid geometry creep when maximized. * src/main.c (real_main): when initially maximized, delay 500 msec before setting paned positions and connecting to signals. 2016-12-14 Peter Bloomfield Build with gpgme version >= 1.8 * configure.ac: use $gpgmecfg --thread=pthread --libs only for gpgme version < 1.8. 2016-12-10 Pawel Salek * Makefile.am: do not include mkinstalldirs any more * libbalsa/imap/auth-cram.c: * libbalsa/imap/pop3.c: fix regression in CRAM-MD5 code; build against openssl-1.1.0 2016-12-09 Peter Bloomfield Version bump to 2.5.3 * configure.ac: bump the version string to 2.5.3 2016-11-23 Peter Bloomfield Correct alignment of recipient labels. * src/sendmsg-window.h: remove redundant GtkSizeGroup; * src/sendmsg-window.c (create_email_or_string_entry), (create_info_pane), (sw_attachment_list): do not use it. 2016-11-23 Peter Bloomfield * libbalsa/misc.c (libbalsa_font_string_to_css): make new CSS parsing conditional on gtk version 3.22. 2016-11-22 Peter Bloomfield Adapt to new recipient strings * src/sendmsg-window.c (update_bsmsg_identity), (setup_headers_from_message), (setup_headers_from_identity), (set_cc_from_all_recipients), (sendmsg_window_set_field), (bsmsg2message), (check_suggest_encryption): 2016-11-21 Peter Bloomfield Save the correct window geometry * libbalsa/source-viewer.c (lsv_size_allocate_cb): save the window geometry from gtk_window_get_size instead of the GtkAllocation. * src/balsa-mblist.c (bmbl_mru_size_allocate_cb): ditto. * src/message-window.c (size_alloc_cb): ditto. * src/sendmsg-window.c (sw_size_alloc_cb): ditto. * src/main-window.c (bw_window_state_event_cb): simplify the code. 2016-11-20 Peter Bloomfield Disable accelerated compositing in webkit2, to avoid some gdk warnings; see thread at https://lists.webkit.org/pipermail/webkit-gtk/2016-November/002863.html * src/main.c (main): set WEBKIT_DISABLE_COMPOSITING_MODE environment variable. 2016-11-20 Peter Bloomfield Save the main window state more carefully * src/main-window.c (bw_window_state_event_cb): note when the main window is either maximized or fullscreen, and save the information as TRUE or FALSE. 2016-11-20 Peter Bloomfield Save the correct window geometry * src/main-window.c (bw_size_allocate_cb): save the window geometry from gtk_window_get_size instead of the GtkAllocation. 2016-11-19 Peter Bloomfield * libbalsa/misc.c: document libbalsa_font_string_to_css. 2016-11-19 Peter Bloomfield Silence some whining about "Using Pango syntax for the font: style property is deprecated; please use CSS syntax". * libbalsa/misc.c (libbalsa_font_string_to_css): new function. * libbalsa/misc.h: export it. * libbalsa/source-viewer.c (libbalsa_show_message_source): use it. * src/balsa-mime-widget-message.c (add_header_gchar): ditto. * src/balsa-mime-widget-text.c (bm_modify_font_from_string): ditto. * src/sendmsg-window.c (create_email_or_string_entry), (create_text_area): ditto. 2016-11-15 Peter Bloomfield Use Unicode characters for double quotation marks and ellipses. * libbalsa/address-book-gpe.c (libbalsa_address_book_gpe_open_db), (libbalsa_address_book_gpe_load): * libbalsa/address-book-ldap.c (libbalsa_address_book_ldap_load), (libbalsa_address_book_ldap_add_address), (libbalsa_address_book_ldap_remove_address), (libbalsa_address_book_ldap_modify_address): * libbalsa/address-book-text.c (lbab_text_open_temp), (lbab_text_close_temp), (libbalsa_address_book_text_modify_address): * libbalsa/application-helpers.c (libbalsa_window_add_accelerator): * libbalsa/files.c (balsa_file_finder): * libbalsa/html.c (lbh_navigation_policy_decision_requested_cb): * libbalsa/libbalsa-conf.c (lbc_readfile), (lbc_init), (lbc_sync): * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_accept_low_trust_key): * libbalsa/libbalsa-gpgme.c (get_key_from_name): * libbalsa/mailbox.c (get_from_field), (libbalsa_mailbox_new_from_config), (mbox_model_get_value): * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_load_config), (imap_cache_manager_new_from_file): * libbalsa/mailbox_local.c (lbm_local_save_tree), (lbml_subject_gather), (lbm_local_sync_real): * libbalsa/mailbox_maildir.c (lbm_maildir_parse), (maildir_sync_add): * libbalsa/mailbox_mbox.c (lbm_mbox_check_files), (lbm_mbox_stream_seek_to_message), (lbm_mbox_save), (libbalsa_mailbox_mbox_sync): * libbalsa/mailbox_mh.c (libbalsa_mailbox_mh_sync): * libbalsa/message.c (lbmsg_set_header): * libbalsa/misc.c (libbalsa_lock_file): * libbalsa/send.c (ensure_send_progress_dialog): * libbalsa/source-viewer.c (lsv_show_message): * libinit_balsa/assistant_helper.c (balsa_init_create_to_directory): * libinit_balsa/assistant_page_directory.c (unconditional_mailbox), (verify_mailbox_entry): * src/balsa-app.c (check_new_messages_auto_cb), (open_mailbox_by_url): * src/balsa-index.c (bndx_popup_menu_create), (balsa_index_transfer), (pipe_out_watch): * src/balsa-mblist.c (bmbl_mru_menu), (bmbl_mru_combo_box_setup): * src/balsa-message.c (tree_mult_selection_popup), (balsa_message_set), (mpart_content_name), (display_part), (part_create_menu), (create_mdn_reply), (libbalsa_msg_try_decrypt), (libbalsa_msg_try_mp_signed), (libbalsa_msg_part_2440): * src/balsa-mime-widget-message.c (bm_header_extend_popup): * src/balsa-mime-widget-text.c (text_view_url_popup), (text_view_populate_popup), (handle_url), (bmwt_populate_popup_menu), (check_text_encoding): * src/balsa-mime-widget-vcalendar.c (balsa_mime_widget_new_vcalendar): * src/filter-edit-callbacks.c (fe_apply_pressed): * src/filter-edit-dialog.c (build_action_page), (filters_edit_dialog): * src/filter-run-callbacks.c (fr_apply_selected_pressed), (fr_apply_now_pressed), (fr_add_pressed_func): * src/folder-conf.c (folder_conf_imap_sub_node), (folder_conf_delete): * src/mailbox-conf.c (mailbox_conf_delete): * src/mailbox-node.c (check_local_path), (imap_dir_cb), (bmbn_scan_children_idle), (balsa_mailbox_node_get_context_menu), (add_local_mailbox), (handle_imap_path), (check_imap_path), (mark_imap_path): * src/main-window.c (bw_get_action), (quit_activated), (header_change_state), (threading_change_state), (ensure_check_mail_dialog): * src/main.c (check_special_mailboxes), (periodic_expunge_cb): * src/message-window.c (mw_set_enabled), (mw_set_active), (mw_header_change_state): * src/pref-manager.c (broken_8bit_codeset_group), (mdn_group), (deleting_messages_group), (server_add_menu_widget): * src/save-restore.c (config_global_load), (config_defclient_save): * src/sendmsg-window.c (sw_set_charset), (add_attachment), (add_urlref_attachment), (tree_add_quote_body), (scan_bodies), (append_parts), (sendmsg_window_set_field), (sw_gpg_mode_change_state): * src/spell-check.c (check_word): * src/store-address.c (store_address_from_entries): * src/toolbar-factory.c (balsa_toolbar_model_insert_icon), (tm_do_popup_menu): * src/toolbar-prefs.c (create_toolbar_page), (tp_page_refresh_available): 2016-11-09 Albrecht Dreß Support for Osmo address book * libbalsa/address-book-osmo.c, libbalsa/address-book-osmo.h: new files; implement read-only Osmo address book core * libbalsa/rfc6350.c, libbalsa/rfc6350.h: new files; simple RFC 6350 to LibBalsaAddress parser * README: add note about new configure item * configure.ac: make Osmo address book configurable (default disabled) * libbalsa/Makefile.am: add new sources * libbalsa/libbalsa.c: initialise address book type * libbalsa/libbalsa.h: include header * src/address-book-config.c: implement configuration dialogue * src/pref-manager.c: add to pref manager 2016-10-23 Peter Bloomfield Improve pop-up menu positioning. * src/pref-manager.c (remote_mailbox_servers_group): use a common helper to connect to "clicked-up" signal; (address_books_group): ditto; (add_menu_cb): common helper; 2016-10-23 Peter Bloomfield Do not crash after cancelling the add-address-book dialog. * src/address-book-config.c (edit_book_response): do not free the AddressBookConfig; (add_vcard_cb), (add_externq_cb), (add_ldif_cb), (add_ldap_cb), (add_gpe_cb), (add_rubrica_cb): do not remove the weak ref that frees the AddressBookConfig. 2016-10-23 Albrecht Dreß Support GCR to display a certificate widget * configure.ac: new option --with-gcr. * libbalsa/libbalsa.c (ask_cert_real): use gcr certificate API to display the certificate. 2016-10-23 Albrecht Dreß Disable header bars in the address book widgets if the environment variable BALSA_DIALOG_HEADERBAR is 0. * src/ab-window.c (balsa_ab_window_new): respect BALSA_DIALOG_HEADERBAR environment variable. 2016-10-23 Peter Bloomfield We no longer use libiconv. * configure.ac: remove --with-iconv option. * libbalsa/address-book-ldap.c: do not include iconv.h. * src/balsa-message.c: ditto. 2016-10-21 Peter Bloomfield Fix deprecation issues in gtk 3.22 Replace gtk_window_set_wmclass, which is deprecated in gtk 3.22, with gtk_window_set_role. * libbalsa/libbalsa.c (ask_cert_real), (ask_timeout_real): * libbalsa/send.c (ensure_send_progress_dialog): * libbalsa/source-viewer.c (libbalsa_show_message_source): * src/ab-window.c (balsa_ab_window_init): * src/filter-edit-dialog.c (filters_edit_dialog): * src/filter-export-dialog.c (filters_export_dialog): * src/filter-run-dialog.c (balsa_filter_run_dialog_new): * src/folder-conf.c (folder_conf_imap_node), (folder_conf_imap_sub_node): * src/information-dialog.c (balsa_information_list): * src/main-window.c (ensure_check_mail_dialog), (bw_display_new_mail_notification): * src/message-window.c (message_window_new): * src/sendmsg-window.c (sendmsg_window_new): * src/toolbar-prefs.c (customize_dialog_cb): 2016-10-21 Peter Bloomfield Fix deprecation issues in gtk 3.22 The Gtk+ API for popping up context menus has changed in 3.22; gtk_menu_popup is deprecated. * src/balsa-index.c (bndx_do_popup): * src/balsa-mblist.c (bmbl_do_popup): * src/balsa-message.c (balsa_headers_attachments_popup), (tree_mult_selection_popup), (tree_button_press_cb): * src/balsa-mime-widget-image.c (balsa_image_button_press_cb): * src/balsa-mime-widget-text.c (balsa_gtk_html_popup): * src/pref-manager.c (address_book_add_cb), (server_add_cb): * src/sendmsg-window.c (attachment_button_press_cb), (attachment_popup_cb): * src/toolbar-factory.c (tm_do_popup_menu): 2016-10-18 Albrecht Dreß Usually, RFC 3156 (PGP/MIME) signature parts (application/pgp-signature, see RFC 3156, sect. 9.2.) should never be encoded as they are 7-bit clean. However, there are implementations which apply an (superfluous) encoding to such parts, which Balsa fails to interpret properly. The attached patch fixes this behaviour, and as a side effect plugs a gmime stream leak when checking a S/MIME signature which is always encoded. * libbalsa/gmime-multipart-crypt.c (g_mime_gpgme_mps_verify): always decrypt the signature; do not leak sigstream. 2016-10-03 Albrecht Dreß Implement the 'AUTH PLAIN' SASL mechanism for POP3 according to RFC 5043 and RFC 4616 * libbalsa/imap/pop3.c (pop_get_capa), (pop_auth_sasl_plain): implement the 'AUTH PLAIN' SASL mechanism for POP3. 2016-10-03 Albrecht Dreß Deprecation cleanups * AUTHORS: * README: * configure.ac: * libbalsa/imap/imap_tst.c (main): * src/balsa-message.c (balsa_message_get_type), (balsa_message_init), (balsa_message_new), (tree_activate_row_cb), (balsa_message_set), (atattchments_menu_cb), (toggle_all_inline_cb), (message_recheck_crypto_cb): * src/balsa-message.h: * src/toolbar-prefs.c (create_toolbar_page): 2016-09-06 Albrecht Dreß * configure.ac: make the help string match the actual default, webkit2. 2016-09-05 Peter Bloomfield Respond to by making webkit2 the default instead of webkit, and warning if Balsa is configured for webkit. * configure.ac: make webkit2 the default HTML widget, and warn if Balsa is configured for webkit. 2016-08-29 Peter Bloomfield Plug memory leak. * src/main-window.c (bw_create_index_widget): do not leak focus-chain GList. 2016-08-21 Albrecht Dreß Always use multithreading, and use only the glib abstraction instead of "native" pthreads. * configure.ac: remove --enable-threads configure option and its consequences. * libbalsa/filter-file.c: remove reference to BALSA_USE_THREADS. * libbalsa/gmime-gpgme-signature.c (g_mime_gpgme_sigstat_new_from_gpgme_ctx): * libbalsa/imap-server.c (libbalsa_imap_server_set_username), (libbalsa_imap_server_set_host), (libbalsa_imap_server_init), (libbalsa_imap_server_finalize), (lb_imap_server_cleanup), (connection_cleanup), (get_or_create), (libbalsa_imap_server_get_handle), (libbalsa_imap_server_get_handle_with_user), (libbalsa_imap_server_release_handle), (libbalsa_imap_server_force_disconnect), (libbalsa_imap_server_close_all_connections), (libbalsa_imap_server_has_free_handles): * libbalsa/imap/imap-commands.c (imap_mbox_handle_noop), (imap_mbox_select), (imap_mbox_examine), (imap_mbox_create), (imap_mbox_delete), (imap_mbox_rename), (imap_mbox_subscribe), (imap_mbox_list), (imap_mbox_lsub), (imap_mbox_status), (imap_mbox_append_multi), (imap_mbox_close), (imap_mbox_expunge), (imap_mbox_expunge_a), (imap_mbox_find_all), (imap_mbox_find_unseen), (imap_mbox_handle_msgno_has_flags), (imap_mbox_handle_fetch_range), (imap_mbox_handle_fetch_set), (imap_mbox_handle_fetch_rfc822), (imap_mbox_handle_fetch_rfc822_uid), (imap_mbox_handle_fetch_body), (imap_mbox_store_flag), (imap_mbox_store_flag_a), (imap_mbox_handle_copy), (imap_mbox_unselect), (imap_mbox_thread), (imap_mbox_sort_msgno), (imap_mbox_sort_filter), (imap_mbox_filter_msgnos), (imap_mbox_complete_msgids), (imap_mbox_get_quota), (imap_mbox_get_my_rights), (imap_mbox_get_acl): * libbalsa/imap/imap-handle.c (imap_mbox_handle_init), (async_process), (idle_start), (imap_mbox_handle_connect), (imap_mbox_handle_reconnect), (imap_handle_force_disconnect), (imap_mbox_handle_get_delim), (imap_mbox_handle_finalize): * libbalsa/imap/imap-tls.c (locking_function), (id_function), (dyn_create_function), (dyn_lock_function), (dyn_destroy_function), (imaptls_thread_setup), (imaptls_thread_cleanup), (imap_create_ssl): * libbalsa/imap/imap_private.h: * libbalsa/imap/imap_search.c (imap_search_exec): * libbalsa/information.h: * libbalsa/libbalsa-conf.c (lbc_lock), (lbc_unlock), (libbalsa_conf_sync), (libbalsa_conf_queue_sync): * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_passphrase), (get_passphrase_idle): * libbalsa/libbalsa-gpgme.c (g_set_error_from_gpgme): * libbalsa/libbalsa.c (libbalsa_init), (ask_idle), (libbalsa_ask), (libbalsa_certs_destroy), (libbalsa_is_cert_known), (libbalsa_am_i_subthread), (libbalsa_lock_mailbox), (libbalsa_unlock_mailbox): * libbalsa/libbalsa.h: * libbalsa/libbalsa_private.h: * libbalsa/mailbox.c (libbalsa_mailbox_class_init), (lbm_index_entry_populate_from_msg), (lbm_index_entry_new_pending), (lbm_index_entry_free), (libbalsa_mailbox_finalize), (libbalsa_mailbox_check), (libbalsa_mailbox_real_lock_store), (lbm_msgno_changed_expunged_cb), (lbm_msgnos_changed_idle_cb), (lbm_msgno_changed), (lbm_msgno_filt_check_idle_cb), (libbalsa_mailbox_msgno_filt_check), (lbm_cache_message), (libbalsa_mailbox_get_message), (libbalsa_mailbox_messages_change_flags), (lbm_set_threading_idle_cb), (lbm_set_threading), (lbm_get_index_entry_expunged_cb), (lbm_get_index_entry_real), (lbm_get_index_entry), (lbm_check_idle), (libbalsa_mailbox_unlock_store): * libbalsa/mailbox.h: * libbalsa/mailbox_imap.c: * libbalsa/mailbox_local.c (lbm_local_save_tree_idle), (message_match_real), (lbml_set_threading_idle_cb), (libbalsa_mailbox_local_set_threading): * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_class_init), (libbalsa_mailbox_mbox_lock_store): * libbalsa/mime-stream-shared.c (libbalsa_mime_stream_shared_unlock): * libbalsa/mime-stream-shared.h: * libbalsa/missing_time.c (ctime_r): * libbalsa/rfc3156.c (libbalsa_gpgme_sig_stat_to_gchar): * libbalsa/send.c (lbs_process_queue), (handle_successful_send), (libbalsa_smtp_event_cb), (libbalsa_process_queue), (balsa_send_message_real): * libbalsa/send.h: * src/ab-main.c: * src/balsa-app.c (ask_passwd_idle), (ask_password_mt), (ask_password): * src/filter-edit-callbacks.c: * src/information-dialog.h: * src/main-window.c (bw_delete_cb), (balsa_window_new), (bw_real_open_mbnode_thread), (balsa_window_real_open_mbnode), (bw_register_open_mailbox), (bw_unregister_open_mailbox), (bw_is_open_mailbox), (check_new_messages_real), (bw_check_messages_thread): * src/main.c (threads_init), (threads_destroy), (real_main), (balsa_cleanup): * src/save-restore.c (pop3_progress_notify): * src/sendmsg-window.c (balsa_sendmsg_destroy_handler): * src/threads.h: ditto. 2016-07-28 Peter Bloomfield Implement a GtkComboBox for selecting a LibBalsaIdentity, and use it for the mailbox properties dialog and as the From address in the compose window. * libbalsa/identity.c (libbalsa_identity_combo_box): implement the widget; * libbalsa/identity.h: export it; * src/mailbox-conf.c (check_for_blank_fields): allow NULL argument; (mailbox_conf_view_new_full): use the widget; (mailbox_conf_view_check): get the identity from the widget instead of the list; * src/sendmsg-window.c (create_from_entry): use the widget. 2016-07-28 Albrecht Dreß Fix a bug in the configure script discovered by Jack * configure.ac: when no external html-to-text converter could be found, undef HTML2TEXT instead of defining it to "". 2016-07-27 Peter Bloomfield Andreas Schmidt suggested an improvement to the list of identities in the mailbox properties dialog. * src/mailbox-conf.c (mailbox_conf_view_new_full): include the identity name as well as the mailing address in the identities combo-box. 2016-07-27 Peter Bloomfield Since porting to GtkApplication, command line options have been handled in a subsequent invocation of Balsa, but not in the startup invocation. * src/main.c (real_main), (parse_options), (handle_remote), (command_line_cb): handle command line options at startup time. 2016-07-24 Peter Bloomfield * configure.ac: issue an error if building in a git tree with deprecated GnomeKeyring. 2016-07-23 Peter Bloomfield Fix building with toolchains that predefine _FORTIFY_SOURCE * configure.ac: undefine _FORTIFY_SOURCE before defining it to have the value 2. 2016-06-30 Peter Bloomfield Use Gspell-1.2 API * configure.ac: check whether we can use the Gspell-1.2 API; * src/sendmsg-window.c (create_text_area): if so, set the enable-language-menu property, to allow the user to change the spell-checker language from the context menu as well as from Balsa's menubar menu. 2016-06-28 Peter Bloomfield Support Gspell as an alternative to GtkSpell * configure.ac: replace --with-gtkspell with --with-spell-checker = (no|gtkspell|gspell) and change the AM_CONDITIONAL BUILD_WITH_GTK_SPELL to BUILD_WITH_SPELL_CHECKER. * src/Makefile.am: use the new AM_CONDITIONAL. * src/balsa-app.c (balsa_app_init): support Gspell. * src/balsa-app.h: ditto. * src/pref-manager.c (apply_prefs), (set_prefs): ditto. * src/save-restore.c (config_global_load), (config_save): ditto. * src/sendmsg-window.c (balsa_sendmsg_destroy_handler), (create_text_area), (create_lang_menu), (message_postpone), (set_locale), (sw_spell_check_change_state), (lang_set_cb), (sendmsg_window_new): Gspell has a different API from GtkSpell. 2016-06-25 Peter Bloomfield Symbolic icon names like pan-down-symbolic now contain hyphens and can no longer use underscores. * src/balsa-message.c: fix symbolic icon names. 2016-06-25 Peter Bloomfield As of gtksource version 2.21.?, only can be included directly. * libbalsa/libbalsa.c: include only gtksource.h. * src/balsa-mime-widget-text.c: ditto. * src/spell-check.c: ditto. 2016-06-22 Albrecht Dreß Fix shrinking message list * src/main-window.c (balsa_window_new), (balsa_window_fix_paned): set the size of the elements of the main window in an idle callback instead of the window creator; * src/main-window.h: export the idle callback; * src/main.c (real_main): add the idle call. 2016-06-19 Peter Bloomfield * src/ab-main.c (libbalsa_dialog_flags): set check_done to a non-zero value. 2016-06-19 Albrecht Dreß Make Gtk3 dialog header bars configurable Basically, a new function libbalsa_dialog_flags() is added to libbalsa.c (or simply expanded to 0 for older Gtk versions than 3.12.0). When being called for the first time, the function checks if the environment variable BALSA_DIALOG_HEADERBAR exists and is set to 0. Only in this case, the header bars are disabled. The function call replaces the macro BALSA_DIALOG_FLAGS. * configure.ac: remove definition of BALSA_DIALOG_FLAGS. * libbalsa/libbalsa.c (libbalsa_dialog_flags): define it; (ask_cert_real): use it. * libbalsa/libbalsa.h: declare it. * libbalsa/identity.c (libbalsa_identity_select_dialog), (libbalsa_identity_config_dialog): * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_select_key), (get_passphrase_real): * libbalsa/send.c (ensure_send_progress_dialog): * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): * src/ab-main.c (libbalsa_dialog_flags): * src/address-book-config.c (create_generic_dialog): * src/balsa-app.c (ask_password_real): * src/balsa-index.c (balsa_index_pipe): * src/balsa-mblist.c (bmbl_mru_show_tree): * src/filter-edit-callbacks.c (fe_edit_condition): * src/filter-edit-dialog.c (filters_edit_dialog): * src/filter-export-dialog.c (filters_export_dialog): * src/folder-conf.c (folder_conf_imap_node), (browse_button_cb), (subfolder_conf_clicked_ok), (folder_conf_imap_sub_node): * src/information-dialog.c (balsa_information_list): * src/mailbox-conf.c (create_generic_dialog): * src/main-window.c (ensure_check_mail_dialog), (bw_find_real): * src/pref-manager.c (open_preferences_manager): * src/sendmsg-window.c (sw_get_user_codeset), (quote_parts_select_dlg), (subject_not_empty): * src/store-address.c (store_address_dialog): * src/toolbar-prefs.c (customize_dialog_cb): all use it. 2016-06-18 Peter Bloomfield Fix saving address when user has only one address book (https://mail.gnome.org/archives/balsa-list/2016-June/msg00030.html) * src/store-address.c (store_address_dialog): always set current address book; (store_address_book_frame): no need to check balsa_app.address_book_list != NULL. 2016-06-11 Peter Bloomfield Set line-wrapping of a long label to TRUE and do not change it. * src/balsa-mime-widget-message.c (expanded_cb): do not change line-wrapping; (add_header_gchar): set line-wrapping to TRUE even if the label is to be ellipsized. 2016-06-11 Peter Bloomfield * src/balsa-mime-widget-message.c (add_header_gchar): in an address, replace '\r' or '\n' with a space. 2016-06-10 Peter Bloomfield * src/balsa-mime-widget-message.c (add_header_gchar): comment on why show-all-headers is used to set the initial state of the expander; (add_header_address_list): new parameter show_all_headers; (bmw_message_set_headers_d): use it. 2016-06-10 Peter Bloomfield * src/balsa-mime-widget-message.c (expanded_cb): cut redundant dynamic cast. 2016-06-07 Peter Bloomfield Drop the --enable-touch-ui configuration option and the corresponding conditionally compiled code * configure.ac: drop the option; * libbalsa/address-view.c and below: drop the code. * libbalsa/imap-server.c (libbalsa_imap_server_init): * libinit_balsa/assistant_init.c (balsa_initdruid_apply), (balsa_initdruid): * libinit_balsa/assistant_page_directory.c (balsa_druid_page_directory_init), (balsa_druid_page_directory_next): * libinit_balsa/assistant_page_directory.h: * libinit_balsa/assistant_page_user.c (balsa_druid_page_user_init), (balsa_druid_page_user_next): * libinit_balsa/assistant_page_user.h: * src/balsa-app.c (balsa_app_init): * src/balsa-app.h: * src/balsa-index.c (bi_apply_other_column_settings): * src/balsa-mblist.c (bmbl_core_mailbox): * src/balsa-message.c: * src/folder-conf.c (folder_conf_clicked_ok), (folder_conf_imap_node): * src/mailbox-conf.c (mailbox_conf_set_values), (update_imap_mailbox), (create_imap_mailbox_dialog): * src/main-window.c (bw_create_index_widget), (new_message_activated), (balsa_window_new), (bw_enable_mailbox_menus), (bw_enable_message_menus), (bw_enable_edit_menus), (balsa_window_enable_continue), (bw_set_threading_menu), (bw_select_part_cb), (bw_send_msg_window_destroy_cb), (update_view_menu): * src/main.c (periodic_expunge_cb): * src/message-window.c: * src/pref-manager.c: * src/save-restore.c (config_global_load), (config_save): * src/sendmsg-window.c (update_bsmsg_identity), (add_attachment), (create_info_pane), (setup_headers_from_identity), (sendmsg_window_set_field), (bsmsg2message), (sw_page_setup_activated), (check_readiness), (sw_reply_to_change_state), (sw_gpg_helper), (sw_gpg_mode_change_state), (init_menus), (bsmsg_update_gpg_ui_on_ident_change), (sendmsg_window_continue): * src/sendmsg-window.h: 2016-06-05 Peter Bloomfield Install gtksourceview helper files in the new folder. * configure.ac: fix BUILD_WITH_GTKSOURCEVIEW. 2016-06-05 Albrecht Dreß As Webkit does not have a method to convert html to text, we cannot quote html-only messages. As a workaround, try to use html2text. * configure.ac: detect an html-to-text-or-markdown filter; * libbalsa/html.c (html2text), (libbalsa_html_to_string): use it. 2016-06-04 Albrecht Dreß Force proper icon sizes * libbalsa/files.c (libbalsa_icon_finder): force proper icon sizes (e.g. in the message structure view). 2016-06-04 Albrecht Dreß We always use gtksourceview-3.0 * Makefile.am: store helper files in a properly named folder; * configure.ac: clean up setting the #define; * libbalsa/libbalsa.c (libbalsa_source_view_new): clean up, use proper helper files folder; * src/balsa-mime-widget-text.c (create_text_widget): clean up; * src/sendmsg-window.c (create_text_area): ditto. 2016-06-04 Albrecht Dreß Delete the Gtkhtml2 code * libbalsa/html.c (libbalsa_html_print): delete the Gtkhtml2 code. 2016-05-31 Peter Bloomfield * configure.ac: restore AC_SUBST(GLIB_GENMARSHAL). 2016-05-31 Peter Bloomfield Build with builddir != srcdir * autogen.sh: chdir to srcdir to create configure, then back to builddir to use it. * libbalsa/imap/Makefile.am: provide path to libimap-marshal.list. 2016-05-31 Albrecht Dreß Reduce the code complexity (in particular conditional parts) by weeding out deprecated stuff. * configure.ac: apply the aforementioned simplifications * libbalsa/filter-funcs.c, libbalsa/filter-private.h, libbalsa/mime.c, libbalsa/misc.h, src/balsa-app.c, src/balsa-app.h, src/balsa-print-object-text.c, src/quote-color.c, src/quote-color.h, src/sendmsg-window.c, src/spell-check.c: always use GRegex * libbalsa/gmime-multipart-crypt.c, libbalsa/gmime-stream-gio.c, libbalsa/mailbox_mbox.c: drop conditional code for gmime < 2.6 * libbalsa/html.h: remove hack for Gtkhtml 2 * libbalsa/libbalsa.c, libbalsa/libbalsa.h: use GDateTime, simplify API of libbalsa_date_to_utf8() * libbalsa/mailbox.c, libbalsa/message.h, libbalsa/rfc3156.c, src/balsa-mime-widget-vcalendar.c, src/balsa-print-object-text.c: use simplified libbalsa_date_to_utf8() API * libbalsa/missing.h, libbalsa/missing_time.c: remove localtime_r, gmtime_r implementations * libbalsa/rfc2445.c: use ISO 8601 GTimeVal and GDateTime functions * libbalsa/send.c: use GTimeZone functions * src/filter-edit-callbacks.c: use GDateTime functions 2016-05-27 Albrecht Dreß Fix accessing MBox files > 2 GByte * libbalsa/mailbox_mbox.c (lbm_mbox_check_file), (lbm_mbox_newline), (lbm_mbox_add_message): use 64-bit sizes; * libbalsa/send.c (libbalsa_message_cb): comment about file size limitation. 2016-05-24 Albrecht Dreß Use G_{BEGIN,END}_DECLS * libbalsa/gmime-application-pkcs7.h: * libbalsa/gmime-gpgme-signature.h: * libbalsa/gmime-multipart-crypt.h: * libbalsa/gmime-part-rfc2440.h: * libbalsa/identity.h: * libbalsa/libbalsa-gpgme-cb.h: * libbalsa/libbalsa-gpgme.h: * libinit_balsa/assistant_init.h: * libinit_balsa/assistant_page_defclient.h: * libinit_balsa/assistant_page_directory.h: * libinit_balsa/assistant_page_finish.h: * libinit_balsa/assistant_page_user.h: * libinit_balsa/assistant_page_welcome.h: * src/balsa-index.h: * src/balsa-message.h: * src/balsa-mime-widget-callbacks.h: * src/balsa-mime-widget-crypto.h: * src/balsa-mime-widget-image.h: * src/balsa-mime-widget-message.h: * src/balsa-mime-widget-multipart.h: * src/balsa-mime-widget-text.h: * src/balsa-mime-widget.h: * src/filter-run.h: * src/print.h: * src/quote-color.h: * src/sendmsg-window.h: * src/spell-check.h: 2016-05-23 Peter Bloomfield * libbalsa/imap/imap_search.c (imap_write_key_date): drop redundant glib version check. 2016-05-20 Albrecht Dreß * src/balsa-mime-widget-crypto.c (balsa_mime_widget_signature_widget): pack the GtkExpander in a GtkBox, to work around a Gtk bug that limits the mouse-sensitive area of the expander when the border-width is set. 2016-05-20 Albrecht Dreß * libbalsa/gmime-multipart-crypt.c (g_mime_gpgme_mps_sign): refactor; (g_mime_gpgme_mpe_encrypt): ditto, removing leak. 2016-05-20 Albrecht Dreß * src/balsa-mime-widget-crypto.c (balsa_mime_widget_signature_widget): remove confusing signature info. 2016-05-17 Peter Bloomfield * src/balsa-mime-widget-message.c (add_header_gchar), (add_header_sigstate): use GtkGrid API better. 2016-05-16 Peter Bloomfield Use top line of digital signature for GtkExpander label instead of "Digital Signature" * src/balsa-mime-widget-crypto.c (balsa_mime_widget_signature_widget): 2016-05-16 Albrecht Dreß Make SSL mandatory * libbalsa/imap/md5-utils.c: remove. * libbalsa/imap/md5-utils.h: ditto. 2016-05-16 Albrecht Dreß With this patch, Balsa will pop up the key selection dialogue containing /all/ keys which may be used for encryption in this case. The user can either select a key, or cancel the operation. This basically is the same behaviour as of Thunderbird. * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_select_key), (key_selection_changed_cb), (sort_iter_cmp_fn): * libbalsa/libbalsa-gpgme-cb.h: * libbalsa/libbalsa-gpgme.c (get_key_from_name), (get_pubkey), (gpgme_add_signer), (gpgme_build_recipients): * libbalsa/libbalsa-gpgme.h: 2016-05-16 Albrecht Dreß * libbalsa/gmime-gpgme-signature.c (libbalsa_cert_subject_readable): This trivial patch makes sure that the GPG key or S/MIME certificate subject string as returned by libbalsa_cert_subject_readable() is utf8-clean. 2016-03-12 Peter Bloomfield * src/main-window.c (bw_display_new_mail_notification): duplicate some lines of code to simplify conditional compilation. 2016-03-12 Peter Bloomfield * libbalsa/imap/imap-handle.c (imap_message_new): use whitespace to resolve ambiguous assignment. 2016-03-12 Peter Bloomfield * libbalsa/libbalsa-gpgme-cb.h: remove Emacs hack. 2016-03-12 Albrecht Dreß * Bug fixes: due to broken assignments in libbalsa_gpgme_init(), the callbacks for selecting a GnuPG key from a list or for accepting low-trust keys individually are never called. When selecting a key, only the first subkey is checked, instead of all potential ones. * Message improvements: When checking a GnuPG signed message where the key has expired, Balsa displays a "Signature could not be checked" error and an informational message containg the "real" result. The patch removes the (wrong) former message. * Code cleanups: change the return value of all crypto-related functions which return an essentially bool value to gboolean instead of (g)int, remove hacks for Emacs (still someone using it?) in header files which confuse almost all other tools, fix a few minor glitches, and remove a few unused statements. * libbalsa-gpgme.c: fix callback assignment bug, implement new function to verify all subkeys of a key * rfc3156.c: remove confusing error message * gmime-application-pkcs7.h, gmime-application-pkcs7.c, gmime-multipart-crypt.c, gmime-multipart-crypt.h, gmime-part-rfc2440.c, gmime-part-rfc2440.h, libbalsa-gpgme.c, libbalsa-gpgme.h: change function return types to gboolean * rfc3156.c: used changed api * gmime-gpgme-signature.h, gmime-multipart-crypt.h, gmime-part-rfc2440.h, libbalsa-gpgme.h: remove Emacs hack * gmime-multipart-crypt.c: reorder statements to avoid duplicated ones (g_mime_gpgme_mps_sign) * gmime-multipart-crypt.c, rfc3156.c: use error checking macro instead of cast * libbalsa-gpgme.c: remove assignments of variables which are never used * send.c, smtp-server.c, src/filter-edit-callbacks.c: remove unused statements 2016-02-23 Peter Bloomfield Build without libnotify * src/main-window.c (bw_is_active_notify): fix conditional code. 2016-02-15 Peter Bloomfield Gtk 3.20 deprecation cleanup * libbalsa/mime.c (is_in_url): gtk_text_iter_begins_tag is deprecated; * src/balsa-mime-widget-text.c (text_view_url_popup), (prepare_url_offsets): ditto; also gdk_display_get_device_manager is deprecated; * src/main-window.c (bw_notebook_label_new): gtk_button_set_focus_on_click is deprecated. 2016-02-15 Albrecht Dreß Build with Gtk+ < 3.12 * configure.ac: define BALSA_DIALOG_FLAGS as either GTK_DIALOG_USE_HEADER_BAR or 0. * libbalsa/identity.c (libbalsa_identity_select_dialog), (libbalsa_identity_config_dialog): * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_select_key), (get_passphrase_real): * libbalsa/libbalsa.c (ask_cert_real): * libbalsa/send.c (ensure_send_progress_dialog): * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): * src/address-book-config.c (create_generic_dialog): * src/balsa-app.c (ask_password_real): * src/balsa-index.c (balsa_index_pipe): * src/balsa-mblist.c (bmbl_mru_show_tree): * src/filter-edit-callbacks.c (fe_edit_condition): * src/filter-edit-dialog.c (filters_edit_dialog): * src/filter-export-dialog.c (filters_export_dialog): * src/folder-conf.c (folder_conf_imap_node), (browse_button_cb), (subfolder_conf_clicked_ok), (folder_conf_imap_sub_node): * src/information-dialog.c (balsa_information_list): * src/mailbox-conf.c (create_generic_dialog): * src/main-window.c (ensure_check_mail_dialog), (bw_find_real): * src/pref-manager.c (open_preferences_manager): * src/sendmsg-window.c (sw_get_user_codeset), (quote_parts_select_dlg), (subject_not_empty), (bsmsg_check_format_compatibility): * src/store-address.c (store_address_dialog): * src/toolbar-prefs.c (customize_dialog_cb): use it. 2015-09-21 Peter Bloomfield * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_ctx_menu_save): use only the basename of an attachment's filename. 2015-09-21 Peter Bloomfield * libbalsa/body.c (libbalsa_message_body_save_temporary): use only the basename of an attachment's filename. 2015-07-23 Peter Bloomfield Fix the image-loading option for HTML message parts * libbalsa/html.c (lbh_navigation_policy_decision): do not hide the info-bar unless we are loading an actual image; (lbh_resource_notify_response_cb): new function--we do not know what we are loading until we have an actual response; (lbh_resource_load_started_cb): just connect to the "notify::response" signal; (libbalsa_html_new): add debugging. 2015-06-07 Peter Bloomfield Fix bgo #750516 (pachoramos1@gmail.com) * balsa.desktop.in.in: use the same macro TOOLKIT_CATEGORIES as in balsa-mailto-handler.desktop.in.in. * configure.ac: actually define said macro. 2015-05-20 Peter Bloomfield Silence some autoconf and automake complaints. * configure.ac: silence autoconf. * libbalsa/imap/Makefile.am: silence automake. * libinit_balsa/Makefile.am: ditto. 2015-04-10 Peter Bloomfield * src/sendmsg-window.c (delete_handler), (bsmsg_check_format_compatibility): mark strings for translation. 2015-04-10 Peter Bloomfield * src/information-dialog.c (balsa_information_list): make the "Close" button use GTK_RESPONSE_CANCEL, to move the button to the left. 2015-04-01 Peter Bloomfield * src/sendmsg-window.c (quote_parts_select_dlg), (collect_for_quote), (quote_body): add a cancel button and provide a parent for the quote-parts dialog. 2015-03-30 Peter Bloomfield Clean up store-address dialog * src/store-address.c (store_address_book_frame): add a label to explain address-book combo-box; (store_address_note_frame): add space after header name; (store_address_add_address): increase notebook tab label to 15 characters; (store_address_add_lbaddress): ditto. 2015-03-28 Peter Bloomfield * src/balsa-mime-widget-crypto.c (balsa_mime_widget_signature_widget): put digital signature info in a GtkExpander. 2015-03-27 Peter Bloomfield * src/balsa-message.c: do not crash when current part is changed while the find-bar is showing. 2015-03-26 Peter Bloomfield * src/store-address.c (store_address_dialog): grab the keyboard focus to the default button, "OK", instead of the address book combo-box. 2015-03-26 Peter Bloomfield * src/store-address.c (balsa_store_address_from_messages): clean up code; (store_address_response): drop response for "save this address and keep the dialog open"; (store_address_dialog): use header bar, and change buttons to standard OK/Cancel; (store_address_book_frame): do not put a GtkFrame around the address-book combo-box; (store_address_note_frame): do not put a GtkFrame around the address notebook. 2015-03-25 Peter Bloomfield Do not use header bar in GtkMessageDialog, it does nothing * libbalsa/identity.c (delete_ident_cb): * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_accept_low_trust_key): * libbalsa/libbalsa.c (ask_timeout_real): * libbalsa/rfc3156.c (check_gpg_child): * src/ab-main.c (ab_warning): * src/balsa-message.c: * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_ctx_menu_save): * src/folder-conf.c (folder_conf_delete): * src/information-dialog.c (balsa_information_dialog): 2015-03-25 Peter Bloomfield * src/sendmsg-window.c (sw_get_user_codeset), (quote_parts_select_dlg), (bsmsg_check_format_compatibility): use header bars in dialogs. 2015-03-25 Peter Bloomfield * src/pref-manager.c (open_preferences_manager): use a header bar. 2015-03-25 Peter Bloomfield * src/main-window.c (ensure_check_mail_dialog), (bw_find_real): use header bars in dialogs. 2015-03-25 Peter Bloomfield * src/mailbox-conf.c (create_local_mailbox_dialog): use GTK_RESPONSE_CANCEL instead of CLOSE; (create_generic_dialog): use header bar. 2015-03-25 Peter Bloomfield * src/information-dialog.c (balsa_information_dialog), (balsa_information_list): use header bars in dialogs. 2015-03-25 Peter Bloomfield * src/folder-conf.c (folder_conf_imap_node), (browse_button_cb), (subfolder_conf_clicked_ok), (folder_conf_imap_sub_node), (folder_conf_delete): use header bars in dialogs. 2015-03-25 Peter Bloomfield * src/filter-edit-callbacks.c (fe_edit_condition): use header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_ctx_menu_save): use header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * src/balsa-message.c: use header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * src/balsa-mblist.c (bmbl_mru_show_tree): use header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * src/balsa-index.c (balsa_index_pipe): use header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * src/balsa-app.c (ask_password_real): use header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * src/address-book-config.c (create_generic_dialog): use header bar in all dialogs. 2015-03-24 Peter Bloomfield * src/ab-window.c (balsa_ab_window_new): avoid multiple dynamic casts. 2015-03-24 Peter Bloomfield * src/ab-window.c (balsa_ab_window_new): drop redundant dynamic casts to GtkWidget 2015-03-24 Peter Bloomfield Use header bar * src/ab-window.c (balsa_ab_window_new): use header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * src/ab-main.c (ab_warning): use header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): use a header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * libbalsa/send.c (ensure_send_progress_dialog): use a header bar in dialog. 2015-03-24 Peter Bloomfield Use header bar * libbalsa/rfc3156.c (check_gpg_child): use a header bar in dialog. 2015-03-24 Peter Bloomfield Use header bars * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_select_key), (lb_gpgme_accept_low_trust_key), (get_passphrase_real): use header bars in dialogs. 2015-03-24 Peter Bloomfield Use GtkDialog API and GTK_DIALOG_* flags instead of g_object_new and GObject properties * src/filter-edit-dialog.c (filters_edit_dialog): * src/filter-export-dialog.c (filters_export_dialog): * src/sendmsg-window.c (subject_not_empty): * src/toolbar-prefs.c (customize_dialog_cb): 2015-03-24 Peter Bloomfield * libbalsa/libbalsa.c (ask_cert_real), (ask_timeout_real): use header bars. 2015-03-24 Peter Bloomfield * libbalsa/misc.c (libbalsa_create_grid_entry): set hexpand on the entry. 2015-03-24 Peter Bloomfield Use header bars in identity dialogs * libbalsa/identity.c (libbalsa_identity_select_dialog), (delete_ident_cb), (libbalsa_identity_config_dialog): use header bars. (append_ident_notebook_page), (setup_ident_frame): remove redundant argument. 2015-03-23 Peter Bloomfield Set minimum vertical space for recipient list * src/sendmsg-window.c (create_email_entry): try to give the recipient list around two lines of space. 2015-03-23 Peter Bloomfield Deprecation cleanup--I missed one :( * src/balsa-mime-widget-text.c (fill_text_buf_cited): GtkTextTag:foreground-gdk is deprecated. 2015-03-23 Peter Bloomfield Deprecation cleanup * src/balsa-mime-widget-text.c (quote_tag): GtkTextTag:foreground-gdk is deprecated. 2015-03-23 Peter Bloomfield Deprecation cleanup * src/balsa-app.c (balsa_app_init): GtkSettings:gtk-fallback-icon-theme is deprecated. 2015-03-23 Peter Bloomfield Use a transient parent and a header bar in the no-subject dialog * src/sendmsg-window.c (subject_not_empty): use a transient parent and a header bar. 2015-03-14 Peter Bloomfield Use a transient parent for filter dialogs * libbalsa/filter.h: add parent window to filters_edit_dialog and filters_export_dialog API. * src/filter-edit-dialog.c (filters_edit_dialog): use it, and add a header bar. * src/filter-export-dialog.c (filters_export_dialog): ditto. * src/main-window.c (filters_activated), (export_filters_activated): pass the main window as the transient parent. 2015-03-14 Peter Bloomfield Use a transient parent for the BalsaFilterRunDialog, and manage sensitivity of various buttons * libbalsa/filter.h: add parent window to filters_run_dialog API. * src/filter-run-dialog.c (balsa_filter_run_dialog_new): use it, and add a header bar. (available_list_selection_changed), (selected_list_selection_changed): callbacks for selection "changed" signals, so we can set the sensitivity of various buttons. (balsa_filter_run_dialog_init): connect to the signals, and save the buttons in BalsaFilterRunDialog. (filters_run_dialog): new API. * src/filter-run.h: new members in BalsaFilterRunDialog for the buttons. * src/mailbox-node.c (mb_filter_cb): pass the main window as the transient parent for the dialog. * src/main-window.c (select_filters_activated): ditto. 2015-03-14 Peter Bloomfield Use a header bar in the toolbar editor * src/toolbar-prefs.c (customize_dialog_cb): use a header bar. (create_toolbar_page): add tooltips to direction buttons. 2015-03-14 Peter Bloomfield Abandon buttons with both an icon and text, and use a symbolic icon where we keep the icon. * src/balsa-app.c: remove balsa_stock_button_with_label. * src/balsa-app.h: ditto. * src/ab-window.c (balsa_ab_window_init): drop icons. * src/filter-edit-dialog.c (build_left_side), (build_right_side): ditto. * src/filter-run-dialog.c (balsa_filter_run_dialog_init): drop icons from "Apply" buttons; drop labels from direction buttons. * src/spell-check.c (balsa_spell_check_init): drop icons. * src/toolbar-prefs.c (create_toolbar_page): drop labels from direction buttons. 2015-03-13 Peter Bloomfield * src/ab-window.c (balsa_ab_window_init): use gtk_button_new_from_icon_name for a button with only an icon, no text. 2015-03-13 Peter Bloomfield * src/balsa-message.c: use gtk_button_new_from_icon_name for a button with only an icon, no text. 2015-03-12 Peter Bloomfield Use symbolic icons * src/balsa-icons.c (balsa_register_pixbufs): use window-close-symbolic instead of window-close. * src/message-window.c: ditto. * src/sendmsg-window.c: ditto. * src/toolbar-factory.c: ditto. * src/main-window.c (bw_notebook_label_new): ditto, and give up on making close-button small--it's not working. 2015-03-12 Peter Bloomfield Clean up spell checker * src/spell-check.c (balsa_spell_check_new): set the window title as an object property; (balsa_spell_check_new_with_text): use static cast instead of dynamic cast; indentation; (balsa_spell_check_init): title is now set as an object property. 2015-03-12 Peter Bloomfield BalsaSpellCheck no longer uses any properties of GtkDialog, so instead make it a direct subclass of GtkWindow * src/sendmsg-window.c (sw_spell_check_activated), (sw_spell_check_weak_notify): weak-ref the spell checker instead of waiting for the "response" signal. * src/spell-check.c (balsa_spell_check_class_init), (balsa_spell_check_new), (balsa_spell_check_init), (balsa_spell_check_start), (balsa_spell_check_destroy), (spch_finish): make BalsaSpellCheck a subclass of GtkWindow, instead of GtkDialog. 2015-03-09 Peter Bloomfield Avoid critical message from GtkSourceView * src/spell-check.c (balsa_spell_check_start), (spch_finish): save the current state in a GtkSourceBuffer when we are using GtkSourceview. 2015-03-09 Peter Bloomfield Build with the home-grown spell checker * src/spell-check.c (balsa_spell_check_init): put button grid in the content-area, now that accessing the action-area is deprecated. 2015-03-09 Peter Bloomfield * src/balsa-icons.c (balsa_register_pixbufs): use freedesktop.org standard window-close icon instead of gtk-close 2015-03-04 Peter Bloomfield Respect the "All headers" option on the "View" menu (Helmut Jarausch, ) * src/balsa-mime-widget-message.c (balsa_mime_widget_message_set_headers), (balsa_mime_widget_message_set_headers_d): set the show-all-headers parameter correctly. 2015-03-03 Albrecht Dreß Improve printing of text/rfc822-headers parts * src/balsa-print-object-header.c (balsa_print_object_header_new_real), (balsa_print_object_header_from_message), (balsa_print_object_header_from_body), (header_add_string), (header_add_list): implement and respect new parameter gboolean print_all_headers. 2015-03-02 Peter Bloomfield Remove unnecessary parameter * src/balsa-mime-widget-message.c (add_header_gchar), (add_header_address_list), (bmw_message_set_headers_d): we do not need to pass the BalsaMessage. 2015-03-02 Peter Bloomfield Show all headers in a text/rfc822-headers part * src/balsa-mime-widget-message.c (add_header_gchar): new parameter gboolean show_all_headers; (balsa_mime_widget_new_message), (add_header_address_list), (bmw_message_set_headers_d), (bmw_message_set_headers), (balsa_mime_widget_message_set_headers), (balsa_mime_widget_message_set_headers_d): use it. 2015-03-02 Peter Bloomfield Provide a parent window for the send-progress dialog * libbalsa/send.c (ensure_send_progress_dialog), (libbalsa_message_send), (lbs_process_queue), (libbalsa_process_queue): new parameter GtkWindow *parent. * libbalsa/send.h: ditto. * src/balsa-message.c: use it. * src/balsa-mime-widget-message.c (extbody_send_mail): ditto. * src/balsa-mime-widget-vcalendar.c (vevent_reply): ditto. * src/main-window.c (send_queued_mail_activated): ditto. * src/sendmsg-window.c (send_message_handler): ditto. 2015-03-01 Peter Bloomfield Fix alignment of text/rfc822-headers parts widget * src/balsa-mime-widget-message.c (balsa_mime_widget_new_message): do not override default settings of horizontal align and expand. 2015-03-01 Albrecht Dreß Display and print text/rfc822-headers parts * libbalsa/body.[hc]: parse text/rfc822-headers parts, and store them in the body structure * src/balsa-mime-widget.c, src/balsa-mime-widget-message.c: display a text/rfc822-headers part * src/balsa-print-object.c: print a text/rfc822-headers part 2015-03-01 Albrecht Dreß Obfuscate the message-id header * libbalsa/send.c (libbalsa_set_message_id): obfuscate the message-id header (in response to bgo #738155). 2015-03-01 Peter Bloomfield Use pan-down-symbolic instead of balsa-drop-down * images/16x16/Makefile.am: balsa-drop-down has been removed * src/balsa-icons.c (balsa_register_pixmaps): change to pan-down-symbolic 2015-03-01 Peter Bloomfield * images/16x16/balsa-drop-down.png: remove it. 2015-02-27 Albrecht Dreß Enable the request of Delivery Status Notifications * libbalsa/identity.[hc]: define default DSN setting, load and store it * libbalsa/identity.c, src/balsa-index.c, src/filter-edit-callbacks.c: fix clang nagging about a misplaced 'static const' qualifier * libbalsa/message.h: add request dsn flag * libbalsa/send.c: instruct libesmtp to request the DSN * libbalsa/send.c: pass const parameter as const * src/balsa-icons.c: add braces around macro * src/sendmsg-window.[hc]: add GUI stuff for requesting the DSN 2015-02-23 Peter Bloomfield Actually change spell-checking language * src/sendmsg-window.c (sw_spell_detach), (sw_spell_attach): detach any current spell-checker before attaching a new one. 2015-02-22 Peter Bloomfield Fix some spacing issues * src/toolbar-prefs.c (customize_dialog_cb): allocate extra vertical space to the available and current toolbar item lists; (create_toolbar_page): separate the 'restore' and 'current' buttons by minimum 5px. 2015-02-20 Peter Bloomfield * src/main-window.c (bw_enable_mailbox_menus): suppress cppcheck null pointer error. 2015-02-20 Peter Bloomfield * src/ab-main.c (address_book_change_state): do not crash after deleting address book. 2015-02-20 Peter Bloomfield * libbalsa/application-helpers.c (libbalsa_window_get_menu_bar), (libbalsa_window_set_accels): remove old accel group before setting new one. 2015-02-19 Peter Bloomfield Make the address book editor accelerators actually work * libbalsa/application-helpers.c (libbalsa_window_set_accels): new helper; (libbalsa_window_get_menu_bar) use it. * libbalsa/application-helpers.h: export it. * src/ab-main.c (set_address_book_menu_items): use it. 2015-02-19 Peter Bloomfield * libbalsa/address-book-text.c (lbab_text_group_address): compile with MAKE_GROUP_BY_ORGANIZATION defined. 2015-02-18 Peter Bloomfield * src/toolbar-prefs.c (customize_dialog_cb), (standard_button_cb), (create_toolbar_page), (tp_page_refresh_available), (tp_page_add_selected), (tp_page_remove_selected): conditionally compiled debug code to check for unimplemented action names. 2015-02-18 Peter Bloomfield Fix broken toolbar items * src/message-window.c: correct action names. * src/main-window.c (show_all_headers_change_state), (show_preview_pane_change_state), (bw_add_win_action_entries): ditto, and implement missing actions. 2015-02-18 Albrecht Dreß * src/balsa-mime-widget-text.c (create_text_widget): allow for GtkSourceView versions greater than 2. 2015-02-17 Peter Bloomfield Restore toolbar editing * src/main-window.c (balsa_window_get_toolbar_model), (bw_add_app_action_entries), (bw_add_win_action_entries), (balsa_window_add_action_entries), (bw_set_menus), (balsa_window_new): * src/main-window.h: * src/message-window.c (message_window_get_toolbar_model), (message_window_add_action_entries), (message_window_new): * src/message-window.h: * src/sendmsg-window.c (sendmsg_window_get_toolbar_model), (sendmsg_window_add_action_entries), (sendmsg_window_new): * src/sendmsg-window.h: * src/toolbar-factory.c (balsa_toolbar_model_finalize), (balsa_toolbar_model_init), (balsa_toolbar_remove_all), (tm_load_model), (tm_save_model), (balsa_toolbar_model_new), (tm_add_action), (balsa_toolbar_model_add_entries), (balsa_toolbar_model_get_current), (balsa_toolbar_model_is_standard), (balsa_toolbar_model_insert_icon), (balsa_toolbar_model_clear), (tm_has_second_line), (tm_populate), (tm_changed_cb), (tm_toolbar_weak_notify), (balsa_toolbar_new): * src/toolbar-factory.h: * src/toolbar-prefs.c (customize_dialog_cb), (wrap_toggled_cb), (create_toolbar_page), (tp_find_icon), (tp_page_refresh_available), (tp_page_refresh_current), (tp_store_set), (replace_nl_with_space): 2015-02-16 Albrecht Dreß Disable SSLv3, with an option in the code to override, and enable TLSv1.1 and 1.2 * libbalsa/imap/imap-tls.c (imap_create_ssl): 2015-02-16 Peter Bloomfield Fix some alignment issues * src/pref-manager.c (open_preferences_manager), (set_align), (attach_entry_full), (attach_information_menu), (attach_label), (checking_group), (quoted_group), (mdn_group), (main_window_group), (threading_group), (add_pref_menu), (deleting_messages_group), (message_window_group), (folder_scanning_group), (create_mdn_reply_menu), (pm_group_new), (pm_combo_box_new): revert to deprecated GtkMisc stuff until gtk_label_set_{xy}align is available. 2015-02-15 Peter Bloomfield * src/sendmsg-window.c (create_lang_menu): do not leak language names. 2015-02-15 Peter Bloomfield * libbalsa/imap/auth-cram.c (imap_auth_cram): cosmetic change to length of copy in strncat. 2015-02-15 Albrecht Dreß Build with clang (ver. LLVM 3.4) * libbalsa/files.c: remove unused assignment (detected by cppcheck) * libbalsa/imap/auth-cram.c: fix possible writing behind buffer end * libbalsa/imap/imap-commands.c: remove check for a value >= 0 for an unsigned value * libbalsa/imap/imap-handle.c, libbalsa/mailbox_imap.c: add empty 'if' body * libbalsa/mailbox_imap.c, libbalsa/send.c, libbalsa/smtp-server.c: fix enum mismatch * libbalsa/mailbox_mbox.c: don't assign a signed value to an unsigned * libbalsa/message.h, libbalsa/mailbox_mh.c: introduce proper "invalid" flag (clang optimises the current solution away, as it can never be true) 2015-02-11 Peter Bloomfield Port BalsaMessage from GtkNotebook to GtkStack * src/balsa-message.c (balsa_message_get_type): BalsaMessage now subclasses GtkBox instead of GtkNotebook. * src/balsa-message.h: ditto. 2015-02-10 Peter Bloomfield Deprecation cleanup * src/sendmsg-window.c (create_email_or_string_entry), (create_text_area): gtk_widget_override_font is deprecated, use CSS instead. 2015-02-10 Peter Bloomfield Deprecation cleanup * src/balsa-mime-widget-text.c (draw_cite_bar_real): gtk_widget_override_color is deprecated, use CSS instead. 2015-02-10 Peter Bloomfield Deprecation cleanup * src/balsa-mime-widget-text.c (bm_modify_font_from_string): gtk_widget_override_font is deprecated, use CSS instead. 2015-02-10 Peter Bloomfield * src/balsa-mime-widget-image.c (balsa_mime_widget_image_dispose): fix typo. 2015-02-10 Peter Bloomfield Deprecation cleanup * src/balsa-mime-widget-message.c (add_header_gchar): gtk_widget_override_font is deprecated, use CSS instead. 2015-02-10 Peter Bloomfield Deprecation cleanup * src/balsa-mime-widget-image.c (balsa_mime_widget_image_dispose), (balsa_mime_widget_new_image): gtk_style_context_get_background_color and gtk_widget_override_background_color are deprecated; when we replace the GtkNotebook with a GtkStack, we should get consistent backgrounds again. 2015-02-10 Peter Bloomfield Deprecation cleanup * src/balsa-message.c (balsa_message_init): gtk_style_context_get_background_color and gtk_widget_override_background_color are deprecated; when we replace the GtkNotebook with a GtkStack, we should get consistent backgrounds again. 2015-02-10 Peter Bloomfield Deprecation cleanup * libbalsa/source-viewer.c (libbalsa_show_message_source): gtk_widget_override_font is deprecated, use CSS instead. 2015-02-08 Peter Bloomfield * src/main-window.c (balsa_window_new): vertically center the new skinny progress bar. 2015-02-08 Peter Bloomfield Allow for quoted strings in vcal items * libbalsa/rfc2445.c (vcal_strchr): replacement for strchr that ignores matches in quoted strings; (vcal_strsplit_at_char): replacement for g_strsplit that uses vcal_strchr; (libbalsa_vcal_new_from_body): use them. 2015-02-03 Peter Bloomfield Simplify BalsaMailboxConfView destruction * src/mailbox-conf.c (mailbox_conf_view_new_full): use g_free as a weak-ref-notify instead of a wrapper. 2015-02-02 Peter Bloomfield Simplify notebook-label destruction * src/main-window.c (bw_notebook_label_new): use g_signal_connect_object to handle destruction of label, instead of a weak-ref. 2015-02-02 Peter Bloomfield Close compose windows on exit * src/sendmsg-window.c (balsa_sendmsg_destroy_handler), (sendmsg_window_new): weak-ref the main-window and close any compose window that is still open. 2015-02-02 Peter Bloomfield Prune some dead code * src/balsa-message.c (balsa_message_init), (balsa_message_new): close-with-msg is unused. * src/balsa-message.h: remove it, and its setter. * src/message-window.c (message_window_idle_handler), (mw_set_selected): setter has gone away. 2015-02-02 Peter Bloomfield Compose window may outlive main window * src/main-window.c (bw_send_msg_window_destroy_cb): check for NULL main-window. * src/sendmsg-window.c (balsa_sendmsg_destroy_handler): ditto. 2015-01-29 Peter Bloomfield Possible fix for RedHat bug #1050738 (Geoff Leach) * src/balsa-index.c (bndx_compose_foreach): check for NULL compose window. 2015-01-29 Peter Bloomfield Possible fix for RedHat bug #831889 (Geoff Leach) * src/sendmsg-window.c (collect_for_quote): check for NULL root. 2015-01-29 Peter Bloomfield Possible fix for RedHat bug #1097953 (Geoff Leach) * src/main-window.c (balsa_window_class_init), (balsa_window_new), (bw_close_mailbox_on_timer): use balsa_window_real_close_mbnode to close the mailbox instead of directly removing the notebook page. * src/message-window.c (destroy_message_window), (message_window_new): disconnect mailbox signals more carefully. 2015-01-28 Peter Bloomfield * balsa.appdata.xml: new appdata file 2015-01-28 Peter Bloomfield * src/balsa-icons.c (load_balsa_pixmap), (balsa_register_pixmaps): prune much pointless code. * src/sendmsg-window.c (subject_not_empty), (check_suggest_encryption): fix broken icons. * src/toolbar-factory.c (balsa_toolbar_new): ditto. 2015-01-28 Peter Bloomfield * src/ab-main.c (bab_cleanup), (set_address_book_menu_items), (get_main_menu), (bab_window_list_new), (bab_window_new), (ab_warning), (bab_set_intial_address_book), (main): streamline code. 2015-01-27 Peter Bloomfield Fix bug #741805 (Anders Jonsson) * help/C/balsa.sgml: fix spelling of "Portuguese". * src/sendmsg-window.c: ditto. 2015-01-27 Peter Bloomfield Deprecation cleanup * .gitignore: add "compile" * configure.ac: use webkit2gtk-4.0 * libbalsa/address.c (libbalsa_address_get_edit_widget): * libbalsa/html.c (lbh_navigation_policy_decision), (lbh_new_window_policy_decision): * libbalsa/imap/imap-handle.c: * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_select_key): * libbalsa/send.c: * libbalsa/url.c: * src/address-book-config.c (add_radio_buttons), (create_externq_dialog): * src/balsa-app.c (balsa_stock_button_with_label): * src/balsa-icons.c (load_balsa_pixmap): * src/balsa-message.c (bm_find_bar_new), (balsa_message_init): * src/balsa-mime-widget-crypto.c (balsa_mime_widget_signature_widget): * src/balsa-mime-widget-message.c (add_header_gchar), (add_header_sigstate): * src/balsa-mime-widget-vcalendar.c (balsa_mime_widget_new_vcalendar): * src/filter-edit-dialog.c (build_action_page): * src/main-window.c (bw_window_state_event_cb), (bw_is_active_notify), (bw_notebook_label_new), (bw_display_new_mail_notification): * src/main-window.h: * src/pref-manager.c (attach_label), (checking_group), (quoted_group), (mdn_group), (main_window_group), (add_pref_menu), (deleting_messages_group), (folder_scanning_group), (pm_group_new): * src/print-gtk.c (message_prefs_widget): * src/sendmsg-window.c (create_email_or_string_entry), (sw_attachment_list), (quote_parts_select_dlg), (subject_not_empty), (check_suggest_encryption): 2015-01-27 Peter Bloomfield * src/ab-main.c (bab_load_cb), (bab_set_address_book), (address_book_change_state), (set_address_book_menu_items), (address_book_change), (file_new_vcard_activated), (file_new_extern_activated), (file_new_ldif_activated), (file_new_ldap_activated), (file_new_gpe_activated), (file_new_rubrica_activated), (file_properties_activated), (file_delete_activated), (file_quit_activated), (entry_new_activated), (entry_delete_activated), (help_about_activated), (get_main_menu), (list_selection_changed_cb), (list_row_activated_cb), (bab_get_filter_box), (bab_window_new), (main): port to GApplication and friends. * ui/Makefile.am: add ab-main.ui. 2015-01-27 Peter Bloomfield * ui/ab-main.ui: GtkBuilder description of address-book editor UI. 2014-01-28 Pawel Salek * src/spell-check.c: do not use deprecated icon names. 2014-01-25 Peter Bloomfield Remove accelerators from app-menu; duplicate "new message", "address book", and "quit" on main-window's "file" menu. * src/main-window.c (bw_set_menus): duplicate "new message", "address book", and "quit" on main-window's "file" menu, with accelerators; * ui/main-window.ui: remove accelerators from app-menu. 2013-12-16 Albrecht Dreß * libbalsa/rfc3156.c (libbalsa_body_decrypt): tree view icons were handled differently for GPG and S/MIME. 2013-12-16 Albrecht Dreß Fix bgo #720443 (Lilith Bryant, dark141 at gmail dot com) * libbalsa/rfc3156.c (libbalsa_body_decrypt): trivial patch to fix the OL pk7 S/MIME issue. 2013-12-13 Peter Bloomfield Fix S/MIME sending and Outlook2007 reception; bgo #720423 (Lilith Bryant, dark141 at gmail dot com) * libbalsa/rfc3156.c (libbalsa_message_body_protection): x-pkcs7-mime is synonymous with pkcs7-mime; (libbalsa_encrypt_mime_object): use pkcs7 instead of leaking it. * src/balsa-message.c (libbalsa_msg_try_decrypt): x-pkcs7-mime is synonymous with pkcs7-mime. 2013-09-20 Peter Bloomfield Disable GtkInfoBar workarounds * libbalsa/html.c (lbh_info_bar): disable GtkInfoBar workaround. * src/balsa-mime-widget-message.c (bm_header_widget_new): ditto. 2013-09-14 Peter Bloomfield * src/balsa-mime-widget-message.c (bm_header_widget_new): replace GtkInfoBar with a simple GtkBox and a GtkButtonBox, because GtkInfoBar prevents the GtkLabel from wrapping (bgo #707093) 2013-08-30 Peter Bloomfield * src/balsa-mime-widget-message.c (bm_header_widget_new): make sure buttons are arranged vertically; would not be an issue, except that GtkLabels are not wrapped in a GtkInfoBar (bgo #707093). 2013-08-30 Peter Bloomfield * libbalsa/html.c (lbh_info_bar): make sure buttons are arranged vertically. 2013-08-30 Peter Bloomfield * libbalsa/html.c (lbh_info_bar): break message string into three separate lines, to work around GtkInfoBar breakage (bgo #707093). 2013-08-16 Peter Bloomfield Deprecation cleanup * src/main-window.h: * src/message-window.h: * src/sendmsg-window.h: * src/toolbar-factory.c: * src/toolbar-factory.h: 2013-08-16 Peter Bloomfield * src/sendmsg-window.c (sw_close_activated): mark window as being destroyed; (sw_get_action): check for window being destroyed, and return NULL if so; (sw_action_set_enabled), (sw_action_get_enabled), (sw_action_set_active), (sw_action_get_active): check for NULL action. 2013-08-15 Peter Bloomfield * src/main-window.c (bw_get_action): wrapper for g_action_map_lookup_action; (bw_action_set_boolean), (bw_action_get_boolean), (bw_action_set_string), (bw_action_set_enabled), (hide_change_state), (balsa_window_new), (balsa_window_update_book_menus): use it; (bw_set_filter_menu): use g_simple_action_set_state, to avoid recursion; (update_view_menu): remove redundant call to balsa_message_set_wrap. 2013-08-14 Peter Bloomfield * src/main-window.c (hide_change_state), (bw_set_filter_menu), (bw_filter_to_int): initialize the hide-messages menu items with g_simple_action_set_state instead of g_action_change_state, which does not seem to work for these items. 2013-08-13 Peter Bloomfield * src/toolbar-factory.c (tm_toolbar_weak_notify): disconnect model's "changed" signal handler when toolbar is destroyed. 2013-08-13 Pawel Salek * src/sendmsg-window.c: compile without gpgme. 2013-08-13 Peter Bloomfield * src/sendmsg-window.c (sendmsg_window_continue): fix action name. 2013-08-13 Peter Bloomfield * src/sendmsg-window.c (bsmsg_setup_gpg_ui_by_mode): set gpg mode correctly. 2013-08-13 Peter Bloomfield * src/sendmsg-window.c (init_menus): add transition code to read old message header choices. 2013-08-10 Peter Bloomfield * src/main-window.c (bw_action_set_boolean): use g_action_change_state instead of g_simple_action_set_state, so that the state is actually changed (Carlos Franke). 2013-08-04 Pawel Salek * src/sendmsg-window.c: compile with GtkSourceview 2013-07-31 Peter Bloomfield Port compose window to GMenu and friends * src/sendmsg-window.c (delete_event_cb), (sw_close_activated), (destroy_event_cb), (sw_edit_activated), (sw_select_ident_activated), (sw_get_action), (sw_action_set_enabled), (sw_actions_set_enabled), (sw_action_get_enabled), (sw_action_set_active), (sw_action_get_active), (update_bsmsg_identity), (add_urlref_attachment), (sw_attach_file_activated), (sw_include_messages_activated), (sw_attach_messages_activated), (sw_can_undo_cb), (sw_can_redo_cb), (quote_parts_select_dlg), (sw_insert_sig_activated), (sw_quote_activated), (sendmsg_window_get_toolbar_model), (bsmsg_identities_changed_cb), (insert_initial_sig), (bsm_prepare_for_setup), (bsm_finish_setup), (set_cc_from_all_recipients), (decode_and_strdup), (sendmsg_window_process_url), (sw_attach_file), (sw_include_file_activated), (subject_not_empty), (check_suggest_encryption), (send_message_handler), (sw_toolbar_send_activated), (sw_send_activated), (sw_queue_activated), (message_postpone), (sw_postpone_activated), (sw_save_activated), (sw_page_setup_activated), (sw_print_activated), (sw_buffer_insert_text), (sw_buffer_set_undo), (sw_spell_attach), (sw_undo_activated), (sw_redo_activated), (sw_cut_activated), (sw_copy_activated), (sw_paste_activated), (sw_select_text_activated), (sw_wrap_body_activated), (sw_reflow_activated), (check_readiness), (sw_entry_helper), (sw_from_change_state), (sw_recips_change_state), (sw_reply_to_change_state), (sw_fcc_change_state), (sw_request_mdn_change_state), (sw_show_toolbar_change_state), (sw_flowed_change_state), (sw_send_html_change_state), (sw_gpg_helper), (sw_sign_change_state), (sw_encrypt_change_state), (sw_gpg_mode_change_state), (init_menus), (sw_spell_check_change_state), (sw_spell_check_activated), (lang_set_cb), (bsmsg_update_gpg_ui_on_ident_change), (bsmsg_setup_gpg_ui), (bsmsg_setup_gpg_ui_by_mode), (sw_menubar_foreach), (sendmsg_window_new), (sendmsg_window_compose), (sendmsg_window_compose_with_address), (sendmsg_window_reply), (sendmsg_window_reply_embedded), (sendmsg_window_forward), (sendmsg_window_continue): * src/sendmsg-window.h: add member ready-to-send. * src/toolbar-factory.c (tm_toolbar_weak_notify), (balsa_toolbar_new): drop GtkUIManager code. * src/toolbar-prefs.c (customize_dialog_cb): ditto. * ui/Makefile.am: add sendmsg-window.ui. 2013-07-31 Peter Bloomfield * ui/sendmsg-window.ui: new file with xml input for GtkBuilder. 2013-07-29 Peter Bloomfield Fix part of bug #704718 (Geoffrey Leach). * src/pref-manager.c (apply_prefs), (set_prefs): apply and set BalsaApplication::fatal_message. 2013-07-28 Peter Bloomfield * src/message-window.c (mw_reset_show_all_headers), (mw_set_buttons_sensitive), (mw_set_message), (message_window_move_message), (mw_mru_menu_cb), (mw_select_part_cb), (message_window_new): move code to eliminate local declarations. 2013-07-28 Peter Bloomfield * src/message-window.c: make message-window a GtkApplicationWindow, and port menus from GtkUIManager to GtkBuilder and from GtkAction to GAction. * src/toolbar-prefs.c: temporarily disable editing message-window toolbar. * ui/message-window.ui: new file. * ui/Makefile.am: add it. 2013-07-28 Peter Bloomfield * libbalsa/application-helpers.c (libbalsa_window_get_menu_bar): add callback-data argument; (libbalsa_window_add_accelerator): new public method; (libbalsa_radio_activated): common callback for the "activated" signal of a radio-GAction. * libbalsa/application-helpers.h: new API. * libbalsa/source-viewer.c (libbalsa_show_message_source): use new API. * src/main-window.c (bw_set_menus): ditto, 2013-07-23 Peter Bloomfield * src/main-window.c (bw_alt_n_cb), (bw_set_alt_bindings), (balsa_window_new): restore n key bindings to change mailbox tab. 2013-07-22 Peter Bloomfield * src/main-window.c (toolbars_activated), (identities_activated), (bw_set_menus): restore Settings submenu. 2013-07-22 Peter Bloomfield * src/toolbar-factory.c (tm_load_model): do not load stale options. 2013-07-22 Peter Bloomfield * src/main-window.c (bw_set_menus): use installed ui file. * ui/Makefile.am: install it. * ui/main-window.ui: new file. 2013-07-22 Peter Bloomfield Move GAction-toggled callback to application-helpers * libbalsa/application-helpers.c (libbalsa_window_get_menu_bar), (libbalsa_toggle_activated): install GAction-toggled callback. * libbalsa/application-helpers.h: declare it. * libbalsa/source-viewer.c: use it. * src/main-window.c (bw_set_menus): ditto. 2013-07-22 Peter Bloomfield Make main-window a GtkApplicationWindow, and port menus from GtkUIManager to GtkBuilder and from GtkAction to GAction * src/main-window.c (balsa_window_get_toolbar_model), (bw_action_set_boolean), (bw_action_get_boolean), (bw_action_set_string), (bw_action_set_enabled), (bw_app_action_set_enabled), (bw_actions_set_enabled), (toggle_activated), (radio_activated), (bw_show_or_hide_widget), (new_message_activated), (new_mbox_activated), (new_maildir_activated), (new_mh_activated), (new_imap_box_activated), (new_imap_folder_activated), (new_imap_subfolder_activated), (address_book_activated), (prefs_activated), (help_activated), (about_activated), (quit_activated), (continue_activated), (get_new_mail_activated), (send_queued_mail_activated), (send_and_receive_mail_activated), (page_setup_activated), (print_activated), (copy_activated), (select_all_activated), (select_thread_activated), (find_activated), (find_next_activated), (find_in_message_activated), (filters_activated), (export_filters_activated), (expand_all_activated), (collapse_all_activated), (zoom_in_activated), (zoom_out_activated), (zoom_normal_activated), (next_message_activated), (previous_message_activated), (next_unread_activated), (next_flagged_activated), (reset_filter_activated), (mailbox_select_all_activated), (mailbox_edit_activated), (mailbox_delete_activated), (mailbox_expunge_activated), (mailbox_close_activated), (empty_trash_activated), (select_filters_activated), (remove_duplicates_activated), (reply_activated), (reply_all_activated), (reply_group_activated), (forward_attached_activated), (forward_inline_activated), (pipe_activated), (next_part_activated), (previous_part_activated), (save_part_activated), (view_source_activated), (copy_message_activated), (select_text_activated), (move_to_trash_activated), (toggle_flag), (toggle_flagged_activated), (toggle_deleted_activated), (toggle_new_activated), (toggle_answered_activated), (store_address_activated), (show_mailbox_tree_change_state), (show_mailbox_tabs_change_state), (show_toolbar_change_state), (show_statusbar_change_state), (show_sos_bar_change_state), (wrap_change_state), (hide_change_state), (bw_reset_show_all_headers), (header_change_state), (threading_change_state), (bw_set_menus), (bw_enable_next_unread), (balsa_window_new), (bw_enable_expand_collapse), (bw_next_unread_mailbox), (bw_enable_mailbox_menus), (balsa_window_update_book_menus), (bw_enable_message_menus), (bw_enable_edit_menus), (bw_enable_view_menus), (enable_empty_trash), (balsa_window_enable_continue), (bw_enable_part_menu_items), (bw_set_threading_menu), (bw_set_filter_menu), (bw_filter_to_int), (bw_get_condition_from_int), (balsa_window_open_mbnode), (balsa_window_close_mbnode), (bw_notebook_label_style), (bw_mailbox_changed), (bw_notebook_label_notify), (bw_notebook_label_new), (bw_real_open_mbnode_idle_cb), (bw_real_open_mbnode_thread), (balsa_window_real_open_mbnode), (bw_focus_idle), (balsa_window_real_close_mbnode), (balsa_identities_changed), (bw_close_mailbox_on_timer), (balsa_window_destroy), (balsa_window_refresh), (bw_register_open_mailbox), (bw_unregister_open_mailbox), (bw_is_open_mailbox), (bw_check_mailbox_list), (bw_add_mbox_to_checklist), (bw_imap_check_test), (bw_progress_dialog_destroy_cb), (bw_progress_dialog_response_cb), (ensure_check_mail_dialog), (bw_mailbox_check), (check_new_messages_real), (bw_check_new_messages), (check_new_messages_count), (bw_check_messages_thread_idle_cb), (bw_check_messages_thread), (mail_progress_notify_cb), (send_progress_notify_cb), (bw_get_new_message_notification_string), (bw_display_new_mail_notification), (mw_mbox_change_connection_status), (bw_change_connection_status_idle), (balsa_window_find_current_index), (bw_open_mailbox_cb), (bw_find_real), (bw_hide_changed_set_view_filter), (bw_reset_filter), (update_view_menu), (balsa_window_set_statusbar), (balsa_window_next_unread): * src/main-window.h: BalsaWindow now subclasses GtkApplicationWindow. * src/message-window.c (message_window_new): use new toolbar API. * src/sendmsg-window.c (sendmsg_window_new): ditto. * src/toolbar-factory.c (balsa_toolbar_model_add_entries), (tm_has_second_line), (tm_changed_cb), (tm_changed_old_cb), (tm_toolbar_weak_notify), (tm_realize_cb), (balsa_toolbar_new): main-window has a GActionMap, not a GtkUIManager. * src/toolbar-factory.h: temporary API. * src/toolbar-prefs.c (customize_dialog_cb), (create_toolbar_page): temporary transition code. 2013-07-22 Peter Bloomfield * src/balsa-icons.c (load_balsa_pixmap): do not leak pixbuf. 2013-07-22 Peter Bloomfield * src/balsa-icons.c (load_balsa_pixmap): add built-in icon with the correct size. 2013-07-22 Peter Bloomfield More GtkStock deprecation cleanup * src/balsa-app.c (balsa_stock_button_with_label): * src/balsa-icons.c (load_balsa_pixmap), (balsa_register_pixmaps), (balsa_register_pixbufs): * src/balsa-message.c (bm_header_tl_buttons): * src/balsa-mime-widget-crypto.c (balsa_mime_widget_crypto_frame): * src/main-window.c: 2013-07-21 Peter Bloomfield * libbalsa/application-helpers.c (extract_accels_from_menu), (get_accel_group), (libbalsa_window_get_menu_bar): make the application-window not show the application's menubar here. * libbalsa/source-viewer.c (libbalsa_show_message_source): instead of here. 2013-07-21 Peter Bloomfield * libbalsa/application-helpers.c (accel_info_free), (accel_activate), (extract_accel_from_menu_item), (extract_accels_from_menu), (libbalsa_window_get_accel_group), (libbalsa_window_get_menu_bar): new file defining libbalsa_window_get_menu_bar. * libbalsa/application-helpers.h: ditto. * libbalsa/Makefile.am: add them to SOURCES. * libbalsa/source-viewer.c: use libbalsa_window_get_menu_bar to construct the menu-bar and add the accelerators to the window. 2013-07-21 Peter Bloomfield More GtkStock deprecation cleanup * src/balsa-index.c (bndx_popup_menu_create), (create_stock_menu_item): * src/balsa-message.c (bm_header_tl_buttons), (get_crypto_content_icon): * src/balsa-mime-widget-crypto.c (balsa_mime_widget_crypto_frame): * src/balsa-mime-widget-image.c (balsa_mime_widget_new_image): * src/balsa-mime-widget-text.c (bmwt_populate_popup_menu): 2013-07-20 Peter Bloomfield * README: minor updates. 2013-07-20 Peter Bloomfield Install and use a directory for GtkBuilder *.ui files * ui/Makefile.am: new file. * ui/main-window.ui: ditto. * ui/source-viewer.ui: ditto. * Makefile.am: add ui to SUBDIRS. * configure.ac: add ui/Makefile to AC_OUTPUT. * libbalsa/source-viewer.c: use installed ui file. 2013-07-20 Peter Bloomfield * src/main-window.c: use new prototype for source viewer. 2013-07-20 Peter Bloomfield * libbalsa/source-viewer.c (lsv_close_activated), (lsv_copy_activated), (lsv_select_activated), (lsv_toggle_activated), (lsv_escape_change_state), (lsv_app_set_menus), (libbalsa_show_message_source): port source viewer to GMenu. * libbalsa/libbalsa.h: new prototype for source viewer. * src/balsa-index.c (bndx_view_source): use it. * src/message-window.c (view_msg_source_cb): ditto. * src/sendmsg-window.c (sendmsg_window_new_from_list): ditto. 2013-07-18 Peter Bloomfield More GtkStock deprecation cleanup * configure.ac: to build, we must drop -DGDK_MULTIHEAD_SAFE. * libbalsa/files.c (libbalsa_icon_finder): gtk_icon_size_lookup_for_settings is deprecated for gtk_icon_size_lookup. * src/balsa-index.c (balsa_index_set_column_widths): ditto. * src/balsa-app.c (balsa_stock_button_with_label): gtk_image_new_from_stock is deprecated for gtk_image_new_from_icon_name. 2013-07-18 Peter Bloomfield Clean up deprecation of stock icons * libbalsa/html.c (lbh_info_bar), (lbh_show_info_bar): * libbalsa/identity.c (libbalsa_identity_select_dialog), (libbalsa_identity_config_dialog): * libbalsa/information.c (libbalsa_information_varg): * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_select_key), (get_passphrase_real): * libbalsa/send.c (ensure_send_progress_dialog): * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): * libbalsa/source-viewer.c: * src/ab-main.c (bab_get_edit_button_box), (bab_get_filter_box): * src/ab-window.c (balsa_ab_window_new), (balsa_ab_window_init): * src/address-book-config.c (create_local_dialog), (create_generic_dialog): * src/balsa-app.c (ask_password_real): * src/balsa-icons.c (load_balsa_pixmap), (balsa_register_pixbufs): * src/balsa-icons.h: * src/balsa-index.c (bndx_popup_menu_create), (balsa_index_pipe): * src/balsa-mblist.c (bmbl_mru_show_tree): * src/balsa-message.c (part_context_dump_all_cb): * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_ctx_menu_save): * src/balsa-mime-widget-image.c (balsa_mime_widget_new_image): * src/balsa-mime-widget-text.c (bmwt_populate_popup_menu): * src/filter-edit-callbacks.c (fe_edit_condition): * src/filter-edit-dialog.c (build_left_side), (build_action_page), (build_right_side), (filters_edit_dialog): * src/filter-export-dialog.c (filters_export_dialog): * src/filter-run-dialog.c (balsa_filter_run_dialog_init): * src/folder-conf.c (folder_conf_imap_node), (browse_button_cb), (folder_conf_imap_sub_node): * src/information-dialog.c (balsa_information_list): * src/mailbox-conf.c (mailbox_conf_delete), (create_local_mailbox_dialog), (create_generic_dialog): * src/main-window.c: * src/message-window.c: * src/pref-manager.c (open_preferences_manager): * src/sendmsg-window.c (delete_handler), (sw_get_user_codeset), (add_urlref_attachment), (sw_attach_dialog), (quote_parts_select_dlg), (include_file_cb), (subject_not_empty), (check_suggest_encryption), (bsmsg_check_format_compatibility): * src/spell-check.c (balsa_spell_check_init): * src/store-address.c (store_address_dialog): * src/toolbar-factory.c: * src/toolbar-prefs.c (customize_dialog_cb), (create_toolbar_page): 2013-07-14 Peter Bloomfield Fix bgo #704159 (Igor Pashev) * configure.ac: add check for struct utsname.domainname, and AC_USE_SYSTEM_EXTENSIONS. * libbalsa/filter-file.c: do not define __EXTENSIONS__. * libbalsa/send.c (libbalsa_set_message_id): check HAVE_STRUCT_UTSNAME_DOMAINNAME as well as _GNU_SOURCE. 2013-06-23 Peter Bloomfield * src/sendmsg-window.c (to_add), (create_email_entry): restore drag-and-drop of a string to the To: header. 2013-06-23 Peter Bloomfield * src/sendmsg-window.c (create_email_entry), (sw_attachment_list): clean up dead and redundant code. 2013-06-21 Peter Bloomfield * src/sendmsg-window.c (create_email_or_string_entry), (create_string_entry), (create_email_entry), (create_from_entry), (create_info_pane): consolidate most size-group code. 2013-06-21 Peter Bloomfield * src/sendmsg-window.c (create_info_pane), (sw_attachment_list): use a GtkSizeGroup to restore alignment of attachment list. * src/sendmsg-window.h: new member size_group. 2013-06-21 Peter Bloomfield * src/sendmsg-window.c (drag_data_quote), (bsmsg2message), (send_message_handler): check for NULL tree-view. 2013-06-21 Peter Bloomfield * src/sendmsg-window.c (remove_attachment), (change_attach_mode), (show_attachment_widget), (add_attachment), (add_urlref_attachment), (create_info_pane), (sw_attachment_list), (sendmsg_window_new): put attachment list in its own pane. * src/sendmsg-window.h: add members tree_view and paned, and remove member attachments[]. 2013-06-17 Peter Bloomfield * src/sendmsg-window.c (create_info_pane): allow the recipients widget and the attachments list to expand; (sendmsg_window_new): use a GtkPaned to allow the user to change the space allocated to the headers. 2013-06-10 Peter Bloomfield * src/save-restore.c (config_global_load): change default to UseSystemFonts=true. * src/balsa-app.c (balsa_app_init): ditto. 2013-06-09 Peter Bloomfield Add the option to use system fonts * src/balsa-app.h: new member gboolean use_system_fonts. * src/balsa-app.c (balsa_app_init): initialize it. * src/balsa-mime-widget-message.c (add_header_gchar): respect it. * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (bm_modify_font_from_string): ditto. * src/pref-manager.c (open_preferences_manager), (apply_prefs), (attach_font_button), (preview_font_group), (use_system_fonts_cb): allow user to choose it. * src/save-restore.c (config_global_load), (config_save): save and restore it. * src/sendmsg-window.c (create_email_or_string_entry), (create_text_area): respect it also for compose window. 2013-05-30 Peter Bloomfield * src/sendmsg-window.c (balsa_sendmsg_destroy_handler), (sw_broker_cb), (create_lang_menu), (sendmsg_window_continue), (sw_spell_language_changed_cb), (sw_spell_attach), (set_locale), (lang_set_cb): handle language changes fromGtkSpell's context menu. * src/sendmsg-window.h: spell_check_lang is no longer const. 2013-05-29 Peter Bloomfield GNOME Goal: Notification Sources * balsa.desktop.in.in: add X-GNOME-UsesNotifications=true * libbalsa/information.c (libbalsa_information_varg): set "desktop-entry" hint for NotifyNotification. * src/main-window.c: ditto. 2013-05-28 Peter Bloomfield * configure.ac: check GtkSpell version, and avoid explicit dependence on enchant when possible. * src/sendmsg-window.c: use gtkspell_get_language_list when available, instead of enchant API. 2013-05-26 Peter Bloomfield * src/main-window.c: report network availability with a human-readable time; combine two idle callbacks into one. 2013-05-22 Peter Bloomfield Cast new mailboxes as LibBalsaMailbox, to reduce static and dynamic casting. * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_new): return new mailbox as (LibBalsaMailbox *). * libbalsa/mailbox_imap.h: ditto. * libbalsa/mailbox_local.c: ditto. * libbalsa/mailbox_local.h: ditto. * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_new): ditto. * libbalsa/mailbox_maildir.h: ditto. * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_new): ditto. * libbalsa/mailbox_mbox.h: ditto. * libbalsa/mailbox_mh.c (libbalsa_mailbox_mh_new): ditto. * libbalsa/mailbox_mh.h: ditto. * libinit_balsa/assistant_page_directory.c (unconditional_mailbox): remove static casts to (LibBalsaMailbox *). * src/mailbox-node.c (imap_scan_attach_mailbox), (balsa_mailbox_node_new_imap), (add_local_mailbox): avoid dynmaic casts to LIBBALSA_MAILBOX. 2013-05-22 Peter Bloomfield * src/balsa-message.c (part_info_init): do not mess with scroll bars. * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): ditto. 2013-05-22 Peter Bloomfield * src/sendmsg-window.c (create_info_pane): use create_email_or_string_entry for Fcc header. 2013-05-20 Peter Bloomfield * libbalsa/html.c: drop obsolete include. 2013-05-19 Peter Bloomfield Implement add-messages at LibBalsaMailboxLocal level, and use a new add-message method for the backends. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_class_init): new add-messages method. * libbalsa/mailbox_local.h: new member LibBalsaMailboxLocalClass::add_message. * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_class_init), (lbm_maildir_add_message): implement LibBalsaMailboxLocalClass::add_message. * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_class_init), (lbm_mbox_add_message): ditto. * libbalsa/mailbox_mh.c (libbalsa_mailbox_mh_class_init), (lbm_mh_add_message): ditto. 2013-05-18 Peter Bloomfield * libbalsa/mailbox_local.c: avoid zero-divide. * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_open): do not change LibBalsaMailboxLocal::sync_time or ::sync_cnt. * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_open): ditto. * libbalsa/mailbox_mh.c (libbalsa_mailbox_mh_open): ditto. 2013-05-18 Peter Bloomfield * libbalsa/mailbox_local.c: restore syncing mailbox in a thread. 2013-05-16 Peter Bloomfield * libbalsa/imap/imap-handle.c (idle_start): use try-lock to avoid blocking main thread; (imap_handle_idle_enable): use g_timeout_add_seconds. 2013-05-16 Peter Bloomfield * libbalsa/mailbox.h: scrap LibBalsaMailboxView::mailing_list_address. * libbalsa/mailbox.c (libbalsa_mailbox_view_free): ditto. * src/save-restore.c (config_load_mailbox_view), (config_save_mailbox_view): ditto. * src/sendmsg-window.c (set_list_post_address): ditto. 2013-05-04 Peter Bloomfield * src/balsa-mime-widget-message.c (add_header_sigstate): fix typo. 2013-05-02 Peter Bloomfield * configure.ac: bump glib and gtk required versions. * libbalsa/imap-server.c (libbalsa_imap_server_init), (libbalsa_imap_server_finalize): drop conditional code. * libbalsa/libbalsa-conf.c (lbc_lock), (lbc_unlock): ditto. * libbalsa/libbalsa.c (libbalsa_init): ditto. * libbalsa/mime-stream-shared.c (lbmss_stream_class_init), (libbalsa_mime_stream_shared_lock), (libbalsa_mime_stream_shared_unlock): ditto. * libinit_balsa/assistant_page_user.c (balsa_druid_page_user_init): ditto. * src/balsa-mime-widget-text.c (bm_widget_new_vcard): ditto. * src/balsa-mime-widget-vcalendar.c (balsa_vevent_widget): ditto. * src/filter-edit-callbacks.c (fe_apply_pressed), (fe_filters_list_selection_changed): ditto. * src/filter-edit-dialog.c (fe_make_color_buttons): ditto. * src/folder-conf.c (folder_conf_imap_sub_node): ditto. * src/main-window.c: ditto. * src/main-window.h: ditto. * src/main.c (threads_init): ditto. * src/sendmsg-window.c (render_attach_size): ditto. 2013-05-02 Peter Bloomfield * libbalsa/libbalsa.c (libbalsa_init): reduce glib requirement to 2.32. * src/main.c (threads_init): ditto. * src/balsa-message.c (balsa_message_init): typo. 2013-05-01 Peter Bloomfield Replace "ghelp:" help URIs by "help:" URIs * libbalsa/identity.c (help_ident_cb): * libbalsa/smtp-server.c (smtp_server_response): * src/address-book-config.c (help_button_cb): * src/filter-edit-callbacks.c (condition_dialog_response), (fe_dialog_response): * src/filter-run-callbacks.c (fr_dialog_response): * src/folder-conf.c (folder_conf_response): * src/main-window.c: * src/pref-manager.c (balsa_help_pbox_display): * src/toolbar-prefs.c (tp_dialog_response_cb): 2013-04-30 Peter Bloomfield * configure.ac: fix broken NetworkManager-glib logic. 2013-04-29 Peter Bloomfield * src/sendmsg-window.c (delete_handler): tell the user the message is to "(No name)" only as a last resort; thanks to Jack Ostroff for reporting. 2013-04-27 Pawel Salek * NEWS: release balsa-2.5.1 2013-04-27 Peter Bloomfield Port to new documentation infrastructure * .gitignore: change as in * Makefile.am: ditto. * autogen.sh: remove gnome-doc-tool code. * bootstrap.sh: ditto. * configure.ac: test `which yelp-build` to detect yelp-tools package, warn if not found, but continue to configure with documentation disabled. 2013-04-25 Peter Bloomfield Improve path checking in the first-time assistant * libinit_balsa/assistant_helper.c (balsa_init_add_grid_entry): return the GtkEntry. * libinit_balsa/assistant_helper.h: modified API. * libinit_balsa/assistant_page_directory.c (unconditional_mailbox): report NULL mailbox error; (verify_mailbox_entry), (verify_button_clicked_cb), (verify_button): add a button for the user to verify paths. (entry_changed_cb), (balsa_druid_page_directory_init): desensitize the "next" button when any entry is changed, to make the user verify the new path; (balsa_druid_page_directory): set row spacing for vbox; (balsa_druid_page_directory_prepare): desensitize the "next" button initially; (balsa_druid_page_directory_back): declare as void, not gboolean. (balsa_druid_page_directory_next): ditto; move path verification to verify_mailbox_entry. * libinit_balsa/assistant_page_directory.h: remove Entry{Data,Master} members, and for convenience add GtkAssistant *druid; balsa_druid_page_directory_later is conditional on ENABLE_TOUCH_UI. 2013-04-25 Peter Bloomfield * configure.ac: detect _FILE_OFFSET_BITS in configure.ac; pancake, https://github.com/xtraeme/xbps-packages/commit/ a06181186ef559d84c120e3e9a3a557d4e4914dc. 2013-04-23 Peter Bloomfield * src/main-window.c: build with glib < 2.32. 2013-04-23 Peter Bloomfield Clean up LibESMTP header includes * libbalsa/message.h: * libbalsa/misc.h: * libbalsa/send.c: * libbalsa/send.h: * libbalsa/smtp-server.c: * libbalsa/smtp-server.h: 2013-04-23 Peter Bloomfield * configure.ac: fix URI for finding libesmtp. 2013-04-23 Peter Bloomfield * Makefile.am: use HAVE_GNOME_DOC_UTILS instead of BUILD_WITH_G_D_U. * configure.ac: make sure HAVE_GNOME_DOC_UTILS and ENABLE_SK are defined. 2013-04-22 Peter Bloomfield More efficient use of space in header widget * src/balsa-message.c (display_face): hide the face-box when empty. * src/balsa-mime-widget-message.c (bm_header_widget_new): allow the face-box to be non-homogeneous. 2013-04-22 Peter Bloomfield Port to GNetworkMonitor from NetworkManager * configure.ac: if configure --with-nm when GNetworkMonitor is available (glib >= 2.32), announce that we will actually use GNetworkMonitor. * src/main-window.c: Use GNetworkMonitor, when available, instead of NetworkManager. * src/main-window.h: replace NMState nm_state with gboolean network_available. 2013-04-22 Peter Bloomfield New message header widget, based on GtkInfoBar * src/balsa-message.c (bm_header_tl_buttons), (balsa_message_init): return an array of buttons instead of a widget; (display_face): get container from BalsaMessage. * src/balsa-message.h: new member. * src/balsa-mime-widget-message.c (balsa_mime_widget_new_message_tl), (bm_header_extend_popup), (bm_header_widget_new), (label_size_allocate_cb), (expanded_cb), (add_header_gchar), (add_header_address_list), (foreach_label), (balsa_mime_widget_message_set_headers), (balsa_mime_widget_message_set_headers_d), (add_header_sigstate): new widget. * src/balsa-mime-widget-message.h: new API for passing buttons. 2013-04-22 Peter Bloomfield * src/balsa-index.c (bndx_scroll_on_open_idle), (balsa_index_scroll_on_open): scroll in an idle handler, after the mailbox has been opened. 2013-04-16 Peter Bloomfield * libbalsa/address-view.c (lbav_drop_down_activated_cb), (libbalsa_address_view_new): use LibBalsaCellRendererButton for the drop-down icon, so that we can drop down the combo-box when the icon is clicked. 2013-04-15 Peter Bloomfield Fix miscounting of unread messages * libbalsa/mailbox_local.h: new member gboolean _LibBalsaMailboxLocalMessageInfo::loaded. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_load_message), (lbm_local_restore_tree): use it to indicate when we are changing flags on a message that has not yet been counted. * libbalsa/mailbox_mbox.c (parse_mailbox), (lbm_mbox_restore): initialize it to FALSE. 2013-04-12 Peter Bloomfield * src/balsa-mime-widget-message.c (bm_header_widget_realized): set colors from the treeview instead of the scrolled window. 2013-04-11 Peter Bloomfield * libbalsa/misc.c (lb_create_size_group_func): we no longer use GtkTable. 2013-04-11 Peter Bloomfield * src/balsa-message.c (bm_on_set_style), (bm_find_scroll_to_rectangle), (balsa_message_init), (select_part): remove dependence on GtkViewPort. * src/balsa-message.h: ditto. * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_key_press_event): ditto. * src/balsa-mime-widget-image.c (balsa_mime_widget_new_image): ditto. 2013-04-11 Peter Bloomfield * src/toolbar-prefs.c (create_toolbar_page): gtk_scrolled_window_add_with_viewport is deprecated. 2013-04-11 Peter Bloomfield * libbalsa/misc.c (lb_create_size_group_func): GtkTable is deprecated. 2013-04-11 Peter Bloomfield * libbalsa/libbalsa.c (libbalsa_init): g_thread_supported is deprecated in glib-2.36. 2013-04-10 Peter Bloomfield * src/balsa-mblist.c (update_mailbox_idle), (bmbl_mailbox_changed_cb): replace Gdk lock with our own lock. 2013-04-09 Peter Bloomfield * libbalsa/imap/imap_tst.c (main): g_type_init is deprecated. * src/main.c (threads_init): ditto. 2013-04-08 Peter Bloomfield * configure.ac: add webkit2 as an option for --with-html-widget. 2013-04-08 Peter Bloomfield * libbalsa/html.c (lbh_get_web_view): can-select and select-all sometimes pass the web-view and sometimes the container. * src/balsa-mime-widget-text.c (bm_select_all_cb), (bmwt_populate_popup_menu): add "select all" to the webKitWebView context menu, the same as for a GtkTextView 2013-04-08 Peter Bloomfield * libbalsa/html.c (lbh_context_menu_cb): pass the GdkEvent when emitting "popup-menu"; * libbalsa/html.h: define key for GdkEvent. * src/balsa-mime-widget-text.c (balsa_gtk_html_popup): use it to pass the event time when popping up the menu. 2013-04-08 Peter Bloomfield * libbalsa/send.c (libbalsa_set_message_id): constify two strings. 2013-04-07 Peter Bloomfield * src/balsa-mime-widget-message.c (bmwm_set_headers_d_idle_cb), (balsa_mime_widget_message_set_headers_d): queue iheader widget resize in an idle handler, to get the size right the first time. * src/main-window.c: initially hide the preview. 2013-04-06 Peter Bloomfield * configure.ac: simplify WebKit2 configuration. 2013-04-06 Peter Bloomfield * configure.ac: require GtkSourceView 3.2 * src/sendmsg-window.c: gtksource.h is the main header; fixes bgo #697454 (Dominique Leuenberger). 2013-04-06 Peter Bloomfield * libbalsa/html.c (libbalsa_html_popup_menu_widget), (libbalsa_html_print): actually print the HTML part. 2013-04-05 Peter Bloomfield * libbalsa/html.c (lbh_context_menu_cb), (libbalsa_html_new): catch WebKit's "context-menu" signal, and emit "popup-menu" on the parent widget instead. * src/balsa-mime-widget-text.c (balsa_gtk_html_popup): do not unref the popup menu. 2013-04-04 Peter Bloomfield * libbalsa/html.c (lbh_info_bar_response_cb): no need to reload; (lbh_resource_load_started_cb): no need for cache; (lbh_cid_cb), (libbalsa_html_new): register the "cid:" protocol handler only once, to avoid crashing the web process. 2013-04-04 Peter Bloomfield Handle "cid:" protocol for images * libbalsa/html.c (lbh_info_bar_response_cb), (lbh_info_bar): simplify info-bar code. (lbh_resource_load_started_cb), (lbh_cid_cb), (libbalsa_html_new): set up a handler for "cid:" protocol. 2013-04-03 Peter Bloomfield * libbalsa/filter-funcs.c (append_header_names), (append_flag_names): do not mark text-free string for translation. * libbalsa/imap-server.c (is_info_cb): ditto. 2013-04-02 Peter Bloomfield * libbalsa/html.c (lbh_get_body_content_utf8): sanitize UTF-8 text. 2013-03-31 Peter Bloomfield Do not leak search-text * libbalsa/html.c (lbh_webkit_info_free), (libbalsa_html_new), (lbh_search_failed_to_find_text_cb), (lbh_search_found_text_cb), (lbh_search_init), (lbh_search_continue), (libbalsa_html_search): move search info to LibBalsaWebKitInfo, and free search-text in the GDestroyNotify function. 2013-03-30 Peter Bloomfield Refactor HTML search code to work with asynchronous search in Webkit2. * libbalsa/html.c (lbh_web_process_crashed_cb): spew message only when debugging; (lbh_search_failed_to_find_text_cb), (lbh_search_found_text_cb), (lbh_search_init), (lbh_search_continue), (libbalsa_html_search): work with asynchronous search; (libbalsa_html_get_selection_bounds): is now gboolean, return FALSE in Webkit2 version. * libbalsa/html.h: new protoypes. * src/balsa-message.c (bm_find_cb), (bm_find_entry_changed_cb), (bm_find_again), (balsa_message_destroy): work with asynchronous search. * src/balsa-message.h: add gpointer member to store HTML search info. 2013-03-28 Peter Bloomfield * libbalsa/html.c (lbh_navigation_policy_decision), (lbh_new_window_policy_decision), (lbh_response_policy_decision): Clicking a link may cause a new window policy decision, instead of a navigation policy decision; we handle both cases. 2013-03-27 Peter Bloomfield * libbalsa/html.c: reduce zoom factor to +/- 20%. 2013-03-27 Peter Bloomfield * libbalsa/html.c (lbh_info_bar_response_cb), (lbh_info_bar_realize_cb), (lbh_show_info_bar), (lbh_resource_load_started_cb), (libbalsa_html_new): Use regex scan of HTML text to detect downloads, because Webkit2 does not alert us in time to control them. 2013-03-24 Peter Bloomfield Initial check in support for WebKitGtk2 * configure.ac: add webkit2 as an html-engine option; default is still webkit. * libbalsa/html.c (lbh_get_body_content_utf8), (lbh_webkit_info_free), (lbh_mouse_target_changed_cb), (lbh_navigation_policy_decision), (lbh_new_window_policy_decision), (lbh_response_policy_decision), (lbh_decide_policy_cb), (lbh_info_bar_response_cb), (lbh_show_info_bar), (lbh_resource_load_started_cb), (lbh_web_process_crashed_cb), (libbalsa_html_new), (libbalsa_html_to_string), (lbh_get_web_view), (libbalsa_html_can_zoom), (libbalsa_html_zoom), (libbalsa_html_can_select), (libbalsa_html_select_all), (libbalsa_html_copy), (libbalsa_html_can_search), (lbh_js_run_script), (lbh_js_object_get_property), (libbalsa_html_search_text), (libbalsa_html_get_selection_bounds), (libbalsa_html_popup_menu_widget), (libbalsa_html_get_view_widget), (libbalsa_html_can_print), (libbalsa_html_print): support webkit2 option. 2013-03-21 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_set_view_filter): clean up logic. 2013-03-21 Peter Bloomfield * src/main-window.c: set mailbox view filter on opening, not on notebook page change. 2013-03-19 Peter Bloomfield * src/balsa-index.c (balsa_index_load_mailbox_node), (bndx_mailbox_changed_cb): connect signal not swapped. 2013-03-19 Peter Bloomfield GdkThreads deprecation cleanup * libbalsa/libbalsa.c (libbalsa_lock_mailbox), (libbalsa_unlock_mailbox): strip out GdkThreads-related code. * libbalsa/libbalsa.h: ditto. * libbalsa/mailbox.c (libbalsa_mailbox_msgno_find), (mbox_model_get_path), (libbalsa_mailbox_search_iter_step): ditto. * src/main.c (threads_init), (threads_destroy): ditto. 2013-03-19 Peter Bloomfield * src/main-window.c: use thread to check for new mail. 2013-03-17 Peter Bloomfield * src/mailbox-node.c (mb_rescan_cb): reopen mailboxes in the UI callback, (balsa_mailbox_node_rescan): not in the recursive function * src/balsa-app.c (balsa_open_mailbox_list): make sure first mailbox in the list is not hidden. 2013-03-17 Peter Bloomfield * src/balsa-app.c (open_mailbox_by_url), (balsa_open_mailbox_list): change gboolean open_mailboxes_idle_cb() to void balsa_open_mailbox_list(). * src/balsa-app.h: ditto. * src/mailbox-node.c (balsa_mailbox_node_rescan): ditto. * src/main.c (open_mailboxes_idle_cb), (scan_mailboxes_idle_cb): open_mailboxes_idle_cb is now just the idle callback. 2013-03-17 Peter Bloomfield Reopen mailboxes after rescanning * src/mailbox-node.c (imap_dir_cb): do not unref mbnode; (imap_scan_create_mbnode): do not ref mbnode; protect view during rescanning; (balsa_mailbox_node_rescan): reopen mailboxes after scanning. 2013-03-17 Peter Bloomfield * libbalsa/libbalsa-conf.c (libbalsa_conf_sync), (libbalsa_conf_sync_idle_cb): remove source in public method. 2013-03-16 Peter Bloomfield * libbalsa/mailbox_local.c (lbm_local_queue_save_tree): build with threads disabled. 2013-03-16 Peter Bloomfield * libbalsa/libbalsa-conf.c (libbalsa_conf_sync_idle_cb), (libbalsa_conf_queue_sync): fix error and use lock only when using threads. 2013-03-16 Peter Bloomfield Queue config syncs instead of syncing immediately, except on exit cleanup * libbalsa/libbalsa-conf.c (libbalsa_conf_sync_idle_cb), (libbalsa_conf_queue_sync): new API libbalsa_conf_queue_sync. * libbalsa/libbalsa-conf.h: ditto. * src/ab-main.c (address_book_change), (file_delete_cb): use it. * src/save-restore.c (config_address_book_save), (config_address_book_delete), (config_mailbox_add), (config_folder_add), (config_mailbox_delete), (config_folder_delete), (config_mailbox_update), (config_folder_update), (config_filters_save), (config_mailbox_filters_save): ditto. 2013-03-16 Peter Bloomfield * src/main-window.c: do not leak object refs on error. 2013-03-16 Peter Bloomfield * src/mailbox-node.c (balsa_mailbox_node_dispose): make sure LibBalsaMailboxView::open is correct before saving the view. 2013-03-15 Peter Bloomfield * src/balsa-app.c (append_url_if_open): libbalsa_conf_foreach passes an encoded URL. * src/mailbox-node.c (check_url_func): ditto. 2013-03-14 Peter Bloomfield Streamline handling of LibBalsaMailboxView * libbalsa/mailbox.c (libbalsa_mailbox_finalize): free the view; (libbalsa_mailbox_view_free), (lbm_get_view): check for NULL view; (libbalsa_mailbox_set_identity_name), (libbalsa_mailbox_set_threading_type), (libbalsa_mailbox_set_sort_type), (libbalsa_mailbox_set_sort_field), (libbalsa_mailbox_set_show), (libbalsa_mailbox_set_subscribe), (libbalsa_mailbox_set_exposed), (libbalsa_mailbox_set_open), (libbalsa_mailbox_set_filter), (libbalsa_mailbox_set_unread), (libbalsa_mailbox_set_total), (libbalsa_mailbox_set_mtime), (libbalsa_mailbox_get_filter): drop LibBalsaMailboxView::frozen and the hash table. * libbalsa/mailbox.h: ditto. * src/balsa-app.c (balsa_app_destroy), (append_url_if_open), (open_mailbox_by_url), (open_mailboxes_idle_cb), (balsa_add_open_mailbox_urls): traverse views in the config instead of in the hash table. * src/mailbox-conf.c (mailbox_conf_add), (mailbox_conf_view_check): ditto. * src/mailbox-node.c (balsa_mailbox_node_dispose), (check_url_func), (check_local_path), (load_mailbox_view), (check_imap_path): ditto. * src/pref-manager.c (update_view_defaults), (apply_prefs): ditto. * src/main.c (real_main), (balsa_cleanup): no hash table. * src/save-restore.c (config_view_remove), (config_defclient_save): no hash table. (config_mailbox_had_property), (config_mailbox_was_open), (config_mailbox_was_exposed), (config_load_mailbox_view), (config_save_mailbox_view): new methods. * src/save-restore.h: ditto. 2013-03-14 Peter Bloomfield * libbalsa/libbalsa-conf.c (libbalsa_conf_has_key): new function. * libbalsa/libbalsa-conf.h: ditto. 2013-03-11 Peter Bloomfield Lock mailbox to avoid race * libbalsa/mailbox.c (lbm_changed_idle_cb), (lbm_changed_schedule_idle), (libbalsa_mailbox_changed), (lbm_check_idle), (lbm_queue_check): lock the mailbox while storing the id of an idle call, to avoid a race with the main thread callback. * libbalsa/mailbox_local.c (lbm_local_queue_save_tree), (lbml_load_messages_idle_cb), (libbalsa_mailbox_local_load_messages), (libbalsa_mailbox_local_prepare_threading): ditto. 2013-03-07 Peter Bloomfield Use --with-gnome more carefully * configure.ac: set HAVE_GNOME when configuring --with-gnome. * libinit_balsa/assistant_init.c (balsa_initdruid): default-client makes sense on non-GNOME builds. * libinit_balsa/assistant_page_defclient.c (balsa_druid_page_defclient_toggle): ditto. * libinit_balsa/assistant_page_defclient.h: ditto. * src/main.c (config_init), (mailboxes_init): ditto. * src/save-restore.c (config_defclient_save): ditto. * src/main-window.c: gnome-triggers code is totally dead. 2013-03-06 Peter Bloomfield * src/main.c (scan_mailboxes_idle_cb): do not pass unowned string. 2013-03-06 Peter Bloomfield Combine all mailboxes to be opened at startup into a single array. * src/balsa-app.c (open_mailboxes_idle_cb), (balsa_add_open_mailbox_urls): * src/balsa-app.h: new method balsa_add_open_mailbox_urls; drop hacky extra-open-ref. * src/main.c (initial_open_inbox), (balsa_check_open_mailboxes), (scan_mailboxes_idle_cb), (balsa_cleanup), (handle_remote): collect mailbox URLs in an array. 2013-03-06 Peter Bloomfield * src/balsa-index.c (bndx_queue_draw_idle_cb), (bndx_mailbox_changed_idle): queue redrawing the message index each time anything changes, to try to fix mis-rendering. 2013-03-04 Peter Bloomfield * src/main.c (initial_open_inbox), (balsa_cleanup): remember when we have opened Inbox twice. * src/balsa-app.h: add member to remember it. 2013-03-03 Peter Bloomfield * src/balsa-index.c (balsa_index_scroll_on_open): always use an idle callback to select a message or set the tree-view's cursor. 2013-03-02 Peter Bloomfield * libbalsa/mailbox.c (lbm_changed_schedule_idle), (libbalsa_mailbox_msgno_filt_in), (libbalsa_mailbox_msgno_filt_out): set mailbox_changed only when it really has changed. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_class_init), (libbalsa_mailbox_local_changed), (lbm_local_save_tree_real), (lbm_local_queue_save_tree), (lbml_load_messages_idle_cb), (libbalsa_mailbox_local_load_messages): implement the "changed" vfunc, and use it to schedule saving the message tree structure. * libbalsa/mailbox_local.h: new member to temporarily hold the current last msgno. 2013-03-02 Peter Bloomfield * libbalsa/server.c (libbalsa_server_save_config): report error saving password. 2013-03-02 Peter Bloomfield Re-enable mailbox check in a subthread * libbalsa/mailbox.c (libbalsa_mailbox_progress_notify), (libbalsa_mailbox_msgno_inserted), (libbalsa_mailbox_msgno_removed), (libbalsa_mailbox_unlink_and_prepend), (lbm_set_msg_tree): insert subthread warnings. (lbm_check_idle): check mailbox in a subthread. * libbalsa/mailbox_local.c (lbml_load_messages_idle_cb), (libbalsa_mailbox_local_load_messages): load messages in the main thread, in an idle callback; (libbalsa_mailbox_local_finalize): remove any pending idle call. * libbalsa/mailbox_local.h: new member of LibBalsaMailboxLocal for the idle id. 2013-03-01 Peter Bloomfield * libbalsa/mailbox.h: idle id is guint, not gulong. 2013-03-01 Peter Bloomfield * libbalsa/mailbox.h: new LibBalsaMailbox members changed_idle_id and queue_check_idle_id. * libbalsa/mailbox.c (libbalsa_mailbox_finalize), (libbalsa_mailbox_check), (lbm_changed_idle_cb), (lbm_changed_schedule_idle), (libbalsa_mailbox_changed), (libbalsa_mailbox_msgno_filt_in), (libbalsa_mailbox_msgno_filt_out), (lbm_check_real), (lbm_queue_check): use them. 2013-02-28 Peter Bloomfield * src/balsa-index.c: refactor and simplify. 2013-02-28 Peter Bloomfield * src/main-window.c: survive torture test. 2013-02-28 Peter Bloomfield * libbalsa/mailbox.c (lbm_msgno_filt_check), (lbm_msgno_filt_check_idle_cb), (libbalsa_mailbox_msgno_filt_check): check message against view filter synchronously when in the main thread. 2013-02-28 Pawel Salek * configure.ac: remove dependency on legacy gnome-icon-scheme pkg. * NEWS, configure.ac: release balsa-2.5.0 2013-02-28 Peter Bloomfield * libbalsa/mailbox.c: build with threads disabled. 2013-02-27 Peter Bloomfield * libbalsa/mailbox.c (lbm_run_filters_on_reception_idle_cb), (libbalsa_mailbox_run_filters_on_reception): run filters in an idle callback. 2013-02-26 Peter Bloomfield * src/main-window.c: do not use another idle handler to set the mailbox view-filter. 2013-02-26 Peter Bloomfield Instead of forgetting open mailboxes, do not remember them in the first place. * src/balsa-app.c (append_url_if_open): revert. * src/main.c (scan_mailboxes_idle_cb): ditto. * src/save-restore.c (save_view): remember open mailbox only if balsa_app.remember_open_mboxes. 2013-02-26 Peter Bloomfield * src/balsa-app.c (ask_password): use a mutex to make sure that only one dialog pops up at a time. 2013-02-26 Peter Bloomfield * libbalsa/mailbox_local.c (lbm_local_save_tree_real), (lbm_local_queue_save_tree): check that the message tree has changed in the idle handler, instead of in the scheduler. 2013-02-26 Peter Bloomfield * src/balsa-app.c (append_url_if_open): in_sync is gboolean. 2013-02-26 Peter Bloomfield * src/balsa-app.c (append_url_if_open): mark view out-of-sync only if it really is. 2013-02-26 Peter Bloomfield * src/balsa-app.c (append_url_if_open), (open_mailboxes_idle_cb): if we are not remembering open mailboxes, forget them. * src/main.c (scan_mailboxes_idle_cb): always call open_mailboxes_idle_cb so we can forget them. 2013-02-25 Peter Bloomfield * src/sendmsg-window.c (balsa_sendmsg_destroy_handler), (sendmsg_window_new), (bsmsg2message), (sw_buffer_changed): remove annoying wrap timeout, and carry out autosave timeout without disturbing the compose window. * src/sendmsg-window.h: remove timeout id. 2013-02-25 Peter Bloomfield * libbalsa/mailbox.c (lbm_msgno_filt_check): check that mailbox is still open. 2013-02-25 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_search_iter_ref): allow NULL iter. 2013-02-25 Peter Bloomfield * configure.in: actually error out if libsecret devel is not installed. 2013-02-24 Peter Bloomfield Port from GnomeKeyring to libsecret. * configure.in: implement --with-libsecret as an alternative to GnomeSecret. * libbalsa/imap-server.c (libbalsa_imap_server_new_from_config): use libsecret if configured. * libbalsa/server.c (libbalsa_server_load_config), (libbalsa_server_save_config): ditto. * libbalsa/server.h: ditto. * src/balsa-app.c (ask_password_real): new string to request saving in secret service. * src/folder-conf.c (folder_conf_imap_node): ditto. * src/mailbox-conf.c (create_imap_mailbox_dialog): ditto. 2013-02-23 Peter Bloomfield * update all copyrights to 2013. 2013-02-23 Peter Bloomfield * src/main.c (handle_remote): handle -h option. 2013-02-23 Peter Bloomfield * libbalsa/mailbox.c (lbm_msgno_changed), (libbalsa_mailbox_msgno_changed): make sure parent message is checked. 2013-02-23 Peter Bloomfield * libbalsa/mailbox.c (lbm_msgno_filt_check), (libbalsa_mailbox_msgno_filt_check): use an idle callback to check whether to filter a message in or out. 2013-02-21 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_finalize), (lbm_msgno_row_changed), (lbm_msgnos_changed_idle_cb), (lbm_msgno_changed), (lbm_get_index_entry): restore threaded versions of get_index_entry and msgno_changed. 2013-02-21 Peter Bloomfield * src/ab-main.c (main): deprecation cleanup. 2013-02-21 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_finalize): build without threads. 2013-02-21 Peter Bloomfield * src/main-window.c: do not leave progress bar crawling. 2013-02-21 Peter Bloomfield * src/balsa-index.c (balsa_index_load_mailbox_node): move libbalsa_mailbox_open call to balsa_window_real_open_mbnode. * src/balsa-index.h: drop unused argument. * src/main-window.c: open mailbox in a thread. 2013-02-21 Peter Bloomfield * src/main.c (balsa_progress_set_text): do not check for subthread, as balsa_window_setup_progress is thread-safe. 2013-02-20 Peter Bloomfield * src/main-window.c: set up progress bar in an idle callback. 2013-02-20 Peter Bloomfield * src/main-window.c: change button sensitivity in an idle callback. 2013-02-20 Peter Bloomfield * src/balsa-app.c (balsa_find_iter_by_data): check for sub-thread. 2013-02-20 Peter Bloomfield * src/balsa-app.c (balsa_find_url): thread-safe. 2013-02-20 Peter Bloomfield * libbalsa/send.c (balsa_send_message_real_idle_cb), (balsa_send_message_real): close outbox in an idle callback. 2013-02-20 Peter Bloomfield * libbalsa/libbalsa-gpgme.c (libbalsa_gpgme_init): use g_message instead of g_warning. 2013-02-20 Peter Bloomfield * configure.in: new option --enable-debug-threads. * libbalsa/libbalsa.h: use it to define gdk_threads_enter() to detect a sub-thread. 2013-02-20 Peter Bloomfield Build with enable-threads; check POP3 mail and send messages in threads. * libbalsa/libbalsa.c (libbalsa_lock_mailbox), (libbalsa_threads_init), (libbalsa_threads_has_lock): rip out gdk_threads-related code. * libbalsa/libbalsa.h: ditto. * src/main.c (threads_init): ditto. * libbalsa/imap-server.c (connection_cleanup): not ready for threads. * libbalsa/mailbox.c (libbalsa_mailbox_class_init), (lbm_get_index_entry), (lbm_check_idle): ditto. * libbalsa/mailbox_local.c (lbm_local_save_tree_idle): ditto * libbalsa/mailbox_pop3.c: use a thread. * libbalsa/mailbox_pop3.h: ditto. * libbalsa/send.c (lbs_process_queue), (libbalsa_process_queue): * src/main-window.c: ditto. 2013-02-16 Peter Bloomfield * libbalsa/libbalsa-conf.c (lbc_lock), (lbc_unlock): call lbc_init() only once. 2013-01-15 Peter Bloomfield * src/main-window.c: emit signal instead of calling NULL class method. 2013-01-08 Peter Bloomfield * src/pref-manager.c (create_layout_types_menu): use relevant enum. 2013-01-08 Peter Bloomfield * src/main-window.c: mailbox index cannot shrink. 2012-12-08 Peter Bloomfield * src/main-window.c: use idle callback to check mail when not threaded. 2012-11-27 Peter Bloomfield * src/balsa-index.c (balsa_index_scroll_on_open): use idle callback only from a subthread. 2012-11-21 Peter Bloomfield Build with gtk 3.6, at least without threads * libbalsa/information.c: include libbalsa.h. * libbalsa/libbalsa.h: when not threaded, define gdk_threads_{enter,leave} to nothing. * libbalsa/mailbox.c (lbm_cache_message): when not threaded, avoid recursive signal call. * libbalsa/misc.c: remove deprecated GtkTable code. * libbalsa/misc.h: ditto. * src/balsa-mime-widget-image.c (img_check_size): build with gdk_threads_{enter,leave} defined to nothing. * src/filter-edit-callbacks.c (fe_apply_pressed), (fe_filters_list_selection_changed): deprecation cleanup. * src/filter-edit-dialog.c (fe_make_color_buttons): ditto. * src/main-window.c: CSS cleanup. * src/pref-manager.c (apply_prefs), (set_prefs): deprecation cleanup. 2012-11-14 Peter Bloomfield Port to newly released Gtkspell 3.0 * configure.in: renamed pkg-config file. * src/sendmsg-window.c (sw_spell_attach), (sw_spell_detach): new API. 2012-10-29 * configure.in, NEWS: release 2.4.91 2012-10-22 Pawel Salek * libbalsa/imap/pop3.c: fix long-line POP3 bug reported by Rob Landley. 2012-09-30 Peter Bloomfield * src/store-address.c (store_address_add_address), (store_address_add_list): store a group as a distribution list, if the address book implements lists. 2012-09-30 Peter Bloomfield * libbalsa/libbalsa.c (ask_cert_real): replace "&" by "&" in marked-up string. 2012-09-17 Peter Bloomfield Fix bgo #684124 * libinit_balsa/assistant_page_defclient.c (balsa_druid_page_defclient_init): capitalize "Balsa". * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_ctx_menu_save): capitalize "URI". * src/filter-edit-dialog.c (filters_edit_dialog): space after ".". 2012-09-17 Ildar Mulyukov * balsa.desktop.in.in: fix desktop categories. 2012-09-17 Peter Bloomfield Revert all changes moving Gtk access from subthreads to main thread. * libbalsa/libbalsa.c (libbalsa_threads_enter): * libbalsa/mailbox.c (lbm_index_entry_new_from_msg), (libbalsa_mailbox_close), (libbalsa_mailbox_msgno_inserted), (libbalsa_mailbox_msgno_removed), (libbalsa_mailbox_msgno_filt_check), (lbm_cache_message): * libbalsa/mailbox_local.c (libbalsa_mailbox_local_load_messages): * src/balsa-app.c (find_url), (balsa_find_url): * src/balsa-index.c (balsa_index_load_mailbox_node): * src/balsa-index.h: * src/main-window.c: * src/main.c (balsa_progress_set_text), (balsa_progress_set_fraction): 2012-09-08 Peter Bloomfield * configure.in: _NL_MEASUREMENT_MEASUREMENT is an enum and not a define. * src/print-gtk.c (get_default_user_units): use HAVE__NL_MEASUREMENT_MEASUREMENT. 2012-08-10 Peter Bloomfield * libbalsa/body.c (libbalsa_message_body_get_part_stream): simplify filter selection switch. 2012-08-09 Peter Bloomfield * src/balsa-mime-widget-message.c (bm_header_widget_realized): use BalsaMessage::scroll as the context for header widget colors. 2012-07-22 Peter Bloomfield * src/store-address.c (store_address_book_frame): reduce scope of variables. 2012-07-22 Peter Bloomfield * src/sendmsg-window.c (update_bsmsg_identity): reduce scope of variables; (tree_add_quote_body): suppress null pointer warning. 2012-07-22 Peter Bloomfield * src/save-restore.c (pop3_progress_notify): suppress memory leak warning. 2012-07-22 Peter Bloomfield * src/main-window.c: use sscanf field limits; suppress null pointer warning. 2012-07-22 Peter Bloomfield * src/mailbox-conf.c (mailbox_conf_update): reduce scope of variable. 2012-07-22 Peter Bloomfield * src/balsa-mime-widget.c (balsa_mime_widget_new_unknown): reduce scope of variables. 2012-07-22 Peter Bloomfield * src/balsa-index.c (pipe_out_watch): reduce scope of variable. 2012-07-22 Peter Bloomfield * libinit_balsa/assistant_page_directory.c (unconditional_mailbox): reduce scope of variable. 2012-07-22 Peter Bloomfield * libbalsa/send.c (balsa_send_message_real): suppress memory leak warning. 2012-07-22 Peter Bloomfield * libbalsa/message.c (prepend_header_misc): check loop index value before using it. 2012-07-22 Peter Bloomfield * libbalsa/mailbox_pop3.c (mp_load_uids): reduce scope of variable. 2012-07-22 Peter Bloomfield * libbalsa/mailbox_mh.c (lbm_mh_parse_mailbox), (lbm_mh_handle_seq_line), (lbm_mh_check): use sscanf field limits. 2012-07-22 Peter Bloomfield * libbalsa/mailbox_mbox.c (lbm_mbox_stream_seek_to_message): avoid unread variable error. 2012-07-22 Peter Bloomfield * libbalsa/mailbox_imap.c (is_child_of), (create_cache_copy), (libbalsa_mailbox_imap_sort): reduce scope of variables. 2012-07-22 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_type_from_path): reduce scope of variable. 2012-07-22 Peter Bloomfield * libbalsa/libbalsa.c (libbalsa_guess_mail_spool), (asn1time_to_string), (x509_get_part): reduce scope of variables; (libbalsa_get_image_from_x_face_header): use sscanf field limit. 2012-07-22 Peter Bloomfield * libbalsa/imap/siobuf.c (sio_set_tlsclient_ssl), (sio_set_tlsserver_ssl), (raw_read): reduce scope of variables. 2012-07-22 Peter Bloomfield * libbalsa/imap/pop3.c (parse_list_response): use sscanf field limits. 2012-07-22 Peter Bloomfield * libbalsa/imap/imap_tst.c (get_user), (user_cb): reduce scope of variables. 2012-07-22 Peter Bloomfield * libbalsa/imap/imap_search.c (imap_search_key_new_string), (imap_search_exec_unlocked): reduce scope of variables. 2012-07-22 Peter Bloomfield * libbalsa/imap/imap-tls.c (imap_check_server_identity): reduce scope of variable. 2012-07-22 Peter Bloomfield * libbalsa/imap/imap-handle.c (imap_handle_disconnect), (imap_cmd_step), (imap_get_sequence), (ir_get_append_copy_uids), (ir_status), (ir_quota), (ir_body_extension), (ir_handle_response): suppress unread-variable error, use sscanf field limits, reduce scope. 2012-07-22 Peter Bloomfield * libbalsa/imap/imap-commands.c (imap_assure_needed_flags), (imap_mbox_sort_msgno_srv), (imap_mbox_sort_filter): reduce scope of variables. 2012-07-22 Peter Bloomfield * libbalsa/imap-server.c (libbalsa_imap_server_get_handle, libbalsa_imap_server_get_handle_with_user): reduce scope of variables; suppress incorrect null pointer error. 2012-07-22 Peter Bloomfield * libbalsa/gmime-multipart-crypt.c (sign_prepare): reduce scope. 2012-07-22 Peter Bloomfield * libbalsa/gmime-gpgme-signature.h: suppress cppcheck syntax error. 2012-07-22 Peter Bloomfield * libbalsa/address-book-extern.c (parse_externq_file): use *scanf field limits to satisfy cppcheck. 2012-07-15 Peter Bloomfield * src/mailbox-node.c (balsa_mailbox_local_append): simplify. 2012-07-15 Peter Bloomfield * libbalsa/mailbox_imap.c (imap_cache_manager_new_from_file): do not leak FILE on error. 2012-07-15 Peter Bloomfield * libbalsa/imap/pop3.c (pop_check_status): remove redundant else clause. 2012-07-15 Peter Bloomfield * libbalsa/identity.h: typo. 2012-07-15 Peter Bloomfield * libbalsa/identity.c (libbalsa_identity_get_signature): limit scope of fp. 2012-07-15 Peter Bloomfield * src/sendmsg-window.c (edit_with_gnome): plug mem leak. 2012-07-15 Peter Bloomfield * libbalsa/address.c (libbalsa_address_extract_name): plug mem leak. 2012-07-15 Peter Bloomfield * libbalsa/address-book-ldif.c (libbalsa_address_book_ldif_save_address): fseek before writing to stream. 2012-07-15 Peter Bloomfield * libbalsa/imap/imap_compress.c (imap_compress_init): memset size of struct, not size of pointer to struct. 2012-07-15 Peter Bloomfield * src/balsa-mime-widget-text.c (structured_phrases_toggle): typo. 2012-07-15 Peter Bloomfield * libbalsa/imap/imap_search.c (imap_write_key_string): typo. 2012-07-15 Albrecht Dreß * src/sendmsg-window.c (edit_with_gnome): fix mem leak on error. 2012-07-15 Albrecht Dreß * src/mailbox-conf.c (mailbox_conf_delete): fix mem leak on error. 2012-07-15 Albrecht Dreß * src/information-dialog.c (balsa_information_real): fix mem leak on NULL main widget. 2012-07-15 Albrecht Dreß * src/folder-conf.c (folder_conf_imap_sub_node): fix mem leak on error. 2012-07-15 Albrecht Dreß * src/balsa-index.c (bndx_start_pipe_messages_array): fix mem leak on error. 2012-07-15 Albrecht Dreß * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_add_message): fix mem leak on error. 2012-07-15 Albrecht Dreß * libbalsa/mailbox_imap.c (imap_cache_manager_new_from_file): do not leak open file on error. 2012-07-15 Albrecht Dreß * libbalsa/filter-funcs.c (libbalsa_filter_export_sieve): do not leak open file. 2012-07-15 Albrecht Dreß * libbalsa/address-book-ldap.c (libbalsa_address_book_ldap_get_address): drop useless assignment to nick_name, fix mem leak; (libbalsa_address_book_ldap_modify_address): fix mem leak. 2012-07-15 Albrecht Dreß * libbalsa/address-book-extern.c (parse_externq_file): pipe stream must be closed with pclose, not fclose. 2012-07-13 Peter Bloomfield * libbalsa/mime.c (process_mime_part): build --with-html-widget=no; fixes bgo #679869 (Aljosha). 2012-07-04 Peter Bloomfield * src/main-window.c: manage sensitivity of check mail button in unthreaded build. 2012-06-27 Peter Bloomfield * src/save-restore.c (config_load_sections), (config_mailbox_init), (config_address_book_load), (config_address_books_load), (config_identities_load), (load_mru): prepend to GList and reverse it, instead of appending; use g_list_free_full(). 2012-06-25 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_msgno_filt_out), (lbm_msgno_filt_check): find node once, not twice. 2012-06-19 Peter Bloomfield * libbalsa/mailbox.c (lbm_node_has_unseen_child), (lbm_get_index_entry), (mbox_model_get_value): get index entry by message number instead of by GNode. 2012-06-13 Peter Bloomfield * libbalsa/mailbox.c (lbm_msgno_inserted_idle_cb): lock mutex before signalling cond. 2012-06-13 Peter Bloomfield * src/balsa-app.c (find_url_idle_cb): lock mutex before signalling cond. 2012-06-12 Peter Bloomfield * libbalsa/mailbox.c (lbm_message_expunged_cb), (lbm_msgno_removed_idle_cb), (libbalsa_mailbox_msgno_removed), (lbm_msgno_filt_check_idle_cb), (libbalsa_mailbox_msgno_filt_check): update message number if a message is expunged. 2012-06-11 Peter Bloomfield * libbalsa/mailbox.c (lbm_msgno_filt_check_idle_cb): unref the LibBalsaMailboxSearchIter. 2012-06-11 Peter Bloomfield * libbalsa/imap-server.c: remove redundant parentheses. 2012-06-11 Peter Bloomfield Ref count LibBalsaMailboxSearchIter * libbalsa/mailbox.c (libbalsa_mailbox_run_filters_on_reception), (libbalsa_mailbox_msgno_filt_check), (libbalsa_mailbox_search_iter_new), (libbalsa_mailbox_search_iter_ref), (libbalsa_mailbox_search_iter_unref), (libbalsa_mailbox_messages_change_flags): ref count LibBalsaMailboxSearchIter, and unref it instead of free. * libbalsa/mailbox.h: new member ref_count. * libbalsa/mailbox_local.c (lbm_local_update_view_filter): unref LibBalsaMailboxSearchIter instead of free. * src/balsa-index.c (bndx_destroy), (bndx_select_next_with_flag): ditto. * src/filter-run-callbacks.c (run_filters_on_mailbox): ditto. * src/main-window.c: ditto. 2012-06-10 Peter Bloomfield * libbalsa/libbalsa.c (libbalsa_scanner_error_quark), (libbalsa_mailbox_error_quark), (libbalsa_image_error_quark): GQuarks for GError. * libbalsa/libbalsa.h: export them. 2012-06-10 Peter Bloomfield * libbalsa/imap/pop3.c (pop_imap_error_quark): a GQuark for use in g_set_error. * libbalsa/imap/pop3.h: export it. 2012-06-09 Peter Bloomfield * libbalsa/mailbox.h: do not export libbalsa_mailbox_msgno_filt_{in,out}. * libbalsa/mailbox.c: declare them static. 2012-06-09 Peter Bloomfield * libbalsa/mailbox.c (lbm_msgno_filt_check), (lbm_msgno_filt_check_idle_cb), (libbalsa_mailbox_msgno_filt_check): check whether message matches current view filter in an idle callback instead of in subthread. 2012-06-08 Peter Bloomfield * libbalsa/mailbox.c (lbm_msgno_removed_idle_cb), (libbalsa_mailbox_msgno_removed): use GSlice instead of g_new(); use g_idle_add instead of gdk_threads_add_idle. 2012-06-08 Peter Bloomfield * libbalsa/mailbox.c (lbm_check_and_sort), (lbm_set_threading_idle_cb), (lbm_set_threading): sort in an idle callback instead of subthread. * libbalsa/mailbox_local.c (lbml_set_threading), (lbml_set_threading_idle_cb), (libbalsa_mailbox_local_set_threading): set threading type in an idle callback instead of subthread. 2012-06-07 Peter Bloomfield * src/main.c (progress_set_text), (progress_set_text_idle_cb), (balsa_progress_set_text), (progress_set_fraction), (progress_set_fraction_idle_cb), (balsa_progress_set_fraction): call Gtk in idle callbacks instead of subthreads. 2012-06-07 Peter Bloomfield * libbalsa/mailbox.c (lbm_msgno_inserted), (lbm_msgno_inserted_idle_cb), (libbalsa_mailbox_msgno_inserted): block subthread and use an idle callback to insert message in main thread. * libbalsa/mailbox_local.c (libbalsa_mailbox_local_load_messages): do not grab GDK lock. 2012-06-07 Peter Bloomfield * libbalsa/libbalsa.c (libbalsa_threads_enter): warn when locking a subthread, to help find bad code paths. 2012-06-07 Peter Bloomfield * src/main-window.c: check for NULL index. 2012-06-07 Peter Bloomfield * src/balsa-index.c (bndx_find_root): check for NULL tree model. 2012-06-07 Peter Bloomfield * src/main-window.c: check for NULL focus widget. 2012-06-06 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_close), (lbm_msgno_removed), (lbm_msgno_removed_idle_cb), (libbalsa_mailbox_msgno_removed): use an idle callback to remove the message from the tree-model. 2012-06-06 Peter Bloomfield * src/balsa-app.c (find_url_func), (find_url), (find_url_idle_cb), (balsa_find_url): block the subthread and use an idle callback to find the BalsaMailboxNode for the URL. 2012-06-06 Peter Bloomfield * libbalsa/mime-stream-shared.c (libbalsa_mime_stream_shared_lock): build with glib < 2.32. 2012-06-05 Peter Bloomfield Make changes in previous commit conditional on glib version at least 2.32. * libbalsa/imap-server.c (libbalsa_imap_server_init), (libbalsa_imap_server_finalize): make previous changes conditional on glib version at least 2.32. * libbalsa/libbalsa-conf.c (lbc_lock), (lbc_unlock): ditto. * libbalsa/mime-stream-shared.c (lbmss_stream_class_init), (libbalsa_mime_stream_shared_lock), (libbalsa_mime_stream_shared_unlock): ditto. 2012-06-05 Peter Bloomfield Deprecation cleanup; fixes bgo #677381 * libbalsa/imap-server.c (libbalsa_imap_server_init), (libbalsa_imap_server_finalize): deprecation cleanup. * libbalsa/libbalsa-conf.c (lbc_lock), (lbc_unlock): ditto. * libbalsa/mime-stream-shared.c (lbmss_stream_class_init), (libbalsa_mime_stream_shared_lock), (libbalsa_mime_stream_shared_unlock): ditto. 2012-06-03 Peter Bloomfield * src/main-window.c: change sensitivity of mail-check button in the main thread, in an idle callback. 2012-06-03 Peter Bloomfield Call Gtk from only the main thread when opening a mailbox * libbalsa/mailbox.c (lbm_cache_message): avoid infinite recursion. * libbalsa/mailbox.h: do not export libbalsa_mailbox_index_entry_new_from_msg. * src/balsa-index.c (bndx_set_mailbox), (bndx_open_mailbox), (balsa_index_load_mailbox_node): open mailbox in a subthread. * src/balsa-index.h: do not export balsa_index_load_mailbox_node and balsa_index_scroll_on_open. * src/main-window.c: start opening mailbox in the main thread. 2012-05-28 Peter Bloomfield * src/balsa-index.c (bi_view_on_open, balsa_index_scroll_on_open): set the cursor on the most recent message, even when not selecting it. 2012-05-28 Peter Bloomfield * src/main-window.c: restore "identities-changed" signal. 2012-05-28 Peter Bloomfield * src/main-window.c: show mailbox list on startup only if necessary; fixes point 1 of (Carlos Franke). 2012-05-27 Peter Bloomfield * src/main-window.c: use class methods instead of emitting signals. * src/main-window.h: define class getter. 2012-05-21 Peter Bloomfield * libbalsa/imap/md5-utils.c (md5_final): avoid gcc whining. 2012-04-22 Pawel Salek * src/balsa-app.{c,h}: free mem on exit. Longer 'short' mailbox names. * src/balsa-mblist.c: use them. * src/mailbox-node.h: remove unused bit field. * src/main-window.c: check_mailboxes must be called from main thread. 2012-04-20 Peter Bloomfield * src/main-window.c: hide current message immediately, instead of in the idle callback; use gdk_threads_add_idle convenience function. * src/balsa-message.c (balsa_message_set): message is already hidden. 2012-04-19 Peter Bloomfield * libbalsa/body.c (libbalsa_message_body_get_pixbuf): apply embedded orientation to pixbuf. 2012-04-16 Peter Bloomfield * src/balsa-mblist.c (balsa_mblist_mru_add): add folder to the MRU folder list as well as to the given list, if different. 2012-04-16 Peter Bloomfield Revert previous commit; fixes from Ildar Mulyukov * src/balsa-app.c (balsa_app_init): * src/balsa-app.h: * src/save-restore.c (config_mailbox_set_as_special), (config_global_load), (config_save): * src/sendmsg-window.c (create_info_pane): 2012-03-27 Peter Bloomfield Use a single MRU folder list * src/balsa-app.h: drop separate Fcc list. * src/balsa-app.c (balsa_app_init): ditto. * src/save-restore.c (config_mailbox_set_as_special): use combined list; (config_global_load), (config_save): do not save and restore separate Fcc list. * src/sendmsg-window.c (create_info_pane): use combined list. 2012-03-27 Peter Bloomfield Remember geometry of MRU mailbox tree * src/balsa-app.h: new members mru_tree_{width,height} * src/balsa-mblist.c (bmbl_mru_size_allocate_cb): save them when the dialog's size is changed; (bmbl_mru_show_tree): use the saved values. * src/save-restore.c (config_global_load), (config_save): save and restore them. 2012-03-20 Peter Bloomfield * configure.in: work around "intltool-update -m" bug: it knows about m4_esyscmd, not m4_esyscmd_s. 2012-03-06 Peter Bloomfield * src/main-window.c: update last-check-time only if connected. 2012-03-06 Peter Bloomfield * src/main-window.c: check local mailboxes even when network is not connected. 2012-03-06 Peter Bloomfield * libbalsa/libbalsa-gpgme-cb.c (lb_gpgme_passphrase): build with --disable-threads. 2012-02-08 Albrecht Dreß * libbalsa/gmime-part-rfc2440.c (g_mime_part_rfc2440_verify): check for empty return from GpgME. 2012-02-03 Peter Bloomfield * configure.in: remove obsolete BUILD_WITH_GNOME. 2011-12-20 Peter Bloomfield * configure.in: use git tag to set version. 2011-12-20 Peter Bloomfield * Makefile.am: drop GNOME_Balsa.server.in from balsa_extra_dist. 2011-12-20 Peter Bloomfield * .gitignore: add .libs. 2011-12-20 Albrecht Dreß * libbalsa/rfc3156.c: suppress GLib warning when the message is only encrypted; return 'no error' for encrypted-only RFC 2440 messages; re-wrap a few over-long lines * src/balsa-message.c: properly pick up return values from libbalsa * src/balsa-mime-widget-crypto.[hc]: changes needed for drawing encrypted-only frame * src/balsa-mime-widget-multipart.c: use new crypto frame api * src/balsa-mime-widget.c: draw frame around encrypted-only rfc 2440 part * src/print-gtk.c: encrypted-only frame print implementation 2011-12-18 Peter Bloomfield * src/main.c (balsa_check_open_mailboxes), (scan_mailboxes_idle_cb), (balsa_check_open_compose_window), (real_main), (handle_remote): reuse identical code. 2011-12-18 Peter Bloomfield * .cvsignore: delete. * .gitignore: add. 2011-12-17 Peter Bloomfield * src/main.c (handle_remote): do not leak option-handling resources. 2011-12-17 Peter Bloomfield * src/main-window.c: build --without-nm; thanks to Jack . 2011-12-17 Peter Bloomfield * src/main.c (handle_remote): use the capabilities of g_application_command_line_print. 2011-12-17 Peter Bloomfield * src/main.c (scan_mailboxes_idle_cb), (real_main), (handle_remote), (command_line_cb): free option-handling resources when no longer needed, instead of later; ignore other options when --get-stats is requested by a second instance, as in the primary instance; add comments to document logic. 2011-12-16 Peter Bloomfield * src/main.c: do not leak option-context; use opt-attach-list as gchar ** instead of GSlist; do not pass GApplication to handle-remote. 2011-12-16 Peter Bloomfield * src/sendmsg-window.c: drop ctrl-Q accelerator for file:queue-for-sending. 2011-12-15 Peter Bloomfield Migrate to GApplication * GNOME_Balsa.server.in: remove obsolete file. * Makefile.am: remove reference to obsolete file. * configure.in: remove libUnique configuration, and bump glib requirement to 2.28. * src/main.c (balsa_init), (scan_mailboxes_idle_cb), (real_main), (balsa_cleanup), (handle_remote), (command_line_cb), (main): migrate to GApplication. 2011-12-10 Peter Bloomfield * libbalsa/libbalsa-gpgme-cb.c: include stdlib.h directly. 2011-12-10 Albrecht Dreß New crypto implementation * libbalsa/Makefile.am: new files. * libbalsa/body.c (libbalsa_message_body_protect_state): use new implementation. * libbalsa/gmime-application-pkcs7.c (g_mime_application_pkcs7_decrypt_verify), (g_mime_application_pkcs7_encrypt): ditto. * libbalsa/gmime-application-pkcs7.h: ditto. * libbalsa/gmime-gpgme-context.c: new file. * libbalsa/gmime-gpgme-context.h: ditto. * libbalsa/gmime-gpgme-signature.c (g_mime_gpgme_sigstat_new_from_gpgme_ctx), (g_mime_gpgme_sigstat_finalize), (hex_decode), (libbalsa_cert_subject_readable), (g_mime_gpgme_sigstat_init): ditto. * libbalsa/gmime-gpgme-signature.h: ditto. * libbalsa/gmime-part-rfc2440.c (g_mime_part_check_rfc2440), (g_mime_part_rfc2440_sign_encrypt), (g_mime_part_rfc2440_verify), (g_mime_part_rfc2440_decrypt): use new implementation. * libbalsa/gmime-part-rfc2440.h: ditto. * libbalsa/rfc3156.c (libbalsa_sign_mime_object), (libbalsa_encrypt_mime_object), (libbalsa_body_check_signature), (libbalsa_body_decrypt), (libbalsa_rfc2440_sign_encrypt), (libbalsa_rfc2440_verify), (libbalsa_rfc2440_decrypt), (libbalsa_gpgme_validity_to_gchar_short), (append_time_t), (libbalsa_signature_info_to_gchar): ditto. * libbalsa/rfc3156.h: ditto. * src/balsa-message.c (libbalsa_msg_part_2440): ditto. * src/main.c (main): ditto. 2011-12-03 Peter Bloomfield * src/sendmsg-window.c (create_text_area): remove redundant dynamic cast; use more appropriate identifier. 2011-12-03 Peter Bloomfield * src/sendmsg-window.c (create_text_area): build without GtkSourceView. 2011-12-02 Peter Bloomfield Add mailto-handler desktop file * balsa-mailto-handler.desktop.in.in: new file. * balsa.desktop.in.in: do not use -m. 2011-11-12 Peter Bloomfield * libbalsa/rfc3156.c (libbalsa_body_check_signature): use only one dynamic cast. 2011-11-10 Peter Bloomfield * libbalsa/rfc3156.c (libbalsa_body_check_signature): restore handling of application/x-pkcs7-signature. 2011-11-09 Peter Bloomfield Build with GMime version >= 2.5.7 * configure.in: check GMime version. * libbalsa/gmime-application-pkcs7.c (g_mime_application_pkcs7_sign), (g_mime_application_pkcs7_verify), (g_mime_application_pkcs7_encrypt), (g_mime_application_pkcs7_decrypt): build with GMime version >= 2.5.7. * libbalsa/gmime-application-pkcs7.h: ditto. * libbalsa/gmime-gpgme-context.c (g_mime_gpgme_context_get_type), (g_mime_gpgme_context_class_init), (g_mime_gpgme_context_finalize), (g_mime_gpgme_digest_id): ditto. * libbalsa/gmime-gpgme-context.h: ditto. * libbalsa/gmime-part-rfc2440.c (g_mime_part_rfc2440_sign_encrypt), (g_mime_part_rfc2440_verify), (g_mime_part_rfc2440_decrypt): * libbalsa/gmime-part-rfc2440.h: ditto. * libbalsa/rfc3156.c (password_request_func), (libbalsa_sign_mime_object), (libbalsa_encrypt_mime_object), (libbalsa_body_check_signature), (libbalsa_body_decrypt): ditto. 2011-10-26 Peter Bloomfield * src/sendmsg-window.c (create_info_pane): do not set vertical expand flag on attachment frame, it causes weird vertical spacing when the attachments are shown. 2011-10-26 Peter Bloomfield * src/main.c (threads_init): use g_type_init, which is required, not g_threads_init, which is redundant. 2011-10-24 Peter Bloomfield * src/main.c (balsa_handle_automation_options), (balsa_init), (scan_mailboxes_idle_cb): handle multiple -o options. 2011-10-22 Peter Bloomfield * src/balsa-app.c (open_mailboxes_idle_cb): select first command-line mailbox; see discussion at https://mail.gnome.org/archives/balsa-list/2011-October/msg00010.html 2011-10-21 Peter Bloomfield * src/main-window.c: when network is connected, check mail in the subthread, so that the signal handler can return. 2011-10-14 Peter Bloomfield gtk_assistant_set_page_header_image and gtk_assistant_set_page_side_image are deprecated. * images/Makefile.am: no need for balsa-logo.png and balsa-watermark.png. * libinit_balsa/assistant_init.c (balsa_initdruid): * libinit_balsa/assistant_page_defclient.c (balsa_druid_page_defclient): * libinit_balsa/assistant_page_defclient.h: * libinit_balsa/assistant_page_directory.c (balsa_druid_page_directory): * libinit_balsa/assistant_page_directory.h: * libinit_balsa/assistant_page_finish.c (balsa_druid_page_finish): * libinit_balsa/assistant_page_finish.h: * libinit_balsa/assistant_page_user.c (balsa_druid_page_user): * libinit_balsa/assistant_page_user.h: * libinit_balsa/assistant_page_welcome.c (balsa_druid_page_welcome): * libinit_balsa/assistant_page_welcome.h: deprecation cleanup. 2011-10-14 Peter Bloomfield Gtk{HV}Paned is deprecated. * src/main-window.c: deprecation cleanup. 2011-10-14 Peter Bloomfield Gtk{HV}Separator is deprecated. * src/filter-edit-dialog.c (filters_edit_dialog): deprecation cleanup. 2011-10-14 Peter Bloomfield Gtk{HV}ButtonBox is deprecated. * src/ab-main.c (bab_get_edit_button_box): * src/ab-window.c (balsa_ab_window_init): * src/balsa-mime-widget-vcalendar.c (balsa_vevent_widget): * src/filter-edit-dialog.c (build_left_side), (build_right_side): * src/filter-run-dialog.c (balsa_filter_run_dialog_init): * src/main-window.c: * src/toolbar-prefs.c (create_toolbar_page): deprecation cleanup. 2011-10-13 Peter Bloomfield Gtk{HV}Box is deprecated. * libbalsa/address.c (libbalsa_address_get_edit_widget): * libbalsa/html.c (libbalsa_html_new): * libbalsa/identity.c (append_ident_notebook_page), (ident_dialog_add_boxes), (libbalsa_identity_config_dialog): * libbalsa/rfc3156.c (select_key_from_list), (get_passphrase_real): * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): * libbalsa/source-viewer.c (libbalsa_show_message_source): * libinit_balsa/assistant_page_defclient.c (balsa_druid_page_defclient): * libinit_balsa/assistant_page_directory.c (balsa_druid_page_directory): * libinit_balsa/assistant_page_user.c (balsa_druid_page_user): * src/ab-main.c (bab_get_filter_box), (bab_window_new): * src/ab-window.c (balsa_ab_window_init): * src/balsa-app.c (balsa_stock_button_with_label): * src/balsa-message.c (bm_header_tl_buttons), (bm_find_bar_new), (balsa_message_init): * src/balsa-mime-widget-crypto.c (balsa_mime_widget_signature_widget), (balsa_mime_widget_crypto_frame): * src/balsa-mime-widget-message.c (balsa_mime_widget_new_message), (bmw_message_extbody_url), (bmw_message_extbody_mail), (balsa_mime_widget_new_message_tl), (bm_header_widget_new): * src/balsa-mime-widget-multipart.c (balsa_mime_widget_new_multipart): * src/balsa-mime-widget-vcalendar.c (balsa_mime_widget_new_vcalendar), (balsa_vevent_widget): * src/balsa-mime-widget.c (balsa_mime_widget_new_unknown): * src/filter-edit-callbacks.c (build_type_notebook), (build_condition_dialog): * src/filter-edit-dialog.c (build_left_side), (build_match_page), (build_action_page), (build_right_side), (filters_edit_dialog): * src/filter-run-dialog.c (balsa_filter_run_dialog_init): * src/folder-conf.c (folder_conf_imap_sub_node): * src/mailbox-conf.c (balsa_server_conf_get_advanced_widget): * src/main-window.c: * src/message-window.c (message_window_new): * src/pref-manager.c (open_preferences_manager), (vbox_in_container), (color_box), (remote_mailbox_servers_group), (outgoing_mail_group), (checking_group), (message_colors_group), (add_pref_menu), (misc_group), (deleting_messages_group), (folder_scanning_group), (address_books_group), (pm_page_new), (pm_group_new): * src/print-gtk.c (message_prefs_widget): * src/sendmsg-window.c (sw_get_user_codeset), (quote_parts_select_dlg), (sendmsg_window_new), (subject_not_empty), (check_suggest_encryption): * src/toolbar-prefs.c (customize_dialog_cb), (create_toolbar_page): deprecation cleanup. 2011-10-13 Peter Bloomfield * src/sendmsg-window.h: remove redundant member header_table. * src/sendmsg-window.c (create_email_or_string_entry), (create_string_entry), (create_email_entry), (create_from_entry), (create_info_pane), (create_text_area): ditto; migrate from GtkTable to GtkGrid. 2011-10-13 Peter Bloomfield * src/print-gtk.c (begin_print), (add_font_button), (add_margin_spinbtn), (message_prefs_widget): migrate from GtkTable to GtkGrid. 2011-10-13 Peter Bloomfield * src/pref-manager.c (attach_entry), (attach_entry_full), (attach_information_menu), (attach_label), (checking_group), (quoted_group), (broken_8bit_codeset_group), (mdn_group), (word_wrap_group), (other_options_group), (main_window_group), (display_formats_group), (information_messages_group), (attach_font_button), (preview_font_group), (create_grid), (message_window_group): migrate from GtkTable to GtkGrid. 2011-10-06 Peter Bloomfield * src/main-window.c: migrate from GtkTable to GtkGrid. 2011-10-06 Peter Bloomfield * src/mailbox-conf.c (balsa_server_conf_get_advanced_widget), (balsa_server_conf_add_checkbox), (balsa_server_conf_add_spinner), (create_local_mailbox_dialog), (create_pop_mailbox_dialog), (create_imap_mailbox_dialog), (mailbox_conf_view_new_full), (mailbox_conf_view_new): migrate from GtkTable to GtkGrid. * src/mailbox-conf.h: ditto. 2011-10-06 Peter Bloomfield * src/folder-conf.c (folder_conf_imap_node), (folder_conf_imap_sub_node): migrate from GtkTable to GtkGrid. 2011-10-06 Peter Bloomfield * src/filter-edit-dialog.c (build_match_page), (fe_make_color_buttons), (build_action_page), (build_right_side): migrate from GtkTable to GtkGrid. 2011-10-06 Peter Bloomfield * src/filter-edit-callbacks.c (build_type_notebook): add a margin to notebook pages. 2011-10-06 Peter Bloomfield * src/filter-edit-callbacks.c (add_button), (add_check), (get_field_frame), (build_type_notebook): migrate from GtkTable to GtkGrid. 2011-10-05 Peter Bloomfield * src/balsa-mime-widget-vcalendar.c (balsa_vevent_widget): migrate from GtkTable to GtkGrid. 2011-10-05 Peter Bloomfield * src/address-book-config.c (create_gpe_dialog): build with GPE address book. 2011-10-05 Peter Bloomfield * src/balsa-mime-widget-text.c (bm_widget_new_vcard): make button span two columns, and left-align labels instead of right. 2011-10-04 Peter Bloomfield * src/balsa-mime-widget-text.c (bm_widget_new_vcard): migrate from GtkTable to GtkGrid. 2011-10-04 Peter Bloomfield * src/address-book-config.c (add_radio_buttons), (create_local_dialog), (create_externq_dialog), (create_ldap_dialog), (create_gpe_dialog): migrate from GtkTable to GtkGrid. 2011-10-04 Peter Bloomfield * src/ab-window.c (balsa_ab_window_init): migrate from GtkTable to GtkGrid. 2011-10-03 Peter Bloomfield Migrate from GtkTable to GtkGrid * libinit_balsa/assistant_helper.c (balsa_init_add_grid_entry), (balsa_init_add_grid_option), (balsa_init_add_grid_checkbox): * libinit_balsa/assistant_helper.h: * libinit_balsa/assistant_page_directory.c (balsa_druid_page_directory_init): * libinit_balsa/assistant_page_user.c (balsa_druid_page_user_init): 2011-10-03 Peter Bloomfield * libbalsa/smtp-server.c (smtp_server_add_widget), (libbalsa_smtp_server_dialog): migrate from GtkTable to GtkGrid. 2011-10-03 Peter Bloomfield * libbalsa/identity.c (append_ident_notebook_page), (setup_ident_frame), (ident_dialog_add_checkbutton), (ident_dialog_add_check_and_entry), (ident_dialog_add_entry), (ident_dialog_add_file_chooser_button), (ident_dialog_add_boxes), (ident_dialog_add_gpg_menu), (ident_dialog_add_smtp_menu): migrate from GtkTable to GtkGrid. 2011-10-03 Peter Bloomfield * libbalsa/address.c (libbalsa_address_get_edit_widget): migrate from GtkTable to GtkGrid. 2011-10-03 Peter Bloomfield * libbalsa/misc.c (libbalsa_create_grid), (libbalsa_create_grid_label), (libbalsa_create_grid_check), (libbalsa_create_grid_entry), (lb_create_size_group_func): new GtkGrid helpers. * libbalsa/misc.h: export them. 2011-10-03 Peter Bloomfield * src/pref-manager.c (remote_mailbox_servers_group), (address_books_group), (address_book_add_cb), (server_add_cb), (server_add_menu_widget): do not leak menus. 2011-10-02 Peter Bloomfield * src/pref-manager.c (address_book_add_cb), (server_add_cb): do not ref-sink and unref popup menus. 2011-10-02 Peter Bloomfield * src/save-restore.c (config_defclient_save): do not use uninitialized GError. 2011-09-28 Peter Bloomfield * configure.in: check for javascriptcoregtk with recent webkit; thanks to Vincent Untz and Marcus Hüwe; fixes bgo #660263. 2011-09-18 Peter Bloomfield * src/print-gtk.c (draw_page): use ngettext for plural; fixes bgo #659390. 2011-09-09 Peter Bloomfield * src/main-window.c: use checking_mail_lock to protect access to checking_mail. * src/main.c (balsa_cleanup): ditto. * src/threads.h: declare checking_mail. 2011-09-08 Peter Bloomfield * src/main-window.c: set view-filter in an idle callback. 2011-09-06 Peter Bloomfield * src/balsa-mblist.c (bmbl_mru_show_tree): try better default size for mblist widget. 2011-09-01 Peter Bloomfield * libbalsa/misc.c (lb_text_attr): add gssize len argument; (libbalsa_text_attr_string): pass -1; (libbalsa_text_attr_file): pass len; avoid stack buffer overflow. 2011-08-31 Peter Bloomfield * libbalsa/misc.c (libbalsa_text_attr_file): use GFile methods. * src/sendmsg-window.c (sw_set_charset): check for error return. 2011-08-30 Peter Bloomfield * src/main-window.c: call gtk_container_resize_children after adding the notebook page for a newly opened mailbox; should not be necessary, but seems to fix . 2011-08-30 Peter Bloomfield * configure.in: webkit can be used with threads disabled if glib version is 2.24 or later. 2011-08-29 Pawel Salek * libbalsa/filter-funcs.c: implement libbalsa_condition_to_string_user * libbalsa/filter.h: add libbalsa_condition_to_string_user() proto. * src/filter-edit-callbacks.c: use it to provide more user-friendly filter view. 2011-08-28 Peter Bloomfield * src/main-window.c: when network connection is reestablished, check mail if elapsed time since last check exceeds mail check interval. * src/main-window.h: new member last_check_time. 2011-08-28 Peter Bloomfield * libbalsa/body.c (libbalsa_message_body_get_pixbuf): check for error before closing loader. * src/balsa-print-object-image.c (balsa_print_object_image): use g_message instead of g_warning for image format error. 2011-08-26 Peter Bloomfield Make BalsaMimeWidgetImage a subclass of BalsaMimeWidget * src/balsa-mime-widget-image.h: subclass boilerplate. * src/balsa-mime-widget-image.c (balsa_mime_widget_image_init), (balsa_mime_widget_image_class_init): ditto. (balsa_mime_widget_image_dispose): disconnect signal handler. (balsa_mime_widget_new_image): store signal handler id. 2011-08-21 Peter Bloomfield * libbalsa/libbalsa-vfs.c (libbalsa_vfs_get_size): get size as guint64. * libbalsa/libbalsa-vfs.h: ditto. * src/sendmsg-window.c (add_attachment), (add_urlref_attachment), (create_info_pane): ditto; (render_attach_size): use g_format_size() instead of deprecated g_format_size_for_display(). 2011-08-21 Peter Bloomfield * libbalsa/address-view.c (lbav_ensure_blank_line_idle_cb): remove irrelevant comment. * src/sendmsg-window.c (create_info_pane): create "Reply-To:" entry before regular recipients, so the latter get the focus. 2011-08-20 Peter Bloomfield * src/main-window.h: add BalsaWindow::bottom_bar. * src/main-window.c: use it to hide both the progress bar and the status bar. 2011-08-20 Peter Bloomfield (lbav_ensure_blank_line): use gdk_threads_add_idle() for convenience; * libbalsa/address-view.c (lbav_ensure_blank_line_idle_cb): no need to check GSource removal. 2011-08-20 Peter Bloomfield * src/sendmsg-window.c (create_lang_menu): use enchant_broker_dict_exists() to check languages for Balsa's spell-checker. 2011-08-19 Peter Bloomfield * libbalsa/address-view.c (lbav_ensure_blank_line_idle_cb), (lbav_set_text), (lbav_editing_done), (lbav_row_editing_cb), (libbalsa_address_view_new): use GtkCellEditable's "editing-done" signal to capture address, instead of GtkCellRendererText's "edited" and "editing-canceled" signals. 2011-08-15 Peter Bloomfield * configure.in: when building with-gtkspell, check for gtkspell-3.0; do not warn about gtkspell or html widget. 2011-08-09 Peter Bloomfield Migrate spell-checker from PSpell to Enchant * configure.in: change tests. * src/balsa-app.c (balsa_app_init): remove all PSpell options. * src/balsa-app.h: ditto * src/pref-manager.c (open_preferences_manager), (apply_prefs), (set_prefs), (create_spelling_page): ditto. * src/save-restore.c (config_global_load), (config_save): * src/sendmsg-window.c (spell_check_cb): ditto. * src/spell-check.c (balsa_spell_check_class_init), (spch_set_property), (spch_get_property), (balsa_spell_check_new), (balsa_spell_check_new_with_text), (balsa_spell_check_set_text), (balsa_spell_check_set_language), (balsa_spell_check_init), (ignore_cb), (ignore_all_cb), (change_cb), (change_all_cb), (learn_cb), (cancel_cb), (done_cb), (balsa_spell_check_start), (balsa_spell_check_next), (highlight_idle), (balsa_spell_check_learn), (balsa_spell_check_fix), (balsa_spell_check_destroy), (spch_finish), (setup_suggestions), (check_word), (finish_check), (check_error), (next_word), (switch_word), (spch_save_word_iters), (spch_restore_word_iters): migrate. * src/spell-check.h: remove PSpell options. 2011-07-21 Peter Bloomfield * libbalsa/imap/siobuf.c (raw_write), (sio_flush_buffer), (sio_flush): indicate when buffer has been deallocated. 2011-07-13 Peter Bloomfield * configure.in: remove references to gtk+-2.0. 2011-06-22 Peter Bloomfield Drop bad-address-color * src/balsa-app.h: * src/balsa-mime-widget-message.c (add_header_sigstate): * src/pref-manager.c (open_preferences_manager), (apply_prefs), (set_prefs), (colors_subpage): * src/save-restore.c (config_global_load), (config_save): * src/sendmsg-window.c (balsa_sendmsg_destroy_handler), (create_info_pane): * src/sendmsg-window.h: 2011-06-22 Peter Bloomfield * src/sendmsg-window.c (add_attachment): do not cast non-widget to GtkWidget*. 2011-06-10 Peter Bloomfield * src/balsa-mime-widget-message.c (bm_header_widget_realized): set the foreground and background colors for SELECTED state as well as for NORMAL, so that selected text is distinguished. 2011-06-05 Peter Bloomfield * src/save-restore.c (config_identities_load): load identities in the order in which they were saved. * src/sendmsg-window.c (balsa_sendmsg_destroy_handler), (sw_combo_box_changed), (create_from_entry): move selected identity to the front of balsa_app.identities; see (Carlos Franke). 2011-06-01 Peter Bloomfield Respond to * src/sendmsg-window.c (setup_headers_from_message): make the blank line in the recipient widget not a Bcc: line; (setup_headers_from_identity): ditto. 2011-05-31 Peter Bloomfield * src/main.c (mw_message_received_cb): present compose window; (main): give unique_app_new_with_commands a non-NULL startup-id, because when NULL it creates a fake timestamp, which results in the running window being presented. 2011-05-28 Peter Bloomfield * src/main.c (balsa_handle_automation_options): do not send ACTIVATE when asked for status; see https://mail.gnome.org/archives/balsa-list/2011-May/msg00015.html 2011-04-16 Peter Bloomfield Use GDesktopAppInfo instead of GAppInfo * configure.in: add gio-unix-2.0 to gnome-extras so we can use GDesktopAppInfo. * src/save-restore.c (config_defclient_save): use GDesktopAppInfo instead of GAppInfo to set Balsa as default client. 2011-04-15 Peter Bloomfield Fix bz #647695; Pawel's patch for master, with one change. * src/balsa-message.c (bm_find_bar_new), (balsa_message_init), (balsa_message_find_in_message): show all of the widget before adding the find bar. * src/message-window.c (message_window_new): show the widget, not show all. 2011-04-14 Peter Bloomfield * src/save-restore.c (config_defclient_save): fix launch commandline. 2011-04-13 Peter Bloomfield Migrate from GConf * configure.in: do not check gconf-2.0. * libinit_balsa/assistant_page_defclient.c (balsa_druid_page_defclient_init), (balsa_druid_page_defclient), (balsa_druid_page_defclient_toggle): use GAppInfo to check default mailer. * src/save-restore.c (config_defclient_save): use GAppInfo to set default mailer. * website/faq.html: update. 2011-04-06 Peter Bloomfield * src/main-window.c: implement alt-n to switch to mailbox n. 2011-04-06 Peter Bloomfield * balsa.desktop.in: declare Balsa to be MimeType=x-scheme-handler/mailto. 2011-04-05 Peter Bloomfield * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): new GtkSourceView macro. 2011-02-05 Peter Bloomfield * src/balsa-message.c (hide_all_parts): just destroy the children, no need to recurse deeper. 2011-02-05 Peter Bloomfield * src/balsa-mblist.c (bmbl_init): remove redundant and crashing column-set-visible. 2011-02-05 Peter Bloomfield * configure.in: GtkHtml-4 is the new GtkHtml-3. * libbalsa/html.c (libbalsa_html_new), (lbh_size_request_cb): ditto; do not connect to "size-request" signal. 2011-01-30 Peter Bloomfield Revert from GSettings to GConf for default client stuff * configure.in: * libinit_balsa/assistant_page_defclient.c (balsa_druid_page_defclient): * src/save-restore.c (config_defclient_save): 2011-01-30 Peter Bloomfield Silence whining from gcc-4.6 * libbalsa/files.c (libbalsa_icon_finder): * libbalsa/filter-funcs.c (libbalsa_filter_export_sieve): * libbalsa/identity.c (libbalsa_identity_get_signature): * libbalsa/imap-server.c (libbalsa_imap_server_finalize): * libbalsa/imap/imap-handle.c (ir_esearch): * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_open): * libbalsa/mailbox_local.c (libbalsa_mailbox_local_load_config): * libbalsa/mailbox_maildir.c (libbalsa_mailbox_maildir_add_message): * libbalsa/rfc2445.c (date_time_2445_to_time_t): * libbalsa/rfc3156.c (get_passphrase_cb): * libbalsa/server.c (libbalsa_server_user_cb): * libbalsa/smtp-server.c (libbalsa_smtp_server_finalize), (libbalsa_smtp_server_class_init): * src/address-book-config.c (create_generic_dialog): * src/main.c (config_init), (mailboxes_init): * src/save-restore.c (config_filter_load), (config_filters_save), (config_defclient_save): * src/sendmsg-window.c (edit_with_gnome_check): * src/spell-check.c (balsa_spell_check_class_init): 2011-01-30 Peter Bloomfield * src/toolbar-factory.c (balsa_toolbar_model_finalize), (balsa_toolbar_model_new): do not refer to "org.gnome.*" when not HAVE_GNOME; (tm_populate), (tm_default_style): add empty second line only for GTK_TOOLBAR_BOTH. 2011-01-30 Peter Bloomfield * configure.in: restore HAVE_GNOME to wrap reference to "org.gnome.*". 2011-01-30 Peter Bloomfield * balsa.desktop.in: add MimeType=x-scheme-handler/mailto. 2011-01-29 Peter Bloomfield * src/toolbar-factory.c (balsa_toolbar_model_finalize), (tm_gsettings_change_cb), (balsa_toolbar_model_new), (tm_default_style): really use the desktop default when so configured. 2011-01-28 Peter Bloomfield Migrate from GConf to GSettings * libinit_balsa/assistant_page_defclient.c (balsa_druid_page_defclient): * src/ab-main.c (main): * src/main.c (config_init), (mailboxes_init), (main): * src/save-restore.c (config_global_load), (config_defclient_save): * src/save-restore.h: * src/toolbar-factory.c (tm_gsettings_change_cb), (balsa_toolbar_model_new), (tm_default_style): 2011-01-28 Peter Bloomfield * src/balsa-index.c (balsa_index_load_mailbox_node): fix failed assertion. 2011-01-24 Peter Bloomfield * configure.in: new deprecation tests GDK_MULTIHEAD_SAFE, GDK_MULTIDEVICE_SAFE. * libbalsa/files.c (libbalsa_icon_finder): add widget argument so we can find settings. * libbalsa/files.h: ditto. * libbalsa/filter.c (libbalsa_filter_mailbox_messages): deprecation cleanup. * libbalsa/identity.c (help_ident_cb), (md_response_cb): ditto. * libbalsa/smtp-server.c (smtp_server_response): ditto. * libbalsa/source-viewer.c (copy_cb): ditto. * src/address-book-config.c (help_button_cb): ditto. * src/balsa-app.c (balsa_app_init): ditto. * src/balsa-icons.c (load_balsa_pixmap): ditto. * src/balsa-index.c (balsa_index_set_column_widths): ditto. * src/balsa-message.c (display_part): ditto. * src/balsa-mime-widget-message.c (extbody_call_url): ditto. * src/balsa-mime-widget-text.c (fix_text_widget), (url_copy_cb), (check_over_url), (handle_url), (fill_text_buf_cited): ditto. * src/balsa-print-object-default.c (balsa_print_object_default): ditto. * src/balsa-print-object-text.c (balsa_print_object_text_vcard), (balsa_print_object_text_calendar): ditto. * src/filter-edit-callbacks.c (condition_dialog_response), (fe_dialog_response): ditto. * src/filter-run-callbacks.c (fr_dialog_response): ditto. * src/folder-conf.c (folder_conf_response): ditto. * src/main-window.c: ditto. * src/pref-manager.c (balsa_help_pbox_display): ditto. * src/sendmsg-window.c (on_open_url_cb), (add_attachment): ditto. * src/toolbar-prefs.c (tp_dialog_response_cb): ditto. 2011-01-23 Peter Bloomfield * src/balsa-mime-widget-text.c (text_view_url_popup): deprecation cleanup. 2011-01-23 Peter Bloomfield * libbalsa/address-view.c (lbav_ensure_blank_line_idle_cb), (libbalsa_address_view_new): clean up, and make LibBalsaAddressView opaque. * libbalsa/address-view.h: ditto. 2011-01-23 Peter Bloomfield * configure.in: change html-widget default to "webkit", and warn if it is not chosen; change gtkspell default to "no", and warn if it is not chosen; clarify GtkSourceView option. 2011-01-21 Peter Bloomfield * libbalsa/html.c (lbh_show_info_bar), (libbalsa_html_new): use GtkBox packing instead of the event-box. 2011-01-21 Peter Bloomfield * libbalsa/html.c (lbh_info_bar_response_cb), (lbh_show_info_bar), (lbh_resource_request_starting_cb), (libbalsa_html_new): put info-bar in an event-box, and only when needed. 2011-01-19 Peter Bloomfield * src/save-restore.c (config_global_load), (save_color), (load_color): save rgba() colors with "RGBA" suffix. 2011-01-19 Peter Bloomfield Pass default screen instead of NULL to gtk_show_uri * libbalsa/identity.c (help_ident_cb): * libbalsa/smtp-server.c (smtp_server_response): * src/address-book-config.c (help_button_cb): * src/balsa-mime-widget-message.c (extbody_call_url): * src/balsa-mime-widget-text.c (store_button_coords), (check_over_url), (handle_url): * src/filter-edit-callbacks.c (condition_dialog_response), (fe_dialog_response): * src/filter-run-callbacks.c (fr_dialog_response): * src/folder-conf.c (folder_conf_response): * src/main-window.c: * src/pref-manager.c (balsa_help_pbox_display): * src/sendmsg-window.c (on_open_url_cb): * src/toolbar-prefs.c (tp_dialog_response_cb): 2011-01-17 Peter Bloomfield * src/sendmsg-window.c (create_email_or_string_entry): new override font API. 2011-01-17 Peter Bloomfield * src/balsa-mime-widget-image.c (bmwi_context_changed_cb), (balsa_mime_widget_new_image): set background color from viewport. 2011-01-17 Peter Bloomfield * src/balsa-mime-widget-crypto.c (balsa_mime_widget_signature_widget), (balsa_mime_widget_crypto_frame): reorganize window-showing. 2011-01-17 Peter Bloomfield * src/balsa-icons.c (balsa_register_pixbufs): new icon-render API. * src/balsa-mime-widget.c (balsa_mime_widget_new), (balsa_mime_widget_new_unknown): ditto. * src/toolbar-prefs.c (tp_store_set): ditto. 2011-01-17 Peter Bloomfield * src/balsa-app.h: port from GdkColor to GdkRGBA. * src/balsa-cite-bar.c (balsa_cite_bar_draw): ditto, and from GtkStyle to GtkStyleContext. * src/balsa-message.c (bm_on_set_style), (balsa_message_init), (get_crypto_content_icon): ditto. * src/balsa-mime-widget-image.c (balsa_mime_widget_new_image): ditto. * src/balsa-mime-widget-message.c (balsa_mime_widget_new_message), (balsa_mime_widget_new_message_tl), (bm_header_widget_realized), (bm_header_widget_set_style), (bm_header_widget_new), (bmwm_buffer_set_prefs), (balsa_mime_widget_message_set_headers_d): ditto, and reorganize widget-showing. * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (bm_modify_font_from_string), (quote_tag), (draw_cite_bar_real), (bm_widget_new_vcard), (fill_text_buf_cited): ditto, and drop allocate_quote_colors. * src/balsa-mime-widget-vcalendar.c: reorganize widget-showing. * src/balsa-print-object-text.c (balsa_print_object_text_draw): port from GdkColor to GdkRGBA. * src/main-window.c: port from GtkStyle to GtkStyleContext. * src/pref-manager.c (apply_prefs), (set_prefs): port from GdkColor to GdkRGBA. * src/quote-color.c (is_a_quote): drop allocate_quote_colors. * src/quote-color.h: ditto. * src/save-restore.c (save_color), (load_color): port from GdkColor to GdkRGBA. * src/sendmsg-window.c (add_urlref_attachment), (create_email_or_string_entry), (create_text_area): ditto. 2011-01-17 Peter Bloomfield * libbalsa/source-viewer.c (libbalsa_show_message_source): new override font API. 2011-01-17 Peter Bloomfield * libbalsa/libbalsa.c (libbalsa_source_view_new): drop support for GtkSourceView-1. * libbalsa/libbalsa.h: ditto. 2011-01-15 Pawel Salek * autogen.sh: port fixes from bootstrap.sh (inspired by pancake). * configure.in: support libgtkhtml-3.15 lib version. * libbalsa/imap-server.c: libbalsa_imap_server_get_handle() check if the parameter passed is non-null (credit to pancake). * libbalsa/imap/imap-handle.c: zeroize released pointers (pancake). * libinit_balsa/assistant_page_user.c: fix widget packing (pancake). * src/balsa-index.c: return FALSE on failure (pancake). 2011-01-11 Peter Bloomfield * src/balsa-mime-widget-message.c (balsa_mime_widget_new_message): show the message. 2011-01-09 Peter Bloomfield * configure.in: do not configure Bonobo/Corba; do not check GtkSourceview version. * Makefile.am: unversioned GtkSourceview test. 2011-01-08 Peter Bloomfield * src/pref-manager.c (quoted_group), (mdn_group): let GtkLabel wrap text. 2011-01-08 Peter Bloomfield * src/balsa-mblist.c (bmbl_mru_show_tree): make the mailbox tree dialog a reasonable size. 2010-12-29 Peter Bloomfield * src/balsa-mime-widget-image.c (img_check_size): revert; use previous calculation, with a different magic number (16). 2010-12-28 Peter Bloomfield * src/balsa-mime-widget-image.c (img_check_size): use parent width. 2010-12-28 Peter Bloomfield * libbalsa/filter.c (libbalsa_filter_mailbox_messages): do not use GnomeSound. 2010-12-28 Peter Bloomfield Clean up dead code and trailing white space * libbalsa/address.c (addrlist_drag_drop_cb): * libbalsa/identity.c (ident_dialog_get_path): * libinit_balsa/assistant_helper.c (entry_changed_cb): * src/ab-window.c (balsa_ab_window_init): * src/balsa-index.c (bndx_string_width), (bndx_popup_position_func): * src/balsa-mblist.c (bmbl_drag_motion), (bmbl_drag_cb): * src/balsa-message.c (bm_find_pass_to_entry), (balsa_get_parent_window), (balsa_message_grab_focus): * src/main-window.c: * src/sendmsg-window.c (drag_data_quote), (subject_not_empty), (check_suggest_encryption): * src/toolbar-factory.c (tm_popup_position_func), (tm_do_popup_menu): 2010-12-28 Peter Bloomfield Do not support BonoboActivation * src/balsa-bonobo.c: deleted. * src/balsa-bonobo.h: ditto. 2010-12-28 Peter Bloomfield Initial commit for gtk3 development branch * configure.in: * libbalsa/address-view.c (lbav_key_pressed_cb): * libbalsa/body.c (libbalsa_message_body_get_pixbuf): * libbalsa/cell-renderer-button.c (libbalsa_cell_renderer_button_activate): * libbalsa/html.c (lbh_resource_request_starting_cb), (lbh_info_bar_widget), (libbalsa_html_new): * libbalsa/identity.c (ident_dialog_add_gpg_menu), (add_show_menu), (ident_dialog_add_smtp_menu): * libbalsa/misc.c (libbalsa_charset_button_new): * libbalsa/smtp-server.c (smtp_server_tls_widget): * libinit_balsa/assistant_helper.c (balsa_init_add_table_option): * src/ab-main.c (ew_key_pressed): * src/ab-window.c (balsa_ab_window_load_books), (balsa_ab_window_init): * src/address-book-config.c (create_generic_dialog): * src/balsa-app.c (balsa_app_init), (balsa_app_destroy): * src/balsa-app.h: * src/balsa-cite-bar.c (balsa_cite_bar_class_init), (balsa_cite_bar_init), (balsa_cite_bar_get_preferred_width), (balsa_cite_bar_get_preferred_height), (balsa_cite_bar_draw): * src/balsa-index.c (bndx_class_init), (bndx_destroy), (bndx_popup_position_func), (bndx_pipe_response), (balsa_index_pipe): * src/balsa-mblist.c (bmbl_class_init), (bmbl_mru_show_tree): * src/balsa-message.c (balsa_message_class_init), (bm_find_scroll_to_rectangle), (bm_find_pass_to_entry), (balsa_message_destroy), (select_part): * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_key_press_event): * src/balsa-mime-widget-crypto.c (balsa_mime_widget_signature_widget), (balsa_mime_widget_crypto_frame): * src/balsa-mime-widget-image.c (balsa_mime_widget_new_image), (img_check_size): * src/balsa-mime-widget-text.c (gtk_widget_destroy_insensitive), (text_view_populate_popup), (fill_text_buf_cited): * src/balsa-mime-widget.c (balsa_mime_widget_new), (balsa_mime_widget_new_unknown): * src/filter-edit-callbacks.c (fe_user_header_add), (get_field_frame): * src/filter-edit-dialog.c (fe_build_option_menu): * src/folder-conf.c (browse_button_cb): * src/mailbox-conf.c (mailbox_conf_combo_box_make), (balsa_server_conf_get_advanced_widget), (mailbox_conf_view_new_full): * src/mailbox-node.c (balsa_mailbox_node_get_context_menu): * src/main-window.c: * src/message-window.c (message_window_new): * src/pref-manager.c (apply_prefs), (checking_group), (quoted_group), (word_wrap_group), (main_window_group), (pspell_settings_group), (misc_group), (deleting_messages_group), (folder_scanning_group), (option_menu_cb), (add_show_menu), (pm_combo_box_new): * src/quote-color.c (allocate_quote_colors): * src/sendmsg-window.c (sw_get_user_codeset), (sw_scroll_size_request), (create_email_entry), (create_info_pane), (create_text_area): * src/spell-check.c (balsa_spell_check_class_init), (balsa_spell_check_destroy): * src/store-address.c (store_address_book_frame): * src/toolbar-factory.c (tm_popup_position_func): 2010-12-09 Peter Bloomfield * balsa.1.in: do not use macro URL; fixes gnome bz #636801. 2010-12-09 Pawel Salek * configure.in: make detection more automatic; fix gnome bz #636805. 2010-12-05 Peter Bloomfield * src/toolbar-factory.c (tm_populate): do not make 2-line toolbar button text if we are using the desktop default and it is GTK_TOOLBAR_BOTH_HORIZ; fixes a strange vertical alignment issue when using the default and it is GTK_TOOLBAR_BOTH_HORIZ. 2010-11-19 Pawel Salek * Configure.in: compile against libnotify-0.4.x as well. 2010-11-19 Pawel Salek * src/main-window.c: * libbalsa/information.c: compile against libnotify-0.7.0 * configure.in, NEWS: release 2.4.9 2010-11-16 Peter Bloomfield * libbalsa/mailbox_imap.c (multi_append_cb): cast quotient, not numerator. 2010-11-16 Peter Bloomfield * libbalsa/mailbox_imap.c (multi_append_cb): do not break gettext with concatenated string. 2010-11-12 Peter Bloomfield * src/balsa-message.c (bm_next_part_info): look for next part above current part, if necessary; fixes https://mail.gnome.org/archives/balsa-list/2010-November/msg00003.html 2010-11-07 Peter Bloomfield Implement LibBalsaCompletion as a copy of (deprecated) GCompletion * libbalsa/completion.c: new file. * libbalsa/completion.h: new file. * libbalsa/Makefile.am: build them. * libbalsa/abook-completion.c: use LibBalsaCompletion. * libbalsa/address-book-extern.c (libbalsa_address_book_externq_alias_complete): ditto. * libbalsa/address-book-gpe.c: ditto. * libbalsa/address-book-ldap.c (libbalsa_address_book_ldap_alias_complete): ditto. * libbalsa/address-book-rubrica.c (libbalsa_address_book_rubrica_init), (libbalsa_address_book_rubrica_alias_complete), (lbab_rubrica_load_xml): ditto. * libbalsa/address-book-text.c (libbalsa_address_book_text_init), (libbalsa_address_book_text_finalize), (lbab_text_load_file), (libbalsa_address_book_text_alias_complete): ditto. * libbalsa/address-book-text.h: ditto. * libbalsa/address-book.c (libbalsa_address_book_alias_complete): ditto. * libbalsa/address-book.h: ditto. * libbalsa/address-view.c (lbav_get_matching_addresses): ditto. 2010-11-07 Albrecht Dreß Gtk3 deprecation cleanup * libbalsa/address.c (addrlist_drag_drop_cb): * libbalsa/imap/imap-handle.c (imap_get_flag), (imap_cmd_get_tag): * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_message_match), (libbalsa_mailbox_imap_get_matchings), (libbalsa_mailbox_imap_subscribe), (libbalsa_imap_rename_subfolder), (libbalsa_imap_new_subfolder): * src/ab-window.c (balsa_ab_window_init): * src/balsa-cite-bar.c (balsa_cite_bar_expose): * src/balsa-icons.c: * src/balsa-icons.h: * src/balsa-mblist.c (bmbl_drag_motion), (bmbl_drag_cb): * src/main-window.c: * src/sendmsg-window.c (drag_data_quote), (subject_not_empty): 2010-10-14 Peter Bloomfield * libbalsa/mailbox_imap.c (imap_expunge_cb): do not remove invalid array element. 2010-09-26 Peter Bloomfield Use separate mutexes for mailbox locking and checking mail * libbalsa/libbalsa.c (libbalsa_lock_mailbox), (libbalsa_unlock_mailbox): make the mutex static. * libbalsa/libbalsa_private.h: ditto. * src/main-window.c: use checking_mail_lock. * src/main.c (threads_init), (threads_destroy), (balsa_cleanup): * src/threads.h: ditto. 2010-09-01 Peter Bloomfield * src/main-window.c: hold gdk lock while updating UI. 2010-08-31 Peter Bloomfield * src/main-window.c: remove unintended debug spew. 2010-08-30 Peter Bloomfield * src/balsa-mblist.c (balsa_mblist_mailbox_node_redraw): update notebook tab when redrawing. * src/mailbox-conf.c (mailbox_conf_update): ...so we do not need to here. * src/save-restore.c (sr_special_notify, config_mailbox_set_as_special): use weak refs consistently; set names of new special mailboxes to the standard names, and names of previously special mailboxes to what they will be in the next session. 2010-08-21 Pawel Salek * configure.in, NEWS: release 2.4.8 2010-08-13 Pawel Salek * libbalsa/imap/imap-commands.c: check state after locking the handle. * libbalsa/imap/imap-handle.c: ditto. * libbalsa/imap/imap-handle.h: modify state checking macros accordingly. * libbalsa/imap/siobuf.c: set sio->ssl to null after SSL_free(). 2010-08-13 Peter Bloomfield * src/mailbox-conf.c (create_local_mailbox_dialog): use window title to show mailbox type; fixes bgo #625695 (Jack Ostroff). 2010-08-12 Peter Bloomfield * src/balsa-message.c (balsa_message_set): do not crash when message == NULL. 2010-08-05 Peter Bloomfield * libbalsa/mailbox_imap.c (message_info_from_msgno): return NULL if msgno out of range; (imap_flags_cb), (imap_exists_idle), (imap_expunge_cb), (libbalsa_mailbox_imap_message_match), (libbalsa_mailbox_imap_get_message), (lbm_imap_change_user_flags), (libbalsa_mailbox_imap_msgno_has_flags): test for NULL return from message_info_from_msgno. 2010-07-28 Peter Bloomfield * libbalsa/identity.c (libbalsa_identity_init), (libbalsa_identity_finalize), (ident_dialog_update), (display_frame_update), (libbalsa_identity_new_config), (libbalsa_identity_save), (display_frame_set_gpg_mode), (ident_dialog_get_value): do not forget gpgme-related settings when running --without-gpgme. * libbalsa/identity.h: ditto. * libbalsa/rfc3156.h: ditto. 2010-07-28 Peter Bloomfield * src/mailbox-conf.c (balsa_server_conf_get_advanced_widget): disable SSL and TLS widgets when building --without-ssl. 2010-07-25 Pawel Salek * libbalsa/imap/imap-handle.c: work around buggy Gmail. * libbalsa/imap/imap-tls.c: change openssl api used for cert checks. * src/balsa-mime-widget-message.c: warn the user when no embedded message info available. 2010-07-14 Peter Bloomfield Install dialog to ask the user before selecting a different mailbox, and an option to not use it; fixes bug #620221 (ghisha email it). * src/balsa-app.h: new member ask_before_select. * src/balsa-app.c (balsa_app_init): initialize it FALSE. * src/main-window.c: uncomment dialog and make it conditional on balsa_app.ask_before_select. * src/pref-manager.c (open_preferences_manager), (apply_prefs), (set_prefs), (main_window_group): manage it. * src/save-restore.c (config_global_load), (config_save): save and restore it, default FALSE. 2010-07-10 Peter Bloomfield Support IMAP server that complies with RFC 2086 but not with RFC 4013; fixes bug #623910 (Helmut Jarausch). * libbalsa/imap/imap-handle.c (ir_capability_data): check for "RIGHTS=" capability to distinguish RFC-4013-compliant server; (extract_acl): check for "cd" rights when server does not comply with RFC 4013. * libbalsa/imap/imap-handle.h: add IMCAP_RIGHTS to ImapCapability enum. * libbalsa/imap/libimap.h: add IMAP_ACL_OBS_CREATE and IMAP_ACL_OBS_DELETE to ImapAclType enum, and define IMAP_RIGHTS_CAN_WRITE(rights) macro. * libbalsa/mailbox_imap.c (imap_acl_to_str): show "cd" rights when server does not comply with RFC 4013; (libbalsa_mailbox_imap_get_selected_handle): use IMAP_RIGHTS_CAN_WRITE(rights) macro. 2010-07-07 Peter Bloomfield * libbalsa/libbalsa.c (libbalsa_date_to_utf8): return NULL when date is zero; fixes bug #623740 (Helmut Jarausch). 2010-06-04 Peter Bloomfield Drop legacy icon names. * images/16x16/Makefile.am: rename stock_inbox and stock_outbox. * images/16x16/mail-inbox.png: new name. * images/16x16/mail-outbox.png: ditto. * images/16x16/stock_inbox.png: old name. * images/16x16/stock_outbox.png: ditto. * src/balsa-icons.c (load_balsa_pixmap), (balsa_register_pixmaps): use new names. * src/balsa-print-object-text.c (balsa_print_object_text_calendar): ditto. * src/main-window.c: ditto. 2010-06-01 Peter Bloomfield Copy icons removed from gnome-icon-theme-2.30 from an earlier version. * images/16x16/Makefile.am: * images/16x16/stock_book_open.png: * images/16x16/stock_book_red.png: * images/16x16/stock_contact.png: * images/16x16/stock_inbox.png: * images/16x16/stock_mail-receive.png: * images/16x16/stock_mail.png: * images/16x16/stock_outbox.png: * images/24x24/Makefile.am: * images/24x24/stock_book_blue.png: * images/24x24/stock_book_green.png: * images/24x24/stock_book_open.png: * images/24x24/stock_book_red.png: * images/24x24/stock_book_yellow.png: * images/24x24/stock_contact.png: * images/24x24/stock_mail-receive.png: * images/24x24/stock_mail.png: * images/24x24/stock_view-fields.png: 2010-05-20 Peter Bloomfield * src/save-restore.c (config_global_load): do not wrap outgoing message by default, as it disables format=flowed. 2010-05-20 Peter Bloomfield * configure.in: add dependency on gthread-2.0; fixes bug #618979 (Kacper Kowalik); also add -lz to $LIBS, to build without openssl. 2010-05-06 Pawel Salek * libinit_balsa/assistant_page_defclient.c: free memory. * libinit_balsa/assistant_page_{directory,user}.c: ditto. * src/balsa-app.c: free memory on exit. * src/balsa-icons.[hc]: ditto by providing "unregister" functions. * src/main-window.c: unregister the pixmaps. * src/main.c: free configuration on exit. * src/save-restore.c: do not leak memory. 2010-05-01 Pawel Salek * src/balsa-message.c: handle expunge events arriving between fetch and flag set operations. 2010-04-27 Peter Bloomfield * libbalsa/send.h: allocate message with g_new instead of malloc, since we g_free it. 2010-04-26 Albrecht Dreß * libbalsa/rfc3156.c (libbalsa_check_crypto_engine): add hint about failed test for CMS protocol. 2010-04-11 Albrecht Dreß * libbalsa/filter.c (libbalsa_filter_mailbox_messages): build on Lucid β. * src/ab-main.c: ditto. * src/main.c (balsa_cleanup): ditto. 2010-04-07 Peter Bloomfield * src/balsa-index.c (bndx_string_width): use allocation width instead of pixbuf width. 2010-04-06 Peter Bloomfield * libbalsa/mailbox.c (msg_iterator): object-ref the stream if the caller will unref it. 2010-04-05 Peter Bloomfield * libbalsa/mailbox_imap.c (multi_append_cb): round size in kibibytes, for consistency with libbalsa_size_to_gchar. 2010-04-05 Peter Bloomfield * src/balsa-index.c (bndx_string_width), (bndx_instance_init), (balsa_index_set_column_widths): get column width as actual string width. 2010-04-05 Peter Bloomfield * libbalsa/misc.c (libbalsa_size_to_gchar): more compact string representation of a size. 2010-04-05 Pawel Salek * libbalsa/mailbox.c: Mailbox::add_messages would leak a file descriptor each time it was called. 2010-03-29 Peter Bloomfield * src/balsa-index.c (bndx_instance_init), (balsa_index_set_column_widths): set the renderer width for the "Size" column instead of the column width--works reliably; fixes bug #579479 (Jonathan North Washington). 2010-03-27 Peter Bloomfield * src/main-window.c: do not crash on early exit; fixes bug #613998 (Ildar). 2010-03-27 Peter Bloomfield * configure.in: build with gtkhtml2. 2010-03-27 Peter Bloomfield * src/main-window.c: use a single thread to open all mailboxes. 2010-03-27 Peter Bloomfield * src/balsa-app.c (open_mailbox_by_url), (open_mailboxes_idle_cb): open first mailbox not hidden, open the remainder hidden. 2010-03-27 Peter Bloomfield * src/balsa-index.c (bndx_destroy): recheck index->mailbox_node after dropping the gdk lock. 2010-03-27 Peter Bloomfield * libbalsa/mailbox.c (libbalsa_mailbox_close): increase mailbox ref count while closing it. 2010-03-23 Peter Bloomfield * src/main.c: missing include. 2010-03-23 Peter Bloomfield * configure.in: use single-includes. 2010-03-20 Peter Bloomfield * libbalsa/html.c (libbalsa_html_get_view_widget): new method to get the actual view widget. * libbalsa/html.h: ditto. * src/balsa-mime-widget-text.c (bm_widget_new_html): connect to key-press-event on the actual view widget. 2010-03-11 Peter Bloomfield * libbalsa/files.c (libbalsa_icon_finder): allocate string only if needed. 2010-03-07 Albrecht Dreß * src/balsa-mime-widget-text.c: do not mangle quotation characters when copying text. 2010-03-04 Pawel Salek * src/balsa-mime-widget-crypto.c: set the parent right. 2010-03-03 Albrecht Dreß * libbalsa/misc.[hc]: * libbalsa/mailbox.c: make libbalsa_size_to_gchar() a common function. * src/folder-conf.c: use it for displaying IMAP quota. 2010-03-03 Peter Bloomfield * libbalsa/message.c (libbalsa_message_change_flags): check argument validity. * libbalsa/send.c (handle_successful_send): check that the message still belongs to a mailbox. 2010-03-03 Peter Bloomfield * libbalsa/address-view.c (libbalsa_address_view_get_list): do not append NULL list in internet_address_list_append. 2010-02-28 Peter Bloomfield * src/folder-conf.c (folder_conf_imap_sub_node): remove mnemonic from subfolder-of label. 2010-02-20 Peter Bloomfield * src/folder-conf.c (set_ok_sensitive), (folder_conf_imap_sub_node): clean up folder properties dialog and manage Update button sensitivity. * src/mailbox-conf.c (create_local_mailbox_dialog), (create_imap_mailbox_dialog), (mailbox_conf_view_new_full), (mailbox_conf_view_new): use callback to manage Update button sensitivity. * src/mailbox-conf.h: new API. * src/main-window.c: change mailbox Edit to Properties. 2010-02-20 Albrecht Dreß * src/folder-conf.c (folder_conf_imap_sub_node): use Cyrus server's standard names for rights. 2010-02-20 Pawel Salek * libbalsa/gmime-gpgme-signature.c: add missing #include config.h that broke rawhide build. * libbalsa/imap/imap-commands.c: issue SELECT+MYRIGHTS together whenever necessary to save one RTT. * libbalsa/imap/imap-handle.c: add imap_cmd_exec_cmds() helper. * libbalsa/imap/imap_private.h: and its prototype. 2010-02-19 Peter Bloomfield * configure.in: option to configure GMime-2.4 or 2.6. * libbalsa/gmime-gpgme-context.c (g_mime_gpgme_context_finalize), (g_mime_session_passphrase), (g_mime_gpgme_context_new): * libbalsa/gmime-gpgme-context.h: use it. * libbalsa/gmime-stream-gio.c: ditto. * libbalsa/mailbox_mbox.c: ditto. * libbalsa/rfc3156.c (password_request_func), (libbalsa_sign_mime_object), (libbalsa_encrypt_mime_object), (libbalsa_body_check_signature), (libbalsa_body_decrypt), (libbalsa_rfc2440_sign_encrypt), (libbalsa_rfc2440_verify), (libbalsa_rfc2440_decrypt): ditto. 2010-02-17 Albrecht Dreß * libbalsa/imap/imap-commands.c: implement QUOTA, MYRIGHTS and GETACL commands. * libbalsa/imap/imap-handle.h: register QUOTA capability. * libbalsa/imap/imap_private.h: add private fields and enums related to these extensions. * libbalsa/mailbox_imap.[ch]: interface them. * src/folder-conf.c: use them. 2010-02-16 Albrecht Dreß * libbalsa/information.c: build when libnotify is not available. 2010-02-16 Peter Bloomfield * libbalsa/body.c (libbalsa_message_body_get_cid), (libbalsa_message_body_save_temporary), (libbalsa_message_body_get_by_id): strip "<>" from content-id. 2010-02-13 Pawel Salek * configure.in, NEWS: release 2.4.7 2010-02-12 Albrecht Dreß * src/balsa-message.c (bm_previous_part_info): do not return uninitialized BalsaPartInfo. 2010-02-09 Albrecht Dreß * configure.in: more understandable output from html-widget configuration. 2010-02-05 Peter Bloomfield * configure.in: use a case statement to configure html-widget. * libbalsa/html.c: test for HAVE_HTML_WIDGET. * libbalsa/html.h: ditto. * libbalsa/mime.c (process_mime_part): ditto. * src/balsa-message.c (bm_find_entry_changed_cb), (bm_find_again), (preferred_part), (balsa_message_can_select), (balsa_message_find_in_message): ditto. * src/balsa-message.h: ditto. * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): ditto. * src/main-window.c: ditto. * src/message-window.c (mw_select_part_cb): ditto. 2010-02-05 Peter Bloomfield * src/balsa-app.h: new boolean mark_quoted. * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): respect it. * src/pref-manager.c (open_preferences_manager), (apply_prefs), (set_prefs), (quoted_group), (mark_quoted_modified_cb): manage it. * src/save-restore.c (config_global_load), (config_save): save and restore it. 2010-02-05 Peter Bloomfield * libbalsa/mime.c (libbalsa_match_regex): do not loop indefinitely when regex matches zero characters. 2010-02-05 Pawel Salek * libbalsa/imap/imap_compress.c: reduce the compressed stream flushing frequency. * libbalsa/imap/siobuf.c: matching change on the buffering side. 2010-01-27 Pawel Salek * configure.in, NEWS: release 2.4.6. 2010-01-25 Pawel Salek * libbalsa/imap/siobuf.c: fix occassional sio_ungetc() failures for a compressed connection. 2010-01-25 Peter Bloomfield * libbalsa/filter-funcs.c (lbcond_compare_string_conditions), (libbalsa_condition_compare): compare string conditions correctly. * libbalsa/mailbox_local.c (message_match_real): do not pass NULL list to internet_address_list_to_string(). 2010-01-24 Pawel Salek * configure.in, NEWS: release 2.4.5 2010-01-23 Peter Bloomfield * src/save-restore.c (config_identities_save): do not allocate unused array. 2010-01-23 Peter Bloomfield * src/message-window.c (destroy_message_window), (mw_select_part_cb): do not crash on "select-part" signal. 2010-01-23 Peter Bloomfield * src/balsa-message.c (balsa_message_set): clear tree before selecting part; (select_part): emit signal also for NULL part; (balsa_message_can_zoom): check for NULL widget. * src/main-window.c: rely on "select-part" signal for enabling menus. 2010-01-23 Peter Bloomfield * src/main-window.c: update menus only if they will not be updated when a message is shown. 2010-01-23 Pawel Salek * Makefile.am, src/Makefile.am: fix dist target when configured without gnome. * configure.in, NEWS: release balsa-2.4.4 2010-01-23 Pawel Salek * src/main-window.c: update copyright date. * configure.in, NEWS: release 2.4.3 2010-01-22 Peter Bloomfield * libbalsa/libbalsa-conf.c (lbc_sync): do not insert blank comments; save mtime when syncing. 2010-01-22 Peter Bloomfield * libbalsa/address-book-gpe.c (libbalsa_address_book_gpe_load): more sqlite3_free fixes. 2010-01-22 Pawel Salek * libbalsa/misc.c: allocate enough memory for config urls. 2010-01-19 Peter Bloomfield * libbalsa/imap-server.c (libbalsa_imap_server_init): use g_timeout_add_seconds, save the world. * src/balsa-mime-widget-text.c: ditto. * src/information-dialog.c (balsa_information_bar): ditto. * src/main-window.c: ditto. * src/main.c (main): ditto. * src/sendmsg-window.c (sendmsg_window_new): ditto. 2010-01-19 Peter Bloomfield * libbalsa/information.c (libbalsa_information_varg): show note before unreffing it(!). 2010-01-19 Peter Bloomfield * src/main-window.c (bw_quit_nicely): use libbalsa_information_parented, so that notification bubble can be closed when Balsa quits; (bw_real_open_mbnode): hold gdk lock while unreffing mbnode; (balsa_window_real_close_mbnode): more careful test for last notebook page; (empty_trash): check for NULL window. 2010-01-18 Peter Bloomfield * src/balsa-index.c (bndx_mbnode_weak_notify), (bndx_destroy), (balsa_index_load_mailbox_node): clear BalsaIndex::mailbox_node before destroying BalsaIndex. 2010-01-18 Peter Bloomfield * src/balsa-app.c (balsa_find_url): check for NULL mblist_tree_store. 2010-01-18 Peter Bloomfield * libbalsa/information.c (lbi_notification_parent_weak_notify), (lbi_notification_closed_cb), (libbalsa_information_varg): close notification bubble with parent. 2010-01-18 Peter Bloomfield * src/balsa-app.h: move nm_state and check_mail_skipped from BalsaApplication to BalsaWindow. * src/main-window.c: ditto. * src/main-window.h: ditto. 2010-01-17 Peter Bloomfield * src/balsa-app.h: new member mail_check_skipped. * src/main-window.c: use it to remember when we skipped a mail check while disconnected, and to check mail on reconnection. 2010-01-17 Peter Bloomfield * src/main-window.c: restart timer after user checks mail manually. 2010-01-17 Peter Bloomfield * src/balsa-app.c (update_timer): use g_timeout_add_seconds, save the world. 2010-01-17 Peter Bloomfield * src/main-window.c: report NetworkManager state on start-up; skip POP3 checks when disconnected; do not disconnect local IMAP server when NetworkManager is disconnected. 2010-01-17 Pawel Salek * libbalsa/imap/imap-tls.c: check also the length when matching the host name vs the one in the certificate. 2010-01-17 Peter Bloomfield * src/main-window.c: close the new-mail notification instead of showing it with a 1 millisecond time-out. 2010-01-16 Peter Bloomfield * src/balsa-app.h: new member NMState nm_state. * src/main-window.c: use it to save NetworkManager state; connect or disconnect IMAP on changes to/from NM_STATE_CONNECTED. 2010-01-16 Peter Bloomfield * libbalsa/body.c (libbalsa_message_body_save_temporary): make temporary file read-only. 2010-01-15 Pawel Salek * libbalsa/imap/imap_compress.c: * libbalsa/imap/siobuf.c: complete the compression error handling. 2010-01-14 Peter Bloomfield * libbalsa/html.h: new methods for printing. * libbalsa/html.c (libbalsa_html_can_print), (libbalsa_html_print): implement them. * src/balsa-mime-widget-text.c (bmwt_populate_popup_menu), (bmwt_populate_popup_cb): use them. 2010-01-14 Peter Bloomfield * libbalsa/html.h: new methods for printing. * libbalsa/html.c (libbalsa_html_can_print), (libbalsa_html_print): implement them. * src/balsa-mime-widget-text.c (bmwt_populate_popup_menu), (bmwt_populate_popup_cb): use them. 2010-01-14 Peter Bloomfield * configure.in: require NetworkManager version 0.7. * src/main-window.c: use GObject-based API instead of deprecated older API. 2010-01-12 Pawel Salek * libbalsa/html.c: fix libbalsa_html_popup_menu_widget() arg list. 2010-01-12 Peter Bloomfield * libbalsa/html.h: new public method to retrieve the real HTML widget. * libbalsa/html.c (libbalsa_html_popup_menu_widget): ditto. * src/balsa-mime-widget-text.c (bmwt_populate_popup_menu), (balsa_gtk_html_popup), (bmwt_populate_popup_cb), (bm_widget_new_html): use it to implement popup menu for WebKitWebView. 2010-01-11 Peter Bloomfield * libbalsa/address-book-gpe.c (libbalsa_address_book_gpe_alias_complete): free error with sqlite3_free() instead of free(); fixes bug #606676 (Stanislav Brabec). 2010-01-11 Peter Bloomfield * libbalsa/html.h: new API for libbalsa_html_new. * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (bm_widget_new_html): use it. * libbalsa/html.c (lbh_get_body_content, lbh_get_web_view, libbalsa_html_can_zoom, libbalsa_html_zoom, libbalsa_html_can_select, libbalsa_html_select_all, libbalsa_html_copy, libbalsa_html_can_search, libbalsa_html_search_text, libbalsa_html_get_selection_bounds): implement new API; (lbh_info_bar_realize_cb, lbh_info_bar_widget, lbh_resource_request_starting_cb, lbh_info_bar_response_cb, libbalsa_html_new): prepend HTML message part with a GtkInfoBar offering the option to download images. 2010-01-11 Peter Bloomfield * src/balsa-message.c (add_part), (balsa_message_can_select): html widgets can select text. 2010-01-11 Peter Bloomfield * libbalsa/html.c (lbh_js_get_global_context), (lbh_js_run_script), (lbh_js_object_get_property), (libbalsa_html_search_text), (libbalsa_html_get_selection_bounds): use JavaScript to locate or clear selected text; enable text search. 2010-01-11 Pawel Salek * libbalsa/mailbox_imap.c: gmail anwers NO to FETCH, deal with it. 2010-01-10 Albrecht Dreß * src/pref-manager.c (word_wrap_group): increase maximum line length to 998, the RFC 2822 limit. 2010-01-09 Peter Bloomfield * src/balsa-message.c (add_body), (add_multipart_digest), (add_multipart_mixed), (add_multipart), (add_part), (select_part): cleaner recursion. 2010-01-09 Peter Bloomfield * src/balsa-mime-widget-text.c (url_open_cb), (check_call_url), (handle_url), (bm_widget_new_html): combine link-clicked handling for text/plain and text/html parts. 2010-01-08 Pawel Salek * libbalsa/imap/imap_compress.c: improve error handling. * libbalsa/mailbox_imap.c: catch error conditions early. 2010-01-06 Peter Bloomfield * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): do not leak HTML source. 2010-01-05 Pawel Salek * libbalsa/imap/siobuf.[ch]: change encode interface so that compression callback do not need to allocate too much memory. * libbalsa/imap/imap_compress.c: modify the callbacks accordingly. * libbalsa/imap/imap-handle.c: make sure we do not leave some unflushed compressed data around. * configure.in: zlib.h is unconditionally required. 2010-01-05 Peter Bloomfield * libbalsa/html.c (libbalsa_html_new): remove dead code. 2010-01-05 Peter Bloomfield * src/balsa-message.c (add_part), (select_part): remove dead or redundant code. 2010-01-05 Peter Bloomfield * libbalsa/html.c (libbalsa_html_new): put webkit in document-viewer mode instead of the default browser mode. 2010-01-05 Peter Bloomfield * src/balsa-app.h: omit point size from default font names. * src/pref-manager.c (open_preferences_manager), (check_font_button), (apply_prefs), (font_button_check_font_size), (attach_font_button), (preview_font_group), (font_modified_cb), (default_font_size_cb): add option to use default font sizes. 2010-01-05 Peter Bloomfield * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (quote_tag): define constants for margins. 2010-01-04 Peter Bloomfield * libbalsa/misc.c (libbalsa_create_entry): use gtk_entry_set_text instead of gtk_editable_insert_text, to avoid a bogus warning. 2010-01-04 Peter Bloomfield * src/save-restore.c (config_global_load): default to no message wrap and prefer text/plain over text/html. 2010-01-04 Peter Bloomfield * src/balsa-message.c (bm_find_entry_changed_cb), (bm_find_again), (balsa_message_find_in_message): build --without-gtkhtml --without-webkit. 2010-01-04 Peter Bloomfield * libbalsa/imap/imap_compress.c: add missing includes of stdlib.h, string.h. 2010-01-03 Peter Bloomfield * src/main-window.c: better menu item label (Pawel). 2010-01-03 Pawel Salek * libbalsa/imap-server.c: enable compression by default. * libbalsa/imap/Makefile.am: add imap_compress.[hc] * libbalsa/imap/imap-commands.c: imap_cmd_exec returns ImapResponse. * libbalsa/imap/imap-handle.c: add COMPRESS=DEFLATE capability * libbalsa/imap/imap_compress.[ch]: support the extension. * libbalsa/imap/imap_tst.c: allow compression testing. 2010-01-02 Peter Bloomfield * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text), (quote_tag): get font description from widget; scale size from points to pixels; use 60% of size for width. 2010-01-02 Peter Bloomfield * src/balsa-app.h: new members to save hidden toolbars. * src/save-restore.c (config_global_load), (config_save): save and restore them. * src/main-window.c: options to hide toolbar, SoSbar, and status bar. * src/main-window.h: add toolbar and sos_bar members. * src/message-window.c (message_window_new), (mw_show_toolbar_cb): option to hide toolbar. * src/sendmsg-window.c (sendmsg_window_new), (sw_show_toolbar_cb): option to hide toolbar. * src/sendmsg-window.h: add toolbar member. 2010-01-02 Pawel Salek * libbalsa/imap/pop3.c: Report errors occuring during downloading process earlier to avoid saving corrupted messages. * libbalsa/mailbox_pop3.c: do not leak file descriptors on some errors. 2010-01-01 Peter Bloomfield * src/sendmsg-window.c: Do not crash in touch-ui version. 2010-01-01 Peter Bloomfield * configure.in: Allow configure --enable-touch-ui=no and --disable-touch-ui. 2010-01-01 Pawel Salek * libbalsa/send.c: Fix bug 605807. 2009-12-30 Pawel Salek * configure.in: gtkspell build requires enchant now as well.\ * src/main-window.c: * src/sendmsg-window.c: compile with --enable-touch-ui 2009-12-30 Peter Bloomfield * src/sendmsg-window.c (create_lang_menu): use enchant_broker_dict_exists() to check languages. 2009-12-29 Pawel Salek * libbalsa/rfc3156.c: * src/main-window.c: add comments to aid translations... * src/sendmsg-window.c: ... to fix bug 605435. 2009-12-29 Peter Bloomfield * libbalsa/html.c (lbh_resource_request_starting_cb), (lbh_new_window_policy_decision_requested_cb), (libbalsa_html_new): use "notify::progress" signal instead of deprecated "load-progress-changed"; use "new-window-policy-decision-requested" signal to more carefully control new windows. 2009-12-29 Peter Bloomfield * configure.in: require webkitgtk version 1.1.14 or newer. * libbalsa/html.c (lbh_resource_request_starting_cb), (libbalsa_html_new): use WebKitwebView's "resource-request-starting" signal to handle cid: requests and disable all others. * libbalsa/body.c (libbalsa_message_body_save_temporary): use body->filename in preference to content_id. * libbalsa/body.h: remove now redundant functions. * libbalsa/message.c: ditto. * libbalsa/message.h: ditto. 2009-12-26 Peter Bloomfield * libbalsa/html.c (lbh_filter_src), (libbalsa_html_new), (libbalsa_html_url_requested): implement two ways of handling cid: URLs in WebKitwebView. 2009-12-26 Peter Bloomfield * libbalsa/message.h: add tempdir member and new methods. * libbalsa/message.c (libbalsa_message_finalize), (libbalsa_message_get_part_by_id), (libbalsa_message_save_parts_by_id), (libbalsa_message_has_cid_part), (libbalsa_message_get_tempdir): implement and use them. 2009-12-26 Peter Bloomfield * libbalsa/libbalsa.h: new error code. 2009-12-20 Peter Bloomfield * libbalsa/body.h: new member LibBalsaMessageBody::own_dir, TRUE if the temporary file for the body is in its own temporary directory/ * libbalsa/body.c (libbalsa_message_body_new), (libbalsa_message_body_free), (libbalsa_message_body_save_temporary): if the body has a filename, save the temporary file in its own temporary directory. 2009-12-20 Peter Bloomfield * libbalsa/filter-funcs.c (lbcond_new): save negated as 0 or 1, to simplify later comparison. (libbalsa_condition_compare): return FALSE if negate differs; drop now-redundant test for flag conditions. 2009-12-19 Peter Bloomfield * libbalsa/filter-funcs.c (libbalsa_condition_compare): simplify, and fix string and boolean filter comparisons. 2009-12-16 Peter Bloomfield * libbalsa/send.c (libbalsa_message_create_mime_message): do not append NULL list in internet_address_list_append. 2009-12-16 Mario Mikocevic * balsa.spec.in: for 2.4.2 to successfuly compile a rpm, a small patch is needed. 2009-12-14 Peter Bloomfield * configure.in: put LIBNM_GLIB_CFLAGS in BALSA_CFLAGS instead of CFLAGS--required to build with CFLAGS+="-DG_DISABLE_SINGLE_INCLUDES -DGDK_PIXBUF_DISABLE_SINGLE_INCLUDES -DGTK_DISABLE_SINGLE_INCLUDES" 2009-12-10 Peter Bloomfield * src/balsa-app.c (check_new_messages_auto_cb): pass balsa_app.main_window instead of NULL to check_new_messages_real, so we can manage the sensitivity of the check action. 2009-12-08 Peter Bloomfield * src/sendmsg-window.c (guess_identity_from_list): do not pass NULL list to internet_address_list_to_string(). 2009-12-07 Peter Bloomfield * libbalsa/filter.c (libbalsa_condition_matches): do not pass NULL list to internet_address_list_to_string(). 2009-12-06 Pawel Salek * configure.in * NEWS: release balsa-2.4.2 2009-12-03 Peter Bloomfield * src/balsa-message.c (bm_find_set_status), (bm_find_scroll_to_rectangle), (bm_find_scroll_to_selection), (bm_find_entry_changed_cb), (bm_find_again): implement search-text for HTML parts; desensitize find-next and find-previous when find-entry is empty. 2009-12-03 Peter Bloomfield * libbalsa/html.c (lbh_navigation_policy_decision_requested_cb), (libbalsa_html_new), (libbalsa_html_search_text), (libbalsa_html_get_selection_bounds), (libbalsa_html_can_search): implement search-text for webkit backend, but only if we can scroll to the text. * libbalsa/html.h: implement libbalsa_html_search_text. 2009-11-16 Peter Bloomfield * src/balsa-message.c (balsa_message_find_in_message): grab focus only if entry is realized. 2009-11-15 Peter Bloomfield * libbalsa/html.c (lbh_size_request_cb): remove debugging aid; (lbh_navigation_policy_decision_requested_cb): do not handle signal unless it is a real request; (libbalsa_html_new): remove debugging aids. * src/balsa-message.c (select_part): queue-resize is redundant. 2009-11-12 Pawel Salek * libbalsa/imap/imap-handle.c: fix a corner case locking problem. * src/main-window.c: remove a warning. * configure.in: work around lib rename. 2009-11-11 Pawel Salek * configure.in: add NetworkManager-glib support. * libbalsa/imap-server.c: Disconnect quickly if asked to. * libbalsa/imap/imap-commands.c: add private unlocked select command. * libbalsa/imap/imap-handle.c: locking changes. * libbalsa/imap/imap-handle.h: add ..force_disconnect() prototype. * libbalsa/imap/imap_private.h: add select_unlocked() prototype. * libbalsa/mailbox.c: stop-gap performance fix. * libbalsa/mailbox_imap.[hc]: Add force_disconnect(), reconnect(), is_connected(). * src/main-window.c: listen to libnm events. 2009-11-08 Peter Bloomfield * libbalsa/imap/imap-tls.c (imap_check_server_identity): openssl has been constified--second try, should build with both latest and earlier openssl. 2009-11-08 Peter Bloomfield * libbalsa/imap/imap-tls.c (imap_check_server_identity): revert--it's going to take more work! 2009-11-08 Peter Bloomfield * libbalsa/imap/imap-tls.c (imap_check_server_identity): openssl has been constified. 2009-11-07 Peter Bloomfield * src/balsa-mime-widget-vcalendar.c (balsa_vevent_widget, vevent_reply): use macros to cast enum to or from gpointer. 2009-11-07 Peter Bloomfield * libbalsa/rfc2445.c (text_2445_unescape): "\N" encodes newline. 2009-11-01 Peter Bloomfield * libbalsa/html.c (lbh_size_request_cb): only increase the requisition; (lbh_navigation_policy_decision_requested_cb): be silent; (libbalsa_html_new): indentation. * src/balsa-message.c (add_part): give the content the surplus space. 2009-10-31 Peter Bloomfield * libbalsa/html.c (lbh_navigation_policy_decision_requested_cb): check reason for request. (libbalsa_html_new): do not leak GtkAdjustments. 2009-10-30 Peter Bloomfield * libbalsa/html.c (lbh_navigation_policy_decision_requested_cb, lbh_web_view_ready_idle, lbh_web_view_ready_cb, lbh_create_web_view_cb, libbalsa_html_new): handle a clicked link that requires a new window. 2009-10-28 Peter Bloomfield * src/balsa-mime-widget.c (balsa_mime_widget_destroy): unref widget instead of destroying. 2009-10-28 Peter Bloomfield * libbalsa/html.c (libbalsa_html_zoom, libbalsa_html_can_select, libbalsa_html_select_all, libbalsa_html_copy): add comments and indent; (libbalsa_html_search_text): build with all widgets. 2009-10-27 Peter Bloomfield * libbalsa/html.h: new methods for text search, to access WebKitWebView capability. * libbalsa/html.c (libbalsa_html_can_search, libbalsa_html_search_text): implement them. * src/balsa-message.c (bm_find_entry_changed_cb, bm_find_again, balsa_message_find_in_message): use them. * src/balsa-mime-widget.c (balsa_mime_widget_destroy): work-around weird WebKitWebView-GtkClipboard issue. 2009-10-27 Peter Bloomfield * src/toolbar-factory.c: show text for "compose" instead of "trash/delete". 2009-10-24 Peter Bloomfield * src/toolbar-factory.h: new member button_data::is_important. * src/toolbar-factory.c (tm_set_tool_item_label): use it. 2009-10-24 Peter Bloomfield * src/balsa-app.h: do not include toolbar-factory.h. 2009-10-15 Peter Bloomfield GSEAL cleanup * configure.in: enable GSEAL if gtk version >= 2.18. * libbalsa/address-view.c (lbav_entry_changed_cb): * libbalsa/address.c (addrlist_drag_received_cb): * libbalsa/html.c (lbh_size_request_cb): * libbalsa/identity.c (libbalsa_identity_select_dialog), (md_sig_path_changed_cb), (ident_dialog_get_path), (libbalsa_identity_config_dialog): * libbalsa/libbalsa.c (ask_cert_real): * libbalsa/misc.c (lb_create_size_group_func): * libbalsa/rfc3156.c (select_key_from_list), (get_passphrase_real): * libbalsa/send.c (ensure_send_progress_dialog): * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): * libbalsa/source-viewer.c (lsv_size_allocate_cb), (libbalsa_show_message_source): * libinit_balsa/assistant_helper.c (entry_changed_cb): * src/ab-main.c (edit_new_entry_cb), (addrlist_drag_get_cb): * src/ab-window.c (balsa_ab_window_init): * src/address-book-config.c (create_generic_dialog), (create_externq_dialog), (create_ldap_dialog), (create_gpe_dialog): * src/balsa-app.c (ask_password_real): * src/balsa-index.c (bndx_drag_cb), (bndx_mailbox_changed_cb), (bndx_popup_position_func), (bndx_expand_to_row), (balsa_index_pipe), (balsa_index_ensure_visible): * src/balsa-mblist.c (bmbl_drag_cb), (bmbl_mru_show_tree): * src/balsa-message.c (bm_on_set_style), (bm_find_scroll_to_iter), (bm_find_pass_to_entry), (gtk_tree_hide_func), (select_part), (scroll_set), (balsa_get_parent_window), (balsa_message_grab_focus): * src/balsa-mime-widget-callbacks.c (scroll_change), (balsa_mime_widget_key_press_event): * src/balsa-mime-widget-image.c (balsa_mime_widget_new_image), (img_check_size): * src/balsa-mime-widget-message.c (bm_header_widget_realized): * src/balsa-mime-widget-text.c (gtk_widget_destroy_insensitive), (draw_cite_bar_real): * src/balsa-mime-widget.c (vadj_change_cb): * src/filter-edit-callbacks.c (condition_validate), (fill_condition_widgets), (build_condition_dialog): * src/filter-edit-dialog.c (filters_edit_dialog): * src/filter-export-dialog.c (filters_export_dialog): * src/filter-run-dialog.c (balsa_filter_run_dialog_init): * src/folder-conf.c (folder_conf_imap_node), (browse_button_cb), (subfolder_conf_clicked_ok), (folder_conf_imap_sub_node): * src/information-dialog.c (balsa_information_list): * src/mailbox-conf.c (create_pop_mailbox_dialog), (create_imap_mailbox_dialog): * src/main-window.c (bw_quit_nicely): * src/message-window.c (size_alloc_cb): * src/pref-manager.c (open_preferences_manager), (apply_prefs), (set_prefs), (timer_modified_cb), (mailbox_close_timer_modified_cb), (imap_toggled_cb), (convert_8bit_cb): * src/print-gtk.c (check_margins), (message_prefs_apply): * src/sendmsg-window.c (sw_size_alloc_cb), (sw_get_user_codeset), (attachments_add), (sw_scroll_size_request), (drag_data_quote), (quote_parts_select_dlg), (subject_not_empty), (check_suggest_encryption): * src/spell-check.c (balsa_spell_check_init): * src/store-address.c (store_address_dialog): * src/toolbar-factory.c (tm_popup_position_func): * src/toolbar-prefs.c (customize_dialog_cb), (wrap_toggled_cb): 2009-10-15 Peter Bloomfield Re-implement BalsaCiteBar as a GTK_NO_WINDOW widget * src/balsa-cite-bar.h: make BalsaCiteBar opaque. * src/balsa-cite-bar.c (balsa_cite_bar_class_init), (balsa_cite_bar_init), (balsa_cite_bar_resize), (balsa_cite_bar_size_request), (balsa_cite_bar_expose): 2009-10-15 Peter Bloomfield Use gtk_window_present instead of gdk_window_raise * libbalsa/identity.c (libbalsa_identity_select_dialog): * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): * src/address-book-config.c (balsa_address_book_config_new): * src/balsa-index.c (balsa_index_pipe): * src/filter-edit-dialog.c (filters_edit_dialog): * src/filter-export-dialog.c (filters_export_dialog): * src/filter-run-dialog.c (filters_run_dialog): * src/folder-conf.c (folder_conf_imap_node): * src/mailbox-conf.c (mailbox_conf_new), (mailbox_conf_edit): * src/main-window.c: * src/pref-manager.c (open_preferences_manager): * src/sendmsg-window.c (address_book_cb), (spell_check_cb): * src/store-address.c (balsa_store_address_from_messages): * src/toolbar-prefs.c (customize_dialog_cb): 2009-10-09 Stanislav Brabec Fix #596309 * configure.in: require gnome-icon-theme. * src/balsa-app.c (balsa_app_init): set gnome-icon-theme as fallback. 2009-10-08 Peter Bloomfield * src/address-book-config.c (create_local_dialog, create_vcard_dialog, create_ldif_dialog, create_generic_dialog, create_externq_dialog, create_ldap_dialog, create_gpe_dialog, create_rubrica_dialog): show address book type in dialog title. 2009-10-08 Peter Bloomfield * libbalsa/mailbox.c (lbm_changed, libbalsa_mailbox_changed): do not emit mailbox-changed signal in a sub-thread. 2009-10-08 Peter Bloomfield * libbalsa/mailbox_mbox.c (lbm_mbox_armored_object): use g_mime_object_encode when available. 2009-10-08 Peter Bloomfield * src/address-book-config.c (edit_book_response): check for NULL address-book. 2009-10-01 Peter Bloomfield * libbalsa/mailbox_mbox.c (lbm_mbox_prepare_object, lbm_mbox_armored_object): use GMimeMultipart api to traverse message ourselves instead of using g_mime_multipart_foreach. 2009-09-30 Peter Bloomfield * src/toolbar-factory.c (tm_do_popup_menu): do not crash when default is "text beside items"; fixes https://mail.gnome.org/archives/balsa-list/2009-September/msg00045.html 2009-09-28 Laurent Coudeur * src/spell-check.c (balsa_spell_check_init, balsa_spell_check_start, balsa_spell_check_learn, setup_suggestions, check_pspell_errors): mark strings for translation. 2009-09-26 Peter Bloomfield * libbalsa/mailbox_mbox.c (lbm_mbox_prepare_object): count GMimeMessagePart as well as GMimePart when skipping parts. 2009-09-25 Peter Bloomfield * libbalsa/mailbox_mbox.c (lbm_mbox_prepare_object), (lbm_mbox_armored_object): detect when g_mime_multipart_foreach will recursively descend into a signed or encrypted multipart, and set a counter to skip the parts that should not be changed. 2009-09-24 Peter Bloomfield * src/balsa-app.c (append_url_if_open): use a GPtrArray to collect URLs instead of a GString; (open_mailboxes_idle_cb): ditto; do not leak urls. 2009-09-24 Peter Bloomfield * src/balsa-app.c (open_mailboxes_idle_cb): do not open most recent mailbox if no mailboxes were open. 2009-09-24 Peter Bloomfield * src/balsa-app.c (open_mailbox_by_url), (open_mailboxes_idle_cb): respect current-mailbox-url when -o command line option is used. * src/main-window.c: do not clear current-mailbox-url when last mailbox is closed, as it may get saved that way. * src/main.c (initial_open_inbox): open inbox hidden. 2009-09-11 Peter Bloomfield Open most recent mailbox first on restart * libbalsa/libbalsa-marshal.list: new marshaller. * src/balsa-app.h: new member current_mailbox_url. * src/save-restore.c (config_global_load), (config_save): save and restore it. * src/main-window.h: new api for open-mbnode class method. * src/balsa-mblist.h: new method balsa_mblist_open_mailbox_hidden; * src/balsa-app.c (open_mailboxes_idle_cb): use them. * src/balsa-index.c (balsa_index_transfer): ditto. * src/balsa-mblist.c (bmbl_open_mailbox), (balsa_mblist_open_mailbox), (balsa_mblist_open_mailbox_hidden): ditto. * src/mailbox-node.c (load_mailbox_view): ditto. * src/main-window.c: ditto. 2009-09-11 Peter Bloomfield * src/mailbox-conf.c (mailbox_conf_set_values): initialize mailbox name for local mailbox; (local_mailbox_dialog_cb), (create_local_mailbox_dialog): catch file chooser events to check for a real change; (create_imap_mailbox_dialog), (mailbox_conf_view_new_full), (mailbox_conf_view_new): new api. 2009-09-10 Peter Bloomfield * src/mailbox-conf.c (mailbox_conf_view_cb), (mailbox_conf_view_new_with_size_group): set "Update" button sensitive when a control is changed. 2009-09-07 Peter Bloomfield * src/main.c (balsa_handle_automation_options): encode URI for UniqueMessageData. (mw_message_received_cb): decode URI received from UniqueMessageData. 2009-09-07 Peter Bloomfield * libbalsa/misc.c (libbalsa_urlencode): handle 8-bit characters. 2009-09-07 Peter Bloomfield * libbalsa/libbalsa-conf.c (lbc_init): do not read config file twice. 2009-09-07 Peter Bloomfield * libinit_balsa/assistant_init.c (balsa_init_begin): minimal init assistant. * libinit_balsa/assistant_page_user.c (balsa_druid_page_user_init): ditto. 2009-09-04 Peter Bloomfield * libbalsa/address-book-vcard.c (libbalsa_address_book_vcard_parse_address): accept "email:name@host" as well as "email;type=blah:name@host". 2009-09-03 Peter Bloomfield * configure.in: oops--revert. 2009-09-03 Peter Bloomfield * configure.in: do not allow configure with both webkit and gtkhtml. 2009-08-29 Albrecht Dreß Improve the Mac OS X integration for a native "Carbon" build * libbalsa/Makefile.am: * libbalsa/identity.c (libbalsa_identity_select_dialog), (delete_ident_cb), (libbalsa_identity_config_dialog): * libbalsa/rfc3156.c (check_gpg_child), (select_key_from_list), (accept_low_trust_key), (get_passphrase_real): * libbalsa/smtp-server.c (libbalsa_smtp_server_dialog): * libbalsa/source-viewer.c (libbalsa_show_message_source): * src/ab-main.c: * src/address-book-config.c (create_local_dialog), (create_generic_dialog), (bad_path): * src/balsa-app.c (ask_password_real): * src/balsa-icons.c (register_balsa_pixmaps): * src/balsa-index.c (balsa_index_pipe): * src/balsa-mblist.c (bmbl_mru_show_tree): * src/balsa-message.c (part_context_dump_all_cb), (create_mdn_dialog): * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_ctx_menu_save): * src/filter-edit-callbacks.c (fe_edit_condition): * src/folder-conf.c (folder_conf_imap_node), (browse_button_cb), (subfolder_conf_clicked_ok), (folder_conf_imap_sub_node), (folder_conf_delete): * src/information-dialog.c (balsa_information_dialog), (balsa_information_list): * src/mailbox-conf.c (mailbox_conf_delete), (create_local_mailbox_dialog), (create_generic_dialog): * src/main-window.c: * src/message-window.c (message_window_new): * src/pref-manager.c (open_preferences_manager): * src/sendmsg-window.c (delete_handler), (change_attach_mode), (sw_get_user_codeset), (sw_attach_dialog), (quote_parts_select_dlg), (sendmsg_window_new), (sendmsg_window_set_field), (include_file_cb), (check_suggest_encryption), (send_message_handler), (bsmsg_check_format_compatibility): * src/store-address.c (store_address_dialog): * src/threads.h: * src/toolbar-prefs.c (customize_dialog_cb): 2006-08-27 Pawel Salek * libbalsa/imap/imap-handle.c: namespace queries need to encode the prefix. * libbalsa/imap/imap_tst.c: test mailbox name encoding. * libbalsa/imap/util.c: encode backslash and quote marks. 2009-08-26 Peter Bloomfield set-statusbar is a BalsaWindow method. * src/balsa-index.c (balsa_index_transfer): * src/balsa-mblist.c (balsa_mblist_open_mailbox), (bmbl_update_mailbox): * src/balsa-mblist.h: * src/main-window.c: * src/main-window.h: 2009-08-20 Peter Bloomfield * src/main-window.c: build with --disable-threads. 2009-08-19 Peter Bloomfield * libbalsa/address-book-gpe.c (libbalsa_address_book_gpe_open_db): show file name in error message. 2009-08-19 Peter Bloomfield * src/main-window.c: Manage sensitivity of "Get New Mail" action. * src/main.c (mw_message_received_cb, main): ditto. 2009-08-19 Peter Bloomfield Allow only one compose window per draft message. * src/balsa-index.c (bndx_row_activated): check for NULL return from sendmsg_window_continue. * src/sendmsg-window.c (balsa_sendmsg_destroy_handler, sw_save_draft): clear object data. (sendmsg_window_continue): present existing window if it exists and return NULL, and use object data to remember window. 2009-08-19 Peter Bloomfield * src/balsa-mime-widget-message.c (bm_header_widget_new): use GTK_WRAP_WORD_CHAR so that over-long words do not force over-wide window. * src/balsa-mime-widget-text.c (balsa_mime_widget_new_text): ditto. * src/balsa-mime-widget-vcalendar.c: ditto. 2009-08-11 Peter Bloomfield * src/balsa-print-object-header.c (header_add_list): do not print header line with NULL address string. 2006-08-09 Pawel Salek * NEWS, configure.in: release balsa-2.4.1 2009-08-04 Peter Bloomfield * configure.in: new option --with-canberra=no. * libbalsa/filter.c (libbalsa_filter_mailbox_messages): use libcanberra-gtk in preference to libgnome for filter sounds. 2009-08-02 Peter Bloomfield * src/sendmsg-window.c (bsmsg_set_subject_from_body): use existing subject for continued draft message; new name and api; (update_bsmsg_identity), (bsm_finish_setup), (sendmsg_window_forward): use new name and api. 2009-08-01 Peter Bloomfield * libbalsa/body.c (libbalsa_message_body_get_pixbuf): workaround for IE's use of non-IANA registered mime-type "image/pjpeg" for progressive JPEG image. 2009-08-01 Peter Bloomfield * src/sendmsg-window.c (set_entry_to_subject): do not drop subject when continuing a new message. 2006-07-30 Pawel Salek * libbalsa/imap/imap-commands.c: lock LIST fixed. 2009-07-28 Peter Bloomfield * libbalsa/address-view.c (lbav_add_from_list), (lbav_add_from_string): streamline code. 2006-07-28 Pawel Salek * libbalsa/address-view.c: protect against empty InternetAddressLists. * libbalsa/imap/imap-commands.c: lock LIST, LSUB, STATUS as well. 2009-07-26 Peter Bloomfield * src/balsa-mblist.c: do not include gdk/gdkfont.h. 2009-07-26 Peter Bloomfield Partial fixes for bug #589764, André Klapper. * libbalsa/imap/pop3.c (pop_authenticate): use g_ascii_strncasecmp. * src/quote-color.c (allocate_quote_colors): remove "gdk_color_black" from comment. 2009-07-26 Peter Bloomfield * src/sendmsg-window.c: do not include gnome.h. 2009-07-26 Peter Bloomfield * src/main-window.c: remove redundant gtk version checks and dead code. 2009-07-25 Peter Bloomfield * libinit_balsa/assistant_helper.c (balsa_init_create_to_directory): show specific error message. 2009-07-23 Peter Bloomfield Check for NULL InternetAddressList * libbalsa/send.c (do_multipart_crypto): * src/sendmsg-window.c (sw_cc_add_list): * src/store-address.c (store_address_add_list): 2009-07-21 Peter Bloomfield Save send type in draft message * src/sendmsg-window.h: new member is_continue. * src/sendmsg-window.c (delete_handler), (guess_identity), (sendmsg_window_new), (sendmsg_window_continue), (message_postpone): use it instead of SEND_CONTINUE. (sendmsg_window_set_title), (set_entry_to_subject), (replace_identity_signature): we no longer use SEND_CONTINUE. 2009-07-20 Peter Bloomfield * configure.in: make silent rules by default. 2006-07-12 Pawel Salek * src/sendmsg-window.c: do insert new signatures on identity switch (reported on balsa-list). 2009-07-09 Peter Bloomfield * src/message-window.c (mw_expunged_cb): check for NULL message. 2009-07-09 Peter Bloomfield * libbalsa/mailbox_mbox.c (libbalsa_mailbox_mbox_sync): check for error in GMimeParser. 2009-06-30 Peter Bloomfield * configure.in: test for res_init. * libbalsa/imap/imap-handle.c (imap_socket_open): use it to recover faster after reconnecting to the internet. 2009-06-27 Peter Bloomfield * src/spell-check.h: build --without-gtkspell. 2006-06-24 Pawel Salek * libbalsa/imap/imap-{commands,handle}.c: catch errors early on for more accurate error messages. * libbalsa/imap/imap_search.c: ditto. * libbalsa/imap/imap-handle.h: warn if idle_disable's result is ignored. * libbalsa/mailbox_imap.c: correct tranformation of rfc822 groups from ImapAddress to InternetAddress (together with Peter B). * src/sendmsg-window.c: check that string is not-null before setting window title. 2006-06-11 Pawel Salek * libbalsa/mailbox_imap.c: do not create empty address lists. This makes the message compose code believe that reply-to is set. 2009-06-07 Peter Bloomfield Build with threads disabled * libbalsa/mailbox.c (lbm_msgno_changed): fix conditional code. 2009-06-07 Peter Bloomfield Update display in an idle callback. * libbalsa/mailbox.h: new array of msgnos that have changed. * libbalsa/mailbox.c (libbalsa_mailbox_finalize), (lbm_msgno_changed_expunged_cb), (lbm_msgnos_changed_idle_cb), (lbm_msgno_changed), (libbalsa_mailbox_msgno_changed), (lbm_get_index_entry_real): use it to update display in an idle callback, instead of in the sub-thread in which the message info was set up. 2009-06-07 Peter Bloomfield * src/sendmsg-window.c (repl_identity_signature), (insert_initial_sig): remember cursor position when adding or changing signature. 2009-06-03 Peter Bloomfield Build with threads disabled * configure.in: must enable threads to use WebKit. * libbalsa/imap-server.c (libbalsa_imap_server_set_username), (libbalsa_imap_server_set_host), (libbalsa_imap_server_init), (libbalsa_imap_server_finalize), (lb_imap_server_cleanup), (get_or_create), (libbalsa_imap_server_get_handle), (libbalsa_imap_server_get_handle_with_user), (libbalsa_imap_server_release_handle), (libbalsa_imap_server_force_disconnect), (libbalsa_imap_server_close_all_connections), (libbalsa_imap_server_has_free_handles): use macros to manage locks. * libbalsa/imap/imap_private.h: add TRYLOCK macro. 2009-05-27 Peter Bloomfield * src/balsa-mime-widget-callbacks.c (balsa_mime_widget_key_press_event): emitting "popup-menu" requires the address of the return value. 2006-05-23 Pawel Salek * src/balsa-index.[ch]: switch between full and narrow index views. * src/main-window.[ch]: switch between ordinary and wide-screen layouts. * src/save-restore.c: save the layout as an enum. * src/balsa-app.[ch]: set default layout. * src/pref-manager.c: main window layout type is a drop-down list now. 2009-05-13 Peter Bloomfield * src/mailbox-node.c (find_dir), (balsa_mailbox_local_append): parent of a top-level mailbox should be the root node. 2009-05-13 Peter Bloomfield * src/mailbox-node.c (balsa_mailbox_node_rescan): clear mn->scanned, so that we append the subtree. 2009-05-07 Peter Bloomfield Implement select thread * src/balsa-index.c (balsa_index_select_thread): new method to select all messages in thread containing current message. * src/balsa-index.h: ditto. * src/main-window.c: use it. 2009-05-04 Peter Bloomfield Add filter for colorizing messages * libbalsa/filter.h: add FILTER_COLOR to FilterActionType enum, and FILTER_N_TYPES sentinel. * libbalsa/filter.c (libbalsa_filter_mailbox_messages): act on it. * libbalsa/libbalsa_private.h: add color members to LibBalsaMailboxIndexEntry. * libbalsa/mailbox.h: new methods to set color; expand LibBalsaMailboxColumn enum. * libbalsa/mailbox.c (lbm_index_entry_populate_from_msg), (mbox_model_init), (mbox_model_get_value), (lbm_set_color), (libbalsa_mailbox_set_foreground), (libbalsa_mailbox_set_background): implement them. * src/balsa-index.c (bndx_instance_init): set color in all columns. * src/filter-edit-callbacks.c (fe_action_selected), (fe_apply_pressed), (fe_filters_list_selection_changed), (fe_color_check_toggled), (fe_color_set): * src/filter-edit-dialog.c (fe_make_color_buttons), (build_action_page): add option to choose colors. * src/filter-edit.h: new callbacks. * src/filter-run-callbacks.c (fr_apply_selected_pressed_func), (fr_add_pressed_func): ditto. * src/save-restore.c (config_filter_load), (config_filters_load): scrap broken pre-2.1 compatibility code. 2009-04-29 Ildar Mulyukov * balsa.desktop.in: respect https://specifications.freedesktop.org/menu-spec/latest/apa.html 2009-04-29 Peter Bloomfield * libbalsa/mailbox.h: new member sort_field_prev in LibBalsaMailboxView. * libbalsa/mailbox.c (libbalsa_mailbox_set_sort_field, mbox_compare_func, mbox_set_sort_column_id): use it to save previous sort_field, and to resolve ties wrt current sort_field--work around for lack of a stable mailbox sort. 2009-04-23 Peter Bloomfield bump version to 2.4.0, and require GMime-2.4, GLib-2.16, and Gtk-2.14. 2009-04-21 Peter Bloomfield port to GMime-2.4 2009-04-21 Peter Bloomfield create balsa-2-3 branch for updates to the pre-GMime-2.4 tree. 2009-04-21 Peter Bloomfield * balsa.doap: new description-of-a-project file. 2009-04-15 Peter Bloomfield * src/balsa-mime-widget.c: (balsa_mime_widget_new_unknown): ellipsize message label. 2009-04-06 Albrecht Dreß * src/balsa-print-object.c: (balsa_print_object_emb_message, balsa_print_object_mp_crypto, balsa_print_objects_append_from_body): fix mem leak, select print handlers from a list which needs two helpers due to different prototypes; * src/balsa-print-object-header.c: (balsa_print_object_header_new_real): fix mem leak; * src/print-gtk.c: (begin_print): simplify code. 2009-04-02 Peter Bloomfield Make sure that config.h is included before any header that refers to a symbol defined there. * libbalsa/address-book-gpe.h: * libbalsa/body.h: * libbalsa/filter-private.h: * libbalsa/gmime-stream-gio.h: * libbalsa/gmime-stream-gnome-vfs.h: * libbalsa/html.h: * libbalsa/identity.h: * libbalsa/libbalsa.h: * libbalsa/libbalsa_private.h: * libbalsa/mailbox.h: * libbalsa/message.h: * libbalsa/mime-stream-shared.h: * libbalsa/misc.h: * libbalsa/missing.h: * libbalsa/rfc3156.h: * libbalsa/send.h: * libbalsa/server.h: * libinit_balsa/Makefile.am: * libinit_balsa/assistant_page_defclient.h: * src/balsa-app.h: * src/balsa-bonobo.h: * src/balsa-icons.h: * src/balsa-message.h: * src/balsa-mime-widget-crypto.h: * src/balsa-print-object-header.h: * src/main-window.h: * src/print.h: * src/quote-color.h: * src/save-restore.h: * src/sendmsg-window.h: * libbalsa/libbalsa-conf.c: include config.h. * libinit_balsa/assistant_page_defclient.c: ditto. * libinit_balsa/assistant_init.c: ditto. 2009-04-02 Peter Bloomfield * src/balsa-print-object-decor.c: include config.h. * src/balsa-print-object-image.c: ditto. 2009-03-31 Albrecht Dreß * libbalsa/rfc2445.c: (libbalsa_vcal_new_from_body, date_time_2445_to_time_t): fix "critical" warnings due to comparison of wrong variable, and if a line is empty. * src/balsa-print-object-default.c: (balsa_print_object_default_draw): print the icon top-aligned. * src/balsa-print-object-text.c: (balsa_print_object_text_calendar): break huge iCal parts over multiple pages if necessary. 2009-03-26 Peter Bloomfield * libbalsa/missing_time.c: build with enable-threads. 2009-03-19 Peter Bloomfield * Makefile.am: install BonoboActivation files only if !BUILD_WITH_UNIQUE. * src/Makefile.am: ditto. 2009-03-19 Peter Bloomfield Build --without-esmtp * libbalsa/libbalsa.h: typedef LibBalsaSmtpServer only if ENABLE_ESMTP. * libbalsa/identity.h: include "libbalsa.h" instead of "smtp-server.h". 2006-03-19 Pawel Salek * libbalsa/imap/imap-handle.c: make IDLE startup asynchronous. * libbalsa/imap/imap_private.h: provide EAT_LINE macro. * libbalsa/imap/imap-commands.c: use it. 2009-03-13 Peter Bloomfield Offer libUnique as an alternative to BonoboActivation to ensure single instance. * configure.in: new option --with-unique=no. * src/Makefile.am: Bonobo files are conditional. * src/main.c: (main, balsa_main_check_new_messages, mw_message_received_cb, balsa_handle_automation_options): implement it. (balsa_init): Initialize Gtk only once, and check for error. 2009-03-11 Albrecht Dreß * libbalsa/rfc2445.c: (libbalsa_vcal_new_from_body): ignore nested description. * src/balsa-mime-widget-vcalendar.c: (balsa_vevent_widget): use GtkTextView to show wrapped description. 2009-03-11 Peter Bloomfield * libbalsa/address-book-ldap.c: (rfc_2254_escape): do not include gnome.h; use g_{new,free} instead of {malloc,free}. 2009-03-03 Peter Bloomfield Consistently initialize Gerror, and use g_clear_error when it helps. * libbalsa/gmime-stream-gio.c: * libbalsa/libbalsa-conf.c: (lbc_init), (lbc_sync): * libbalsa/mailbox_local.c: (lbm_local_save_tree): * libbalsa/source-viewer.c: (lbsv_app_set_menus): * src/ab-main.c: (get_main_menu), (main): * src/balsa-icons.c: (load_balsa_pixmap): * src/filter-edit-callbacks.c: (condition_dialog_response), (fe_dialog_response): * src/filter-run-callbacks.c: (fr_dialog_response): * src/main-window.c: * src/main.c: (main): * src/message-window.c: (message_window_new): * src/sendmsg-window.c: (sendmsg_window_new): 2009-03-03 Peter Bloomfield * libbalsa/identity.c: free force-key-id. * src/balsa-icons.c: (load_balsa_pixmap): unref icon-set. * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text, bm_widget_new_vcard): free ptr in balsa_mime_widget_new_text instead of in bm_widget_new_vcard. 2009-03-01 Peter Bloomfield * libbalsa/mailbox_imap.c: (libbalsa_mailbox_imap_open): do not leak ImapCacheManager. 2009-02-28 Peter Bloomfield * libbalsa/body.c: (libbalsa_message_body_get_pixbuf): tell GdkPixbufLoader the mime type; some types, apparently including compressed SVG, cannot be reliably identified by looking at the data. 2009-02-28 Peter Bloomfield * src/main-window.c: tighten some old code. 2009-02-28 Peter Bloomfield * src/main.c: (initial_open_unread_mailboxes, initial_open_inbox, main): really check new mail after building the tree. 2009-02-27 Peter Bloomfield * src/main-window.c: * src/main.c: (balsa_main_check_new_messages, main): on startup, check new mail in an idle handler, after the mailbox tree has been built. 2009-02-27 Peter Bloomfield * src/balsa-message.c: libbalsa_can_display is needed only if HAVE_GTKHTML. 2009-02-26 Paweł Sałek * libbalsa/imap/imap-commands.c: do not deadlock when opening imap mailbox with new messages, sorted on the client side. 2009-02-25 Peter Bloomfield make sure -DHAVE_CONFIG_H is passed as a compiler flag. * configure.in: * libbalsa/Makefile.am: * src/Makefile.am: Test HAVE_CONFIG_H before including config.h. * libbalsa/abook-completion.c: * libbalsa/address-book-extern.c: * libbalsa/address-book-gpe.c: * libbalsa/address-book-ldap.c: * libbalsa/address-book-ldif.c: * libbalsa/address-book-rubrica.c: * libbalsa/address-book-text.c: * libbalsa/address-book-vcard.c: * libbalsa/address-book.c: * libbalsa/address-view.c: * libbalsa/address.c: * libbalsa/body.c: * libbalsa/body.h: * libbalsa/cell-renderer-button.c: * libbalsa/files.c: * libbalsa/files.h: * libbalsa/filter-error.c: * libbalsa/filter-file.c: * libbalsa/filter-funcs.c: * libbalsa/filter.c: * libbalsa/folder-scanners.c: * libbalsa/folder-scanners.h: * libbalsa/gmime-gpgme-context.c: * libbalsa/gmime-part-rfc2440.c: * libbalsa/gmime-stream-gio.c: * libbalsa/gmime-stream-gio.h: * libbalsa/gmime-stream-gnome-vfs.c: * libbalsa/gmime-stream-gnome-vfs.h: * libbalsa/html.c: * libbalsa/html.h: * libbalsa/identity.c: * libbalsa/identity.h: * libbalsa/imap-server.c: * libbalsa/imap-server.h: * libbalsa/information.c: * libbalsa/libbalsa-conf.h: * libbalsa/libbalsa-vfs.c: * libbalsa/libbalsa-vfs.h: * libbalsa/libbalsa.c: * libbalsa/libbalsa.h: * libbalsa/mailbox-filter.c: * libbalsa/mailbox.c: * libbalsa/mailbox.h: * libbalsa/mailbox_imap.c: * libbalsa/mailbox_local.c: * libbalsa/mailbox_local.h: * libbalsa/mailbox_maildir.c: * libbalsa/mailbox_mbox.c: * libbalsa/mailbox_mh.c: * libbalsa/mailbox_pop3.c: * libbalsa/mailbox_remote.c: * libbalsa/message.c: * libbalsa/message.h: * libbalsa/mime-stream-shared.c: * libbalsa/mime-stream-shared.h: * libbalsa/mime.c: * libbalsa/misc.c: * libbalsa/missing_time.c: * libbalsa/rfc2445.c: * libbalsa/rfc3156.c: * libbalsa/rfc3156.h: * libbalsa/send.c: * libbalsa/send.h: * libbalsa/server.c: * libbalsa/smtp-server.c: * libbalsa/smtp-server.h: * libbalsa/source-viewer.c: * libinit_balsa/assistant_helper.c: * libinit_balsa/assistant_helper.h: * libinit_balsa/assistant_init.h: * libinit_balsa/assistant_page_defclient.h: * libinit_balsa/assistant_page_directory.c: * libinit_balsa/assistant_page_directory.h: * libinit_balsa/assistant_page_finish.c: * libinit_balsa/assistant_page_finish.h: * libinit_balsa/assistant_page_user.c: * libinit_balsa/assistant_page_user.h: * libinit_balsa/assistant_page_welcome.h: * libinit_balsa/balsa-druid-page-defclient.h: * libinit_balsa/balsa-druid-page-directory.h: * libinit_balsa/balsa-druid-page-finish.c: * libinit_balsa/balsa-druid-page-finish.h: * libinit_balsa/balsa-druid-page-user.c: * libinit_balsa/balsa-druid-page-user.h: * libinit_balsa/balsa-druid-page-welcome.h: * libinit_balsa/balsa-initdruid.h: * libinit_balsa/helper.c: * libinit_balsa/helper.h: * libinit_balsa/init_balsa.c: * src/ab-main.c: * src/ab-window.c: * src/ab-window.h: * src/address-book-config.c: * src/balsa-app.c: * src/balsa-bonobo.c: * src/balsa-bonobo.h: * src/balsa-icons.c: * src/balsa-icons.h: * src/balsa-index.c: * src/balsa-mblist.c: * src/balsa-message.c: * src/balsa-message.h: * src/balsa-mime-widget-callbacks.c: * src/balsa-mime-widget-callbacks.h: * src/balsa-mime-widget-crypto.c: * src/balsa-mime-widget-crypto.h: * src/balsa-mime-widget-image.c: * src/balsa-mime-widget-message.c: * src/balsa-mime-widget-multipart.c: * src/balsa-mime-widget-text.c: * src/balsa-mime-widget-vcalendar.c: * src/balsa-mime-widget.c: * src/balsa-print-object-default.c: * src/balsa-print-object-header.c: * src/balsa-print-object-header.h: * src/balsa-print-object-text.c: * src/balsa-print-object.c: * src/balsa-print-object.h: * src/filter-edit-callbacks.c: * src/filter-edit-dialog.c: * src/filter-export-callbacks.c: * src/filter-export-dialog.c: * src/filter-run-callbacks.c: * src/filter-run-dialog.c: * src/folder-conf.c: * src/information-dialog.c: * src/information-dialog.h: * src/mailbox-conf.c: * src/mailbox-node.c: * src/main-window.c: * src/main.c: * src/message-window.c: * src/pref-manager.c: * src/pref-manager.h: * src/print-gtk.c: * src/print.c: * src/print.h: * src/quote-color.c: * src/quote-color.h: * src/save-restore.c: * src/save-restore.h: * src/sendmsg-window.c: * src/sendmsg-window.h: * src/spell-check.c: * src/spell-check.h: * src/store-address.c: * src/store-address.h: * src/toolbar-factory.c: * src/toolbar-factory.h: * src/toolbar-prefs.c: * src/toolbar-prefs.h: 2009-02-25 Peter Bloomfield * src/main-window.h: add new_mail_tray and new_mail_note to BalsaWindow. * src/main-window.c: use gtk_window_set_urgency_hint to show new mail; consolidate notify::is-active handling. 2009-02-21 Paweł Sałek * libbalsa/files.c: * src/balsa-index.c: build against oldish gtk/gnome. * libbalsa/rfc2445.c: with gcc-3.x * libbalsa/imap/imap-commands.c: lock the handle when issuing asynchronous EXPUNGE. 2009-02-18 Paweł Sałek * src/sendmsg-window.c:, src/{ab-,}main.c: * libbalsa/rfc2445.c: we include stdlib.h unconditionally. 2009-02-16 Albrecht Dreß and Peter Bloomfield * src/balsa-message.c: (handle_mdn_request, create_mdn_reply, create_mdn_dialog, mdn_dialog_response): check all identities. * src/balsa-mime-widget-vcalendar.c: (vevent_reply): use smtp-server for attendee's identity. 2009-02-16 Albrecht Dreß * configure.in: detect the *time_r function declarations. * libbalsa/missing.h: HAVE_DECL_*TIME_R is always defined to a value. 2009-02-16 Albrecht Dreß and Paweł Sałek * src/main-window.c: use g_(malloc|free) instead of malloc and free * src/sendmsg-window.c, src/ab-main.c, src/main.c: add missing include of stdlib.h if it is available * configure.in: always define _XOPEN_SOURCE * libbalsa/missing.h: declare (local|gm|c)time_r if necessary * libbalsa/rfc2445.c: add proper casting macros, catch and convert \r\n line endings (iCal compatibility), work around iCal method parameter bug, fix crash on NULL pointers passed to conversion funcs. * libbalsa/filter-funcs.c: use glib for time conversion if available. * libbalsa/mailbox_imap.c: sync the cache when closing mbox. 2009-02-15 Peter Bloomfield * src/balsa-mime-widget-vcalendar.c: (balsa_vevent_widget, vevent_reply): check all identities. 2009-02-12 Peter Bloomfield * src/balsa-message.h: new member gint BalsaMessage::tab_position, the position of the tab for header values. * src/balsa-mime-widget.h: new member GtkWidget * BalsaMimeWidget::header_widget, pointer to the header widget for the message. * src/balsa-mime-widget-message.c: (balsa_mime_widget_new_message, balsa_mime_widget_new_message_tl, bm_header_widget_new, bmwm_set_tabs, add_header_gchar, balsa_mime_widget_message_set_headers, bmwm_buffer_set_prefs, balsa_mime_widget_message_set_headers_d): set the tab position 6 pixels beyond the length of the longest header label; set user prefs for fonts and colors each time we render a message, in case prefs have changed. 2009-02-12 Inaki Larranaga Murgoitio * configure.in: Added 'eu' (Basque) to ALL_LINGUAS 2009-02-08 Albrecht Dreß * libbalsa/rfc2445.[hc]: Implement VCALENDAR and VEVENT objects. * src/balsa-mime-widget-vcalendar.[hc]: display vevent's, and the stuff for sending a text/calendar reply; * src/balsa-mime-widget.c: call functions to display text/calendar * src/balsa-print-object-text.[hc]: support print these parts * src/balsa-print-object.c:: call functions to print text/calendar * src/balsa-message.c: make text/calendar the preferred part. * src/balsa-print-object-default.c: catch missing pixbuf * src/Makefile.am, libbalsa/Makefile.am: add new source files 2009-02-07 Albrecht Dreß * INSTALL: minimum gtk version upgraded, link cleanup (Incomplete!). * configure.in: Check min versions, new option for Mac OS X desktop, check for *time_r funcs, remove unnecessary check for iconv * src/filter-edit.h, src/balsa-index.c, src/balsa-mblist.c * src/mailbox-conf.c, src/filter-edit-dialog.c, src/pref-manager.c * src/address-book-config.c, libbalsa/misc.[hc] * libbalsa/libbalsa-conf.[hc], libbalsa/address.c, libbalsa/identity.c * src/filter-edit-callbacks.c: Assume we have Gtk+/glib >= 2.6.0 * libbalsa/imap/imap_search.c: use GDate instead of localtime_r (avoid dependency to libbalsa) * libbalsa/rfc3156.c: use glib random func * libbalsa/Makefile.am, libbalsa/missing{_time.c,.h}: add system-dependent time_r funcs * src/main-window.c: Add basic Mac OS X menu integration, assume we have Gtk+/glib >= 2.6.0 * src/sendmsg-window.c: Add basic Mac OS X menu integration, use g_strdup. * src/save-restore.[hc], libinit_balsa/assistant_page_defclient.[hc], * libinit_balsa/assistant_init.c: No Gnome default client without Gnome * src/toolbar-factory.c, src/main.c, src/Makefile.am Build without Gnome support * src/print-gtk.c: Mac OS X doesn't define _NL_MEASUREMENT_MEASUREMENT * src/balsa-icons.c: Remove unnecessary include. * src/balsa-bonobo.[hc]: Only compiled if building with Gnome support * src/balsa-app.c: Gdk on Mac OS X cannot create a new colour map, fall back to system * src/ab-main.c: Build Gnome stuff only when available, assume we have Gtk+/glib >= 2.6.0, add basic Mac OS X menu integration. 2009-02-07 Paweł Sałek * src/main-window.c: get rid of spurious new-mail notifications. 2009-01-25 Peter Bloomfield * libbalsa/mailbox_local.c: (lbm_local_restore_tree): check for stale cache file. * libbalsa/mailbox_mbox.c: (lbm_mbox_restore): ditto. 2009-01-24 Albrecht Dreß Small compatibility fixes * src/sendmsg-window.c: search for toplevel window, not for Gnome application; * libbalsa/send.c, libbalsa/imap/imap-handle.c: do not use strcasecmp which OS X apparently doesn't define; * libbalsa/rfc3156.c: use utf8-clean time conversion helper. 2009-01-23 Peter Bloomfield * src/main-window.c: use unique names in GtkActionGroup. * src/sendmsg-window.c: (sendmsg_window_ui_manager_new): ditto. 2009-01-23 Peter Bloomfield * src/main-window.c: Gtk-2.16 deprecation cleanup. 2009-01-21 Peter Bloomfield * libbalsa/body.c: (libbalsa_message_body_get_part_stream, libbalsa_message_body_get_message_part_stream): new helpers; (libbalsa_message_body_get_stream): use them; (libbalsa_message_body_get_content, libbalsa_message_body_save_stream): set GError when returning error. * libbalsa/files.c: (libbalsa_default_attachment_pixbuf, libbalsa_icon_finder): remove unused GError. * src/balsa-mime-widget-callbacks.c: (balsa_mime_widget_ctx_menu_save): clear GError. 2009-01-20 Peter Bloomfield * libbalsa/body.c: (libbalsa_message_body_get_stream): check that we have a GMimePart; (libbalsa_message_body_save_stream): use libbalsa_message_body_stream_add_filter; * libbalsa/mailbox_imap.c: (libbalsa_mailbox_imap_get_msg_part): check for GMimeMultipart and GMimeMessagePart, as well as GMimePart. 2009-01-20 Peter Bloomfield * libbalsa/gmime-stream-gio.c: (stream_read, stream_write, stream_seek, stream_substream, g_mime_stream_gio_new_with_bounds): build on 32-bit box with GMime-2.2. * libbalsa/gmime-stream-gio.h: ditto. 2009-01-20 Peter Bloomfield Fix BUG - threading view and selecting, reported by Mario Mikocevic (https://mail.gnome.org/archives/balsa-list/2009-January/msg00015.html) * src/balsa-index.h: new boolean BalsaIndex::collapsing. * src/balsa-index.c: (bndx_test_collapse_row_cb) new callback to set it; (bndx_tree_collapse_cb): clear it; (bndx_selection_changed): use it to manage preview; (bndx_instance_init) connect to "test-collapse-row" signal to set it; 2009-01-18 Paweł Sałek * NEWS, configure.in: release 2.3.28 2009-01-16 Peter Bloomfield * libbalsa/misc.c: (libbalsa_set_fallback_codeset): do not allocate and leak strings, now that bug #509434 has been fixed. * src/balsa-icons.c: (load_balsa_pixmap): free the icon_source. * src/save-restore.c: include stdlib.h. * src/sendmsg-window.c: (delete_handler, sendmsg_window_set_title): do not leak address list. 2009-01-16 Paweł Sałek * libbalsa/files.c: simplify conditional code. * libbalsa/mailbox_imap.c: the only way to make sure that the exist handler does not trigger imap operations and a related deadlock is to process it entirely in an idle handler. Fetch message data using seqnos, otherwise we can get surprising EXPUNGE notifications. * libbalsa/imap/imap-handle.c: some imap servers send data in the same packet as the IDLE prompt. Process it immediately. 2009-01-15 Peter Bloomfield * src/print-gtk.c: (add_margin_spinbtn): do not leak string. 2009-01-10 Peter Bloomfield * src/main-window.c: fix string--marcel telka sk (fixes bug #567323). 2009-01-03 Peter Bloomfield * src/sendmsg-window.c: (send_message_handler): fix string--leonardof gnome org (fixes bug #566426). 2009-01-03 Peter Bloomfield * libbalsa/imap/imap-commands.c: (imap_mbox_thread): do not shadow-declare rc. 2009-01-03 Albrecht Dreß * libbalsa/html.c: (libbalsa_html_new): tell WebKit the charset. 2009-01-03 Peter Bloomfield * libbalsa/send.c: (libbalsa_create_rfc2440_buffer): use ngettext to handle plural--leonardof gnome org (fixes bug #566420). 2009-01-03 Peter Bloomfield * libbalsa/gmime-gpgme-context.c: (g_mime_gpgme_encrypt): clarify string--leonardof gnome org (fixes bug #566415). 2009-01-02 Albrecht Dreß * configure.in: prefer gio >= 2.16.0, fallback to gnome-vfs. * libbalsa/gmime-stream-gnome-vfs.[hc]: build only if using gnome-vfs * libbalsa/files.[hc]: implement icon lookup for gio * libbalsa/libbalsa-vfs.[hc]: add support for GIO * libbalsa/gmime-stream-gio.[hc]: gmime gio stream wrapper. * libbalsa/misc.c: remove unnecessary #include of gnome-vfs.h * libbalsa/Makefile.am: add gmime-stream-gio.[hc] * src/balsa-print-object-default.c: use libbalsa-vfs instead of gnome-vfs, enabling in this way a clean GIO usage. * src/sendmsg-window.c: call external editor through gio or gnome-vfs; use libbalsa-vfs helper to open attachment with external app; show description in attachment list * src/balsa-mime-widget-callbacks.[ch]: use libbalsa-vfs to open parts * src/balsa-mime-widget-text.c: use changed balsa-mime-widget-callbacks API. * src/ab-window.c: launch app using glib * src/balsa-message.c: use description instead of plain MIME type. * src/balsa-mime-widget.c: create a mime button via libbalsa-vfs. 2009-01-02 Paweł Sałek * src/main-window.c: report number of deleted message duplicates. * libbalsa/mailbox.[ch]: provide it. * libbalsa/imap-server.c: using binary fetches breaks integrity checks. 2008-12-30 Paweł Sałek * NEWS, configure.in: release 2.3.27 2008-12-30 Paweł Sałek * libbalsa/imap/imap_search.c: keep ImapHandle locked when searching. * libbalsa/imap/imap-handle.c: .. and when switching to IDLE mode. * libbalsa/imap/imap-commands.c: and when threading and sorting. 2008-12-27 Paweł Sałek and Peter Bloomfield * src/balsa-mime-widget-message.c: call balsa_message_save_part() from header context menu. * src/balsa-message.[ch]: implement balsa_message_save_part(). Call it from the "Message parts" tab. * libbalsa/mailbox_imap.c: mark GMimeMessagePart as saveable as well. * libbalsa/mailbox_local.c: ditto. * libbalsa/body.c: GMime streams for MessageParts have to be created in a particular way. 2008-12-24 Paweł Sałek * src/balsa-mblist.c: there are no unread mailboxes at destroy time. * src/balsa-message.c: display an interesting case of multipart/related embedded in a multipart/alternative. 2008-12-24 Peter Bloomfield * src/mailbox-node.c: (balsa_mailbox_node_rescan): handle rescan of whole tree (mn == NULL). 2008-12-24 Peter Bloomfield * src/balsa-app.c: (balsa_app_destroy): do not empty trash--it's too late. * src/main-window.c: in notebook-switch-page callback, check if Balsa is quitting. * src/save-restore.c: (sr_special_notify, config_mailbox_init): weak-ref special mailboxes, and at notify time, if Balsa is quitting, empty the trash. 2008-12-21 Paweł Sałek * configure.in: we require gnome-keyring >= 1.0 Remove some of the race conditions as found with helgrind. * src/balsa-app.c: do not manually destroy widgets. * src/main.c: cleanup explicitly before exit from main, no signals needed. * libbalsa/mailbox_{imap,local}.c: lock mailbox. * libbalsa/mailbox.c: keep the lock a bit longer. * libbalsa/libbalsa.c: preregister more object types. * libbalsa/imap/imap-{commands,handle}.c: lock the handle. 2008-12-20 Peter Bloomfield button for MDN in message composition toolbar (Jean-Luc Coulon) * src/balsa-icons.h: define new icon. * src/balsa-icons.c: (register_balsa_pixmaps): register it as "stock_mail-reply". * src/toolbar-factory.c: list it with short label. * src/sendmsg-window.c: use it with tooltip. 2008-12-14 Paweł Sałek * src/main-window.c: Add ability to display recent messages only. * libbalsa/imap-server.c: give more details in error messages. * libbalsa/imap/imap-handle.c: ditto. * libbalsa/imap/imap-commands.[ch]: Add "peek" argument to imap_mbox_handle_fetch_rfc822(). 2008-12-06 Peter Bloomfield rewrite of libbalsa_insert_with_url * libbalsa/mime.c: (libbalsa_unwrap_buffer, mark_urls, prescanner, libbalsa_html_encode_hyperlinks): pass string length to prescanner; (get_ml_url_reg): make sure the url ends with a real url character; (libbalsa_insert_with_url): avoid allocating and freeing strings. * libbalsa/misc.h: new signature for libbalsa_url_cb_t. * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text): avoid allocating and freeing strings; (url_found_cb): new signature for libbalsa_url_cb_t. * src/sendmsg-window.c: (edit_with_gnome_check, repl_identity_signature, insert_selected_messages, drag_data_quote, continue_body, fill_body_from_part, insert_signature_cb, sendmsg_window_set_field, do_insert_string_select_ch, insert_file_response, sw_wrap_body, sendmsg_window_new_from_list): use gtk_text_buffer_insert_at_cursor instead of libbalsa_insert_with_url. 2008-12-03 Peter Bloomfield * libbalsa/html.c: (lbh_size_request_cb, libbalsa_html_new): use gtk_widget_set_scroll_adjustments instead of a signal; dynamic cast once instead of many times. 2008-12-01 Peter Bloomfield Initial experimental support for WebKit. * configure.in: configure it. * libbalsa/html.c: (lbh_hovering_over_link_cb, lbh_size_request_cb, lbh_navigation_requested_cb, libbalsa_html_new, libbalsa_html_to_string, libbalsa_html_can_zoom, libbalsa_html_zoom, libbalsa_html_can_select, libbalsa_html_select_all, libbalsa_html_copy, lbh_new): new conditional section; new api needed, because WebKitWebView has different signals and is not a subclass of GtkLayout. * libbalsa/html.h: new api. * src/balsa-mime-widget-text.c: (pointer_over_url, bm_widget_on_url, bm_widget_link_clicked, bm_widget_new_html): adapt to new api. 2008-11-22 Albrecht Dreß Use only static format strings. * libbalsa/libbalsa-vfs.c: (libbalsa_vfs_create_stream), (libbalsa_vfs_file_unlink): * libbalsa/send.c: (libbalsa_message_create_mime_message): * src/ab-main.c: (ab_warning): * src/sendmsg-window.c: (check_suggest_encryption), (send_message_handler): * src/store-address.c: (store_address_from_entries): 2008-11-22 Peter Bloomfield * libinit_balsa/assistant_init.c: include stdlib.h. * libinit_balsa/assistant_page_directory.c: ditto. * src/balsa-app.c: ditto. * src/balsa-mime-widget-text.c: ditto. * src/spell-check.c: ditto. 2008-11-22 Peter Bloomfield * libbalsa/html.h: work around gtkhtml2's use of deprecated api. 2008-11-22 Peter Bloomfield disable deprecated apis only in svn tree (fixes bug #561875). * configure.in: * libbalsa/Makefile.am: * libinit_balsa/Makefile.am: * src/Makefile.am: 2008-11-21 Paweł Sałek * src/save-restore.c: connect signal to ask interactively for SMTP passwords. * src/balsa-app.c: display the type of the password (imap/smtp). * libbalsa/smtp-server.c: ask for password when one needs one. 2008-11-19 Paweł Sałek * configure.in: detect gnome-keyring-2.24 to work around bug 556530. * libbalsa/{imap-,}server.c: store passwords asap to keyring (Peter B.). * libbalsa/server.h: use own schema only with buggy gnome-keyring. 2008-11-17 Peter Bloomfield * src/main-window.c: make "about" website clickable. 2008-11-17 Paweł Sałek * src/{folder,mailbox}-conf.c: capitalize according to HID. * src/{balsa-app,pref-manager}.c: ditto. * libbalsa/identity.c: ditto. * configure.in: gnome-keyring detection. * libbalsa/smtp-server.c: store server protocol. * libbalsa/imap-server.c: read password from keyring. * libbalsa/server.[ch]: ditto. 2008-11-16 Paweł Sałek * src/balsa-mime-widget-{message,text}.c: fall back to gnome_url_Show if gtk2 >= 2.14.0 is unavailable. * src/sendmsg-window.c: ditto. 2008-11-15 Peter Bloomfield Use gtk_show_uri instead of gnome_help_display and gnome_url_show, in various places; no longer need to include in as many places. * libbalsa/identity.c: (help_ident_cb): replace gnome_help_display and gnome_url_show with gtk_show_uri. * libbalsa/smtp-server.c: (smtp_server_response): ditto. * src/address-book-config.c: (help_button_cb): ditto. * src/balsa-message.c: ditto. * src/balsa-mime-widget-callbacks.c: ditto. * src/balsa-mime-widget-message.c: (extbody_call_url): ditto. * src/balsa-mime-widget-text.c: (handle_url), (balsa_gtk_html_link_clicked): ditto. * src/filter-edit-callbacks.c: (condition_dialog_response), (fe_dialog_response): ditto. * src/filter-run-callbacks.c: (fr_dialog_response): ditto. * src/folder-conf.c: (folder_conf_response): ditto. * src/main-window.c: ditto. * src/message-window.c: ditto. * src/pref-manager.c: (balsa_help_pbox_display): ditto. * src/sendmsg-window.c: (on_open_url_cb): ditto. * src/toolbar-prefs.c: (tp_dialog_response_cb): ditto. * src/balsa-app.h: do not include * src/balsa-index.h: ditto. * src/balsa-message.h: ditto. * src/spell-check.c: ditto. * src/spell-check.h: ditto. * src/balsa-mime-widget.h: ditto. * libbalsa/body.h: include . 2008-11-14 Peter Bloomfield * libbalsa/address-book.c: include only top level . * libbalsa/address-view.h: ditto. * libbalsa/cell-renderer-button.h: ditto. * libbalsa/information.c: ditto. * src/balsa-cite-bar.h: ditto. 2008-11-08 Paweł Sałek * configure.in: replace --without-gnome with --with-gnome to reduce confusion described on the web site. * doc/balsa.omf.in: fix #559825. 2008-10-14 Peter Bloomfield & Pawel Salek * bootstrap.sh: run gnome-doc-prepare. * src/Makefile.am: clean generated IDL files. * doc/C/balsa.xml: follow DTD. * doc/Makefile.am: use new gnome-doc format. * sounds/Makefile.am: clean up generated files. * configure.in: detect gnome-doc * Makefile.am: adapt to gnome-doc. 2008-10-12 Petr Kovar * configure.in: Added "be" and "mk" to ALL_LINGUAS. 2008-10-09 Peter Bloomfield * src/main-window.c: smaller notebook tab button. 2008-10-08 Peter Bloomfield * src/main-window.c: update the magic number. 2008-10-03 Mario Blättermann * doc/de/*: Added partial German translation * doc/Makefile.am: Added de to the translation subdirs 2008-09-28 Peter Bloomfield * libbalsa/mailbox_mbox.c: turn off debugging. 2008-09-22 Peter Bloomfield * src/pref-manager.c: (checking_group, misc_group, deleting_messages_group): GtkAdjustment::page_size must be zero when the GtkAdjustment is used in a GtkSpinButton. 2008-09-15 Peter Bloomfield * libbalsa/mailbox_mbox.c: (lbm_mbox_stream_seek_to_message): fix stupid comparison. 2008-09-15 Peter Bloomfield * libbalsa/mailbox_mbox.c: (lbm_mbox_stream_seek_to_message): do not trash stack. 2008-09-15 Peter Bloomfield * libbalsa/mailbox_mbox.c: (lbm_mbox_stream_seek_to_message, libbalsa_mailbox_mbox_check): cast off_t and ssize_t to long in calls to g_print. 2008-09-14 Peter Bloomfield * libbalsa/mailbox_mbox.c: (lbm_mbox_stream_seek_to_message): better debugging. 2008-09-14 Paweł Sałek * src/balsa-index.c: process messages with external program - asynchronously. 2008-09-14 Peter Bloomfield * libbalsa/body.c: (libbalsa_message_body_get_stream): fail if message has no mailbox. * libbalsa/mailbox_mbox.c: (free_message_info, free_messages_info): plug memory leak; (lbm_mbox_stream_seek_to_message, libbalsa_mailbox_mbox_open, libbalsa_mailbox_mbox_sync): debugging output; (libbalsa_mailbox_mbox_check): ditto; more careful check for new mail. * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text): check for NULL part. * src/balsa-print-object-text.c: (balsa_print_object_text_vcard): ditto * src/sendmsg-window.c: (fill_body_from_part, bsm_finish_setup): ditto. 2008-09-13 Peter Bloomfield * src/balsa-icons.c: (load_balsa_pixmap): add more fallbacks to cope with woeful gnome-icon-theme-2.23+; use GTK_STOCK_MISSING_IMAGE when all else fails, to avoid Gtk warnings. 2008-09-09 Peter Bloomfield Gtk 2.14 deprecation cleanup * libbalsa/mailbox.c: (mbox_set_sort_func), (mbox_set_default_sort_func): * libbalsa/source-viewer.c: (libbalsa_show_message_source): * libinit_balsa/assistant_page_user.c: (balsa_druid_page_user_init): * libinit_balsa/balsa-druid-page-user.c: (balsa_druid_page_user_init): * src/ab-window.c: (balsa_ab_window_get_type): * src/ab-window.h: * src/balsa-cite-bar.c: (balsa_cite_bar_class_init): * src/balsa-index.c: (balsa_index_get_type), (bndx_class_init), (bndx_popup_menu_create), (create_stock_menu_item): * src/balsa-index.h: * src/balsa-mblist.c: (balsa_mblist_get_type): * src/balsa-mblist.h: * src/balsa-message.c: (balsa_message_get_type), (tree_mult_selection_popup), (add_to_attachments_popup), (add_toggle_inline_menu_item): * src/balsa-message.h: * src/balsa-mime-widget.h: * src/filter-edit-callbacks.c: (build_type_notebook): * src/mailbox-conf.c: (run_mailbox_conf), (mailbox_conf_new), (create_local_mailbox_dialog), (create_pop_mailbox_dialog), (create_imap_mailbox_dialog): * src/mailbox-conf.h: * src/mailbox-node.c: (add_menu_entry), (balsa_mailbox_node_get_context_menu): * src/main-window.c: * src/main-window.h: * src/sendmsg-window.c: (add_attachment), (add_urlref_attachment), (bsmsg_check_format_compatibility): * src/spell-check.c: (balsa_spell_check_get_type), (balsa_spell_check_class_init): * src/spell-check.h: 2006-09-07 Paweł Sałek * libbalsa/imap/imap-handle.c: don't g_source_remove() twice. * NEWS, configure.in: release 2.3.26. 2006-09-06 Paweł Sałek * src/balsa-bonobo.c: raise main window after receiving Bonobo cmds. * src/balsa-app.c: add some HIG padding in the password dialog. * src/balsa-message.c: specify parent for the MDN dialog. * balsa.spec.in: merge minor fixes from Fedora's spec. * libbalsa/imap/imap-handle.c: process HUPs on idle IMAP connections. 2008-08-28 Albrecht Dreß specify a key id for an identity * doc/C/balsa.xml: document it. * libbalsa/gmime-gpgme-context.c: (get_key_from_name): check whether it's a name or an id. * libbalsa/identity.c: (libbalsa_identity_init, libbalsa_identity_finalize, setup_ident_frame, ident_dialog_update, display_frame_update, libbalsa_identity_new_config, libbalsa_identity_save): new entry for forced key id. * libbalsa/identity.h: new member for forced key id. * libbalsa/message.c: (libbalsa_message_init, libbalsa_message_finalize): ditto. * libbalsa/message.h: ditto. * libbalsa/send.c: (lb_send_from): use it. * src/sendmsg-window.c: (bsmsg2message): set it. 2008-08-24 Peter Bloomfield * src/main-window.c: simplify get-toolbar and ui-manager. * src/main-window.h: ditto. * src/message-window.c: (message_window_ui_manager_new, message_window_get_toolbar_model, message_window_new): ditto. * src/message-window.h: ditto. * src/pref-manager.c: (apply_prefs): ditto. * src/sendmsg-window.c: (sendmsg_window_ui_manager_new, sendmsg_window_get_toolbar_model, sendmsg_window_new): ditto. * src/sendmsg-window.h: ditto. * src/toolbar-prefs.c: (customize_dialog_cb): ditto. 2008-08-23 Peter Bloomfield * libbalsa/mime.c: (libbalsa_wrap_view, libbalsa_unwrap_buffer): no more soft newlines. * libbalsa/misc.h: remove libbalsa_prepare_delsp. * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text): no soft-newline tag. * src/sendmsg-window.c: (create_text_area): no soft-newline tag; (bsmsg2message): remove libbalsa_prepare_delsp. 2008-08-20 Peter Bloomfield * libbalsa/mime.c: (dowrap_rfc2646): do not append a space after a trailing tab when format=flowed. 2008-08-20 Peter Bloomfield * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text): plug memory leak. 2008-08-20 Peter Bloomfield * src/sendmsg-window.c: (bsmsg2message): pass the message to sw_wrap_body even if it is flowed, so that libbalsa_unwrap_buffer will remove whitespace preceding a hard newline. 2008-08-03 Peter Bloomfield * libbalsa/send.c: (lbs_list_n_addresses): count the addresses in an InternetAddressList; (lbs_process_queue): handle a message with a single Bcc: holder and no other recipients. 2008-08-03 Peter Bloomfield * src/sendmsg-window.c: (find_locale_index_by_locale): return -1 if locale is not found; (create_lang_menu): default spell-check language to first item in menu, when balsa_app.spell_check_lang is not found; (sendmsg_window_continue): find_locale_index_by_locale is now signed. 2008-08-03 Peter Bloomfield * libbalsa/body.c: (libbalsa_message_body_set_message_part): handle NULL value from g_mime_message_part_get_message. 2008-07-30 Paweł Sałek * libbalsa/gmime-part-rfc2440.c: wrapper is not guaranteed to exist. * libbalsa/gmime-application-pkcs7.c: ditto. * libbalsa/body.c: ditto. * libbalsa/mailbox_imap.c: remove cache file if download failed. 2008-07-02 Peter Bloomfield * libbalsa/address.c: (vcard_strsplit): skip empty fields; (libbalsa_address_new_from_vcard): return NULL if the we do not find a complete vCard with at least one address. * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text): check text/directory as well as text/x-vcard; check for NULL return value; (bm_widget_new_vcard): return NULL if libbalsa_address_new_from_vcard returns NULL. * src/balsa-print-object-text.c: (balsa_print_object_text_vcard): print broken text/x-vcard and non-vcard text/directory parts as text/plain instead of default. * src/balsa-print-object.c: (balsa_print_objects_append_from_body): check text/directory as well as text/x-vcard. 2008-06-17 Peter Bloomfield * libbalsa/mailbox.c: (lbm_cache_message, libbalsa_mailbox_get_message, lbm_get_index_entry_real, lbm_get_index_entry, libbalsa_mailbox_cache_message): cache message info for the display at get-message time. * libbalsa/mailbox_mbox.c: (parse_mailbox): remove redundant call to libbalsa_mailbox_cache_message. 2008-06-17 Peter Bloomfield * libbalsa/libbalsa_private.h: scrap unused cache-unseen-child code. * libbalsa/mailbox.c: (lbm_index_entry_populate_from_msg, lbm_node_has_unseen_child, lbm_msgno_changed, lbm_set_threading, mbox_model_get_value): ditto. 2008-06-14 Paweł Sałek * NEWS, configure.in: release 2.3.25. 2008-06-12 Peter Bloomfield * libbalsa/mailbox_mbox.c: (lbm_mbox_header_cb, parse_mailbox), libbalsa_mailbox_mbox_sync): declare GMimeParserHeaderRegexFunc callback properly, and do not cast references to it. 2008-06-11 Paweł Sałek * libbalsa/imap/imap-handle.c: detect disconnect on write. * src/ab-main.c: add "Delete Entry" menu entry. 2008-06-05 Peter Bloomfield New method libbalsa_mailbox_index_entry_clear to avoid using libbalsa_mailbox_cache_message with a NULL message to clear the index entry. * libbalsa/mailbox.h: remove libbalsa_mailbox_index_entry_free--no need to export; new method libbalsa_mailbox_index_entry_clear. * libbalsa/mailbox.c: (lbm_index_entry_free, libbalsa_mailbox_index_entry_clear, libbalsa_mailbox_free_mindex, libbalsa_mailbox_msgno_removed): replace public libbalsa_mailbox_index_entry_free with static lbm_index_entry_free; new public method libbalsa_mailbox_index_entry_clear; (libbalsa_mailbox_cache_message): require a non-NULL message. * libbalsa/mailbox_imap.c: (imap_exists_cb): use libbalsa_mailbox_index_entry_clear. 2008-06-04 Peter Bloomfield * libbalsa/mime.c: (process_mime_part): quote a flowed message as flowed. 2008-06-04 Peter Bloomfield * src/balsa-mime-widget-message.c: (add_header_gchar): look further into the value, to make sure we detect a long header field. 2008-06-02 Peter Bloomfield * src/balsa-mime-widget-message.c: (bm_header_widget_new, add_header_gchar): let GtkTextView wrap headers. 2008-06-01 Peter Bloomfield * src/main-window.c: tighten code. * src/message-window.c: (mw_header_activate): do not change balsa-app.shown_headers. (show_all_headers_tool_cb): tighten code. 2008-06-02 Pawel Salek * libbalsa/imap/imap-handle.c: be more robust to servers returning resposes in a changed order. Handle GMail's wrong BODYSTRUCTURE response. * libbalsa/imap/imap_private.h: define ImapFetchBodyType to detect changed response order. * libbalsa/imap/imap-commands.c: detect changed response order. 2008-06-01 Peter Bloomfield * src/balsa-message.h: remove unused member show_all_headers. * src/balsa-message.c: (balsa_message_init): do not init it. * src/balsa-mime-widget-message.c: (add_header_gchar, add_header_address_list, balsa_mime_widget_message_set_headers_d): do not test it. 2008-06-01 Peter Bloomfield Make the new mail tray icon optional. * src/balsa-app.h: new member notify_new_mail_icon. * src/balsa-app.c: (balsa_app_init): initialize it to 1. * src/main-window.c: test it. * src/pref-manager.c: (open_preferences_manager, apply_prefs, set_prefs, checking_group): manage it. * src/save-restore.c: (config_global_load, config_save): load and save it. 2008-06-01 Peter Bloomfield * src/main-window.c: reassign icons to get "Expunge" as a toolbar option. * src/toolbar-factory.c: change labels accordingly. 2008-06-01 Pawel Salek * src/balsa-mime-widget-message.c: truncate long headers when "view selected" is chosen. 2008-05-31 Pawel Salek * configure.in, NEWS: release 2.3.24 2008-05-25 Albrecht Dreß Offer the option of sending a new message with both text/plain and text/html versions, specifically to avoid right-to-left text being mangled by text-to-html converters. The option is per-identity. * libbalsa/body.h: new member for html version. * libbalsa/body.c: (libbalsa_message_body_new, libbalsa_message_body_free): manage it. * libbalsa/identity.h: new member for option. * libbalsa/identity.c: (libbalsa_identity_init, libbalsa_identity_set_send_mp_alternative, setup_ident_frame, ident_dialog_update, display_frame_update, libbalsa_identity_new_config, libbalsa_identity_save): manage the option. * libbalsa/misc.h: new methods for html version. * libbalsa/mime.c: (libbalsa_html_encode_hyperlinks, libbalsa_text_to_html): implement them. * libbalsa/send.c: (add_mime_body_plain, libbalsa_message_create_mime_message, libbalsa_create_rfc2440_buffer): create multipart/alternative message with text/plain and text/html parts. * src/sendmsg-window.h: new member for html option. * src/sendmsg-window.c: (update_bsmsg_identity, sendmsg_window_new, sendmsg_window_continue, bsmsg2message, send_message_handler, message_postpone, toggle_mp_alt_cb): manage and act on the option. 2008-05-17 Peter Bloomfield * libbalsa/message.c: (libbalsa_message_load_envelope_from_stream): crlf-filter the stream; detect end-of-file by failed read instead of g_mime_stream_eos. 2008-04-29 Peter Bloomfield * src/sendmsg-window.c: (create_lang_menu): fix whining from Enchant via GtkSpell. 2008-04-28 Peter Bloomfield * src/sendmsg-window.c: use GTK_STOCK_EDIT for "Edit with Gnome". * src/toolbar-factory.c: add it to the legal toolbar buttons. 2008-04-28 Peter Bloomfield * src/balsa-index.c: (balsa_index_select_all): emit changed signal; (balsa_index_count_selected_messages): new method. * src/balsa-index.h: new method balsa_index_count_selected_messages. * src/main-window.c: use it to manage menu item sensitivity. * src/main-window.h: subdivide GtkActionGroups. 2008-04-25 Pawel Salek * libbalsa/mailbox_imap.c: create header even for empty parts. 2008-04-25 Albrecht Dreß * src/balsa-mime-widget-message.c: use URIs instead of paths. * src/sendmsg-window.[ch]: use gnome-vfs for attachment reading. * src/balsa-mime-widget-callbacks.c: ditto. * src/balsa-message.c: allow saving to URIs. * src/main.c: -o flag accepts an URI now. * src/information-dialog.h: add argument checking. * libbalsa/misc.[hc]: return more detailed error information. * libbalsa/body.h: store attachment URIs. * libbalsa/send.[ch]: handle errors when reading from URIs. * libbalsa/files.[ch]: file access operations use URIs now. * libbalsa/misc.c: move some functions to libbalsa-vfs.c * libbalsa/body.c: part operations accept URIs now. 2008-04-22 Pawel Salek * src/balsa-app.c: format=flowed by default. * libinit_balsa/assistant_page_user.[ch]: guess more stuff. * libinit_balsa/assistant_init.c: we have new code already, keep it silent. 2008-04-21 Peter Bloomfield * libbalsa/misc.h: if !USE_REGEX is enough. 2008-04-21 Peter Bloomfield * configure.in: implement --enable-gregex (default=no); change default for --enable-pcre to no. * libbalsa/filter-funcs.c: (libbalsa_condition_regex_free): condition on USE_REGEX. * libbalsa/filter-private.h: ditto. * libbalsa/mime.c: (mark_urls, libbalsa_insert_with_url, libbalsa_unwrap_selection): ditto. * libbalsa/misc.h: ditto. * src/balsa-app.c: ditto. * src/balsa-app.h: ditto. * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text): ditto. * src/balsa-print-object-text.c: (balsa_print_object_text_plain): ditto. * src/print.c: (print_wrap_body): ditto. * src/quote-color.c: (is_a_quote): ditto. * src/quote-color.h: ditto. * src/sendmsg-window.c: (reflow_selected_cb): ditto. * src/spell-check.c: (balsa_spell_check_start, balsa_spell_check_destroy, next_word): ditto. 2008-04-19 Peter Bloomfield * libbalsa/message.c: (lbmsg_set_header): scrap remaining warnings. 2008-04-12 Peter Bloomfield * libbalsa/mailbox_maildir.c: (lbm_maildir_parse_subdirs, libbalsa_mailbox_maildir_sync): make sure the tree is saved after reparsing subdirs. 2008-04-09 Pawel Salek * src/sendmsg-window.c: make postpone button and menu entry work. * libbalsa/message.c: do not complain when setting headers->from again. * libbalsa/imap/imap-handle.[ch]: make set_timeout() return the old value. * libbalsa/imap/imap_private.h: add HANDLE_TRYLOCK macro. * libbalsa/imap/imap-commands.c: use it for noop(). 2008-04-06 Pawel Salek * libbalsa/imap/imap-handle.h: fix that macro. 2008-04-06 Pawel Salek * libbalsa/mailbox_imap.c: initalise ImapSequence data. * libbalsa/imap/imap-handle.h: provide a macro for that purpose. 2008-04-03 Pawel Salek * libbalsa/mailbox_imap.c: don't print warnings on copy when UIDPLUS is unavailable. Better code reuse. * libbalsa/message.c: don't modify invariants. 2008-04-02 Ildar Mulyukov * src/sendmsg-window.c: Some RU/KZ locales fixes. 2008-04-01 Pawel Salek * libbalsa/mailbox_imap.c: use UIDPLUS information returned by server to improve caching. * libbalsa/imap/imap-handle.[ch]: parse returned UIDPLUS data. * libbalsa/imap/imap_private.h: add ImapMboxHandle::uidplus field. * libbalsa/imap/imap-commands.[ch]: add API for accessing UIDPLUS data. 2008-03-31 Pawel Salek * src/spell-check.h: remove lingering reference to pspell.h * balsa.spec.in: update to modern standards. 2008-03-30 Peter Bloomfield * src/filter-edit-callbacks.c: (fill_condition_widgets): fix a critical warning. 2008-03-29 Jean-Luc Coulon * doc/C/balsa.xml: fix typos. 2008-03-26 Peter Bloomfield * src/balsa-message.c: (add_toggle_inline_menu_item): clear force-inline when we create a new check-box. 2008-03-25 Pawel Salek * src/balsa-index.c: pass "peek" parameter to get_message_stream(). * libbalsa/{message,source-viewer}.c: ditto. * libbalsa/mailbox.[ch]: get_message_stream() has "peek" parameter now. * libbalsa/mailbox_{mh,mbox,maildir}.c: make related trivial changes. * libbalsa/mailbox_imap.c: pass "peek" further to save one RTT. 2008-03-20 Peter Bloomfield * src/balsa-message.c: (bm_find_again): actually show "Wrapped". 2008-03-20 Pawel Salek * libbalsa/imap/imap_search.[ch]: make it easier to explicitly select message sets for searching. * libbalsa/imap/imap-handle.c: put coalesce routines back here. * libbalsa/imap/imap-handle.h: move search functions to imap_search.h * libbalsa/imap/imap_private.h: declare coalesce routines here. * libbalsa/imap/imap-commands.c: remove coalesce routines. 2008-03-20 Peter Bloomfield * libbalsa/misc.{c,h}: (libbalsa_path_is_below_dir): careful check for a file being below a directory. * src/mailbox-conf.c: (mailbox_conf_add): use it. * src/mailbox-node.c: (check_local_path): ditto. * src/save-restore.c: (config_mailbox_set_as_special): ditto. * src/sendmsg-window.c: (render_attach_size): use g_format_size_for_display. * libinit_balsa/assistant_page_directory.c: (balsa_druid_page_directory_prepare): use g_build_filename. 2008-03-20 Pawel Salek * src/main-window.c: Fix a runtime warning. * configure.in, NEWS: release 2.3.23 * doc/C/balsa.xml: document Face and X-Face headers. 2008-03-19 Albrecht Dreß * doc/C/balsa.xml: document crypto in help file for composer and identities dialogs. 2008-03-16 Pawel Salek * src/balsa-mime-widget-text.c: plug a leak if gtkhtml disabled. * libbalsa/mailbox_mbox.c: release all resources before disposing the mailbox. * libbalsa/message.c (lbmsg_set_header): plug a leak. 2008-03-11 Peter Bloomfield * libbalsa/mime.c: (mark_urls, libbalsa_insert_with_url): plug leaks, and clean up conditional code. 2008-03-09 Pawel Salek * src/ab-main.c: trying out alternative address book layout. * libbalsa/{address,address-book-ldif}.c: plug some memory leaks. 2008-03-09 Albrecht Dreß * libbalsa/rfc3156.c: (gpg_keyserver_op, check_gpg_child): add "refresh" as an alternative action to "import". * libbalsa/rfc3156.h: add gpg_keyserver_action_t enum for actions. * src/balsa-mime-widget-crypto.c: (balsa_mime_widget_signature_widget, on_gpg_key_button): implement "refresh" button. 2008-03-03 Pawel Salek * libbalsa/mailbox_imap.c: peek only into mailboxes, do no trigger implicit \seen flag toggling. * libbalsa/imap/imap-handle.c: recognize BODY[TEXT]. * libbalsa/imap/imap-commands.[ch]: add peek argument. 2008-03-03 Peter Bloomfield * libbalsa/mailbox.c: (libbalsa_mailbox_messages_change_flags): do not crash when mindex == NULL. 2008-03-02 Peter Bloomfield * src/balsa-index.c: (bndx_instance_init): remember selection-changed signal handler id. (balsa_index_select_all): select all messages without previewing any. * src/balsa-index.h: new member and method. * src/main-window.c: use balsa_index_select_all. 2008-02-27 Peter Bloomfield * libbalsa/mailbox.c: (libbalsa_mailbox_set_view_filter): remember if the view needs to be updated. * libbalsa/mailbox.h: new member. 2008-02-27 Peter Bloomfield * libbalsa/mailbox.c: (libbalsa_mailbox_changed): allow for default count (== -1). * libbalsa/mailbox_imap.c: (lbm_imap_check): get UNREAD count instead of RECENT. * src/balsa-mblist.c: (bmbl_sort_idle, balsa_mblist_mailbox_node_append): inhibit sorting while building the tree, to avoid quadratic cost; prepend to tree instead of appending, for the same reason. * src/balsa-mblist.h: new members for sorting. * src/mailbox-node.c: (add_local_mailbox): respect subscribe-for-new-mail setting. * src/sendmsg-window.c: (update_bsmsg_identity): hide reply-to widget if we showed it temporarily. 2008-02-24 Peter Bloomfield * src/balsa-index.c: (bndx_popup_position_func, bndx_do_popup): add a popup-position func. 2008-02-24 Peter Bloomfield * libbalsa/imap/imap-handle.c: (ir_fetch_seq): compile with gcc-4.3. * src/main.c: (balsa_handle_automation_options): ditto. 2008-02-22 Peter Bloomfield * src/filter-edit-callbacks.c: (fe_typesmenu_cb, condition_validate, clear_condition_widgets, fill_condition_widgets, build_type_notebook): do not offer regex filter. * src/save-restore.c: (view_by_url_prefix, save_view, config_view_remove): new public function to remove a mailbox-view. * src/save-restore.h: ditto. * src/mailbox-conf.c: (mailbox_conf_delete): remove filters and the view. 2008-02-18 Peter Bloomfield * libbalsa/filter-funcs.c: (libbalsa_condition_compare): check for equality. 2008-02-18 Peter Bloomfield * src/balsa-message.c: (bm_find_entry_changed_cb, bm_find_again): use GtkSourceIter's case-insensitive search capability, if available. 2008-02-17 Peter Bloomfield * libbalsa/filter-funcs.c: (libbalsa_condition_compare): allow NULL conditions. * libbalsa/mailbox.c: (libbalsa_mailbox_set_view_filter): update only if the new filter is a real change. 2008-02-17 Peter Bloomfield * src/message-window.c: (mw_find_in_message_cb): add UI for find-in-message. 2008-02-14 Peter Bloomfield * src/main-window.c: fix a comment. 2008-02-14 Peter Bloomfield * src/main-window.c: block the correct signal handler. 2008-02-10 Albrecht Dreß * libbalsa/rfc3156.[hc]: libbalsa_can_encrypt_for_all(). * libbalsa/identity.[ch]: remind if encryption is possible. * src/sendmsg-window.c: encourage encryption if possible. * configure.in: stop if gpgme-enabled build requested but gpgme-config not found (PS). 2008-02-09 Peter Bloomfield * src/balsa-message.c: (bm_find_scroll_to_iter): scroll least amount to get text on screen. 2008-02-09 Peter Bloomfield * src/balsa-mblist.c: (bmbl_select_mailbox): check that button-press event was on the correct window. 2008-02-08 Peter Bloomfield * src/balsa-message.c: (bm_find_again): clean up. 2008-02-08 Peter Bloomfield * src/balsa-message.c: (bm_find_set_status): new function, hides the separator using gtk_separator_tool_item_set_draw instead of gtk_widget_hide; (bm_find_entry_changed_cb, bm_find_again, balsa_message_find_in_message): use bm_find_set_status; (bm_disable_find_entry): boolean => void. 2008-02-08 Peter Bloomfield * libbalsa/libbalsa.c: (libbalsa_threads_leave): restore warning. * src/balsa-message.c: (bm_find_entry_changed_cb, bm_find_again, bm_pass_to_find_entry): do not hide separator, that triggers warnings; (balsa_message_find_in_message): find again only if found. 2008-02-08 Peter Bloomfield * src/balsa-message.c: (bm_find_entry_changed_cb, bm_find_again): do not mess with thread lock. 2008-02-08 Peter Bloomfield * src/balsa-message.c: (bm_pass_to_find_entry): test only SHIFT and CONTROL bits. 2008-02-07 Peter Bloomfield * libbalsa/libbalsa.c: (libbalsa_threads_leave): disable warning about dropping lock when not holding it--GtkTextView seems to trigger it. * src/balsa-message.c: (bm_scroll_to_iter, bm_find_entry_changed_cb, bm_find_again, bm_find_prev_cb, bm_find_next_cb, bm_find_bar_new, bm_pass_to_find_entry, bm_disable_find_entry, balsa_message_init, balsa_message_set, balsa_message_find_in_message): implement find-in-message. * src/balsa-message.h: api for find-in-message. * src/main-window.c: use it. 2008-01-09 Peter Bloomfield * libbalsa/libbalsa.h: add width and height to api for libbalsa_show_message_source. * libbalsa/source-viewer.c: (lsv_size_allocate_cb): save width and height. (libbalsa_show_message_source): add width and height to api; change horizontal scroll policy to GTK_POLICY_AUTOMATIC. * src/balsa-app.h: add source viewer width and height. * src/balsa-index.c: (bndx_view_source): use new api. * src/main-window.c: ditto. * src/message-window.c: (view_msg_source_cb): ditto. * src/save-restore.c: (config_global_load, config_save): load and save source viewer width and height. 2008-01-02 Peter Bloomfield * src/spell-check.c: (balsa_spell_check_start): compile without GtkSpell. 2008-01-01 Peter Bloomfield * configure.in: if glib is 2.14+, we use GRegex, so do not configure PCRE. * libbalsa/filter-funcs.c: (libbalsa_condition_regex_free): use GRegex if available. * libbalsa/filter-private.h: ditto. * libbalsa/filter.c: ditto. * libbalsa/mime.c: (mark_urls, get_url_helper, get_url_reg, get_ml_url_reg, get_ml_flowed_url_reg): ditto. * libbalsa/misc.h: ditto. * src/balsa-app.c: (balsa_quote_regex_new): new function--if GRegex is available, compile the quote regex once, and return a ref. * src/balsa-app.h: balsa_quote_regex_new is new. * src/balsa-message.c: use balsa_quote_regex_new. * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text): ditto. * src/balsa-print-object-text.c: (balsa_print_object_text_plain): ditto. * src/print.c: (print_wrap_body): ditto. * src/quote-color.c: (is_a_quote): use GRegex if available. * src/quote-color.h: ditto. * src/sendmsg-window.c: (reflow_selected_cb): use balsa_quote_regex_new. * src/spell-check.c: (balsa_spell_check_start): use balsa_quote_regex_new. (balsa_spell_check_destroy, next_word): use GRegex if available. 2008-01-01 Peter Bloomfield * configure.in: configuring GtkSourceView when version is not specified, try GtkSourceView2 then GtkSourceView1. 2008-01-01 Albrecht Dreß * Makefile.am: support GtkSourceView2. * configure.in: ditto. * libbalsa/libbalsa.c: (libbalsa_source_view_new): ditto. * src/balsa-mime-widget-text.c: (create_text_widget): ditto. * src/sendmsg-window.c: (sw_can_redo_cb, sw_can_undo_cb, create_text_area): ditto. * balsa-mail-style.xml: new file for GtkSourceView2. * balsa-mail.lang: ditto. balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/ChangeLog-2004-2007000066400000000000000000004121531477646064400231530ustar00rootroot000000000000002007-12-31 Peter Bloomfield * src/mailbox-node.c: (mark_local_path): change from void to gboolean, with FALSE indicating that node->scanned is already set. * libbalsa/folder-scanners.c: (libbalsa_scanner_mdir, libbalsa_scanner_local_dir_helper): use return value. * libbalsa/folder-scanners.h: new definition of LocalMark. 2007-12-30 Pawel Salek * libbalsa/mailbox.h: add ability to add multiple messages at once: replace add_message with add_messages. * libbalsa/mailbox.c: libbalsa_mailbox_add_message uses add_messages handler now. * libbalsa/mailbox_{mh,maildir,mbox}.c: simple implementations. * libbalsa/mailbox_imap.c: MULTIAPPEND-aware add_messages. * libbalsa/imap/imap_tst.c: add anonymous authentication support. * libbalsa/imap/imap-commands.c: add handle locking around imap_mbox_append_multi() and transaction size limits. 2007-12-27 Pawel Salek * libbalsa/mailbox_imap.c: buflen is of size_t type. * libbalsa/imap/imap-handle.[hc]: register MULTIAPPEND extension * libbalsa/imap/imap-commands.[hc]: add MULTIAPPEND aware interface. * libbalsa/imap/imap_tst.c: test it. 2007-12-25 Pawel Salek * NEWS, configure.in: release balsa-2.3.22. 2007-12-24 Peter Bloomfield * libbalsa/address-view.c: (lbav_selection_changed_cb): compile with gtk pre-2.12. 2007-12-23 Peter Bloomfield * libbalsa/address-view.c: (lbav_selection_changed_cb, libbalsa_address_view_new): connect to selection's changed signal, to implement one-click close. * libbalsa/address-view.h: add members needed for one-click actions; remove deadwood. 2007-12-23 Albrecht Dreß * src/main-window.c: show tray icon on mail arrival. 2007-12-22 Peter Bloomfield * src/sendmsg-window.c: (create_lang_menu): build without GtkSpell. 2007-12-21 Peter Bloomfield * src/sendmsg-window.c: (set_locale): restart spell checker when language is changed. 2007-12-21 Pawel Salek * src/main-window.c: remove duplicate shortcut. * src/sendmsg-window.c: Fix language switching (Peter B). * libbalsa/imap/imap-commands.c: Add a handle lock. 2007-12-18 Peter Bloomfield * libbalsa/filter.c: (libbalsa_condition_matches): new content2reply api. * libbalsa/mailbox_local.c: (message_match_real): ditto. * libbalsa/mime.c: (process_mime_part, process_mime_multipart, content2reply): remove charset callback. * libbalsa/mime.h: ditto. * src/balsa-app.c: (balsa_app_init): new member BalsaApp::spell_check_active; make spell modules conditional. * src/balsa-app.h: * src/save-restore.c: (config_global_load, config_save): manage BalsaApp::spell_check_active. * src/sendmsg-window.c: simplify charset and spell-checker handling. * src/sendmsg-window.h: remove newly redundant members in BalsaSendmsg. 2007-12-16 Pawel Salek * src/balsa-index.c: check in idle functions whether the model still exists. * src/sendmsg-window.c: do not go beyond the end of the string. 2007-12-16 Peter Bloomfield * src/main-window.c: (bw_notebook_label_new): use gtk_widget_set_size_request for the button instead of a signal callback. 2007-12-14 Peter Bloomfield * src/main-window.c: (bw_notebook_label_new): drop redundant event box. * libbalsa/imap/imap-handle.c: (imap_get_address): unfold address string. * libbalsa/mailbox_imap.c: (get_struct_from_cache): crlf-filter the message. 2007-12-13 Peter Bloomfield * libbalsa/mailbox_imap.c: (internet_address_new_from_imap_address, internet_address_new_list_from_imap_address_list): handle RFC 2822 groups. 2007-12-13 Albrecht Dreß * libbalsa/imap/imap-handle.c: (imap_envelope_from_stringi): compile fix. 2007-12-13 Peter Bloomfield * images/16x16/balsa-drop-down.png: new icon, used to signify that the list of recipient types in address-view is a drop-down list. * libbalsa/address-view.c: (libbalsa_address_view_finalize, lbav_ensure_blank_line, lbav_add_from_list, lbav_button_activated_cb, libbalsa_address_view_new, libbalsa_address_view_set_book_icon, libbalsa_address_view_set_close_icon, libbalsa_address_view_set_drop_down_icon): use pixbuf instead of stock-id; use the new icon. * libbalsa/address-view.h: change to pixbuf instead of stock-id. * libbalsa/cell-renderer-button.c: fix documentation. * src/balsa-icons.c: (register_balsa_pixmaps, register_balsa_pixbufs): define and register new icon. * src/balsa-icons.h: ditto. * src/sendmsg-window.c: (create_email_entry): new api for address-view. 2007-12-11 Peter Bloomfield * src/sendmsg-window.c: (sendmsg_window_compose, sw_grab_focus_to_text, sendmsg_window_reply, sendmsg_window_reply_embedded, sendmsg_window_forward, sendmsg_window_continue): grab focus to the message body when replying. 2007-12-11 Jens Granseuer * libbalsa/identity.c: (add_show_menu, ident_dialog_free_values, ident_dialog_get_value): build without ESMTP and GPG/SMIME. 2007-12-10 Peter Bloomfield merge balsa-address-view branch * libbalsa/Makefile.am: * libbalsa/address-entry.c: * libbalsa/address-entry.h: * src/ab-window.c: * src/main.c: * src/save-restore.c: * src/sendmsg-window.c: * src/sendmsg-window.h: 2007-12-08 Peter Bloomfield * libbalsa/libbalsa.c: add pointer libbalsa_progress_set_activity so that libbalsa functions can show activity in the progress bar (currently unused, but it's there when we need it!). * libbalsa/libbalsa.h: ditto; use separate constants for minimum fraction and minimum elapsed time when updating progress bar (Albrecht Dreß). * libbalsa/mailbox.c: (libbalsa_mailbox_msgno_find, lbm_set_threading): check that msg_tree exists. * src/balsa-index.c: (balsa_index_ensure_visible): check that tree_view is realized. * src/balsa-mblist.c: (bmbl_mailbox_changed_cb): no need to grab GDK lock. * src/main-window.c: make sure that increment mode takes precedence over activity mode; use new members in BalsaWindow to avoid using g_object_{set,get}_data. * src/main-window.h: add members to BalsaWindow to avoid using g_object_{set,get}_data; export balsa_window_{increase,decrease}_activity. * src/main.c: (balsa_progress_set_text, balsa_progress_set_fraction, balsa_progress_set_activity, main): use separate constants for minimum fraction and minimum elapsed time when updating progress bar (Albrecht Dreß); initialize libbalsa_progress_set_activity. 2007-12-08 Pawel Salek * balsa.desktop.in: fix bug 414361 in bugzilla.redhat.com. * NEWS, configure.in: release 2.3.21. 2007-12-08 Pawel Salek * src/{main,sendmsg}-window.c...: format string bug fixes (bug 488432, Evil Ninja Squirrel). 2007-12-05 Peter Bloomfield * libbalsa/mailbox.c: (libbalsa_mailbox_changed): hold gdk lock while emitting "changed" signal; (libbalsa_mailbox_msgno_changed, libbalsa_mailbox_msgno_filt_in, libbalsa_mailbox_msgno_removed, libbalsa_mailbox_msgno_filt_out): eliminate obsolete lbm_threads_{enter,leave}. 2007-11-27 Peter Bloomfield Thanks to Nuno Monteiro * src/sendmsg-window.c: (toolbar_send_message_cb): new action for toolbar send/queue button. * src/toolbar-factory.c: correct toolbar button labels. 2007-11-26 Albrecht Dreß * libbalsa/address-view.c: (lbav_focus_out_cb, lbav_row_editing_cb): on focus-out, accept a unique match. 2007-11-17 Peter Bloomfield * src/save-restore.c: * src/balsa-app.c: * src/balsa-app.h: add fields to save/restore maximized state of windows. * src/main-window.c: * src/message-window.c: * src/sendmsg-window.c: use them. 2007-11-16 Peter Bloomfield * libbalsa/address-view.c: (lbav_clean_text): new helper to remove control characters from text. (lbav_add_from_list, lbav_set_text_at_path): use it. 2007-11-13 Peter Bloomfield Bug #496316: Send/Queue button has inconsistent labeling. * src/toolbar-factory.h: new function balsa_toolbar_button_text. * src/toolbar-factory.c: (balsa_toolbar_button_text, tm_has_second_line, tm_set_tool_item_label): implement and use it. * src/toolbar-prefs.c: (tp_store_set): use it. 2007-11-10 Peter Bloomfield * src/balsa-message.c: (balsa_get_parent_window): use gtk_widget_get_toplevel. 2007-11-07 Peter Bloomfield * src/balsa-app.c: * src/balsa-app.h: * src/main-window.c: * src/message-window.c: * src/save-restore.c: * src/sendmsg-window.c: revert previous unintentional commit of changes in src/. 2007-11-07 Peter Bloomfield * libbalsa/address-view.c: (lbav_set_text_at_path), (lbav_combo_edited_cb), (lbav_row_editing_cb), (lbav_button_activated_cb), (libbalsa_address_view_add_to_row): check validity of iter. 2007-11-03 Peter Bloomfield * libbalsa/address-view.c: * libbalsa/address-view.h: do not copy strings. * src/sendmsg-window.c: mark strings for translation. 2007-11-03 Peter Bloomfield * libbalsa/address-view.c: * src/sendmsg-window.c: simplify LibBalsaAddressView api. * src/main.c: (main): libbalsa_address_book_list has gone away. 2007-11-03 Peter Bloomfield * libbalsa/address-view.c: (libbalsa_address_view_finalize): do not leak GtkTreeRowReference; (lbav_append_addresses), (lbav_ensure_blank_line_idle_cb), (lbav_ensure_blank_line), (lbav_row_editing_cb), (libbalsa_address_view_new): remove debugging output. 2007-10-31 Peter Bloomfield * src/main-window.c: connect to "activate" signal instead of "changed", to see every click on threading options. 2007-10-30 Peter Bloomfield * libbalsa/address-view.c: * libbalsa/address-view.h: * src/save-restore.c: * src/sendmsg-window.c: * src/sendmsg-window.h: use a separate widget for Reply-To. 2007-10-27 Peter Bloomfield * libbalsa/address-view.c: localize address types; check address types. 2007-10-26 Peter Bloomfield * libbalsa/address-view.c: (lbav_sort_func): make sort-func reflexive; (libbalsa_address_view_new): more debug info. 2007-10-26 Peter Bloomfield * libbalsa/address-view.c: make blank line sort below addresses of the same type; try to have only one blank line. 2007-10-25 Peter Bloomfield * libbalsa/cell-renderer-button.c: * libbalsa/cell-renderer-button.h: forgot to add these for initial commit. 2007-10-25 Peter Bloomfield * libbalsa/Makefile.am: * libbalsa/address-entry.c: * libbalsa/address-entry.h: * libbalsa/address-view.c: * libbalsa/address-view.h: * src/ab-window.c: * src/main.c: * src/save-restore.c: * src/sendmsg-window.c: * src/sendmsg-window.h: initial commit on address-view branch. 2007-10-24 Albrecht Dreß * src/balsa-icons.c: * src/balsa-message.c: * src/balsa-print-object-text.c: More balsa Tangofication. 2007-10-23 Albrecht Dreß * configure.in: * libbalsa/Makefile.am: * libbalsa/address-book-rubrica.c: * libbalsa/address-book-rubrica.h: * libbalsa/libbalsa.c: * libbalsa/libbalsa.h: * src/ab-main.c: * src/ab-window.c: * src/address-book-config.c: * src/main.c: * src/pref-manager.c: add support for Rubrica address book. 2007-10-17 Peter Bloomfield * libbalsa/mailbox_maildir.c: skip check only if mtime matches exactly. * src/balsa-index.c: revert to scrolling in an idle callback, but now at low priority. 2007-10-15 Peter Bloomfield * libbalsa/mailbox_local.c: clarify simple and flat threading. 2007-10-14 Peter Bloomfield * libbalsa/mailbox.c: (lbm_get_view): do not assert url is not in hash table; (lbm_sort): set msg-tree-changed; (libbalsa_mailbox_unlink_and_prepend): set msg-tree-changed only if we are sure it was. * libbalsa/mailbox_local.c: (lbm_local_update_view_filter): set msg-tree-changed only if it is a flags-only filter; fix bug saving and restoring simple threading. * src/main-window.c: avoid critical warning if Balsa is closed during a threading. 2007-10-10 Peter Bloomfield * libbalsa/Makefile.am: * libbalsa/address-book-extern.c: * libbalsa/address-book-ldap.c: * libbalsa/address-book-ldif.c: * libbalsa/address-book-text.c: * libbalsa/address-book-vcard.c: * libbalsa/address-book.c: * libbalsa/address.c: * libbalsa/body.c: * libbalsa/files.c: * libbalsa/filter-error.c: * libbalsa/filter-file.c: * libbalsa/filter.c: * libbalsa/gmime-application-pkcs7.c: * libbalsa/gmime-gpgme-context.c: * libbalsa/i18n.h: * libbalsa/identity.c: * libbalsa/imap-server.c: * libbalsa/libbalsa-conf.c: * libbalsa/libbalsa.c: * libbalsa/mailbox-filter.c: * libbalsa/mailbox.c: * libbalsa/mailbox_imap.c: * libbalsa/mailbox_local.c: * libbalsa/mailbox_maildir.c: * libbalsa/mailbox_mbox.c: * libbalsa/mailbox_mh.c: * libbalsa/mailbox_pop3.c: * libbalsa/message.c: * libbalsa/mime.c: * libbalsa/misc.c: * libbalsa/rfc3156.c: * libbalsa/send.c: * libbalsa/server.c: * libbalsa/smtp-server.c: * libbalsa/source-viewer.c: * libinit_balsa/assistant_helper.c: * libinit_balsa/assistant_init.c: * libinit_balsa/assistant_page_defclient.c: * libinit_balsa/assistant_page_directory.c: * libinit_balsa/assistant_page_finish.c: * libinit_balsa/assistant_page_user.c: * libinit_balsa/assistant_page_welcome.c: * libinit_balsa/balsa-druid-page-defclient.c: * libinit_balsa/balsa-druid-page-directory.c: * libinit_balsa/balsa-druid-page-finish.c: * libinit_balsa/balsa-druid-page-user.c: * libinit_balsa/balsa-druid-page-welcome.c: * libinit_balsa/balsa-initdruid.c: * libinit_balsa/helper.c: * libinit_balsa/init_balsa.c: * src/ab-main.c: * src/ab-window.c: * src/address-book-config.c: * src/balsa-app.c: * src/balsa-index.c: * src/balsa-mblist.c: * src/balsa-message.c: * src/balsa-mime-widget-callbacks.c: * src/balsa-mime-widget-crypto.c: * src/balsa-mime-widget-image.c: * src/balsa-mime-widget-message.c: * src/balsa-mime-widget-multipart.c: * src/balsa-mime-widget-text.c: * src/balsa-mime-widget.c: * src/balsa-print-object-default.c: * src/balsa-print-object-header.c: * src/balsa-print-object-text.c: * src/filter-edit-callbacks.c: * src/filter-edit-dialog.c: * src/filter-export-callbacks.c: * src/filter-export-dialog.c: * src/filter-run-callbacks.c: * src/filter-run-dialog.c: * src/folder-conf.c: * src/information-dialog.c: * src/mailbox-conf.c: * src/mailbox-node.c: * src/main-window.c: * src/main.c: * src/message-window.c: * src/pref-manager.c: * src/print-gtk.c: * src/print.c: * src/save-restore.c: * src/sendmsg-window.c: * src/spell-check.c: * src/store-address.c: * src/toolbar-factory.c: * src/toolbar-prefs.c: include instead of "libbalsa/i18n.h". 2007-10-10 Peter Bloomfield * libbalsa/server.h: include libbalsa.h (bug 477580, Jens Granseuer). 2007-10-10 Peter Bloomfield * src/main-window.c: hide resize grip when window is maximized. * src/sendmsg-window.c: (calculate_expander_toggles): drop unused variable (Albrecht Dreß); (tree_find_single_part), (collect_for_quote): search deeper for a single text part (Albrecht Dreß). 2007-10-09 Peter Bloomfield * src/balsa-index.c: restore 'N' and 'P' actions. * src/main-window.c: use consistent "bw_" prefix on local functions to aid debugging. 2007-10-09 Peter Bloomfield * libbalsa/mailbox.c: (mbox_model_iter_n_children): return 0 if iter is NULL and mailbox has no msg_tree. * src/balsa-index.c: (bndx_scroll_to_row), (balsa_index_scroll_on_open): do not use idle callback; (balsa_index_ensure_visible): typo? 2007-10-09 Peter Bloomfield * src/balsa-index.c: (bndx_selection_changed_real), (bndx_mailbox_changed_func), (bndx_mailbox_changed_cb): when a message is deleted, select next message to be displayed in the signal handler instead of the idle callback. 2007-10-07 Peter Bloomfield * libbalsa/send.c: (msg_queue_item_new), (add_recipients), (lbs_list_has_one_address), (lbs_process_queue), (handle_successful_send): create separate bcc-message only if it has exactly one recipient; really leave message in outbox if any address, including bcc addresses, has an error. 2007-10-05 Peter Bloomfield * src/balsa-index.c: (bndx_selection_changed_real): do not show next message if msgno is no longer in the tree. 2007-10-04 Peter Bloomfield * src/main-window.c: restore enable_mailbox_menus() to index_changed_cb()--removed by mistake a few commits ago. 2007-10-03 Peter Bloomfield * src/main-window.c: use an enum instead of a string to distinguish toolbar types. * src/message-window.c: (mw_get_toolbar_model): ditto. * src/sendmsg-window.c: (sw_get_toolbar_model): ditto. * src/toolbar-factory.c: (tm_load_model), (tm_save_model), (balsa_toolbar_model_new), (tm_do_popup_menu): ditto. * src/toolbar-factory.h: ditto. * src/toolbar-prefs.c: (customize_dialog_cb): ditto. * src/toolbar-prefs.h: ditto. 2007-10-02 Pawel Salek * src/mailbox-node.c, libbalsa/{mailbox_imap,server}.c: remove debug output. * libbalsa/mailbox.c: compile against older glib. * src/sendmsg-window.c: fix bug 481842 (Stephane Raimbault). 2007-10-02 Peter Bloomfield * src/toolbar-factory.c: (tm_do_popup_menu): show the appropriate page of the toolbar editor. * src/toolbar-prefs.c: (customize_dialog_cb): ditto. * src/toolbar-prefs.h: ditto. 2007-10-01 Peter Bloomfield * libbalsa/message.c: (libbalsa_message_header_get_helper), (lb_message_set_headers_from_string): match headers exactly. * src/balsa-message.c: (balsa_message_set_displayed_headers): check whether this is an actual change. * src/main-window.c: connect to "activate" signal instead of "changed", to see every click. * src/message-window.c: (mw_get_ui_manager), (message_window_new), (mw_header_activate_cb), (reset_show_all_headers): ditto. 2007-09-30 Peter Bloomfield * src/main-window.c: clean up. 2007-09-30 Peter Bloomfield * src/main-window.c: block only some actions. * src/message-window.c: (mw_set_active), (message_window_new), (reset_show_all_headers): ditto. * src/sendmsg-window.c: block no actions--just document it. 2007-09-30 Peter Bloomfield * libbalsa/mailbox.c: (lbm_get_index_entry): check for NULL message returned by libbalsa_mailbox_get_message(). * libbalsa/mailbox_local.c: (message_match_real): ditto. * libbalsa/send.c: (lbs_process_queue), (libbalsa_process_queue): ditto. * src/balsa-index.c: (bndx_view_source), (balsa_index_selected_list_func): ditto. * src/balsa-message.c: (balsa_message_set): ditto. * src/main-window.c: ditto. * src/message-window.c: (mw_set_selected): ditto; (shown_hdrs_radio_cb): fix typo. * src/sendmsg-window.c: (attachments_add), (drag_data_quote), (sendmsg_window_new_from_list): ditto. 2007-09-29 Peter Bloomfield * src/main-window.c: block actions while we set active. 2007-09-29 Peter Bloomfield * src/balsa-index.c: (balsa_index_load_mailbox_node): set threading in main-window instead of balsa-index. * src/main-window.c: ditto. 2007-09-29 Peter Bloomfield * src/balsa-index.c: (balsa_index_load_mailbox_node): balsa_window_get_view_filter is no longer exported; (bndx_do_popup): BalsaIndex::window no longer exists. * src/balsa-index.h: remove BalsaIndex::window. * src/main-window.c: do not export balsa_window_get_view_filter. * src/main-window.h: ditto. 2007-09-27 Peter Bloomfield * src/main-window.c: do not export enable_mailbox_menus. * src/main-window.h: ditto. * src/balsa-index.c: (balsa_index_load_mailbox_node): enable_mailbox_menus is no longer exported. 2007-09-27 Peter Bloomfield * doc/C/balsa.xml: fix identity-dialog and toolbar-editor documentation. * libbalsa/identity.c: (append_ident_notebook_page), (setup_ident_frame), (display_frame_set_gpg_mode): show Security page even when GnuPG isn't supported, but grayed out and with an explanatory label. * libbalsa/libbalsa.h: update progress bar after a set time, not a set fraction of the work. * src/main.c: (balsa_progress_set_text), (balsa_progress_set_fraction): ditto. 2007-09-25 Peter Bloomfield * src/toolbar-factory.c: (menu_item_toggled_cb), (tm_popup_idle_cb), (tm_popup_deactivated_cb), (tm_remove_underscore), (tm_popup_position_func), (tm_do_popup_menu), (tm_button_press_cb), (tm_popup_menu_cb), (balsa_toolbar_new): add a popup-position func; clean up. 2007-09-25 Peter Bloomfield * src/toolbar-factory.c: (tm_load_model), (tm_save_model), (tm_gconf_notify), (balsa_toolbar_model_new), (tm_default_style), (tm_set_style), (tm_changed_cb), (do_popup_menu), (balsa_toolbar_new): catch changes in desktop toolbar style. 2007-09-24 Peter Bloomfield * src/toolbar-factory.c: (tm_default_toolbar_style), (tm_load_model), (tm_save_model), (do_popup_menu), (tm_popup_menu_cb), (balsa_toolbar_new): use desktop toolbar style as default. 2007-09-24 Peter Bloomfield * src/toolbar-factory.c: (remove_underscore), (do_popup_menu): respect desktop toolbar style. 2007-09-24 Peter Bloomfield * libbalsa/mailbox_mbox.c: (libbalsa_mailbox_mbox_close_mailbox): keep stream open longer. * src/toolbar-prefs.c: (style_button_cb): emit signal correctly. 2007-09-23 Peter Bloomfield * src/toolbar-factory.c: (tm_save_model): remove old toolbar config before saving new one. 2007-09-23 Peter Bloomfield * libbalsa/identity.c: use GTK_RESPONSE_HELP, so that the "Help" button is created correctly. 2007-09-23 Peter Bloomfield * src/main-window.c: add tooltip for "Quit". * src/toolbar-factory.c: (do_popup_menu): allow "Quit" to be a toolbar button; use gtk_menu_attach_to_widget only if it allows a NULL detacher; add "Customize Toolbars..." item. 2007-09-22 Peter Bloomfield * src/main-window.c: make a stack of "opening mailbox..." messages; new toolbar api. * src/message-window.c: (mw_get_toolbar_model): new toolbar api. * src/save-restore.c: (save_toolbars), (load_toolbars): move toolbar save and load to toolbar-factory.c. * src/sendmsg-window.c: (sw_get_toolbar_model): new toolbar api. * src/toolbar-factory.c: create a popup menu for toolbar. * src/toolbar-factory.h: new toolbar api. * src/toolbar-prefs.c: (style_button_cb), (create_toolbar_page): add a button to popup toolbar style menu. 2007-09-21 Peter Bloomfield * src/ab-main.c: (bab_window_new): migrate from GnomeApp. * src/balsa-app.h: ditto. * src/balsa-index.c: (balsa_index_load_mailbox_node): handle status messages in main-window. * src/balsa-mblist.c: (balsa_mblist_set_status_bar): migrate from GnomeApp. * src/balsa-mime-widget-text.c: (statusbar_pop), (handle_url), (balsa_gtk_html_on_url): ditto. * src/information-dialog.c: (balsa_information_list), (status_bar_refresh), (balsa_information_bar): ditto. * src/mailbox-node.c: (imap_dir_cb): ditto. * src/main-window.c: ditto. * src/main-window.h: ditto. * src/main.c: (threads_init): pass balsa_app.main_window as user data. * src/message-window.c: (message_window_new): migrate from GnomeApp. * src/pref-manager.c: (open_preferences_manager), (set_prefs): ditto. * src/sendmsg-window.c: (sendmsg_window_new): ditto. * src/toolbar-prefs.c: (customize_dialog_cb): ditto. 2007-09-18 Peter Bloomfield * src/balsa-index.c: (bndx_view_source), (bndx_store_address), (bi_toggle_deleted_cb), (bi_toggle_flagged_cb), (bi_toggle_new_cb), (bndx_popup_menu_create), (create_stock_menu_item): connect signals swapped, to match new handler api. 2007-09-18 Peter Bloomfield * libbalsa/mailbox.c: scrap libbalsa_mailbox_register_msgno. * libbalsa/mailbox.h: ditto. * src/balsa-index.c: (bndx_mailbox_message_expunged_cb), (balsa_index_load_mailbox_node): change BalsaIndex::{current,next}_msgno if necessary when a message is expunged. 2007-09-16 Peter Bloomfield * src/sendmsg-window.c: allow the letter 'q' in messages, by restoring ctrl+Q accelerator for "Queue" (thank you, Jean-Luc); restore Sign and Encrypt toolbar buttons (thank you, Albrecht). 2007-09-15 Peter Bloomfield * libbalsa/source-viewer.c: mark more strings for translation. * src/ab-main.c: ditto. * src/toolbar-factory.c: (tm_add_action), (balsa_toolbar_model_add_actions), (balsa_toolbar_model_add_toggle_actions), (tm_populate): tooltips are set by the ui-manager. 2007-09-15 Peter Bloomfield * libbalsa/source-viewer.c: (lbsv_app_set_menus): set translation domain to NULL to enable translation. * src/ab-main.c: (get_main_menu): ditto * src/main-window.c: ditto. * src/message-window.c: (mw_get_ui_manager): ditto. * src/sendmsg-window.c: (sw_get_ui_manager): ditto. 2007-09-15 Peter Bloomfield * src/main-window.c: two more missed translations. 2007-09-15 Peter Bloomfield * src/main-window.c: translate main menu. * src/message-window.c: ditto. * src/sendmsg-window.c: ditto. 2007-09-15 Peter Bloomfield * src/main-window.c: * src/main-window.h: * src/message-window.c: (message_window_new): build --without-gtkhtml. * src/sendmsg-window.c: (sendmsg_window_new): * src/toolbar-factory.c: (tm_changed_cb), (tm_toolbar_weak_notify), (balsa_toolbar_new): * src/toolbar-prefs.c: (customize_dialog_cb): clean up ui-manager object-ref management. 2007-09-14 Peter Bloomfield * src/main-window.c: * src/message-window.c: * src/sendmsg-window.c: * src/toolbar-factory.c: * src/toolbar-factory.h: * src/toolbar-prefs.c: move toolbar-model's "changed" signal handling to toolbar-factory.c. 2007-09-14 Peter Bloomfield * doc/C/balsa.xml: toolbar editing is now really instant-apply. * libbalsa/rfc3156.c: build (--without-ssl ?). * src/ab-window.c: * src/balsa-app.c: * src/balsa-bonobo.c: * src/balsa-index.c: * src/balsa-index.h: * src/balsa-mime-widget-message.c: * src/balsa-mime-widget-text.c: drop GtkWidget from argument list. * src/main.c: GtkAccelMap is now in ~/.balsa/accelmap. * src/pref-manager.c: (apply_prefs): new toolbar api. * src/save-restore.c: (config_global_load): notify user about changes. * src/main-window.c: * src/main-window.h: * src/message-window.c: * src/message-window.h: * src/sendmsg-window.c: * src/sendmsg-window.h: * src/toolbar-factory.c: * src/toolbar-factory.h: * src/toolbar-prefs.c: migrate from GnomeUI to GtkUIManager. 2007-09-08 Albrecht Dreß * src/sendmsg-window.c: allow the user to select message parts to be quoted in the response. 2007-09-07 Pawel Salek * libbalsa/imap/imap-handle.c: fix buffer overflow (#474366, credit goes to Evil Ninja Squirrel). * NEWS, configure.in: release 2.3.20. 2007-09-06 Pawel Salek * libbalsa/mailbox_imap.c: handle expunge race. 2007-09-04 Peter Bloomfield * src/main-window.c: (balsa_window_enable_mailbox_menus), (balsa_window_update_book_menus), (enable_message_menus): manage sensitivity of store-address menu item in touch-pad version. 2007-09-03 Peter Bloomfield * libinit_balsa/assistant_helper.c: (balsa_init_add_table_entry): build with --enable-touch-ui. * libinit_balsa/assistant_helper.h: ditto. * src/main-window.c: (bw_enable_next_unread), (balsa_window_new), (enable_expand_collapse), (balsa_window_enable_mailbox_menus), (balsa_window_update_book_menus), (enable_message_menus), (balsa_window_set_threading_menu), (show_about_box), (show_all_headers_cb), (threading_change_cb), (zoom_cb): remove GtkAction code for now. * src/main-window.h: ditto. * src/sendmsg-window.c: (sendmsg_window_new): build with --enable-touch-ui. * src/spell-check.c: (balsa_spell_check_init): deprecation cleanup. 2007-08-31 Peter Bloomfield * src/main-window.c: (bw_enable_next_unread), (balsa_window_new), (enable_expand_collapse), (balsa_window_enable_mailbox_menus), (balsa_window_set_threading_menu), (contents_cb), (show_about_box), (shown_hdrs_radio_cb), (threading_radio_cb), (zoom_in_cb), (zoom_out_cb), (zoom_100_cb): incomplete port to GtkAction and friends (define USE_GNOMEUIINFO to TRUE in src/main-window.h to see how much work remains :() * src/main-window.h: ditto. 2007-08-27 Peter Bloomfield * libbalsa/send.c: (lbs_process_queue): skip message if it is either flagged or deleted--see http://mail.gnome.org/archives/balsa-list/2007-August/msg00018.html 2007-08-26 Albrecht Dreß * configure.in: s/mime is mature for gpg >= 2.0.4. * src/balsa-mblist.c: (bmbl_store_redraw_mbnode): newer icon sets distinguish between the "delete" (action) and the "trash can" (location) icons. 2007-08-25 Pawel Salek * libbalsa/imap/Makefile.am: disable building imap_tst. * src/balsa-message.[ch]: choose dialog's parent better. * NEWS, configure.in: release 2.3.19. 2007-08-23 Peter Bloomfield * src/toolbar-factory.c: gtk_tool_item_set_tooltip_text is since (2, 11, 6). 2007-08-23 Peter Bloomfield * src/balsa-app.c: (balsa_app_init): deprecation cleanup. * src/balsa-app.h: ditto. * src/balsa-index.c: (balsa_index_ensure_visible): ditto. * src/balsa-message.c: (bm_header_tl_buttons): ditto. * src/main-window.c: (balsa_notebook_label_new), (balsa_change_window_layout): ditto. * src/toolbar-factory.c: ditto. 2007-08-22 Pawel Salek * src/sendmsg-window.c: when (auto-)saving a message, do not bother the user asing questions about charsets. * src/balsa-mime-widget-callbacks.[hc]: parent properly "save part" dialog windows. * src/balsa-message.c: pass the parent. * libbalsa/libbalsa.c,libbalsa/{imap-,}server.c: timeout improvements. 2007-08-20 Pawel Salek * src/save-restore.c: show just one column for mailboxes by default. * src/balsa-app.c: squash a warning. * libinit_balsa/balsa-druid-page-directory.[ch]: finish the port to GtkAssistant. * libbalsa/imap/imap-commands.c: really add headers when BINARY extension is used. 2007-08-19 Pawel Salek * libinit_balsa/balsa-druid-page-{welcome,defclient,directory}.[hc]: * libinit_balsa/balsa-druid-page-{user,finish}.[hc]: * libinit_balsa/init_balsa.c: replace GnomeDruid with GtkAssistant. * libinit_balsa/{balsa-initdruid,helper}.{c,h}: ditto. 2007-08-10 Pawel Salek * libbalsa/mailbox_imap.c: encode cache file names more robustly. * libbalsa/imap/imap-search.c: disable UID ESEARCH for now since some interpretations make it useless. 2007-08-08 Pawel Salek * src/mailbox-conf.h: needs server.h * src/{save-restore,balsa-app}.c: ditto. * libinit_balsa/balsa-druid-page-{directory,user}.c: ditto. * libbalsa/send.c: do not disclose auth data. (PB) * libbalsa/imap-server.c: ditto. * libbalsa/{smtp-,}server.c: needs server.h * libbalsa/mailbox_imap.c: rework persistent caching. * libbalsa/libbalsa.c: disable IMAP timeouts for now - there is some deadlock condition. * libbalsa/mailbox_pop3.c: needs server.h * libbalsa/imap/imap-handle.c: serialize ImapBody, too. * libbalsa/imap/imap-commands.[ch]: imap_mbox_handle_fetch_rfc822() can fetch many messages at once now. 2007-08-06 Albrecht Dreß * libbalsa/mime.c: reflow improvements. * src/balsa-mime-widget-callbacks.c: programs require uris, not filenames. 2007-07-18 Albrecht Dreß * configure.in: safe gpg2 version detection. * src/main.c: ditto; initialize threads before using any glib functions (pb). 2007-07-15 Albrecht Dreß * src/balsa-print-object.c: (cairo_print_pixbuf): print icon colors correctly regardless of endianness. 2007-07-04 Pawel Salek * NEWS, configure.in: release 2.3.17. 2007-07-01 Pawel Salek * libbalsa/imap/pop3.c: validate APOP server stamp. * libbalsa/imap/imap-search.c: split long SEARCH commands into several ones. * libbalsa/mailbox_imap.c: return correct bool code on flag store. 2007-06-21 Peter Bloomfield * src/main-window.c: (display_new_mail_notification): respect balsa_app.notify_new_mail_dialog. * libbalsa/address.c: (vcard_qp_decode): build with GMime >= 2.5.5 2007-06-19 Albrecht Dress * libbalsa/address.[hc]: make VCARD support more RFC-compatible. * src/balsa-mime-widget-text.c: improve displaying. * balsa-print-object-text.[hc]: add printing. 2007-06-17 Pawel Salek * libbalsa/imap/imap-handle.c: handle ESEARCH response. * libbalsa/imap/imap-handle.h: recognize ESEARCH extension. * libbalsa/imap/imap-commands.c: use it to optimize searches. * libbalsa/imap/imap-search.c: ditto. 2007-06-15 Pawel Salek Commit Peter's patches for broader testing... * libbalsa/imap/imap-handle.c: detect disconnection. * libbalsa/imap/imap-commands.c: check for header existence in client side sorting. 2007-06-10 Peter Bloomfield * src/balsa-index.c: (bndx_expand_to_row): avoid critical warnings from GtkTreeView. 2007-06-07 Pawel Salek * src/store-address.[ch]: add ability to create addresses from VCARD strings. * src/balsa-index.c: use new store_address() function names. * src/main-window.c: ditto. * src/balsa-mime-widget-text.c: add ability to store attached e-mail addresses. * libbalsa/address-book-vcard.c: use common VCARD functions. * libbalsa/address.[ch]: move common VCARD functions here. 2007-06-05 Peter Bloomfield * libbalsa/mime.c: (unwrap_rfc2646): inline check for "-- \n". * libbalsa/mailbox.c: (lbm_try_reassemble): do not get message just to test flags. * libbalsa/send.c: (lbs_process_queue), (libbalsa_process_queue): ditto. * src/balsa-index.c: (bndx_mailbox_row_inserted_cb): ditto. 2007-06-05 Peter Bloomfield * libbalsa/mailbox.[ch]: new convenience methods libbalsa_mailbox_msgno_change_flags and libbalsa_mailbox_register_msgno. * libbalsa/message.[ch]: new convenience method libbalsa_message_change_flags. * libbalsa/send.c: use libbalsa_message_change_flags. * src/balsa-index.[ch]: replace BalsaIndex::current_message with BalsaIndex::current_msgno; new members BalsaIndex::has_selection_changed_idle and BalsaIndex::has_mailbox_changed_idle to avoid setting GObject data; new api balsa_index_selected_msgnos_{new,free}. * src/balsa-mblist.c: (bmbl_drag_cb): use new balsa_index_selected_msgnos_{new,free} api. * src/balsa-message.[ch]: use mailbox and msgno instead of message. * src/main-window.[ch]: ditto; use new balsa_index_selected_msgnos_{new,free} api. * src/message-window.[ch]: use mailbox and msgno instead of message. * src/sendmsg-window.[ch]: ditto. 2007-06-03 Peter Bloomfield * libbalsa/mime.c: (unwrap_rfc2646): detect CRLF-terminated signature separator line. 2007-05-28 Peter Bloomfield * libbalsa/imap/pop3.c: (pop_get_uid): check for disconnection to avoid a failed assertion. 2007-05-27 Pawel Salek * src/sendmsg-window.c: Do not wrap for view, if flowed format is selected (Albrecht Dreß). * src/balsa-index.c: extend msgno and size columns. * libbalsa/mailbox_imap.c: silence few devel warnings. * NEWS, configure.in: release 2.3.16. 2007-05-21 Peter Bloomfield * libbalsa/mailbox.c: (lbm_get_index_entry_expunged_cb), (lbm_get_index_entry): catch expunged and renumbered messages. * src/message-window.c: (message_window_move_message), (mw_set_selected): check BalsaIndex::current_msgno instead of BalsaIndex::current_message. 2007-05-11 Peter Bloomfield * libbalsa/html.c: (libbalsa_html_print), (libbalsa_html_print_get_pages_num): build on fc6, and on f7test --without-gtkprint. * libbalsa/html.h: ditto. 2007-05-10 Peter Bloomfield * libbalsa/mailbox_mh.c: (libbalsa_mailbox_mh_sync): rename message files correctly. * libbalsa/mailbox_local.c: (lbm_local_save_tree), (libbalsa_mailbox_local_close_mailbox): really check for empty tree; always save tree on closing. 2007-05-09 Albrecht Dreß * libbalsa/identity.h: add request_mdn field (request MDN by default). * libbalsa/identity.c: (libbalsa_identity_init), (setup_ident_frame), (ident_dialog_update), (display_frame_update), (libbalsa_identity_new_config), (libbalsa_identity_save): manage it. * src/sendmsg-window.c: (update_bsmsg_identity): use it. 2007-05-07 Peter Bloomfield * libbalsa/misc.c: (libbalsa_set_fallback_codeset): allocate the charset strings. * libbalsa/mailbox_local.c: (libbalsa_mailbox_local_get_message): check msgno. * src/balsa-index.c: (bndx_change_flags), (bndx_tree_expand_cb): ditto. * libbalsa/misc.c: (libbalsa_set_fallback_codeset): include UTF-8 as a charset. * src/balsa-message.c: (mdn_dialog_response): do not clear NULL error. 2007-05-06 Albrecht Dreß * configure.in: add HTML flags and libs. 2007-05-06 Peter Bloomfield * libbalsa/html.h: compile with GtkHtml3 and GtkPrint. * libbalsa/mailbox.c: (libbalsa_mailbox_get_message): compile with threads disabled. * libbalsa/mailbox.h: remove LB_MAILBOX_STATE_TREECLEANING from LibBalsaMailboxState enum. * libbalsa/mailbox.c: (libbalsa_mailbox_msgno_filt_out), (lbm_set_threading): remove LB_MAILBOX_STATE_TREECLEANING code; (lbm_get_index_entry_real): check that mailbox is still open; (libbalsa_mailbox_get_message): lock mailbox before checking args. * src/balsa-index.h: add current_msgno to BalsaIndex structure, and remove selected and selection_changed_id; new public method balsa_index_selected_msgnos. * src/balsa-index.c: provide GArray of selected messages only when needed. * src/balsa-mblist.c: (bmbl_drag_cb): use balsa_index_selected_msgnos. * src/main-window.c: (notebook_drag_received_cb): ditto. * src/sendmsg-window.c: ditto. * libbalsa/mailbox_local.h: new LibBalsaMailboxLocalMessageInfo structure and LibBalsaMailboxLocalClass method get_info; remove load_message class method; do not export libbalsa_mailbox_local_queue_sync--it's now static. * libbalsa/mailbox_local.c: implement LibBalsaMailboxClass methods get_message, messages_change_flags, and msgno_has_flags here instead of in back-ends; keep a pool of object-reffed messages. * libbalsa/mailbox_maildir.c: remove LibBalsaMailboxClass methods get_message, messages_change_flags, and msgno_has_flags. * libbalsa/mailbox_mbox.c: ditto * libbalsa/mailbox_mh.c: ditto. * src/balsa-message.c: (display_part): ensure UTF-8; (libbalsa_msg_try_mp_signed), (message_recheck_crypto_cb): notify user only once. * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text): ditto. * configure.in: detect GMime version 2.2.7 * libbalsa/misc.c: (libbalsa_set_fallback_codeset): use g_mime_set_user_charsets when it's available. 2007-05-05 Pawel Salek * libbalsa/identity.[hc]: signature processing belongs here. * src/sendmsg-window.c: use it. * libbalsa/html.h: fix bug 435594. 2007-05-04 Peter Bloomfield * src/balsa-mime-widget-image.c: (img_check_size): use GDK lock in idle callback. 2007-05-03 Peter Bloomfield * src/balsa-message.c: (balsa_message_has_next_part), (balsa_message_has_previous_part): return FALSE unless we have a part. * src/main-window.c: (enable_part_menu_items), (notebook_switch_page_cb): improve message menu item sensitivity. 2007-05-01 Peter Bloomfield * libbalsa/information.c: (libbalsa_information_varg): escape more HTML special characters. * src/main-window.c: (bw_create_index_widget): sensitize button when type of search is changed. * src/balsa-index.c: (bndx_selection_changed): clear preview more reliably. * src/balsa-index.c: (balsa_index_set_threading_type): fix typo. 2007-05-01 Pawel Salek * src/mailbox-node.c: do not print null strings. * src/toolbar-factory.c: apply patch from bug 410095 ,extended. * configure.in, NEWS: release 2.3.15. 2007-04-29 Peter Bloomfield * src/information-dialog.c: (balsa_information_real): do not try to pop up dialog if main-window is NULL. 2007-04-29 Peter Bloomfield * libbalsa/libbalsa.h: add error code for get-duplicates. * libbalsa/mailbox.c: (libbalsa_mailbox_move_duplicates): use it. * libbalsa/mailbox_local.c: check error return from prepare-threading. * src/balsa-index.c: (balsa_index_set_threading_type): ditto. * src/main-window.c: (remove_duplicates_cb): ensure-visible only if no error. * src/main.c: (balsa_progress_set_text), (balsa_progress_set_fraction): check for NULL main-window. 2007-04-29 Peter Bloomfield * src/balsa-mime-widget-text.c: (bm_widget_new_html): fix popup menu for HTML part. 2007-04-28 Peter Bloomfield * libbalsa/information.c: (libbalsa_information_varg): simplify conditional code. 2007-04-27 Peter Bloomfield * libbalsa/information.c: (libbalsa_information_varg): replace '<' with "<" entity in message string. 2007-04-26 Pawel Salek * src/balsa-message.c: do not crash on empty address groups. * libbalsa/imap/imap-commands.c: make GPGME and BINARY work together. 2007-04-25 Christophe Merlet * configure.in: added "oc" (Occitan) to ALL_LINGUAS. 2007-04-24 Pawel Salek * src/balsa-message.c: stop encryption processing if mailbox access fails. * libbalsa/mailbox_imap.c: attempt to handle fetch errors better. * libbalsa/imap/imap-commands.c: BINARY falls back to traditional method encountering UNKNOWN-CTE. 2007-04-23 Pawel Salek * libbalsa/information.c: build on 64-bit architecture. 2007-04-22 Albrecht Dreß * src/balsa-mime-widget-message.c: pass the reported sending code to the user. * src/{sendmsg-window,balsa-message}.c: ditto. * libbalsa/gmime-gpgme-context.c: Work around gpgme "pecularities" - fix bug 419903. * libbalsa/{rfc3156,send}.{c,h}: ditto. * libbalsa/mailbox_imap.c: do not get fooled by shorter binary attachments.(PS) 2007-04-21 Pawel Salek * libbalsa/mailbox_imap.c: plug memory leaks. * libbalsa/imap-server.c: enable binary extension. * libbalsa/imap/imap-handle.c: process BINARY output. * libbalsa/imap/imap-handle.h: add BINARY to the known capability list. * libbalsa/imap/imap-commands.c: issue BINARY commands. * libbalsa/information.c: fix memory leak in notify code. 2007-04-21 Peter Bloomfield * src/main-window.c: (balsa_window_new), (display_new_mail_notification), (cancel_new_mail_notification): pop up new-mail notification only if main-window is not active, and cancel it when main-window becomes active. 2007-04-20 Albrecht Dreß * libbalsa/address-book-ldap.c: support LDAP referrals. 2007-04-20 Peter Bloomfield * src/main-window.c: (display_new_mail_notification): use no more than one NotifyNotification for new mail. 2007-04-16 Pawel Salek * src/balsa-index.c: keep current message visible in the index on filter changes. 2007-04-15 Pawel Salek * src/main-window.c: use libnotify only if the initialization was successful. * libbalsa/information.c: ditto. 2007-04-11 Pawel Salek * libbalsa/imap/siobuf.c: rename external symbols to avoid conflicts with libesmtp. 2007-04-10 Johan Brannlund * configure.in: detect libnotify. * libbalsa/information.c: use it. * libbalsa/libbalsa.c: init it. * libbalsa/{send,server}.c: downgrade some messages to debug. * src/main-window.c: use libnotify for new mail notification. * src/balsa-mblist.c: prefer trailing spaces instead of leading ones. * libbalsa/imap/imap-handle.c: really disconnect (PS). * libbalsa/libbalsa-conf.c: correct CHECK_VERSION (PB). 2007-04-09 Pawel Salek * libbalsa/mailbox_imap.c: do not re-try user-aborted actions. * libbalsa/libbalsa.[ch]: generalize libbalsa_ask() to implement libalsa_abort_on_timeout(). * libbalsa/imap/imap-handle.c: support for distinguising aborted operations from those that timed out. * libbalsa/imap/libimap.h: add IME_TIMEOUT event type. * libbalsa/imap/imap-handle.h: add imap_handle_op_cancelled(). * libbalsa/imap/imap_private.h: add op_cancelled field. * libbalsa/imap/siobuf.[ch]: core of timeout handling. * libbalsa/server.c: ask user what to do on timeout. 2007-04-05 Peter Bloomfield * configure.in: detect gtkhtml-3.14; detect GtkPrint support in gtkhtml3; detect GMime version 2.2.5 or later. * libbalsa/body.c: (libbalsa_message_body_extract_embedded_headers): new GMime api. * libbalsa/html.c: don't use Gnome printing api if GtkPrint is supported. * libbalsa/mailbox_imap.c: new GMime api. (internet_address_new_from_imap_address), (lb_set_headers), (lbm_imap_construct_body): ditto. * libbalsa/message.c: (libbalsa_message_user_hdrs_from_gmime), (lbmsg_set_header), (libbalsa_message_set_subject_from_header): ditto. * src/sendmsg-window.c: ditto. 2007-03-13 Pawel Salek * libbalsa/address-entry.c: fix crash reported on balsa-list. 2007-02-26 Pawel Salek * libbalsa/mailbox_imap.c: fetch small messages in one shot to get rid of one RTT. 2007-02-20 Albrecht Dreß * src/Makefile.am: add balsa-cite-bar.[ch] to balsa_BASE_SRCLIST. * src/balsa-cite-bar.c: (balsa_cite_bar_get_type), (balsa_cite_bar_class_init), (balsa_cite_bar_init), (balsa_cite_bar_new), (balsa_cite_bar_resize), (balsa_cite_bar_destroy), (balsa_cite_bar_realise), (balsa_cite_bar_size_request), (balsa_cite_bar_size_allocate), (balsa_cite_bar_expose): initial commit. * src/balsa-cite-bar.h: initial commit. * src/balsa-mime-widget-text.c: (balsa_mime_widget_new_text), (quote_tag), (fix_text_widget), (destroy_cite_bars), (draw_cite_bar_real), (draw_cite_bars): use cite-bars with quoted text. * src/balsa-print-object-text.c: (balsa_print_object_text_plain), (balsa_print_object_text): use cite-bars only with text/plain message part. * src/balsa-print-object-text.h: new method balsa_print_object_text_plain. * src/balsa-print-object.c: (balsa_print_objects_append_from_body): use balsa_print_object_text_plain. 2007-02-18 Peter Bloomfield * libbalsa/mailbox.c: (libbalsa_mailbox_prepare_threading), (mbox_set_sort_column_id): use success indicator from prepare-threading to avoid crash when mailbox is closed during prepare-threading. * libbalsa/mailbox.h: new declaration for prepare-threading. * libbalsa/mailbox_imap.c: (libbalsa_mailbox_imap_prepare_threading): ditto. * libbalsa/mailbox_local.c: (libbalsa_mailbox_local_prepare_threading): return FALSE if mailbox is closed when updating UI. 2007-02-17 Pawel Salek * src/mailbox-node.c: save cache only for the top-level nodes. * src/main-window.c: remove shortcut conflict. * src/address-book-config.c: add ldap:// prefix (Albrecht Dress). * libbalsa/address-book-ldap.c: AD compatiblity (Albrecht Dress). 2007-02-09 Pema Geyleg * configure.in: added dz to ALL_LINGUAS. 2007-01-23 Peter Bloomfield * src/main-window.c: (balsa_window_new): make balsa_app.appbar a weak pointer. 2007-01-20 Peter Bloomfield * doc/C/balsa.xml: fix typos. 2007-01-20 Peter Bloomfield * libbalsa/body.c: (libbalsa_message_body_get_parameter): check for NULL content-type. 2007-01-20 Peter Bloomfield, Albrecht Dreß * configure.in: check for Subversion instead of CVS; check for langinfo.h. * src/balsa-app.h: GtkPrint fixes and extensions. * src/balsa-print-object-header.c: (balsa_print_object_header_destroy), (balsa_print_object_header_new_real), (balsa_print_object_header_crypto), (balsa_print_object_header_draw): ditto. * src/balsa-print-object-header.h: ditto. * src/balsa-print-object-text.c: (balsa_print_object_text): ditto. * src/balsa-print-object.c: (split_for_layout): ditto. * src/balsa-print-object.h: ditto. * src/print-gtk.c: (begin_print), (draw_page), (get_default_user_units), (add_font_button), (add_margin_spinbtn), (check_margins), (message_prefs_widget), (message_prefs_apply): ditto. * src/save-restore.c: (restore_gtk_page_setup), (config_global_load), (config_save): ditto. 2007-01-15 Peter Bloomfield * libbalsa/mailbox.c: (lbm_msgno_changed), (lbm_get_index_entry_real): less noise. 2007-01-14 Pawel Salek * configure.in: actually use gnome_print_extras. * libbalsa/libbalsa-conf.c: glib-2.6.8 has no g_key_file_[sg]et_double(). 2007-01-14 Albrecht Dreß * configure.in: support GtkPrint. * libbalsa/libbalsa-conf.c: (libbalsa_conf_foreach_keys), (libbalsa_conf_get_double_with_default_), (libbalsa_conf_set_double_): add some missing capability. * libbalsa/libbalsa-conf.h: ditto. * src/Makefile.am: support GtkPrint. * src/balsa-app.c: (balsa_app_init): ditto. * src/balsa-app.h: ditto. * src/main-window.c: (page_setup_cb): ditto. * src/message-window.c: (page_setup_cb): ditto. * src/print.h: ditto. * src/save-restore.c: (load_gtk_print_setting), (restore_gtk_page_setup), (config_global_load), (save_gtk_print_setting), (save_gtk_page_setup), (config_save): ditto. * src/sendmsg-window.c: ditto. 2007-01-07 Pawel Salek * src/mailbox-node.c: g_strconcat() needs trailing NULL. 2007-01-06 Pawel Salek * src/mailbox-node.[hc]: cache IMAP mailbox lists. * libbalsa/filter-funcs.c: init *entire* date struct. 2006-12-28 Pawel Salek * doc/C/balsa.xml: document more advanced IMAP options. * libbalsa/imap-server.[ch]: add ability to disable IDLE. * libbalsa/mailbox_imap.c: fix locking in imap_exists_cb. * libbalsa/imap/imap-handle.[ch]: add ability to disable IDLE. * libbalsa/imap/imap_private.h: ditto. * src/folder-conf.c: UI for IDLE disabling. * src/mailbox-node.c: place mailboxes in scanned locations. 2006-12-12 Pawel Salek * src/sendmsg-window.c: set subject for forwarded messages. * src/store-address.c: set default address book for gtk-2.10. * configure.in, NEWS: release 2.3.14. 2006-12-03 Pawel Salek * libbalsa/mailbox.c: libbalsa_mailbox_get_message() may fail. * libbalsa/mailbox_imap.c: print a message when it does. 2006-12-02 08:48 PeterB * src/sendmsg-window.c: handle "attach" keyword in mailto URLs, carefully. 2006-12-01 Pawel Salek * libbalsa/imap/imap-handle.c: balsa could not handle some response codes. 2006-11-18 Djihed Afifi * configure.in: Added Arabic. 2006-11-09 08:56 PeterB * src/sendmsg-window.c: no need for count when toggling entries; simplify dialog language. 2006-11-08 10:49 PeterB * src/sendmsg-window.c: restore bcc= in mailto URLs, with a popup, and make sure Bcc: header is shown if set. * libbalsa/mailbox_mbox.c: check for NULL mime_message. 2006-11-01 08:46 PeterB * src/sendmsg-window.c: disable attach= and bcc= in mailto URLs pending security review. * src/sendmsg-window.c: handle "attach" keyword in mailto URLs, thanks to Johan Brannlund. * src/main.c: do not try to expunge a read-only mailbox. 2006-10-26 09:42 PeterB * libbalsa/mailbox_mbox.c: drop the mime-stream-shared lock while caching the message--we might grab the gdk lock to update the display. 2006-10-08 Albrecht Dreß * src/pref-manager.c: add a check button to enable or disable playing a "new mail sound". * src/sendmsg-window.c: German is /not/ always the same. * libbalsa/gmime-gpgme-context.c: make a gpgme (crypto) error more meaningful. 2006-10-07 11:08 PeterB * libbalsa/: mailbox.c, mailbox_local.c: build with --disable-threads. 2006-10-04 12:37 PeterB * src/sendmsg-window.c: quote message when quoting, and not when inlining. * libbalsa/mailbox.c: construct new order correctly in imap mailbox. 2006-09-24 Pawel Salek * src/sendmsg-window.c: quote message bodies, not headers only. 2006-09-21 18:32 PeterB * libbalsa/mailbox.c: notify gdk when message info is cached; disable lock check for normal use. 2006-09-18 08:10 PeterB * libbalsa/message.c: Disposition-Notification-To is not a user header. * libbalsa/mailbox_mbox.c: more careful check for From_ line. 2006-09-17 Pawel Salek * src/sendmsg-window.c: cleanup. Compose and forward will insert the signature if requested. 2006-09-15 21:17 PeterB * libbalsa/mailbox.c, libbalsa/mailbox.h, libbalsa/mailbox_imap.c, libbalsa/mailbox_local.c, libbalsa/mailbox_maildir.c, libbalsa/mailbox_mh.c, src/balsa-index.c: check LibBalsaMailboxIndexEntry for pending idle call; defer adding entries to LibBalsaMailbox::mindex, and modify it only in mailbox.c; drop LB_MBOX_MESSAGE_COL, and use libbalsa_mailbox_get_message instead. * libbalsa/mailbox_mbox.c: do not relocate message_info structures, so we can make msg_info->message a weak pointer; access them with a GPtrArray; do not modify LibBalsaMailbox::mindex. * src/main-window.c: more moderate close-icon on notbook tab. 2006-09-12 07:24 PeterB * configure.in: remove spaces around '='. 2006-09-11 20:29 PeterB * libbalsa/: libbalsa_private.h, mailbox.c, mailbox.h, mailbox_local.c: use a sub-thread instead of an idle-handler for getting messages; lock mailbox in libbalsa_mailbox_get_message. * configure.in: report version of gtkhtml-3.x. 2006-09-04 00:32 PeterB * libbalsa/libbalsa_private.h, libbalsa/mailbox.c, libbalsa/mailbox.h, libbalsa/mailbox_imap.c, libbalsa/mailbox_local.c, src/balsa-index.c: use an idle callback in lbm_get_index_entry to handle getting messages; as a result, we can simplify the API for prepare-threading. 2006-09-04 00:14 PeterB * libbalsa/mailbox.c, libbalsa/mailbox_imap.c, libbalsa/message.c, libbalsa/message.h, src/balsa-message.c, src/balsa-mime-widget-message.c, src/sendmsg-window.c: implement and use libbalsa_message_set_subject{,_from_header}; fix canonize_header_value to handle non-ASCII white space. 2006-09-01 Albrecht Dreß * libbalsa/message.c: collapse whitespace into a single space. 2006-08-30 07:55 PeterB * configure.in: build with autoconf-2.60. 2006-08-28 12:04 PeterB * src/main-window.c: make notebook tabs reorderable with drag and drop. 2006-08-27 16:35 PeterB * libbalsa/: mailbox.c, mailbox_local.c: check for NULL message. 2006-08-27 Pawel Salek * libbalsa/address.c: gtk_tree_store not updated until gtk_tree_model loses focus (gtk2-2.8.20). Force it. * libbalsa/mailbox.c: ... gtk-2.8 should be smart enough to detect visible cells - no reason to spent time hinting it (hinting's slow on large mailboxes). 2006-08-26 10:08 PeterB * libbalsa/message.c: check for NULL headers. 2006-08-23 09:49 PeterB * src/: sendmsg-window.c, sendmsg-window.h: replace three gbooleans with a state variable, and use it to simplify "message has been modified" dialog. * libbalsa/: body.c, files.c: check for NULL body. 2006-08-22 Pawel Salek * src/sendmsg-window.c: set identity for compose, Peter's way. * libbalsa/identity.c: do not try unreffing NULL when adding new ident. 2006-08-14 13:07 PeterB * src/sendmsg-window.c: restore setting identity in reply or continuation. 2006-08-10 Pawel Salek * src/sendmsg-window.c: do not use released memory. 2006-08-07 19:46 Pawel Salek * src/sendmsg-window.c: add missing mailbox_close() call. Build fixes. * src/balsa-mime-widget-message.c: Build fixes. 2006-08-07 Pawel Salek * libbalsa/filter.c: use new content2reply(). * libbalsa/mailbox_local.c: ditto. * libbalsa/message.[ch]: extra routines for header manipulation. * libbalsa/mime.[ch]: content2reply accepts a message part now. * src/balsa-message.c: aim at providing common ancestor to LibBalsaMessage and LibBalsaMessageBody. * src/balsa-mime-widget-message.[hc]: call reply to embedded message. * src/sendmsg-window.[hc]: some more related refactoring. Implement reply to embedded message. 2006-08-06 Pawel Salek * src/ab-window.c: use new Sendmsg API with better separation between compose, reply, forward and continue. * src/balsa-bonobo.c: ditto. * src/balsa-index.c: ditto. * src/balsa-mime-widget-message.c: prepare for replying embedded messages. * src/balsa-mime-widget-text.c: use new API. * src/main{-window,}.c: ditto. * src/message-window.c: ditto. * src/sendmsg-window.[ch]: separate better different compose modes so that implementation of replying to embedded messages becomes easier. 2006-07-09 Albrecht Dreß * src/sendmsg-window.c: do not perform crypto on entire message. 2006-07-04 12:09 PeterB * libbalsa/address.c: gtk_list_store_insert_with_values requires gtk version 2.6. 2006-06-29 10:47 PeterB * src/: balsa-index.c, balsa-mblist.c, balsa-message.c, balsa-mime-widget-text.c, balsa-mime-widget.c, pref-manager.c: clear face box instead of hiding it; gtk_object_sink is deprecated in 2.10--use g_object_ref_sink if available. 2006-06-27 Pawel Salek * Makefile.am: gnome specific macros not used any more. * libbalsa/imap-server.c: use client-side sorting. * libbalsa/mailbox_imap.c: set first_unread correctly. * libbalsa/imap/imap-commands.c: implement client-side sorting. * libbalsa/imap/imap-handle.[ch]: add CLIENT_SORT option. * libbalsa/imap/imap_private.h: add the bit field to ImapMboxHandle. 2006-06-26 Pawel Salek * libbalsa/mailbox_imap.c: use the synchronous STORE calls for now. * libbalsa/mailbox_local.c: set first_unread more reliably. * src/balsa-index.c: fix bug 345638. * NEWS: release 2.3.13. 2006-06-25 Albrecht Dreß * src/: ab-window.c, ab-window.h: use a table to improve layout of address selection dialog. 2006-06-22 Pawel Salek * libbalsa/identity.c: fix a regression (patch from PB). * libbalsa/address-entry.c: remove non-printable characters on text paste (AD). 2006-06-17 Pawel Salek * Makefile.am: do not include GNOME_Balsa.server in the tarball. * balsa.spec.in: fedora builds do not require gmime. * configure.in: prepare for release. * libbalsa/identity.c: allow arbitrary sig file names so that arguments can be passed to executable sigs. 2006-06-16 08:17 PeterB * libbalsa/mailbox_imap.c: get mailbox lock before gdk lock. 2006-06-15 21:55 PeterB * libbalsa/mailbox_local.c: drop the gdk lock before returning. 2006-06-01 10:57 PeterB * libbalsa/mailbox_imap.c: free cache-manager. * src/balsa-mblist.c: append subtree when appending exposed unscanned node. 2006-05-31 09:43 PeterB * libbalsa/filter-file.c, libbalsa/filter-funcs.c, libbalsa/filter.c, libbalsa/filter.h, libbalsa/mailbox.c, libbalsa/mailbox_local.c, src/balsa-index.c, src/filter-edit-callbacks.c, src/filter-edit-dialog.c, src/main-window.c: ref-count LibBalsaCondition instead of cloning. * libbalsa/: mailbox_maildir.c, mailbox_mbox.c, mailbox_mh.c: free mailbox info after closing mailbox-local. 2006-05-30 00:22 PeterB * src/balsa-mime-widget-text.c: plug leak. 2006-05-29 15:56 PeterB * libbalsa/: mailbox.c, mailbox.h: implement LibBalsaMailbox::persistent_view_filter. * src/: balsa-index.c, main-window.c: make flag view-filter persistent, so we can restore it when closing a local mailbox. * libbalsa/mailbox_local.c: restore persistent view-filter before saving the tree when closing. 2006-05-26 Pawel Salek * libbalsa/mailbox.c: sort IMAP mailboxes correctly (part of the information returned by the imap server was ignored at this level). * src/balsa-app.c: really respect the "remember passwd" check box. * src/balsa-index.c: do not re-sort on index close. 2006-05-25 11:11 PeterB * libbalsa/smtp-server.c: do not crash without HAVE_SMTP_TLS_CLIENT_CERTIFICATE. 2006-05-20 Albrecht Dreß * src/balsa-icons.[hc]: Choose a better icon for the trash mailbox when GNOME_STOCK_TRASH is unavailable. * configure.in: remove stray '-' as reported by Jean-Luc Coulon. 2006-05-17 Pawel Salek * libbalsa/imap/imap-commands.c: fix return codes of async routines. * libbalsa/imap/imap{-handle,_private}.c: ditto. * libbalsa/mailbox_imap.c: use changed return codes. 2006-05-15 Pawel Salek * libbalsa/imap/imap-handle.c: reset idle_issued flag. handle message-other right, this includes message/delivery-status. * src/balsa-mime-widget.c: display message/delivery-status parts. 2006-05-14 10:46 PeterB * src/sendmsg-window.c: make Yes the default response when user closes unsaved compose window; add Cancel option when user closes auto-saved compose window. * src/sendmsg-window.c: unref, not free, a GObject. 2006-05-13 Pawel Salek * libbalsa/mailbox_imap.c: use async interface for STORE commands. * libbalsa/mailbox_mbox.c: do not use file_set_contents() on OSX. * libbalsa/imap/imap-commands.c: async store_flag_a() * libbalsa/imap/imap-commands.h: proper prototypes. * libbalsa/imap/imap-handle.c: generalize IDLE response handlers to general async command response handlers. * libbalsa/imap/imap_private.h: provide support for handle locking and asynchronous command handling. * src/balsa-index.c: scroll first, fetch messages later. 2006-05-12 09:10 PeterB * website/faq.html: restore website/faq.html, with a new entry for format=flowed. 2006-05-09 Pawel Salek * src/main.c: fix -a handling when GOption API is used. 2006-05-07 14:26 PeterB * libbalsa/imap/imap-handle.c: add message_id to cache. 2006-05-03 Albrecht Dreß * libbalsa/mime.c: Improve recognition of multi-line URLs. * libbalsa/misc.h: store a flag whether URL is in a flowed message. * src/balsa-mime-widget-text.c: initialize this flag. 2006-04-25 Carlos Morgado * libbalsa/address.c (addrlist_drag_drop_cb): fix broken cast on 64b 2006-04-21 09:46 PeterB * libbalsa/mailbox.c: total message count can change while we're working on the tree, so we save it and remove assertions. 2006-04-17 Pawel Salek * libbalsa/address.[ch]: address list of edit vidget is now a drop target. * libbalsa/mailbox_imap.c: get rid of one RTT for simple messages. * libbalsa/mailbox_mbox.c: silence spurious warnings on OSX. * libbalsa/send.c: failure to send a message is an error. * src/ab-main.c: support D&D and address lists. 2006-04-17 Kjartan Maraas * configure.in: Remove obsolete no_NO locale. * po/no.po: And the translation. 2006-04-07 Carlos Morgado * src/balsa-message.c (add_multipart_mixed): fix build without GPGME 2006-04-05 Albrecht Dreß * src/balsa-message.c: fix MDN syntax; add option to show all parts inline. 2006-04-05 13:17 PeterB * src/save-restore.c: do not save UNSET show or subscribe values. 2006-04-01 09:52 PeterB * src/pref-manager.c: do not crash if address book changes are applied after pref manager is closed. * src/address-book-config.c: allow only one dialog per address book. * libbalsa/mailbox.c: don't clear counts until we know they're wrong. 2006-03-27 07:55 PeterB * src/main-window.c: cut down console messages. * src/balsa-mblist.c: if mailbox isn't subscribed for checking, don't notify user about new mail and don't emit BalsaMBList signal. 2006-03-24 Albrecht Dreß * libbalsa/libbalsa.c: proper regex's for highlighting quoted lines. * configure.in: libesmtp sometimes needs -lpthread. 2006-03-24 08:44 PeterB * libbalsa/smtp-server.c: build without HAVE_SMTP_TLS_CLIENT_CERTIFICATE. * libbalsa/mime.c: include ctype header file. * src/balsa-mblist.c: unref the correct object; hold gdk lock while closing mbnode. 2006-03-23 Pawel Salek * libbalsa/send.c: report MAIL FROM SMTP command errors. 2006-03-21 Pawel Salek * libbalsa/mi{me,sc}.c: move PCRE dependency to mime.c * libbalsa/mailbox.c: copy the "deleted" flag as well (Emanuel). 2006-03-18 Pawel Salek * libbalsa/libbalsa.[hc]: * libbalsa/misc.[hc]: move library-dependent stuff to libbalsa.c. 2006-03-17 Pawel Salek * configure.in: create separately list of balsa-ab libraries (12 libs removed). Albrecht Dreß fixed detection of buggy gpgme. * src/Makefile.am: use it. * libbalsa/libbalsa.[hc]: * libbalsa/misc.[hc]: move object-independent stuff to misc.c. * libbalsa/mailbox_pop3.c: include misc.h * src/ab-main.c: register only used objects. 2006-03-16 19:56 PeterB * libbalsa/mailbox.c: notify Gtk when msgno changes. 2006-03-09 Pawel Salek * libbalsa/address-book-ldap.c: use openldap-2.3.x compatible API. * libbalsa/libbalsa.c: the same. * libbalsa/imap/imap-handle.c: treat OpenSSL errors as critical. * src/balsa-mblist.c: don't be mad if an icon is not found. 2006-03-08 10:40 PeterB * src/main-window.c: ensure visible message after changing view filter. 2006-03-06 Ahmad Riza H Nst * configure.in: Added "id" (Indonesian) to the ALL_LINGUAS line 2006-03-05 10:23 PeterB * libbalsa/mailbox.c, libbalsa/mailbox.h, src/balsa-index.c: check whether user closed mailbox during long view-filter update. 2006-03-04 Pawel Salek * libbalsa/mailbox_mbox.c: do not reference freed memory. * NEWS, configure.in: release 2.3.12. 2006-02-28 Pawel Salek * src/balsa-app.c: check mbnode fetched by gtk_tree_model_get()... * src/balsa-mblist.c: ... fixing bug 332980. * NEWS, configure.in: release 2.3.11. 2006-02-27 Albrecht Dreß * src/sendmsg-window.c: explicitly update gpg-mode when identity is changed, as apparently the callback is now called only when the check-button's state is changed. 2006-02-26 19:28 PeterB * src/balsa-index.c: scroll to ensure a visible message only if there isn't one. * doc/C/balsa.xml, src/pref-manager.c: arrange the help file to match the new prefs window; use section titles instead of notebook page numbers to locate help sections. 2006-02-25 13:56 PeterB * src/: balsa-index.c, balsa-index.h, main-window.c: implement balsa_index_ensure_visible, and use it. * src/main.c: set GNOME_PARAM_APP_DATADIR. * libbalsa/address-book-ldap.c, libbalsa/address-book.c, src/address-book-config.c, src/pref-manager.c: give user control over LibBalsaAddressBook::is_expensive. * src/balsa-index.c: try to leave messages showing after changing view filter. 2006-02-15 Pawel Salek * libbalsa/html.c: silence printf(). * libbalsa/{message,mailbox_mbox}.c: remove remains of msg counting. * libbalsa/mailbox_imap.c: fix a crash in low index selection on cache restore (spotted by PeterB). * libbalsa/imap/imap-commands.c: check more return codes. * libbalsa/imap/imap-{handle,search}.c: ditto. 2006-02-21 10:53 PeterB * src/balsa-mblist.c: hide title and make column natural size when using single column. 2006-02-20 22:51 PeterB * src/: sendmsg-window.c, sendmsg-window.h: save reflow widget in BalsaSendmsg, in case user opens multiple windows. 2006-02-19 12:39 PeterB * src/balsa-mblist.c, libbalsa/mailbox.c: show count of hidden messages on status bar; show only non-zero counts. * src/balsa-message.c: make sure widget can focus. 2006-02-18 15:31 PeterB * src/sendmsg-window.c, libbalsa/address-entry.c, libbalsa/address-entry.h: use Escape instead of ctrl+R for manual address completion. * libbalsa/address-book-ldap.c: make LDAP address book expensive. * src/pref-manager.c: edit address book on row-activated; add closure to add_button_to_box. 2006-02-18 Albrecht Dreß * src/balsa-mime-widget-text.c: fix bug 330093 -- 'copy URL' when right-clicking one in a mail. 2006-02-17 21:26 PeterB * src/: balsa-message.c, balsa-message.h, balsa-mime-widget-callbacks.c, main-window.c, main-window.h: one-key mail reading using space bar. * src/main.c: drop gdk lock before syncing mailboxes. * src/mailbox-node.c: check mailbox in an idle handler. * src/balsa-index.c: use the gdk lock to control access to LibBalsaMailbox::msg_tree. * libbalsa/: libbalsa.c, libbalsa.h, mailbox.c, mailbox.h, mailbox_imap.c, mailbox_local.c: use the gdk lock to control access to LibBalsaMailbox::msg_tree. 2006-02-15 Pawel Salek * balsa.desktop.in: Terminal=0 -> Terminal=false * libbalsa/rfc3156.c: failed gpg execution is warning, not just info (Albrecht Dreß). 2006-02-13 22:42 PeterB * src/: balsa-mblist.c, balsa-icons.c, balsa-icons.h: use icon-name GtkTreeViewColumn attribute. * src/: balsa-index.c, balsa-index.h, main-window.c, message-window.c: reset view filter to show unread message. * src/pref-manager.c: move message-window group to display-options page; move format group to character-set page and rename page. * src/balsa-mblist.c: unref pixbufs; dup string only when necessary. 2006-02-12 15:11 PeterB * src/pref-manager.c: let lists expand vertically. * src/pref-manager.c: align controls. * src/pref-manager.c: try to fill pages, as per HIG. 2006-02-11 15:32 PeterB * src/balsa-mblist.c: show unread count in parentheses when not showing info columns. 2006-02-10 08:22 PeterB * src/: balsa-app.c, balsa-index.c: check for NULL index. 2006-02-09 13:11 PeterB * libbalsa/misc.c: disable bracket-checking. 2006-02-07 07:29 PeterB * src/balsa-mblist.c: schedule only one idle callback at a time; move UI update to idle callback. * libbalsa/mailbox_local.c: clear total when restore-tree fails. 2006-02-06 15:46 PeterB * src/main-window.c: use NULL instead of empty string when it will be translated. * src/pref-manager.c: move utf8 out of translated string. * src/balsa-index.c: fix another typo in earlier commit. * libbalsa/rfc3156.c: fix typo in previous commit. * libbalsa/gmime-gpgme-signature.c, libbalsa/mailbox_pop3.c, libbalsa/misc.c, libbalsa/rfc3156.c, po/POTFILES.in, src/balsa-index.c, src/save-restore.c, src/sendmsg-window.c, src/spell-check.c: fix strings--bug 330085. 2006-02-05 21:18 PeterB * src/pref-manager.c: hide notebook borders and remove extra border-width. 2006-02-05 Carlos Morgado * src/pref-manager.c (pspell_settings_group): fix pedantic pspell build 2006-02-05 Albrecht Dreß * src/pref-manager.c: use unicode for special characters; let gtk-label wrap lines. 2006-02-04 12:24 PeterB * libbalsa/misc.c: plug object leak. * src/pref-manager.c: plug widget leak. 2006-02-03 22:04 PeterB * src/pref-manager.c: use tree control instead of nested notebooks. * src/mailbox-conf.c: less ugly alignment. 2006-02-03 Pawel Salek * libbalsa/smtp-server.c: include misc.h for libbalsa_create_label. 2006-02-01 20:30 PeterB * src/address-book-config.c, src/balsa-app.c, src/balsa-app.h, src/balsa-index.c, src/folder-conf.c, src/mailbox-conf.c, libbalsa/identity.c, libbalsa/misc.c, libbalsa/misc.h, libbalsa/smtp-server.c: more consistent dialogs. * libbalsa/mailbox_mbox.c: use cache file to speed up mailbox-check. * src/mailbox-conf.c: create only one dialog for new mailbox and to modify POP3 mailbox. * src/mailbox-conf.c: check for NULL mailbox. 2006-01-29 20:39 PeterB * libbalsa/message.c: avoid infinite recursion. * src/balsa-index.c, src/balsa-index.h, src/balsa-mblist.c, src/balsa-mblist.h, src/mailbox-conf.c, src/main-window.c, src/main.c, src/save-restore.c, libbalsa/mailbox.c, libbalsa/mailbox.h: next-unread chains to all mailboxes with unread mail. * libbalsa/message.c: encode broken headers before passing them to GMime for decoding. 2006-01-29 Pawel Salek * NEWS: release 2.3.10. * src/sendmsg-window.c: parent error dialog properly. gtk-2.4.x compatibility. Do not crash referencing NULL bsmsg->charset in is_charset_ok() when the first entry to this function was cancelled by user. 2006-01-28 22:14 PeterB * src/sendmsg-window.c: don't try to set NULL language for spell-checking; remember if user set utf8. 2006-01-27 Albrecht Dreß * libbalsa/misc.c: a new attempt for proper quote highlighting re's in the composer. * src/balsa-mime-widget-text.c: fixed the never ending highlighting. * libbalsa/rfc3156.c: remove gnome dependency. * configure.in: mime icon install configuration. * images/Makefile.am: ditto. 2006-01-26 05:42 PeterB * src/sendmsg-window.c: leave draft-message nonNULL. 2006-01-24 Pawel Salek * src/main.c, src/ab-main.c: achieve compatibility with libgnome-devel-2.13.7 (bug 178650). 2006-01-24 12:17 PeterB * libbalsa/mailbox.c: update view-filter before setting threading. * src/filter-run-callbacks.c: scroll to selected filter. 2006-01-23 19:02 PeterB * libbalsa/mailbox_mbox.c: check cache file more carefully; better buffering in readln. * src/sendmsg-window.c: initialize retval. 2006-01-22 20:49 PeterB * src/: sendmsg-window.c, sendmsg-window.h: simpler utf8-confirmation; delete draft message if it was auto-saved but not user-saved. 2006-01-22 PeterB, Albrecht Dreß * src/sendmsg-window.c: dialogs suggested by Mişu Moldovan . 2006-01-22 14:30 PeterB * libbalsa/mailbox_mbox.c: use our own rdline function. * libbalsa/mailbox_mbox.c: step to a From_ line before parsing. * libbalsa/mailbox.c: prepare parent messages for threading as well as siblings. 2006-01-20 11:15 PeterB * src/sendmsg-window.c: restore state only for continued messages. * src/: sendmsg-window.c, sendmsg-window.h: fix saving and restoring spell-checker state when postponing; build --without-gtkspell. 2006-01-19 23:27 PeterB * src/sendmsg-window.c: save format=flowed or fixed, and spell-check-language, when postponing a message. 2006-01-18 14:36 PeterB * libbalsa/: mailbox_local.c, mailbox_local.h, mailbox_maildir.c, mailbox_mbox.c, mailbox_mh.c: don't set first-unread to a deleted message; check recent messages for message/partial; load-message is a LibBalsaMailboxLocal method; prepare all recent messages for threading. * src/main.c: reset LibBalsaProgress when we're done with the progress bar. 2006-01-17 13:45 PeterB * src/balsa-index.c: scroll-on-open immediately, not in idle handler. 2006-01-16 18:09 PeterB * src/main.c: re-enable updating progress bar from a subthread, using gdk lock. * libbalsa/mailbox_local.c: downgrade information messages to debug. * libbalsa/libbalsa.h: fix mangled comment. * src/balsa-index.c: schedule only one idle callback when mailbox is changed. * libbalsa/libbalsa.h, src/main.c: use symbolic constants; disable updating progress bar from a subthread. 2006-01-15 Albrecht Dreß * libbalsa/message.h, libbalsa/send.c, src/sendmsg-window.c: save and restore crypto and MDN settings when postponing and continuing. 2006-01-14 19:20 PeterB * src/: balsa-index.c, main-window.c: no need to prepare threading--mailbox code takes care of caching info. * libbalsa/mailbox.c: show progress when filtering-on-reception. * libbalsa/mailbox_local.c, src/main.c: use new LibBalsaProgress api. * libbalsa/mailbox.c: copy flags when copying message instead of getting message; show progress when reassembling message/partial; use new LibBalsaProgress api. * libbalsa/: libbalsa.c, libbalsa.h: simplify LibBalsaProgress and make it more opaque. 2006-01-13 22:15 PeterB * libbalsa/mailbox.c, libbalsa/mailbox_local.c, src/balsa-index.c, src/main-window.c, src/main.c: simplify progress bar updates; use it for filtering. * libbalsa/mailbox_mbox.c: save mailbox info with glib < 2.8; disable debug output. 2006-01-14 Chao-Hsiung Liao * configure.in: Add "zh_HK" to ALL_LINGUAS. 2006-01-12 12:08 PeterB * libbalsa/mailbox.c: must use get-message to get the flags. 2006-01-11 15:45 PeterB * src/balsa-mime-widget-text.c: one more. * src/balsa-mime-widget-text.c: use glib's type conversion macros for gint <=> gpointer. * src/sendmsg-window.c: build with gcc < 4.1. * libbalsa/mailbox_mbox.c: better: use %zd format specifier. * libbalsa/mailbox_mbox.c: cast value to gint for g_print. * libbalsa/: mailbox.c, message.c: reset stream after loading envelope. * libbalsa/mailbox.c: reset stream before adding message. * src/: main-window.c, toolbar-factory.c: add optional toolbar button for expunge. * src/pref-manager.c, src/save-restore.c, libbalsa/smtp-server.c, libbalsa/smtp-server.h: implement and use libbalsa_smtp_server_add_to_list--deletes existing server if new name is a duplicate. * libbalsa/mailbox_mbox.c: don't include From_ line in message length. 2006-01-10 23:43 PeterB * libbalsa/message.c: set message->size from g_mime_stream_length(). * src/main.c: use g_idle_add and data instead of g_io_add_watch and pipes. * src/main-window.c, src/main-window.h: set progress text in status bar; run main loop only if needed. * libbalsa/mailbox_mbox.c: save and restore message info. * src/balsa-index.c: prepare threading/sorting before setting non-flags-only filter. * libbalsa/mailbox_local.c: cache file is not created for empty mailbox. * libbalsa/mailbox.c: use progess bar when copying messages. * src/balsa-index.c, src/main-window.c, src/main-window.h, src/main.c, libbalsa/libbalsa.c, libbalsa/libbalsa.h: use progress bar to show fractional progress; implement wrappers for libbalsa; use it when preparing for threading/sorting. * libbalsa/: mailbox.c, mailbox_local.c, mailbox_maildir.c, mailbox_mbox.c, mailbox_mh.c: simplify local mailbox caching; use progress bar. * src/information-dialog.c: do not stack status-bar messages. * libbalsa/: mime-stream-shared.c, mime-stream-shared.h: shared lock for LibBalsaMimeStreamShared. 2006-01-10 Albrecht Dreß * libbalsa/misc.c, libbalsa/misc.h, src/balsa-mime-widget-text.c, src/sendmsg-window.c, src/sendmsg-window.h: configure GtkSourceView with default=no; use it for hacker-highlighting and multi-level undo. 2006-01-09 10:49 PeterB * src/balsa-message.c: g_return_* argument must not have side-effects. 2006-01-06 Pawel Salek * configure.in, NEWS: release 2.3.9. 2006-01-06 08:48 PeterB * src/main-window.c: check that Balsa didn't quit. 2006-01-05 Albrecht Dreß * configure.in: GnuPG encryption is stable. 2006-01-05 20:35 PeterB * libbalsa/mailbox.c: always set tree-changed if msgno is removed. * libbalsa/misc.c: check for anonymous tag. 2006-01-04 20:48 PeterB * libbalsa/address.c: don't use InternetAddress::name if it's non-NULL but empty. * libbalsa/: mailbox.c, mailbox.h, mailbox_imap.c, mailbox_local.c: new member LibBalsaMailbox::msg_tree_changed; use it to save tree only when needed; manage mailbox->view_filter in mailbox.c. 2006-01-03 22:27 PeterB * libbalsa/libbalsa.c: more careful mailbox lock. 2006-01-01 14:10 PeterB * src/: balsa-app.h, sendmsg-window.c: build without GTKSPELL. 2006-01-01 Carlos Morgado * src/sendmsg-window.c, src/balsa-app.h: fix build without GTKSPELL (first commit!!) 2005-12-31 09:27 PeterB * libbalsa/mailbox_local.c: set first-unread when restoring the tree. * src/balsa-index.h: deadwood. 2005-12-31 08:01 Albrecht Dreß * src/: sendmsg-window.c, sendmsg-window.h: keep spell-check menu-item consistent with toolbar button. 2005-12-30 12:15 PeterB * libbalsa/mailbox_local.c: downgrade warnings to messages and make them more people-friendly. 2005-12-29 20:16 PeterB * src/: balsa-app.c, balsa-app.h, save-restore.c, sendmsg-window.c: handle GtkSpell errors; reattach spell-checker when language is changed; spell-checker language persists until spell-checking is disabled. * libbalsa/mailbox_local.c: special-case flags-only view-filter; prepare threading for all messages in the mailbox. 2005-12-28 07:39 PeterB * libbalsa/imap-server.c: lock imap-servers before checking for non-NULL. 2005-12-28 Pawel Salek * libbalsa/imap-server.c: yet another shot at portable mutex locking. 2005-12-27 16:25 PeterB * libbalsa/imap-server.c: do not try to lock when no servers have been created. * libbalsa/mailbox_mbox.c: make sure message is cached at mailbox-local and mailbox levels. 2005-12-27 Pawel Salek * configure.in, NEWS: release 2.3.8. 2005-12-27 12:33 PeterB * libbalsa/: imap-server.c, server.c: build with gcc-4.1. * libbalsa/mailbox_local.c: check msgno before accessing array. 2005-12-26 23:22 PeterB * src/balsa-index.c: remove unnecessary gdk_threads_{leave,enter}; undo SOS filter before closing, so we save the tree that we need when reopening. * libbalsa/mailbox_local.c: cache sender for filtering; save-tree-file with one record is OK. * libbalsa/mailbox_local.c: use g_file_set_contents when available. 2005-12-25 18:50 PeterB * libbalsa/mailbox.c: disable some time-consuming sanity checks. * libbalsa/mailbox_local.c: more robust, less time-consuming tree file checking. 2005-12-24 23:31 PeterB * src/: balsa-index.c, balsa-index.h: scroll in an idle handler; use prepare-theading. * libbalsa/: mailbox.c, mailbox.h, mailbox_imap.c, mailbox_local.c, mailbox_local.h, mailbox_maildir.c, mailbox_mbox.c, mailbox_mh.c: save and restore sorted and threaded view. 2005-12-23 22:02 PeterB * libbalsa/address-book.c, src/balsa-mime-widget-callbacks.c, src/print.c: harmonize strings. * src/balsa-message.c, libbalsa/identity.c, libbalsa/misc.c, libbalsa/send.c, src/sendmsg-window.c: fix strings (Mişu Moldovan) and comment them (Jean-Luc Coulon). 2005-12-19 07:22 PeterB * src/balsa-mime-widget.c: lock a GMimeStream. 2005-12-18 Pawel Salek * libbalsa/mailbox_imap.c(find_duplicates): do not send UID=0. * libalsa/mailbox.c: attempting to expunge read-only mboxes would be a waste of time. 2005-12-15 Pawel Salek * libbalsa/send.c: use proper time zone in Date: (bug 323871). * src/balsa-index.c: disconnect "selection-changed" handler explicitely - do not trash on mbox close with gtk2-2.8.9. 2005-12-13 08:03 PeterB * src/: sendmsg-window.c, sendmsg-window.h: fix bug 323871; clean up undo/redo. 2005-12-11 18:14 PeterB * src/mailbox-conf.c: use new api for libbalsa_mailbox_local_set_path. * libbalsa/: mailbox_maildir.c, mailbox_maildir.h, mailbox_mbox.c, mailbox_mbox.h, mailbox_mh.c, mailbox_mh.h: implement check-files and set-path methods; simplify new and get-message methods; fixes bug 323448. * libbalsa/: mailbox_local.c, mailbox_local.h: new class methods check-files and set-path; change api for libbalsa_Mailbox_local_set_path. * libbalsa/: mailbox_local.c, mailbox_mh.c, mailbox_mh.h, message.c: fix bug 323448. * src/: toolbar-factory.h, toolbar-prefs.h: remove some obsolete defines and replace some others with an enum. 2005-12-09 Jens Granseuer * src/sendmsg-window.c: compile with gcc-2.95 (bug 323617). * libbalsa/send.c: compile --without-smtp (bug 323618). * src/sendmsg-window.c: compile --without-gtkspell (PS). 2005-12-08 07:43 PeterB * src/: save-restore.c, sendmsg-window.c: remember spell-check state when using GtkSpell (Marcin Deranek, bug 323458). * src/pref-manager.c: no spell-check options when using GtkSpell. * src/: balsa-app.c, balsa-app.h: spell-check members are conditional on HAVE_GTKSPELL. 2005-12-07 Pawel Salek * libbalsa/identity.c: fix a warning with gcc-3.4.x * libbalsa/mailbox_imap.c: use proper arguments to the server-changed signal, fixing a possible crash on server settings' update. 2005-12-07 13:35 PeterB * src/filter-run-callbacks.c: fix bug 323442. 2005-12-04 Pawel Salek * NEWS: release 2.3.7. 2005-12-03 Pawel Salek * balsa.spec.in: require gmime-2.1.17. * libbalsa/{imap-,smtp-,}server.c: clean up saving the config, enable anonymous access. * libbalsa/server.h: add try_anonymous field and config-changed signal. * libbalsa/mailbox_imap.c: ditto. * libbalsa/imap/imap-handle.[hc]: respect name space. * src/balsa-app.c: respect "remember password" checkbox in the password dialog. * src/balsa-index.c: remove redundant scroll_to_cell() call. * src/{folder,mailbox}-conf.c: config anonymous access. * src/mailbox-node.c: listen to "config-changed" signal. * src/save-restore.c: the same. * doc/C/balsa.xml: document anonymous access. 2005-11-28 15:19 PeterB * src/balsa-message.c, src/sendmsg-window.c, libbalsa/filter.c, libbalsa/mailbox_local.c, libbalsa/message.c, libbalsa/message.h, libbalsa/send.c: implement and use accessors for user-headers. 2005-11-27 08:34 PeterB * libbalsa/identity.c: GtkFileChooserButton requires gtk version 2.6. 2005-11-26 16:35 PeterB * libbalsa/mailbox_mbox.c: don't leak message. * libbalsa/mailbox_pop3.c: adjust total size for skipped messages. 2005-11-26 Pawel Salek * libbalsa/identity.c: add missing #include "misc.h" * libbalsa/mailbox_pop3.c: handle procmail-filtered messages. * src/main-window.[hc]: fix a regression: set right default view filter for sentbox. * src/balsa-index.c: * src/balsa-mblist.c: ditto. 2005-11-19 08:47 PeterB * src/balsa-index.c: don't scroll back to current message after mailbox changes. * src/sendmsg-window.c: create Face or X-Face user header from path in identity. * src/balsa-message.c: display face from Face or X-Face header. * libbalsa/send.c: use user-headers correctly. * libbalsa/: misc.c, misc.h: new public methods libbalsa_get_image_from_{,x_}face_header and a corresponding GError domain. * libbalsa/: identity.c, identity.h: port signature-path to GtkFileChooserButton; add Face and X-Face header file paths; change some prototypes to reduce dynamic casting. * configure.in: new configure option --with-compface=no. * acinclude.m4: stop some autotool whining. 2005-11-09 19:11 PeterB * libbalsa/: mailbox.c, mailbox.h, mailbox_imap.c, mailbox_maildir.c, mailbox_mbox.c, mailbox_mh.c, mailbox_pop3.c, message.c, message.h, send.c: change LibBalsaMailbox add-message method to take a GMimeStream and LibBalsaMessageFlag instead of a message; move libbalsa_mailbox_copy_message to message.c and rename libbalsa_message_copy; use new add-message method in mailbox-pop3. 2005-11-06 21:15 Pawel Salek * libbalsa/mailbox_pop3.c: use Mh temporary mailbox until an add_message_from_stream() method is implemented. 2005-11-06 13:42 PeterB * libbalsa/mailbox_mh.c: implement load-config method; use g_mkstemp to make temporary files; sync mailbox even if .mh_sequences doesn't exist. * libbalsa/mailbox_pop3.c: use g_file_open_tmp to open the temp file. 2005-11-06 Pawel Salek * libbalsa/mailbox_pop3.c: last commit broke direct Pop delivery - fix it. * src/sendmsg-window.c: fix compilation without GtkSpell. * Makefile.am: make variables must start in the first column. 2005-11-05 17:15 PeterB * src/Makefile.am: define balsa_gtkspell_extra_dist before using it. * configure.in, src/Makefile.am, src/sendmsg-window.c, src/sendmsg-window.h, src/toolbar-factory.c: new configure option --with-gtkspell, default = no. * src/main-window.c: don't clip close-button icon. 2005-11-04 18:53 PeterB * configure.in: gtkhtml3 has yet another version: 3.8. 2005-11-02 Pawel Salek * libbalsa/mailbox_pop3.c: no need to update config; fix memory leaks. * src/save-restore.c: "config-updated" signal does not exist any more. 2005-10-30 07:54 PeterB * src/sendmsg-window.c: do not mark forwarded message as answered. 2005-10-29 Pawel Salek * src/main-window.[ch]: iron out problems with the last patch * src/balsa-index.c: and switching between different mboxes. 2005-10-29 Pawel Salek * libbalsa/mailbox_imap.c: last commit could trigger recursive searches under certain circumstances. Do it differently. * libbalsa/mailbox.c: more information about move errors. * libbalsa/imap/imap-auth.c: AUTH={PLAIN,ANONYMOUS} implemented. * libbalsa/imap/imap-handle.[hc]: anon support. * libbalsa/imap/imap-search.c: fix a bug in searching. * libbalsa/imap/imap_private.h: add enable_anonymous and enable_binary fields. * libbalsa/imap/pop3.c: minor cleanup. * src/balsa-index.[hc]: extend SoS filter. * src/main-window.[hc]: related changes. 2005-10-28 Pawel Salek * libbalsa/mailbox_imap.c: fix unread msg counts on concurrent mbox access. 2005-10-28 06:37 PeterB * src/: sendmsg-window.c, sendmsg-window.h: use separate members for the message we're replying to, and the draft message we saved. * libbalsa/mailbox_local.c: reverse a loop. * libbalsa/mailbox_mbox.c: look for appended messages in the correct place; always save the from-offset as the start of the message. 2005-10-27 17:56 PeterB * src/save-restore.c: set filters-trash-mbox. 2005-10-23 Pawel Salek * NEWS, configure.in: release 2.3.6 2005-10-19 Pawel Salek * libbalsa/imap/imap-tls.c: be compatible with openssl-0.9.8. * libbalsa/libbalsa-conf.c: fix memory leaks. 2005-10-14 06:53 PeterB * libbalsa/mailbox.c: check for NULL user-data. 2005-10-10 Pawel Salek * libbalsa/imap-server.c: distinguish between failed and cancelled authentication. * libbalsa/libbalsa.h: add cancelled authentication error code. * libbalsa/mailbox_imap.c: handle better errors in ::add_message. * libbalsa/imap/imap-auth.c, auth-{cram,gssapi}.c: cancelled vs failed. * libbalsa/imap/libimap.h: add apriopriate error code. * src/balsa-index.c: do not retry if the authentication was cancelled. * src/sendmsg-window.c: * src/spell-check.c: parent properly spell checking error messages. 2005-10-07 11:25 PeterB * libbalsa/libbalsa-conf.c: fix bug 318171. * src/: filter-edit-callbacks.c, save-restore.c: improve language, per Craig Routledge. 2005-10-06 19:22 PeterB * libbalsa/mailbox.c: sanity check. * src/: filter-edit-callbacks.c, filter-edit-dialog.c: fix various sensitivity problems, including one that blocked deleting the last filter. 2005-09-29 13:01 PeterB * libbalsa/body.c, libbalsa/body.h, libbalsa/misc.c, libbalsa/misc.h, src/balsa-message.c, src/balsa-mime-widget-callbacks.c, src/sendmsg-window.c: fix bug 317240: use mode 0666 to save attachments. 2005-09-28 23:06 PeterB * doc/C/balsa.xml: update identities doc. * doc/C/balsa.xml: document per-identity SMTP server and message splitting. 2005-09-27 20:31 PeterB * src/: balsa-message.c, main-window.c: move BalsaMessage show/hide to balsa-message.c; fix a startup visual glitch. * src/main-window.c: hide irrelevant scrollbar--thanks to Sebastian Zerbe. * libbalsa/mailbox_mbox.c: write separating newline before appending new message, not after. * libinit_balsa/balsa-druid-page-directory.c: manage LibBalsaMailbox::no_reassemble. * src/mailbox-node.c, src/save-restore.c, libbalsa/mailbox.c: manage and use LibBalsaMailbox::no_reassemble; check for a message/partial part that has been wrapped in a multipart/* message. * libbalsa/mailbox.h: new member LibBalsaMailbox::no_reassemble, used to distinguish outbox. * libbalsa/rfc3156.c: check that a GMimeMultipartSigned has both its subparts. 2005-09-22 10:28 PeterB * libbalsa/: mailbox.c, mailbox_imap.c, mailbox_maildir.c, mailbox_mbox.c, mailbox_mh.c: update parent style when child is read. * libbalsa/body.c: allow saving non-GMimePart message parts. 2005-09-20 23:05 PeterB * libbalsa/: mailbox.c, mailbox_mbox.c, send.c: implement message fragmentation and reconstruction using "message/partial" mime type. * libbalsa/: smtp-server.c, smtp-server.h: add guint LibBalsaSmtpServer::big_message and manage it in the dialog. 2005-09-20 Pawel Salek * libbalsa/imap/imap-handle.c: handle lack of headers. * NEWS, configure.in: release 2.3.5 2005-09-15 10:12 PeterB * libbalsa/: mailbox.c, mailbox.h, mailbox_mbox.c: fix unthreaded build. 2005-09-14 Craig Routledge * doc/C/balsa.xml: update compose window file attaching doc. 2005-09-13 Pawel Salek * libbalsa/mailbox_imap.c: return correctly TRUE/FALSE on success. * src/spell-check.c: unavailable word list is a critical error. 2005-09-13 09:36 PeterB * libbalsa/: mailbox.c, mailbox.h, mailbox_mbox.c: implement lock_store class method and public functions. * src/balsa-index.c, libbalsa/body.c, libbalsa/gmime-part-rfc2440.c, libbalsa/html.c, libbalsa/message.c, mailbox_imap.c, mailbox_maildir.c, mailbox_mh.c, libbalsa/rfc3156.c, libbalsa/send.c, libbalsa/source-viewer.c, src/balsa-message.c: lock the mail store instead of a GMimeStream, to avoid unnecessary IMAP fetches. 2005-09-11 Carlos Morgado * po (Module): update for stats 2005-09-06 Pawel Salek * configure.in: SuSE changes broke FC. Negotiate a common solution. 2005-09-05 Pawel Salek * configure.in: merge SuSE kerberos path fixes. * libbalsa/body.[hc]: provide more info on error in save(), save_fd(), save_temporary(), get_content() and get_stream(). * libbalsa/libbalsa.h: add MAILBOX_ACCESS_ERROR code. * libbalsa/mailbox.[ch]: get_message_part() sets GError. * libbalsa/mailbox_{imap,local}.c: modify implementation accordingly. * libbalsa/{message,mime}.c: adjust to changed API. * src/balsa-message.c: ditto. * src/balsa-mime-widget-{callbacks,message,text}.c: * src/balsa-mime-widget.c: ditto. * src/print.c: * src/sendmsg-window.c: ditto when forwarding message. 2005-09-01 11:04 PeterB * src/pref-manager.c: connect file-chooser signal in an idle handler, after the chooser is initialized; test whether user changed window-layout; update toolbars if necessary. 2005-08-28 11:29 PeterB * src/balsa-index.c: simpler fix. * src/balsa-index.c: redisplay current message if filtering cleared it. 2005-08-25 19:55 PeterB * src/pref-manager.c: fix spacing. 2005-08-25 Pawel Salek * configure.in: support selection of the preferred GtkHtml widget. * README: matching description. * libbalsa/address-book-ldap.[ch]: support arbitrary locations of the private address book. * libbalsa/send.c: handle informatively errors of DATA command. * src/ab-window.c: fix reload action. * src/address-book-config.c: support extended LDAP config. * src/balsa-index.c: "Run" is the default action of "Pipe through" 2005-08-22 07:46 PeterB * doc/C/balsa.xml: cleanup. * src/toolbar-factory.c: set button label and tooltip appropriately. 2005-08-21 Jens Seidel * src/filter-export-callbacks.c: * macros/gnome-bonobo-check.m4: * libbalsa/mailbox_mbox.c: Fixed the typo "occured" (also in all effected PO files to avoid fuzzyness) 2005-08-21 09:04 PeterB * doc/C/: balsa.xml, figures/message-window.png, figures/msg-part-select.png: message window documentation contributed by Craig Routledge ; fix "unmatched element" warnings. 2005-08-17 19:03 PeterB * src/balsa-app.c: free filters after destroying mailboxes (fixes a crash-on-exit). 2005-08-04 14:14 PeterB * src/filter-run-callbacks.c, src/filter-run-dialog.c, src/filter-run.h, doc/C/balsa.xml: use separate "apply" buttons for selected available filters and for mailbox filters. 2005-08-01 09:35 PeterB * src/sendmsg-window.c: better fix for bug 312105; plug memory leak. 2005-07-31 22:26 PeterB * src/sendmsg-window.c: fix bug 312105. * src/sendmsg-window.c: fix bug 312091. 2005-07-29 09:52 PeterB * src/: balsa-mime-widget-text.c, sendmsg-window.c: fix some gcc nitpicking. 2005-07-27 18:54 PeterB * libbalsa/libbalsa-conf.c: use blank comment lines only to separate groups. * libbalsa/gmime-gpgme-context.c: compile with -D_FORTIFY_SOURCE=2. 2005-07-24 Carlos Morgado * libbalsa/rfc3156.c: fix FC4 build 2005-07-24 09:03 PeterB * configure.in, src/save-restore.c, src/threads.h, libbalsa/address-book-extern.c, libbalsa/libbalsa.c, libbalsa/mailbox_imap.c, libbalsa/mailbox_mbox.c, libbalsa/mailbox_mh.c, libbalsa/send.c, libbalsa/send.h, libbalsa/imap/imap-commands.c, libbalsa/imap/imap-handle.c: compile with -D_FORTIFY_SOURCE=2. * src/balsa-mime-widget-message.c: do not create separate Fcc header. * libbalsa/message.c: make a single References user-header. * libbalsa/abook-completion.c: match quoted names and angle-bracketed mailboxes. 2005-07-23 Pawan Chitrakar * configure.in: Added ne in ALL_LINGUAS 2005-07-18 08:04 PeterB * src/sendmsg-window.c: make References header according to RFC 2822. 2005-07-15 10:53 PeterB * src/sendmsg-window.c: replace CR and LF in subject header with spaces. 2005-07-12 13:32 PeterB * src/save-restore.c: fix typo; clean up old filters correctly. * src/filter-edit-dialog.c: set button sensitivity when filter name is changed. * libbalsa/: libbalsa-conf.c, libbalsa-conf.h: use default GKeyFile list separator; implement libbalsa_conf_get_vector_with_default directly instead of as a macro. 2005-07-11 12:32 PeterB * src/store-address.c: use balsa_information instead of writing in appbar. * src/spell-check.c: use values from correct enum. * src/mailbox-node.c: use consistent return sequence. * src/: filter-edit-callbacks.c, filter-edit-dialog.c, filter-edit.h: use a single field-frame. 2005-07-09 23:33 PeterB * src/information-dialog.c: use only single-line messages in status bar. 2005-07-08 Pawel Salek * configure.in: -Wdeclare-after-statement is gcc>=4.0 specific. 2005-07-07 23:27 PeterB * src/balsa-index.c: lock a GMimeStream. * src/: save-restore.c, save-restore.h: export config_address_books_load. * src/mailbox-node.c: downgrade scanning problem from error to warning. * src/balsa-app.c: clean up. * src/address-book-config.c: no need to include address-book-gpe.h. * src/: ab-window.c, ab-window.h: reimport all address books after editing. * src/ab-main.c: show default address book initially. * libbalsa/rfc3156.c, src/pref-manager.c, src/sendmsg-window.c: translate strings marked for translation. * libbalsa/: libbalsa.c, libbalsa.h: include address-book-gpe.h in libbalsa.h. * libbalsa/libbalsa-conf.c: detect external modification of config file. * configure.in: catch declaration-after-statement. 2005-07-06 Jens Granseuer * src/filter-run-callbacks.c: fix bug 309574. 2005-07-06 Pawel Salek * src/ab-window.c: use our address book editor. * NEWS, configure.in: release balsa-2.3.4. 2005-07-01 16:14 PeterB * libbalsa/mailbox_pop3.c: destroy LibBalsaMailboxView for POP temporary mailbox. 2005-07-01 Pawel Salek * libbalsa/imap/pop3.c: fix handling rejected POP3 TLS certs #308932. 2005-06-30 21:41 PeterB * libbalsa/imap/imap-commands.c: use more of the GString api. * src/address-book-config.c: make sure filename is shown for LibBalsaAddressBookText. * src/ab-main.c: show address book type in window title; implement File->delete. * libbalsa/address-book-text.c: invalidate time stamp when we change the address book. * libbalsa/address-book-ldif.c: ensure blank line before new entry. * src/main-window.c: make progress bar faster than a snail. * libbalsa/libbalsa-conf.c: use g_file_set_contents to rewrite config files. 2005-06-24 Albrecht Dreß * libbalsa/body.[hc]: implement libbalsa_message_body_protect_state(). * src/Makefile.am: add 7+7 balsa-mime-widget source files. * src/balsa-message.[ch]: use the cleaner design from balsa-mime-widget. 2005-06-22 Pawel Salek * libbalsa/mailbox_imap.c: fix date searching when only upper limit is present. * libbalsa/mailbox_pop3.c: fix memory leak. * libbalsa/imap/imap-search.c: date::range must be signed. * src/filter-edit-callbacks.c: clean up filter dialog. * src/filter-run-{callbacks,dialog}.c: fix "run filters". * src/filter-run.h: add fr_apply_pressed() prototype. 2005-06-17 08:31 PeterB * libbalsa/address-book-vcard.c, libbalsa/address.c, src/Makefile.am, src/ab-main.c, src/address-book-config.c, src/address-book-config.h: implement File->New and File->Properties in balsa-ab. 2005-06-16 Pawel Salek * libbalsa/imap/auth-gssapi.c: 6th parameter to gss_{un,}wrap is int*. 2005-06-14 12:48 PeterB * src/sendmsg-window.c: clear BalsaSendmsg::in_reply_to. * src/sendmsg-window.h: omitted from yesterday's commit. 2005-06-13 23:59 PeterB * src/sendmsg-window.c: create in-reply-to string when we begin a reply, so we can save and restore it without reference to the original message. * src/: balsa-message.c, information-dialog.c: use GTK_WRAP_WORD_CHAR instead of GTK_WRAP_WORD, to allow wrapping of long words. * libbalsa/misc.c: trim trailing whitespace beyond the wrap length. * src/balsa-app.h: use only Monospace and Sans as default fonts. 2005-06-11 Pawel Salek * libbalsa/imap/imap-handle.c: fix trivial bug introduced yesterday. 2005-06-10 Pawel Salek * libbalsa/mailbox_imap.c: survive better cases when number of messages changed in the broken connection. Resync header caches more aggresively. * libbalsa/imap/imap-commands.c: use UID search support. * libbalsa/imap/imap-handle.h: allow searching ranges of messages. * libbalsa/imap/imap-handle.c: never insert cmd==0 to response queue. * libbalsa/imap/imap-search.c: implement it. * src/ab-window.c: Fix "No-address-book" case (bug 158939). * src/main-window.[hc]: ditto. * src/pref-manager.c: ditto. 2005-06-08 Andrew Lau * libbalsa/address-book-ldap.c: include "i18n.h". 2005-06-08 14:13 PeterB * src/balsa-message.c, src/print.c, src/sendmsg-window.c, libbalsa/libbalsa.c, libbalsa/libbalsa.h, libbalsa/mailbox.c, libbalsa/message.h: rename libbalsa_date_to_gchar as libbalsa_date_to_utf8, and return a UTF-8 string. * src/ab-main.c: reuse edit widget for smoother update; reload address book after changing it. * src/address-book-config.c: use new LibBalsaAddressBook subclass structure. * libbalsa/Makefile.am: add dependencies. * libbalsa/: address.c, address.h: use an editable GtkTreeView to edit email addresses; implement libbalsa_address_set_edit_entries to reuse an edit widget. * libbalsa/: address-book-ldif.c, address-book-ldif.h, address-book-text.c, address-book-text.h, address-book-vcard.c, address-book-vcard.h, address-book.c, address-book.h: new class LibBalsaAddressBookText, subclass of LibBalsaAddressBook, with LibBalsaAddressBook{Ldif,Vcard} as subclasses. 2005-06-07 11:56 PeterB * libbalsa/: rfc3156.c, gmime-part-rfc2440.c: lock GMimeStreams. 2005-06-06 Pawel Salek * libbalsa/gmime-gpgme-signature.c: check gpgme_get_key() result. * libbalsa/libbalsa.c: fix bug 306666. * libbalsa/send.c: allow the user to check certificates w/o threads. * src/main-window.c: mbnode->name can be NULL - do not use it and perhaps fix 306636. * NEWS: update for real 2.3.3 release this time. 2005-06-05 Pawel Salek * libbalsa/mailbox_imap.c: Peter found one more fault in imap scanning. * NEWS, configure.in: update for release 2.3.3 2005-06-04 Pawel Salek * balsa.spec.in: extend list of dependencies. * libbalsa/folder-scanners.c: flags are passed by value. * libbalsa/imap/auth-gssapi.c: continue authentication on invalid key. * libbalsa/imap/imap-handle.c: pass flags by value - address was truncated by the marshaller on 64-bit machines. 2005-06-01 20:54 PeterB * libbalsa/message.c: lock a GMimeStream. 2005-05-28 23:12 PeterB * libbalsa/libbalsa.c: look for /var/mail/$USER before /var/spool/mail/$USER: fixes bug 305659. * src/mailbox-node.c: make popup menu more appropriate: fixes bug 305668. 2005-05-26 16:13 PeterB * src/ab-main.c: make radio list work; set window title to be address book name. * libbalsa/source-viewer.c: lock a GMimeStream. 2005-05-24 09:09 PeterB * libbalsa/gmime-part-rfc2440.c: lock a GMimeStream. 2005-05-24 Albrecht Dreß * libbalsa/gmime-gpgme-signature.c: fix the signature verification output. * src/balsa-message.c: check the result of libbalsa_mailbox_get_message_part(). * balsa.spec.in: clean up and fedora extras adaptation. 2005-05-23 19:36 PeterB * configure.in, libbalsa/address-book-gpe.c, libbalsa/address-book-gpe.h, src/address-book-config.c: support SQLite Version 3--fixes bug 305152. * libbalsa/libbalsa-conf.c: compile on systems where gsize != guint. 2005-05-22 17:11 PeterB * libbalsa/: Makefile.am, body.c, gmime-part-rfc2440.c, html.c, mailbox_imap.c, mailbox_maildir.c, mailbox_mbox.c, mailbox_mh.c, message.c, mime-stream-shared.c, mime-stream-shared.h, rfc3156.c, send.c: implement LibBalsaMimeStreamShared, a subclass of GMimeStreamFs with a lock; use it in LibBalsaMailboxMbox in place of the fine-grained mailbox lock. 2005-05-21 Pawel Salek * libbalsa/mailbox_imap.c: get properly signed parts. * src/balsa-message.c: do not reset status of a checked sig. 2005-05-21 09:41 PeterB * src/save-restore.c: save message counts only when they are time-stamped. 2005-05-20 23:56 PeterB * libbalsa/mailbox.c, libbalsa/mailbox.h, libbalsa/mailbox_maildir.c, libbalsa/mailbox_maildir.h, libbalsa/mailbox_mbox.c, libbalsa/mailbox_mh.c, libbalsa/mailbox_mh.h, src/save-restore.c: save and restore mod_time for local mailboxes. 2005-05-12 18:08 PeterB * libbalsa/mailbox_mbox.c: use light-weight parser at get-message time. * src/save-restore.c: really remove unused mailbox views. * libbalsa/address-book-extern.c: fix last part of bug 155382. 2005-05-09 08:32 PeterB * src/balsa-index.c: non-modal pipe-message dialog. 2005-05-07 Pawel Salek * libbalsa/libbalsa{,-conf}.c: disable debugging output. * NEWS, configure.in: release 2.3.2 2005-05-07 Pawel Salek * balsa.1.in: merge patch in DBTS #269787, bugzilla 303422. * libbalsa/address-book-extern.c: fix DBTS#306556, bugzilla 303421. * libbalsa/address-book-gpe.c: remove duplicates from the returned list. * src/ab-window.c: select initially displayed list in the combo. * src/address-book-config.c: fix bad_path() for gtk < 2.6.0. * src/pref-manager.c: Display type of extern address book. * src/balsa-app.c: do not crash when non-existing mailbox specified with -o. * src/balsa-mblist.c: fix -u command line option. * src/main.c: ditto + fix -a when passing it via bonobo. 2005-05-06 23:19 PeterB * src/save-restore.c: slightly more 2.0.x compatibility. * libbalsa/mailbox_mbox.c: use a separate pthread_mutex_t for lbm_mbox_mime_stream_lock(). * src/: filter-edit-callbacks.c, filter-edit-dialog.c, filter-edit.h: manage button sensitivity better. 2005-05-06 Pawel Salek * src/mailbox-conf.c: do not attempt opening closed mailboxes just because their configuration is about to get changed. * src/save-restore.c: s,sa --learn,sa-learn --spam,g. 2005-05-04 Pawel Salek * libbalsa/imap/imap-handle.c: nail down the broken IDLE connection problem. 2005-05-03 22:43 PeterB * src/: balsa-app.h, balsa-index.c, balsa-index.h, main-window.c, save-restore.c: add a drop-down list of most recently used pipe commands; pipe all selected messages through command. * libbalsa/mailbox.c, libbalsa/mailbox.h, libbalsa/mailbox_imap.c, libbalsa/mailbox_maildir.c, libbalsa/mailbox_mbox.c, libbalsa/mailbox_mh.c, libbalsa/message.c, libbalsa/message.h, libbalsa/send.c, libbalsa/source-viewer.c, src/main-window.c: replace message argument of libbalsa_mailbox_get_message_stream with msgno; implement and use libbalsa_message_stream(LibBalsaMessage * message). 2005-05-02 23:58 PeterB * libinit_balsa/balsa-druid-page-user.c: fix bug 302782. 2005-05-02 Pawel Salek * NEWS, configure.in: release 2.3.1. * libbalsa/mailbox_imap.c: handle empty msg-id over imap right. 2005-05-01 Pawel Salek * libbalsa/mailbox_imap.c: implement remove-duplicates for imap too. * libbalsa/imap/imap-commands.c: FetchBodyCb callbacks get seqno now. * libbalsa/imap/imap-commands.h: add imap_mbox_complete_msgids. * libbalsa/imap/imap-handle.c: handle arbitrary header fetches. 2005-04-30 19:57 PeterB * libbalsa/mailbox.c, libbalsa/mailbox.h, libbalsa/mailbox_local.c, src/main-window.c: restore remove-duplicates functionality. 2005-04-28 Pawel Salek * libbalsa/folder-scanners.c: don't break with uw-imap server. 2005-04-27 20:17 PeterB * libbalsa/folder-scanners.c, libbalsa/folder-scanners.h, src/mailbox-node.c: simplify folder scanning. 2005-04-26 14:08 PeterB * libbalsa/identity.c, src/pref-manager.c: compile --without-esmtp and --without-gpgme. 2005-04-21 Pawel Salek * libbalsa/folder-scanners.c: block list-response when asking for a delimiter. * libbalsa/imap-server.[ch]: allow checking for new mail with STATUS. * libbalsa/smtp-server.c: keep old behavior and always save passwd. * libbalsa/imap/imap-commands.[ch]: implement imap_mbox_status(). * libbalsa/imap/imap-handle.c: handle its response. * libbalsa/imap/imap_private.h: even for several issued in parallel. * src/folder-conf.c: configure it. 2005-04-20 21:26 PeterB * src/sendmsg-window.c: simplify setting identity. * libbalsa/imap-server.c, libbalsa/mailbox_pop3.c, libbalsa/server.c, libbalsa/server.h, libbalsa/smtp-server.c, src/folder-conf.c, src/pref-manager.c: lose LibBalsaServer::type. * libbalsa/mailbox.c, libbalsa/mailbox.h, libbalsa/mailbox_maildir.c, libbalsa/mailbox_mbox.c, libbalsa/mailbox_mh.c, src/balsa-mblist.c, src/save-restore.c: add unread and total members to LibBalsaMailboxView, and save them in the config file. * libbalsa/libbalsa-conf.c: preserve blank lines between sections in the config file. 2005-04-19 Pawel Salek * libbalsa/folder-scanners.[hc]: avoid redundant queries for IMAP hierarchy delimiters. * src/mailbox-node.[ch]: ... because we store earlier answers. 2005-04-18 Pawel Salek * libbalsa/imap/imap-handle.c: silence output on the terminal. * src/balsa-icons.c: silence icon debugging. * src/sendmsg-window.c: specify exactly file names in messages - important when attaching multiple messages at once. 2005-04-17 10:57 PeterB * libbalsa/: mailbox.c, mailbox.h, mailbox_local.c: don't keep selected message displayed when changing view filter. 2005-04-16 22:37 PeterB * src/save-restore.c, libbalsa/identity.c: compile with gpgme but without libesmtp. * src/pref-manager.c: append server to balsa_app.smtp_servers when the user OKs it. 2005-04-16 20:23 Pawel Salek * libbalsa/identity.[ch]: compile --without-gpgme * libbalsa/imap/imap-handle.c: survive better broken connections. * src/mailbox-conf.c: generate shorter identity names. * src/save-restore.c: more robust smtp server config loading. 2005-04-16 08:01 PeterB * libbalsa/i18n.h: comment that this header must be included last. * libbalsa/smtp-server.c: include "i18n.h" last. 2005-04-15 17:28 PeterB * libbalsa/Makefile.am, libbalsa/identity.c, libbalsa/identity.h, libbalsa/libbalsa.h, libbalsa/message.c, libbalsa/send.c, libbalsa/send.h, libbalsa/server.h, libbalsa/smtp-server.c, libbalsa/smtp-server.h, libinit_balsa/balsa-druid-page-user.c, src/balsa-app.c, src/balsa-app.h, src/balsa-message.c, src/main-window.c, src/pref-manager.c, src/save-restore.c, src/sendmsg-window.c: implement LibBalsaSmtpServer; use it for per-identity server. 2005-04-12 12:31 PeterB * libbalsa/html.c: convert charset more carefully. 2005-04-10 20:28 PeterB * libbalsa/mailbox_maildir.c: do not overwrite message when renaming. * libbalsa/mailbox_maildir.c: remember correct file name. 2005-04-08 14:30 PeterB * src/save-restore.c: use correct filter group name; remove filter groups with malformed names. 2005-04-07 Albrecht Dreß * src/balsa-message.c: save multiple parts. 2005-04-07 11:18 PeterB * src/sendmsg-window.c: check for NULL charset. 2005-04-06 16:45 PeterB * libbalsa/body.c: ensure stream is a filter-stream. 2005-04-05 20:36 PeterB * src/sendmsg-window.c, src/sendmsg-window.h, libbalsa/filter.c, libbalsa/mailbox_local.c, libbalsa/mime.c, libbalsa/mime.h: yet another shot at finding the best charset in the compose window. * src/sendmsg-window.c: destroy file-chooser dialogs with their parent. 2005-04-05 Pawel Salek * libbalsa/imap/imap-handle.c: proper types for list-response signal handlers. * libbalsa/imap/libimap-marshal.list: ditto. * libbalsa/imap/imap-search.c: compile on darwin. 2005-04-03 Pawel Salek * Makefile.am: s,m4,macros,g; * balsa.spec.in: compile on suse. * configure.in: * libbalsa/imap/auth-gssapi.c: compile against heimdal. 2005-04-01 Steve Murphy * configure.in: Added "rw" to ALL_LINGUAS. 2005-04-01 18:46 PeterB * src/sendmsg-window.c: omit all identity addresses from cc header. * src/balsa-message.c, src/print.c, libbalsa/body.c, libbalsa/html.c, libbalsa/html.h: move charset conversion for html parts to libbalsa/html.c, as it's handled differently by the two widgets. 2005-03-31 19:58 PeterB * src/sendmsg-window.c: remember folder when including file in message content. 2005-03-30 19:45 PeterB * src/balsa-message.c: fix bug 172145. 2005-03-29 21:16 PeterB * src/balsa-message.c: fix bug 172005. * libbalsa/rfc3156.c: pass NULL to g_locale_to_utf8 instead of (ssize_t *), to keep gcc4 quiet. * src/: balsa-message.c, sendmsg-window.c: use glib macros to cast int to pointer and back. 2005-03-26 Albrecht Dreß * libbalsa/rfc3156.c: plug in recently introduced DoS. 2005-03-24 06:59 PeterB * src/ab-main.c: set all locales. * src/main.c: set all locales. * src/main-window.c: make label localizable. 2005-03-24 Pawel Salek * libbalsa/address-book-ldap.c: add missing libbalsa-conf.h * balsa.spec.in: update icon cache after rpm installation. * images/Makefile.am: bug 171388. 2005-03-23 Albrecht Dreß * src/balsa-message.c, libbalsa/gmime-gpgme-context.c, libbalsa/gmime-gpgme-context.h, libbalsa/identity.c, libbalsa/identity.h, libbalsa/rfc3156.c, libbalsa/rfc3156.h, libbalsa/send.c: (1) plug a minor security problem when checking the gpg subkey status; (2) improve dealing with low-validity uid's for encryption; (3) several smaller fixes. 2005-03-23 PeterB * libbalsa/rfc3156.c: fix bug 171415. * libbalsa/address-book-ldap.c, src/ab-main.c: complete migration from GnomeConfig to LibbalsaConf. * src/sendmsg-window.c: strip parameter variables from exec string. 2005-03-22 22:07 PeterB * libbalsa/: libbalsa-conf.c, libbalsa-conf.h: set up correctly for new user. * libbalsa/libbalsa-conf.c: more careful rewrite, more user feedback. * src/main.c: set balsa_icon.png as default window icon. * src/: balsa-message.c, sendmsg-window.c: always pass URI to gnome_vfs_mime_application_launch. * src/sendmsg-window.c: more appropriate version checks. * libbalsa/libbalsa-conf.c: organize key-file info into structures. 2005-03-21 08:08 PeterB * configure.in, src/balsa-message.c, src/sendmsg-window.c: check for GnomeVFS version 2.9 instead of 2.8. 2005-03-20 15:03 PeterB * libbalsa/libbalsa-conf.c: initialize only once in non-threaded build. * libbalsa/libbalsa-conf.c: store new config files in ~/.balsa. * configure.in, libbalsa/misc.c, libbalsa/misc.h, src/balsa-message.c, src/sendmsg-window.c: more appropriate version checks. 2005-03-20 Pawel Salek * src/address-book-config.c: s,GNOME_DISABLE_DEPR,GTK_DISABLE_DEPR, 2005-03-19 23:00 PeterB * libbalsa/libbalsa-conf.h: check Gtk version. * libbalsa/Makefile.am, libbalsa/address-book-ldif.c, libbalsa/address-book.c, libbalsa/body.c, libbalsa/files.c, libbalsa/filter-file.c, libbalsa/filter.h, libbalsa/folder-scanners.c, libbalsa/gmime-part-rfc2440.c, libbalsa/html.c, libbalsa/identity.c, libbalsa/libbalsa-conf.c, libbalsa/libbalsa-conf.h, libbalsa/libbalsa.c, libbalsa/mailbox-filter.c, libbalsa/mailbox.c, libbalsa/mailbox.h, libbalsa/mailbox_imap.c, libbalsa/mailbox_mbox.c, libbalsa/mailbox_mh.c, libbalsa/message.c, libbalsa/misc.c, libbalsa/rfc3156.c, libbalsa/send.c, libbalsa/source-viewer.c, libbalsa/imap/imap-commands.c, libbalsa/imap/imap-commands.h, libbalsa/imap/md5-utils.c, libbalsa/imap/md5-utils.h, libbalsa/imap/util.c, libbalsa/imap/util.h, libinit_balsa/Makefile.am, src/Makefile.am, src/ab-main.c, src/balsa-message.c, src/filter-edit-callbacks.c, src/mailbox-node.c, src/print.c, src/quote-color.c, src/quote-color.h, src/save-restore.c, src/sendmsg-window.c: more Gnome deprecation cleanup, including a GKeyFile replacement for GnomeConfig; fix some nit-picking from gcc 4; restore the *_DISABLE_DEPRECATED defs. * src/sendmsg-window.c: check whether CP125x charset is ok. 2005-03-18 16:29 PeterB * src/main.c: get mbnode before checking it. 2005-03-17 Pawel Salek * libbalsa/imap/imap-handle.c: make the IDLE code behave better on broken connections. * src/balsa-app.h: add pipe_cmd field. * src/main-window.c: allow for piping a message through an external program. (bug 153386). * src/save-restore.c: save and restore last pipe_cmd. 2005-03-16 Pawel Salek * libbalsa/imap/imap-handle.c: provide more info on SSL-related failures. 2005-03-15 Albrecht Dreß * libbalsa/send.c: don't unref NULL GObject. 2005-03-15 13:03 PeterB * libbalsa/body.c: convert charset also for html parts (fixes bug 170456). * libbalsa/mailbox_imap.c: use delim to build path when renaming; use g_build_path() for IMAP paths. 2005-03-14 Albrecht Dreß * libbalsa/message.h, libbalsa/send.c, libbalsa/send.h, src/balsa-app.c, src/balsa-app.h, src/balsa-message.c, src/pref-manager.c, src/save-restore.c, src/sendmsg-window.c: use only quoted-printable encoding. 2005-03-14 19:42 PeterB * libbalsa/body.c: use string returned by g_mime_filter_windows_real_charset() before it's deallocated. 2005-03-10 10:42 PeterB * libbalsa/body.c, libbalsa/filter.c, libbalsa/mailbox_local.c, libbalsa/message.c, libbalsa/mime.c, libbalsa/mime.h, src/sendmsg-window.c, src/sendmsg-window.h: keep track of charset instead of using g_mime_charset_best(). 2005-03-08 18:40 Albrecht Dreß * libbalsa/gmime-part-rfc2440.c: replace use of g_mime_content_type_[gs]et_parameter() by g_mime_object_[gs]et_content_type_parameter(), and g_mime_part_get_content_type() by g_mime_object_get_content_type(). 2005-03-08 10:43 PeterB * libbalsa/: mailbox.c, mailbox.h: remember that we loaded filters. * src/filter-edit-callbacks.c: don't set empty filename; comment out unused LIBESD condition. * libbalsa/Makefile.am, libbalsa/filter-file.c, libbalsa/filter.h, libbalsa/libbalsa-conf.c, libbalsa/libbalsa-conf.h, libbalsa/mailbox-filter.c, src/save-restore.c: move all GnomeConfigIterator code to (new) libbalsa-conf.c; implement GnomeConfig version of libbalsa_conf_foreach_section. 2005-03-04 19:56 Albrecht Dreß * libbalsa/gmime-part-rfc2440.c, src/balsa-message.c, src/balsa-message.h, src/sendmsg-window.c: add and evaluate the RFC 2440 headers properly; write the stream to a new (plain) stream; rename libbalsa_msg_perform_crypto to balsa_message_perform_crypto, add a parameter to decrypt only and export the function; call balsa_message_perform_crypto() to fix the bug Kacper reported. 2005-03-03 20:07 PeterB * libbalsa/: mailbox_mbox.c, mailbox_mbox.h: implement lbm_mbox_mime_stream_{lock,unlock}; use them to avoid interruption of a sequence of GMimeStream operations. 2005-03-01 09:49 PeterB * src/sendmsg-window.c: make file choosers transient for compose window. 2005-02-28 09:09 PeterB * libbalsa/libbalsa.c, libbalsa/libbalsa.h, libbalsa/mailbox.c, src/main.c: move balsa_threads_{enter,leave} to libbalsa/libbalsa.c; change libbalsa_lock_mailbox to reflect recursive gdk lock and remove assumptions about main-thread/sub-thread; hold mailbox lock before asking for gdk lock. * libbalsa/imap/imap-handle.c: downgrade warnings to messages. * libbalsa/misc.c: fix test for " * libbalsa/imap/pop3.c: const char *service should not be static. 2005-02-20 Pawel Salek * balsa.spec.in: icon-related updates. * libbalsa/imap/imap-commands.c: enable IDLE only when really disabled. * libinit_balsa/balsa-druid-page-user.c: do not require incoming server 2005-02-20 12:05 PeterB * src/: balsa-icons.h, balsa-index.c, main-window.c: remove BALSA_PIXMAP_MENU_* definitions. * src/balsa-message.c: make OK the default response in save dialog. 2005-02-20 Craig Routledge * src/main-window.c: bump the date in the about dialog. * doc/C/balsa.xml: bring the Main Window section of the help file up to sync with the user interface. * src/balsa-message.c: add tooltips to the "check crypto" and "attachment" icons. 2005-02-16 20:20 Albrecht Dreß * libbalsa/misc.c, libbalsa/misc.h, src/balsa-message.c, src/sendmsg-window.c: implement libbalsa_ia_rfc2821_equal and use it to exclude self from cc list. 2005-02-16 09:13 PeterB * src/mailbox-conf.c: manage sensitivity of the OK/Update button. 2005-02-15 21:48 Craig Routledge * src/balsa-message.c: better handling of "application/octet-stream". 2005-02-15 21:48 PeterB * src/balsa-message.c: don't allocate unnecessary address strings. * libbalsa/: body.c, mailbox_mbox.c: let GMimeStreams work end-to-end when possible. 2005-02-14 Kjartan Maraas * configure.in: Add «nb» to ALL_LINGUAS. 2005-02-11 19:38 PeterB * src/sendmsg-window.c, libbalsa/misc.c: use "application/octet-stream" as a last resort. 2005-02-09 20:33 PeterB * libbalsa/mailbox.c: don't lock mailbox to change a pseudo-flag. * src/main-window.c: fix the About dialog. 2005-02-08 17:33 PeterB * src/save-restore.c: save the sanitized toolbar. * libbalsa/imap/imap-handle.c: typo. 2005-02-08 Pawel Salek * libbalsa/imap/imap-handle.c: unregister IDLE listener on error. * libbalsa/imap/imap-tls.c: related connection shutting cleanup. * libbalsa/imap/imap_private.h: add imap_handle_disconnect() proto. 2005-02-07 20:45 Albrecht Dreß * src/: save-restore.c, toolbar-factory.c, toolbar-factory.h: fix old toolbar button compatibility. 2005-02-07 Pawel Salek * src/address-book-config.c: compile with gtk-2.4 * balsa.spec.in: distribute new icons. * configure.in: bump version to 2.3.0. * images/24x24/Makefile.am: fix install-data-hook: * libbalsa/Makefile.am: add missing i18n.h file. * libbalsa/mailbox_imap.c: remove debugging output. 2005-02-06 20:43 PeterB * configure.in, images/16x16/Makefile, images/16x16/Makefile.in, images/24x24/Makefile, images/24x24/Makefile.in, libbalsa/address-book-extern.c, libbalsa/address-book-ldif.c, libbalsa/address-book-vcard.c, libbalsa/address-book.c, libbalsa/address.c, libbalsa/body.c, libbalsa/filter-error.c, libbalsa/filter-file.c, libbalsa/filter.c, libbalsa/gmime-application-pkcs7.c, libbalsa/gmime-gpgme-context.c, libbalsa/i18n.h, libbalsa/identity.c, libbalsa/imap-server.c, libbalsa/libbalsa-conf.h, libbalsa/libbalsa.c, libbalsa/mailbox-filter.c, libbalsa/mailbox.c, libbalsa/mailbox_imap.c, libbalsa/mailbox_local.c, libbalsa/mailbox_maildir.c, libbalsa/mailbox_mbox.c, libbalsa/mailbox_mh.c, libbalsa/mailbox_pop3.c, libbalsa/message.c, libbalsa/mime.c, libbalsa/misc.c, libbalsa/send.c, libbalsa/server.c, libbalsa/source-viewer.c, libinit_balsa/balsa-druid-page-defclient.c, libinit_balsa/balsa-druid-page-directory.c, libinit_balsa/balsa-druid-page-finish.c, libinit_balsa/balsa-druid-page-user.c, libinit_balsa/balsa-druid-page-welcome.c, libinit_balsa/balsa-initdruid.c, libinit_balsa/helper.c, libinit_balsa/init_balsa.c, src/ab-window.c, src/address-book-config.c, src/address-book-config.h, src/balsa-app.c, src/balsa-index.c, src/balsa-mblist.c, src/balsa-message.c, src/filter-edit-callbacks.c, src/filter-edit-dialog.c, src/filter-export-callbacks.c, src/filter-export-dialog.c, src/filter-run-callbacks.c, src/filter-run-dialog.c, src/folder-conf.c, src/information-dialog.c, src/mailbox-conf.c, src/mailbox-node.c, src/main-window.c, src/main.c, src/message-window.c, src/pref-manager.c, src/print.c, src/save-restore.c, src/sendmsg-window.c, src/spell-check.c, src/store-address.c, src/toolbar-factory.c, src/toolbar-prefs.c: install and use libbalsa/i18n.h; migrate from GnomeFileEntry to GtkFileChooser; other Gnome-deprecation cleanup. 2005-02-06 18:45 Albrecht Dreß * configure.in, images/Makefile.am, images/16x16/Makefile, images/16x16/Makefile.am, images/16x16/Makefile.in, images/16x16/balsa-encrypted.png, images/16x16/balsa-mark-all.png, images/16x16/balsa-mbox-draft.png, images/16x16/balsa-mbox-sent.png, images/16x16/balsa-mbox-tray-empty.png, images/16x16/balsa-mbox-tray-full.png, images/16x16/balsa-next-flagged.png, images/16x16/balsa-next-part.png, images/16x16/balsa-next-unread.png, images/16x16/balsa-next.png, images/16x16/balsa-postpone.png, images/16x16/balsa-previous-part.png, images/16x16/balsa-previous.png, images/16x16/balsa-reply-all.png, images/16x16/balsa-signature-bad.png, images/16x16/balsa-signature-good.png, images/16x16/balsa-signature-notrust.png, images/16x16/balsa-signature-unknown.png, images/24x24/Makefile, images/24x24/Makefile.am, images/24x24/Makefile.in, images/24x24/balsa-crypt-check.png, images/24x24/balsa-encrypt.png, images/24x24/balsa-encrypted.png, images/24x24/balsa-mark-all.png, images/24x24/balsa-marked-new.png, images/24x24/balsa-next-flagged.png, images/24x24/balsa-next-part.png, images/24x24/balsa-next-unread.png, images/24x24/balsa-next.png, images/24x24/balsa-postpone.png, images/24x24/balsa-preview.png, images/24x24/balsa-previous-part.png, images/24x24/balsa-previous.png, images/24x24/balsa-reply-all.png, images/24x24/balsa-sign.png, images/24x24/balsa-signature-bad.png, images/24x24/balsa-signature-good.png, images/24x24/balsa-signature-notrust.png, images/24x24/balsa-signature-unknown.png, images/24x24/balsa-trash-empty.png, images/mimetypes/Makefile.am, src/balsa-icons.c, src/balsa-icons.h, src/balsa-index.c, src/balsa-mblist.c, src/balsa-message.c, src/filter-edit-dialog.c, src/main-window.c, src/message-window.c, src/sendmsg-window.c, src/spell-check.c, src/toolbar-factory.c, src/toolbar-prefs.c: themable icons. 2005-02-06 Pawel Salek * libbalsa/mailbox_imap.c: fix some corner cases for LibBalsaMessageBody-to-imap section transformation. * libbalsa/mailbox_pop3.c: use backend SSL option. * libbalsa/imap/imap-commands.[ch]: do not guess whether part headers are to be fetched - say it clearly. * libbalsa/imap/imap-handle.c: process all data in IDLE callback. 2005-02-06 Pawel Salek * libbalsa/body.[hc]: filter CRLF on saving text parts. * src/balsa-message.c, sendmsg-window.c: adapt to changed API. * libbalsa/html.c: HAVE_GNOME related fixes. 2005-02-05 17:50 PeterB * libbalsa/Makefile.am, libinit_balsa/Makefile.am, src/Makefile.am: temporarily allow deprecated methods. 2005-02-05 17:49 Albrecht Dreß * src/sendmsg-window.c: fix DnD problem with escaped filenames. 2005-02-03 Pawel Salek * libbalsa/imap/imap-handle.c: clean handle->sio field. 2005-02-02 Pawel Salek * configure.in: minor reordering fixes. * libbalsa/address-book-gpe.c: fix InternerAddress regression. * libbalsa/source-viewer.c: do not expand menu (regression fixed). * libbalsa/imap/imap-commands.c: enable/disable IDLE. * libbalsa/imap/imap-{handle,search}.c: ditto. * libbalsa/imap/imap_private.h: add IDLE related fields. 2005-01-29 Pawel Salek * configure.in: do it by the book (literally). * libbalsa/address-book-extern.c: remove uneeded GNOME dependency. * libbalsa/*.c: ditto. * libinit_balsa/*.c: Druid needs GNOME. * src/balsa-app.c: remove BALSA_MAJOR <2 remains. * src/print.c: drop old gnomeprint-1.* support. 2005-01-29 09:23 PeterB * src/folder-conf.c: fix typo. 2005-01-28 08:44 Craig Routledge * libbalsa/mailbox_local.c: fix bug #147380. 2005-01-27 Pawel Salek * libbalsa/address-book-ldap.c: fix InternerAddress regression. 2005-01-22 Pawel Salek * libbalsa/mailbox_imap.c: do not loose content type paramters - fix message wrapping on replying. 2005-01-20 Pawel Salek * libbalsa/address-entry.c: fix crashes on: domain-expanded address selection; unparsable address. 2005-01-17 23:02 PeterB * src/: balsa-message.c, sendmsg-window.c: port from GtkFileSelection to GtkFileChooserDialog. 2005-01-17 18:14 Albrecht Dreß * src/balsa-message.c, libbalsa/misc.c, libbalsa/misc.h: multiline URL highlighting. 2005-01-17 Pawel Salek * libbalsa/address-entry.c: add missing #include. * libbalsa/identity.h: * libinit_balsa/balsa-druid-page-user.c: port it to InternetAddress. 2005-01-17 14:32 PeterB * libbalsa/address-entry.c: use list->address instead of internet_address_list_get_address. 2005-01-17 13:41 PeterB * src/balsa-message.c, src/message-window.c, src/print.c, src/save-restore.c, src/sendmsg-window.c, src/store-address.c, libbalsa/abook-completion.c, libbalsa/abook-completion.h, libbalsa/address-book-ldif.c, libbalsa/address-book-vcard.c, libbalsa/address-entry.c, libbalsa/address-entry.h, libbalsa/address.c, libbalsa/address.h, libbalsa/body.h, libbalsa/files.h, libbalsa/filter.c, libbalsa/identity.c, libbalsa/identity.h, libbalsa/libbalsa.h, libbalsa/libbalsa_private.h, libbalsa/mailbox.c, libbalsa/mailbox.h, libbalsa/mailbox_imap.c, libbalsa/mailbox_local.c, libbalsa/mailbox_mbox.c, libbalsa/message.c, libbalsa/message.h, libbalsa/misc.c, libbalsa/misc.h, libbalsa/send.c: use GMime's InternetAddress instead of LibBalsaAddress, except for address-book entries. 2005-01-17 10:36 PeterB * src/: toolbar-factory.c, toolbar-prefs.c: remove redundant includes. 2005-01-14 08:32 PeterB * configure.in, images/Makefile.am, src/balsa-message.c, src/expand-alias.c, src/expand-alias.h, src/sendmsg-window.c, images/mimetypes/Makefile, images/mimetypes/Makefile.am, images/mimetypes/Makefile.in, images/mimetypes/gnome-mime-application-pgp-signature.png, images/mimetypes/gnome-mime-application-pkcs7-mime.png, images/mimetypes/gnome-mime-application-pkcs7-signature.png, images/mimetypes/gnome-mime-application-x-pkcs7-signature.png, images/mimetypes/gnome-mime-message-disposition-notification.png, images/mimetypes/gnome-mime-message-external-body.png, images/mimetypes/gnome-mime-message.png, images/mimetypes/gnome-mime-multipart-alternative.png, images/mimetypes/gnome-mime-multipart-encrypted.png, images/mimetypes/gnome-mime-multipart-signed.png, images/mimetypes/gnome-mime-multipart.png: install mime type icons; simplify icon search. 2005-01-13 14:56 PeterB * configure.in, libbalsa/address-entry.c, libbalsa/address-entry.h, libbalsa/files.c, libbalsa/identity.c, libbalsa/mailbox.c, libbalsa/misc.c, libbalsa/misc.h, libbalsa/send.c, libbalsa/source-viewer.c, libinit_balsa/helper.c, src/Makefile.am, src/ab-main.c, src/ab-window.c, src/balsa-app.c, src/balsa-index.c, src/balsa-mblist.c, src/filter-edit-callbacks.c, src/filter-edit-dialog.c, src/filter-edit.h, src/mailbox-conf.c, src/main-window.c, src/main.c, src/pref-manager.c, src/sendmsg-window.c, src/sendmsg-window.h, src/store-address.c, src/toolbar-factory.c: require gtk+-2.0 >= 2.4 and remove GTK_CHECK_VERSION(2,4,0) tests. 2005-01-12 Pawel Salek * libbalsa/imap/imap-commands.c: work around broken dovecot indexes. 2005-01-07 09:47 PeterB * src/main-window.c: Use hyphen instead of underscore in translator credits. * src/balsa-mblist.c: restore separator in balsa_mblist_mru_option_menu(); remove unused variable. 2005-01-07 Pawel Salek * libbalsa/libbalsa.h: add mailbox manipulation error codes. * libbalsa/mailbox_imap.[hc]: return more info on error. * src/folder-conf.c: handle errors better. * src/mailbox-conf.c: ditto. 2005-01-06 Pawel Salek * libbalsa/imap/imap-handle.c: silence debugging output. * libinit_balsa/balsa-druid-page-user.[hc]: port initial wizard improvements. * src/balsa-mblist.c: protect against D&D crashes. 2005-01-05 09:05 PeterB * libbalsa/mailbox_local.c: use second GNode tree in jwz-threading. 2005-01-04 Pawel Salek * libbalsa/mailbox_local.c: remove bogus test from msg matching (PB). 2005-01-03 19:09 PeterB/manu * libbalsa/mailbox_local.c: check for NULL msg-id. 2006-01-02 Pawel Salek * libbalsa/filter.c, libbalsa/misc.[hc]: move in_string_utf8() to misc * libbalsa/libbalsa_private.h: * libbalsa/mailbox.c: move LibBalsaMailboxEntry def to private.h * libbalsa/mailbox_local.c: implement faster searching code (manyfold speedup for large mailboxes). 2004-12-31 12:08 Albrecht Dreß * libbalsa/body.h, libbalsa/files.c, libbalsa/files.h, libbalsa/send.c, src/balsa-message.c, src/print.c, src/sendmsg-window.c, src/pixmaps/info_lock.xpm, src/pixmaps/info_lock_bad.xpm, src/pixmaps/info_lock_encr.xpm, src/pixmaps/info_lock_good.xpm, src/pixmaps/info_lock_sigtrust.xpm: new attachment handling code. 2004-12-30 17:04 PeterB * libbalsa/: mailbox.c, mailbox.h, mailbox_local.c: reduce the amount of tree modification when updating threading. * libbalsa/send.c: convert file name to utf-8 for GMime. 2004-12-29 11:49 PeterB * src/main-window.c: use BALSA_PIXMAP_CLOSE_MBOX instead of GTK_STOCK_CLOSE for Close-mailbox menu item; use GTK_ICON_SIZE_BUTTON for notebook label close button. 2004-12-27 10:02 PeterB * libbalsa/files.c: do not bypass theme when mime-type and filename are both NULL. 2004-12-26 18:45 PeterB * libbalsa/body.c: g_mime_data_wrapper_write_to_stream() decodes the transfer-encoding--we must not. * libbalsa/files.c: look for themed mime-type icon. 2004-12-24 Pawel Salek * libbalsa/body.c: always call gdk_pixbuf_loader_close(). * libbalsa/mailbox_pop3.c: do not try to move messages filtered out by procmail. 2004-12-22 13:25 Albrecht Dreß * libbalsa/: body.c, mime.c: two minor gpg related fixes. 2004-12-20 12:33 PeterB * src/: balsa-index.c, balsa-index.h: re-implement balsa_index_{next,previous}_msgno. * src/message-window.c: save more menu items; use balsa_index_{next,previous}_msgno() to correctly manage menu item and button sensitivity. 2004-12-18 Pawel Salek * libbalsa/imap/imap-handle.c: forgive errors in BODYSTRUCTURE response (work around #160083). 2004-12-18 Craig Routledge * src/balsa-app.[ch]: add mw_action_after_move. * src/message-window.c: use it. * src/pref-manager.c: configure it. * src/save-restore.c: save/restore it. 2004-12-16 14:34 PeterB * libbalsa/body.c: if body->mime_part is a GMimeMessagePart, get the stream for its message, not the part. 2004-12-15 06:43 PeterB * libbalsa/body.c: add some checks. 2004-12-13 09:41 PeterB * libbalsa/html.c: do not write zero bytes, to avoid a gtkhtml-CRITICAL. 2004-12-12 12:23 PeterB * libbalsa/mailbox_imap.c: check for NULL handle. 2004-12-09 15:45 PeterB * libbalsa/address-entry.c, libbalsa/address-entry.h, src/sendmsg-window.c: implement libbalsa_address_entry_addresses() and use it to move address-counting to libbalsa. 2004-12-08 15:11 PeterB * libbalsa/address.c: use InternetAddress methods to manage quoting and stringifying. * libbalsa/address-entry.c: use a hash table to hold LibBalsaAddress objects; parse quoted strings more carefully. 2004-12-07 18:57 PeterB * src/sendmsg-window.c: use libbalsa_wrap_rfc2646() to ensure space-stuffing. * libbalsa/misc.c: append spaces for DelSp=Yes. * libbalsa/gmime-gpgme-context.h: replace GMIME_CHECK_* macros with G_TYPE_*. * libbalsa/mailbox_mbox.c: simplify From_ line armoring. 2004-12-06 16:23 PeterB * libbalsa/: address.c, address.h: parse string with group address; implement libbalsa_address_set_copy_member() to make a copy of a LibBalsaAddress containing only one mailbox. * libbalsa/address-entry.c: parse entry text with group address; make only one completion item per address. * libbalsa/address-book-vcard.c: when not in dist_list_mode and a completion item has more than one address, make multiple single-address LibBalsaAddress objects. * libbalsa/: address.c, address.h, message.c: implement and use libbalsa_address_new_list_from_gmime(); do not ignore RFC 2822 group addresses. 2004-12-04 08:39 PeterB * src/: balsa-index.c, balsa-index.h, message-window.c: remove balsa_index_next_.*_msgno api; implement balsa_index_select() and use it to manage highlighting in the mailbox index. balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/ChangeLog.pre-1.0.0000066400000000000000000004166061477646064400234300ustar00rootroot000000000000002000-11-08 Pawel Salek * src/mailbox-conf.c: fix #30890: Adding POP mail box doesn't appear until after refresh. * libbalsa/send.c: save fcc (NOTE: append mode of libbalsa_mailbox_open() does not work sensibly, redesign this part). 2000-11-08 Pawel Salek * src/balsa-mblist.c: forgotten patch for changing IMAP mailbox's icon. 2000-11-07 Gediminas Paulauskas * src/sendmsg-window.c: (create_text_area) put text widget in scrolled window instead of table+scrollbars. Do not show useless hor. scrollbar. 2000-11-07 Pawel Salek * libbalsa/send.c: fix message multiplication in threaded code on failed relaying. Plug memory leak in local MTA mode. * src/balsa-app.h: change default date format. * src/balsa-message.c: release selection, fix #29362 and #30395. * src/main-window.c: remove deprecated code message deletion on sending * src/sendmsg-window.c: fix Slovak locale. * src/expand-alias.c: fix #30977 (Alt ignored when expansion on). 2000-11-06 Pawel Salek * configure.in: don't postfix BALSA_COMMON_PREFIXES with a comma. Add sk to ALL_LINUGAS. * libbalsa/files.c: change appriopriately. 2000-11-05 Matthew Guenther * src/balsa-index-page.c (close_if_transferred_cb): Remove "transferredp" data to allow for repeat transfers. 2000-11-05 Pawel Salek * README,INSTALL,help/C/README: build instructions for RH-7.0. Some comments and pointers on package dependences, building doc. * balsa.spec.in: include files, not whole directories. * libbalsa/body.c: include forgotten 2000-11-05 Zbigniew Chyla * sounds/*.soundlist: Added Polish translations. 2000-11-03 Pawel Salek * configure.in: bump version to 1.0.pre5 2000-11-02 Matthew Guenther * help/C/Makefile.am: Distribute README with tar.gz. * src/balsa-message.c (balsa_get_font_by_charset): Memory leak fix. 2000-11-02 Pawel Salek * src/main-window.c(balsa_window_enable_continue): try to enable continue menu/button in fast and reasonable way. 2000-11-02 Ian Campbell * src/balsa-index-page.c (create_menu): Wrap the transfer submenu in a scrolled window, do some magic to retain a sensible size for the menu. Fixes bug 18083. * src/balsa-message.c (balsa_message_set): Check for messages with no parts and don't crash. 2000-10-31 Matthew Guenther * help/C/balsa.sgml: Manual updates. * help/C/images/main-window.png: Update to reflect new menus. 2000-10-31 Ian Campbell * src/sendmsg-window.c (add_attachment): Remove g_print("POO\n"). Don't ask, I don't know. * libinit_balsa/balsa-initdruid.gob: If there is a GnomeCard address book in ~/.gnome/ then add it to the list of address books. * libbalsa/address-book-vcard.c: Report a warning if we can't open the mailbox. 2000-10-31 Pawel Salek * INSTALL, README: update install requirements and version numbers. * src/main-window.c: update the contributors list in about dialog. * src/balsa-message.c: place there unified i18n support. The only piece that is missing is charset support in headers but balsa has no information about the proper charset that should be used there. Older versions of GtkText are buggy and use wide characters for single byte charsets. gtk+-1.2.8 seems to work OK. * src/balsa-message.h: i18n api changes. * src/sendmsg-window.c: use new i18n api. Implement the changing of charset in messages in The Right Way - by changing styles. * libbalsa/body.c: rfc2047-decode attachment names. 2000-10-30 Ian Campbell * configure.in: Added a check for gnome-libs >= 1.2.1, since there are bugs in gnome-config prior to this which we are hitting. 2000-10-29 Matthew Guenther * TODO: More stuff to do * src/balsa-icons.[ch]: Move register_balsa_pixmap stuff here, add flagged pixmap to registered pixmaps as BALSA_PIXMAP_FLAGGED so we can use it in menus. Removed BALSA_ICON_FLAGGED stuff. * src/balsa-index.c (clist_set_col_img_from_flag): Use gnome_stock version of flagged pixmap instead of manually loaded one. * src/balsa-index-page.c (idle_handler_cb, create_menu): Safeguard to reduce idle handler calls, again attempting to reduce selection delays. Also add flagged icon to popup menu. * src/main-window.c: Remove register_balsa_pixmap* functions and accessories. Add icon to Toggle Flagged menu item. Move Preferences menu item to Settings menu, every other GNOME program I looked at has it this way. * pixmaps/flagged.xpm: Changed width to 16 so it didn't get mangled by gnome-stock stuff. 2000-10-26 Matthew Guenther * TODO: Add some future projects (after 1.0). * src/balsa-message.c: Plug memory leaks * src/main-window.c: Enable continue button using ->has_unread_messages instead of opening and closing the mailbox. Fixes long delays when selecting large numbers of messages. 2000-10-26 Dan Damian * balsa.desktop: added Romanian translations. * configure.in: Added "ro" to ALL_LINGUAS. 2000-10-23 Pawel Salek * help/C/Makefile.am: include win-config-gen script in the distribution. 2000-10-23 Pawel Salek * configure.in: bump version to 1.0.pre4 * TODO: clean up a bit, remove old, DONE stuff. 2000-10-23 Pawel Salek * balsa.spec.in: don't build rpm with GSS. * src/mailbox-conf.c: do not depend on mblist-window.c * src/main-window.[hc]: remove old set_cursor stuff, I haven't seen it working. Clear up the mailbox/message referencing code. * src/print.c: (int) conversion in isspace() - this function is implemented as macro on Solaris and doesn't like char parameters. * src/sendmsg-window.c: add Russian KOI support thrown away earlier by mistake. * src/balsa-message.[hc]: korean language support fixed. * INSTALL, README: warn about the libgnome bug and RH 7.0 gcc issues. * src/mblist-window.c: mailbox reference cleaning. 2000-10-18 Pawel Salek * src/balsa-message.c: fix SECOND bug in right-button menu generation. One too many bugs in single part of the frozen code. 2000-10-17 Pawel Salek * configure.in: stop if LDAP enabled but not found. Bump version to pre3. * src/address-book-config.c: parent dialog window * src/address-book.c: open compose window on double clicking * src/main-window.c: remove not needed X11/Xutil.h include * src/balsa-message.c: fix a bug in right-button menu generation. 2000-10-16 Pawel Salek * libbalsa/mailbox.c: allow ref'ing messages to make idle_handler work properly. * src/balsa-index-page.c,src/balsa-mblist.c: some extra tests on function arguments. * src/sendmsg-window.c: warn if the file to be attached is unreadable. * src/address-book-config.c: fix #26292 (crash on address book entry creation with empty file name). 2000-10-17 Gediminas Paulauskas * src/pref-manager.c: marked two strings for translation. 2000-10-15 Matthew Guenther * src/balsa-message.c: Changed attachment handling routine to check for both "view" and "open" keys. Made context menu dynamically generated depending on attachment mime type actions. 2000-10-14 Kjartan Maraas * configure.in: Added "nn" to configure.in. 2000-10-13 Matthew Guenther * help/C/.cvsignore: Ignore balsa.rtf, balsa.pdf * help/C/images/.cvsignore: Ignore .eps images * src/sendmsg-window.c: Fix print menu icon 2000-10-13 Ian Campbell * libbalsa/files.[ch]: New function libbalsa_icon_finder, which finds an icon for a part, based on filename or mime type. Contributed by Timothy Alan Chandler . * src/balsa-message.c: Use libbalsa_icon_finder to find icons. Based in parts on a patch from James A Laska * src/sendmsg-window.c: Use libbalsa_icon_finder to find icons. 2000-10-12 Pawel Salek * src/sendmsg-window.c: fix #27784 (crash on replying a message that has no message-id field). Internationalization fixes from Nerijus Baliunas 2000-10-11 Matthew Guenther * src/Makefile.am: Add link to libltdl on command line to improve pspell support on Sun platform. * src/main-window.c: Add new next unread message icon, try using newlines in toolbar descriptions to narrow toolbar width. * src/main-window.c (register_balsa_pixmap): Add parameters to pass to unction indicating the size of the pixmap to register. This prevents uglification of menu icons through multiple resizes by gnome-libs. * src/pixmaps/next_unread.xpm: * src/pixmaps/next_unread_menu.xpm: New next unread message icon. 2000-10-11 Carlos Morgado * src/balsa-index-page.c: fixed bug 26372 - delete from right click on trash folder didn't work * src/balsa-index-page.c: fixed typo that broke compilation. 2000-10-09 Ian Campbell * src/balsa-index-page.c: Disconnect signals from the mailbox when destroying the index page. Spotted by Atsuhiko Yamanaka 2000-10-08 Ian Campbell * src/balsa-app.h: define DEFAULT_SUBJECT_FONT as the bold verison of DEFAULT_MESSAGE_FONT. * src/save-restore.c: Use DEFAULT_SUBJECT_FONT. * src/pref-manager.c: Fix subject font selection to actually work. Also fixup both font selectors so they get initialized with the correct values. 2000-10-06 Pawel Salek * docs/vconvert.awk, docs/pine2vcard: the contributed address book converters by Stewart Evans and Jean-Marc Wislez , respectively. * Makefile.am: add these files to the tarball... * balsa.spec.in: and to the rpm * libbalsa/send.c: formatting touched. 2000-10-06 Ian Campbell * src/*: Fixed some places where indent didn't handle long lines nicely. * src/*: (forgot which files - sorry): Allow the subject to be displayed in another font (ie bold) 2000-10-06 Pawel Salek * NEWS,README,configure.in: release balsa-1.0.pre2 * help/C/Makefile.am: use old-style db2html if db2html with style sheets fails. 2000-10-05 Pawel Salek * libbalsa/mailbox_local.[ch]: libbalsa_mailbox_local_set_path() impl. * libinit_balsa/balsa-druid-page-user.gob: don't corrupt balsa_app.address * src/mailbox-conf.c: use new renaming code. * HACKING: the indentation settled to 4. * src/balsa-mblist.c: don't highlight special mailboxes, fix #26836. 2000-10-05 Ian Campbell * libbalsa/send.c, src/main-window.c: Call pthread_detach on new threads, so we don't need to pthread_join them. * src/main-window.c: Make the reply to all pixmaps use the gnome-stock stuff. This means they will grayout properly. Initial patch was from James A . Laska (again!) 2000-10-05 Szabolcs Ban * balsa.desktop: added Hungarian translations 2000-10-04 Pawel Salek * libbalsa/mime.c,libbalsa/misc.c: don't crash on replying empty mails. 2000-10-04 Ian Campbell * src/Makefile.am: Don't need to include $(top_builddir)/libmutt. * src/main-window.[ch]: Enable/disable the continue toolbar button and menu items. Export balsa_window_enable_continue. Initial patch was from James A . Laska . Also Some random indentation cleanups. * src/balsa-index-page.c: Call balsa_window_enable_continue when a send message window is destroyed. 2000-10-03 Pawel Salek * libbalsa/mailbox_imap.c (mailbox_open): fix memory leak. * libbalsa/server.c: set sensible default for user field. * src/balsa-app.[hc],src/main.c: fix --open-mailbox option. * src/balsa-mblist.c: fix_get_bold_font(), hopefully right this time. * src/save-restore.c: connect get-password signal on mailbox creation. 2000-10-03 Ian Campbell * libinit_balsa/Makefile.am: Fix GOB related rules. The generated files will now only be deleted by maintainer-clean, and not clean or dist-clean. The rule to build the x.[ch] from x.gob is now included all the time, not just with --enable-maintainer-mode. 2000-10-03 Matthew Guenther * src/spell-check.c: Fixed cancelled spell check outputting garbage bug. * help/C/Makefile.am: GDP stylesheet now explicitly required to build sgml, will fail without it. Also build eps images for pdf manual automatically. * help/C/balsa.sgml: Remove extra tag. 2000-10-02 Pawel Salek * src/address-book-config.c: grab the focus to the name field. * src/sendmsg-window.c: many people set language to C (for yet unknown to me reason) when they mean English. Guess their intentions. 2000-10-02 Ian Campbell * configure.in: Set gnomedatadir and gnomeconfdir to ${datadir} and ${sysconfdir} when building with system install disabled, rather than evaluating ${datadir} to get it's value. This allows 'make install prefix=xxx' to work properly. 2000-10-01 Matthew Guenther * help/C/Makefile.am: Change number of win-config redirects created. * help/C/win-config-gen: Small counter fix. * help/C/balsa.sgml: Major changes to bring up to date, new address book stuff, new menus, preferences dialog. More glossary terms and extensive interlinking. * help/C/images/*: New images for updated program. * src/balsa-index.c: Selected message scrolls to center of index. * src/main-window.c, src/sendmsg-window.c, src/balsa-index-page.c: Menu items properly capitalized. * src/spell-check.c, src/sendmsg-window.c: Moved calls to gtk_editable_set_position outside gtk_text_freeze/thaw. Causes random crashes on my machine, possibly a gtk+ bug. Memory leak fix. 2000-10-01 Ian Campbell * libbalsa/message.c: libbalsa_message_move, libbalsa_message_copy, add errro checking and reporting if source and/or destination mailboxes are not writable. Fixes bug #18348. * src/sendmsg-window.c: Include locale.h. Fixes solaris build. 2000-09-29 Pawel Salek * NEWS,README,configure.in: balsa-1.0.pre1 release. 2000-09-29 Pawel Salek * libbalsa/send.c: glib is MT-safe now, use g_new/g_free pair (+Ian's safe_free fix). * src/main-window.c: use g_malloc/g_free. * src/threads.h: use g_new/g_free pair, use strncpy properly. * src/sendmsg-window.c: print warnings with balsa_information. * src/expand-alias.c: fix the hideous memory release bug. 2000-09-29 Christophe Merlet * src/balsa-message.c,src/local-mailbox.c,src/main-window.c, src/mblist-window.c,src/message-window.c,src/pref-manager.c, src/sendmsg-window.c: Fixed marking of strings. Use _( not _ ( to mark strings for translation. 2000-09-28 Ian Campbell * src/address-book.c: Don't swap the message between clists if we are in browse mode. Credit for the dbl-click in address book stuff applied on 2000-09-27 should have gone to James A . Laska but I forgot. He fixed this too. * src/expand-alias.c: Initialise the lists of data to NULL. 2000-09-28 Pawel Salek * Makefile.am: add bzdist target (is it the right way of doing it?) * balsa.spec.in: include bzipped tarball. * help/C/balsa.sgml: add missing closing tag. * libbalsa/message.[ch]: be cautious on message copy and move, return status. * libbalsa/send.c: use malloc() to allocate structures to be freed by free(). (doesn't matter /most/ of the time; sometimes does). * src/balsa-message.c: add missing charsets. * src/sendmsg-window.c: use user's language, if this does not conflict with the message's charset. * src/pref-manager.c: fix deferred crash on default address book deletion. * src/address-book-config.c: show 'expand aliases' checkbox on adding mailbox. 2000-09-27 Ian Campbell * src/address-book.c: Move addresses on double click. * src/balsa-index-page.c: * src/balsa-message.c: * src/main-window.c: * src/mblist-window.c: * src/message-window.c: Add ... to menu items which lead to a dialog. 2000-09-26 Pawel Salek * libbalsa/send.c: compute correctly the sent data percentage. * src/main-window.c: print the percentage correctly (actually, the checking code is redundant..) * src/sendmsg-window.c: updates to the language selection code. setlocale() calls led to really weird hangs (X-server dependent?), got rid of them for this release. * src/mailbox-conf.c: KISS and armour mailbox creation/edition code. 2000-09-26 Ian Campbell * src/main-window.c: simplify select_part_cb. * src/message-window.c: Connect up Copy and Select All menu items. * src/balsa-message.[ch]: New signal 'select_part', emitted when you select a part (odd that). Implemented balsa_message_{can_select,_select_all,_copy} to support menu items. * src/main-window.c: Connect the copy and select all menu items up. 2000-09-25 Ian Campbell * src/balsa-index-page.c, src/mblist-window.c: Made context menu context sensitive. * src/main-window.c, src/message-window.c: Rearrange menus, some items still need to be hooked up (copy and select all) 2000-09-25 Kjartan Maraas * src/spell-check.c: Fixed marking of strings. Use _( not _ ( to mark strings for translation. 2000-09-25 Pawel Salek * src/balsa-message.c(message_set): show headers only when asked to. * src/main-window.c (balsa_window_refresh): remove the deangerous black magic. * src/pref-manager.c: don't call balsa_window_refresh(NULL) * src/sendmsg-window.c: do the font change the old traditional way. The new one via style change led to mysterious occasional hangs in gtk_text code (although this way seems to be the Right Way). * src/mime.c: add the prefix only once when message body wrapping is disabled. 2000-09-24 Pawel Salek * libbalse/send.c: anihillate as many balsa-app dependences as possible (only libbalsa_message_send() depends on it now). * libbalsa/message.h: ditto. * src/main-window.c: use API updated by above. * src/balsa-app.[ch]: remove unused balsa_app.checkbox field. * src/balsa-index.c: kill the message sorting issue (see discussion ad the beginning of the file). * libmutt/pop.c: use LAST if UIDL fails (patch contributed by James A . Laska ). 2000-09-24 Ian Campbell * src/balsa-app.c: Kill a reference to proplist.h 2000-09-23 Carlos Morgado * proplisttognome.pl: never got anywhere, and got removed. anyone cares ? 2000-09-23 Pawel Salek * libbalsa/information.c: idle functions must unregister themselves. this somehow worked on linux but failed on FreeBSD. * libbalsa/address.c(libbalsa_address_new_from_string): never add NULL to the address list. * libbalsa/mailbox_local.c: don't assume that if the file exists, it is readable. * src/balsa-index-page.c: make the message index not focusable in order to simplify the keyboard navigation (next and prev ara available through shortcuts anyway). * src/balsa-index.c: enable auto_sort so incoming messages are put in right place. 'prev' moves to the first message when no messages selected, and 'next' - to the last. * src/balsa-message.c: grab focus to the message so the keyboard scrolling is possible. New language&charset selection. * src/balsa-message.h: new api of get_font_name() * src/local-mailbox.c: don't crash on damaged configuration, when balsa_app.local_mail_directory=NULL * src/mblist-window.c: implement keyboard handler, 'Enter' opens selected mailbox. * src/pref-manager.c: handle missing balsa_app.{replyto,domain} configuration entries correctly (led to lock-up). * src/print.c: achieve gnome-print-0.22 compatibility, fix #25570. * src/sendmsg-window.[hc]: implement new language selection, don't refer fields of deleted structure in the _destroy method. 2000-09-21 Ian Campbell * src/balsa-message.c: Patch from Timothy Alan Chandler to only render a part when needed. I made this non optional, since that seems reasonable. * src/expand-alias.c: Implement case-insensitive expansion. Non-optional for now. Fix a couple of leaks. * src/message.c: * src/save-restore.c: * src/spell-check.c: * src/balsa-app.[ch]: Fix leaks shown up by memprof. * libmutt/parse.c: Pass user_hdrs=1 to mutt_read_rfc822_header. 2000-09-20 Ian Campbell * libbalsa/message.[ch]: Change return type of libbalsa_message_has_attachment() from gint to gboolean. * src/balsa-index.c, src/main-window.c: Set Sensitivity of menu items andtoolbar buttons depending on open mailbox, selected message etc. The context menus still need to be updated to do something similar. 2000-09-20 Pawel Salek * libbalsa/message.[hc]: libbalsa_message_get_text_content() added to be able to print composed messages that are not in any mailbox. * src/print.[hc]: modified accordingly. don't print when preview is selected. Export message_print(LibBalsaMessage*). * src/sendmsg-window.c: fix printing composed messages with gnome-print. 2000-09-19 Matthew Guenther * README: Add (another!) note about pspell library dependency. * src/balsa-app.h: Add check_sig, check_quoted, default to FALSE. * src/pref-manager.c: Add preference whether to check the signature and quoted text when spell checking messages. * src/save-restore.c: Save signature, quoted text checking preference. * src/spell-check.c: Signature checking disabling, quoted text checking preference, fix problem with selecting next word. 2000-09-19 Pawel Salek * src/main.c, src/sendmsg-window.c: quit when -m option launch was cancelled. Strip mailto: if present. * libbalsa/{mailbox_imap.c,mailbox_local.c}: don't access CONTEXT->readonly before checking that the mailbox open was really successful. 2000-09-18 Pawel Salek * src/sendmsg-window.c: fix the multithreaded mode compose-only execution. * src/main-window.c: second part of the fix. * NEWS, README, INSTALL: updated for balsa-0.9.5 * configure.in: updated for balsa-0.9.5, removed hopefully last dependences on libPropList. * balsa.spec.in: include translation files only, not the whole directories. 2000-09-17 Matthew Guenther * src/balsa-index.c (balsa_index_select_next_unread): Fixed so it properly wraps the search around the index. * src/balsa-index.c: Added function balsa_index_select_row, replaced relevent sections of balsa_index_select_next, _prev, and _next_unread. 2000-09-17 Carlos Morgado * Makefile.am: made 'make dist' work without balsa.idl * src/Makefile.am: made 'make dist' work without balsa.idl 2000-09-16 Pawel Salek * src/print.c: wrap headers too. 2000-09-15 Pawel Salek use gnome-print if available. * acconfig.h: HAVE_GNOME_PRINT added. * configure.in: search for gnome-print. * libbalsa/mailbox.c: fix message->references double free hang. * libbalsa/mailbox_pop3.c: fix compilation with disabled threads. * libbalsa/message.c: double free problem fixed. * libbalsa/mime.c: fix some special cases of line wrapping (hopefully I got it right this time, third time). * libbalsa/misc.c: ditto. * libbalsa/misc.h: change libbalsa_make_string_from_list() to have const argument. * src/main-window.c: print API updated. * src/print.[hc]: new gnome-print code. Multiple copies handled. * src/pref-manager.c: connect properly modification signal. disable unused sections when gnome-print is in action. * src/Makefile.am: gnome-print libraries added. 2000-09-15 Ian Campbell * src/address-book.c (ab_switch_cb): Fix crash when multiple addresses were selected. 2000-09-15 Pawel Salek * README: added comment on dotlocking and new mail sound. * src/Makefile.am: removed linking against PropList * Makefile.am: added idl/balsa.idl to EXTRA_DIST (dist test). * src/balsa-mblist.c: fix get_bold_font() crash. * libbalsa/address.[hc]: implement libbalsa_address_get_name() that returns person's name if available, or his first email otherwise. * libbalsa/mime.[hc]: proper reply wrapping, pass wrapping length to content2reply(). * libbalsa/misc.c(libbalsa_wrap_string): nice wrapping. * src/print.c: change to new content2reply() * src/sendmsg-window.c: the same. 2000-09-15 Ian Campbell * libbalsa/mailbox.[ch], libbalsa/mailbox_local.c, libbalsa/mailbox_imap.c: Add readonly flag. * src/main-window.c: Set titlebar using the readonly flag. * src/store-address.c: Fix for when there is no default address book. 2000-09-14 Matthew Guenther * help/C/balsa.sgml: Some updates to reflect changed features. Fixed screenshot graphic tags, they should _not_ include the .png extension. It gets taken care of by the stylesheet and is essential for portability to postscript. The stylesheet to use is not the default cygnus one, but the Gnome Documentation Project one, gdp-both.dsl. * help/C/win-config-gen: Shell script to generate HTML redirect files to get around GNOME's broken context sensitive help. * help/C/Makefile.am: Add call to win-config-gen * help/C/README: Instructions for properly building the documentation from SGML and recommendations for modifying the manual. * help/C/images/*: Updated and new images for manual. Screenshots fixed to conform with GDP standards (Sawfish, microGUI, Default Gtk+ theme). * libbalsa/mailbox.c: Load references header properly. * libbalsa/message.[ch]: Changed References header to be a list of message id's, not just one. * libbalsa/send.c: Use list of references instead of single entry. * src/balsa-app.[ch]: Added function set_tooltip, should be used everywhere to add easy tooltips to most widgets. * src/sendmsg-window.c: Changed toolbar button from "Spelling" to "Check Spelling", for clarity. Fixed References: header implementation. * src/spell-check.c (balsa_spell_check_init): Added tooltips to the control buttons. 2000-09-14 Pawel Salek * src/address-book.c: set parent properly when called from compose window. * src/expand-alias.c: handle lack of address book quietly. * src/sendmsg-window.c: don't allocate space for spell-checker when it's not active. * src/spell-check.c: don't quit on pspell configuration error: imagine you wrote so long and important e-mail that you think it is worth to spell check it... 2000-09-14 Ian Campbell * src/address-book.c: Fix crash if there is no default address book (also fixed potential problem if there are no address books). * src/pref-manager.c: Connect the properties_modified_cb to the set as default address book button. 2000-09-13 Ian Campbell * libbalsa/address.[ch]: Make into a proper Gtk object. * libbalsa/address-book.[ch]: Implement LibBalsaAddressBook. * libbalsa/contact.[ch]: Removed. Functionality now in LibBalsaAddress. * libbalsa/libbalsa.[ch]: Register address book types. Add includes for address books. * libbalsa/mailbox.c: Fix spelling, save config_prefix when loading. * libbalsa/message.c: Free addresses with gtk_object_destroy. * libbalsa/Makefile.am: Add new files. * libinit_balsa/balsa-druid-page-user.gob: Update for LibBalsaAddressBook. * src/address-book.[ch]: Update for LibBalsaAddressBook, select mailbox. Remove AddressData - functionality now in LibBalsaAddress. * src/Makefile.am: Add new files. * src/balsa-app.[ch]: Replace addressbook related fields with address_book_list and default_address_book. * src/store_dialog.[ch]: Move store dialog here, implement address book selection. * src/balsa-index-page.[ch]: Remove store dialog. * src/expand-alias.c: Use all address books which have there expand_alias flag setto look for completions in. * src/main-window.c: Update for moved store dialog. * src/main.c: Update for LibBalsaAddressBook. * src/pref-manager.c: Add address book configuration page. * src/address-book-config.[ch]: New address book configuration dialog. * src/save-restore.[ch]: Save and restore address book list. * src/sendmsg-window.c: Update for LibBalsaAddressBook. 2000-09-11 Carlos Morgado * src/save-restore.c: fixed a couple of off-by-1 errors in config_get_unused_section that caused config corruption 2000-09-11 Ian Campbell * libbalsa/contact.c: Missing #include 2000-09-11 Carlos Morgado * libbalsa/server.c: host and port made not private on server_load 2000-09-11 Carlos Morgado * src/Makefile.am: balsa_SOURCE -> balsa_BASE_SOURCE, make way for balsa_IDL_SOURCE (inactive ATM) 2000-09-11 Ian Campbell * libbalsa/body.c: Close the file after saving. Fixes bug #24055. * libbalsa/mailbox_local.c: When loading from config, setup local->type correctly. 2000-09-10 Ian Campbell * src/mailbox.[ch], src/mailbox_*.c, src/server.[ch]: Implement loading config as a function of the mailbox alongside saving. Push saving of relavent properties into the parent classes and make sure to chain the save_config and load_config calls. Use non-private settings where appropriate. Add a function libbalsa_mailbox_new_from_config which will create a mailbox from a config section. * src/libbalsa.c: Register mailbox types at intialization, to be sure they exist when we try to load the mailboxes. * src/Makefile.am: Don't need libmutt twice in LDADD. * src/main.c: Save configuration before exiting. * src/save-restore.c: Take advantage of mailboxes loading themselves. Use non-private settings where appropriate. Split the large Global section into smaller ones. Rename some keys to not be abbriviated. 2000-09-10 Pawel Salek * src/sendmsg-window.c: SelectAll by Michael Duelli 2000-09-10 Carlos Morgado * proplisttognome.pl: utility to convert old style config to new. not nearly done 2000-09-09 Matthew Guenther * src/spell-check.c (next_word): Fix next word heuristics, switch all debug and informational messages to balsa_information calls. * src/information-dialog.c (balsa_information_list): Make list of messages scroll as new messages are appended. * src/pref-manager.c: Moved quoted text regex to incoming mail options pane. 2000-09-09 Ian Campbell * libbalsa/mailbox_*.c: Use gnome_config_set_bool instead of g_c_set_int. Use the actual classnames as the type when saving. * src/balsa-app.c: parse the mblist color. * src/balsa-app.h: Define default colors as an rgb:xxxx/xxxx/xxxx string rather than as 3 numbers. Make open_mailbox field into a GList of pointers to mailboxes, rename it open_mailbox_list. * src/main-window.c: Use open_mailbox_list. * src/main.c: --open-mailbox cmdline option needed fixing. * src/save-restore.c: Save and load colors as a single string, instead of as three numbers. Split global into sections. directly use some gnome_config functions where appropriate. For strings pass defaults in a key=default rather than checking ourselves. Use bool types where appropriate. 2000-09-09 Pawel Salek * libbalsa/server.[hc]: load configuration on its own. * src/save-restore.c: changed apriopriately. 2000-09-09 Pawel Salek * libbalsa/mailbox.[hc]: implement save-config signal and libbalsa_mailbox_save_config() method. add pkey configuration field. * libbalsa/mailbox_imap.c: implement save-config signal. * libbalsa/mailbox_pop3.c: implement save-config signal. * libbalsa/mailbox_local.c: implement save-config signal. * libbalsa/misc.[ch]: ind_mailbox_func() moved from src/mailbox-conf.c * libbalsa/server.[ch]: rot() moved from mailbox-conf.c, libbalsa_server_save_conf() implemented * libinit_balsa/balsa-druid-page-finish.gob: new conf hooked in. * libinit_balsa/balsa-druid-page-directory.gob: initialize created mailboxes. * libinit_balsa/balsa-initdruid.gob: new configuration hooked in. * src/balsa-app.[ch]: new configuration hooked in. * src/mailbox-conf.[ch]: new configuration hooked in. * src/main-window.c: new pop config update hooked in. * src/main.c: new configuration hooked in. * src/pref-manager.c: new configuration hooked in. * src/save-restore.[ch]: new configuration code implemented. 2000-09-08 Matthew Guenther * INSTALL: Added comment about pspell dependency * configure.in: Check for pspell library * src/spell-check.[ch]: Complete rewrite to use pspell for spell checking. Could be improved but pretty good for now. * src/send-message.[ch]: Add BalsaSpellCheck widget and callbacks, disable most menus and toolbar buttons when spell check is running. Not elegant but it works. * src/balsa-app.[ch]: Added spell check settings, which pspell module to use, what spelling mode, and a minimum word size to check. Also moved the quoted text regular expression here. * src/balsa-message.c: Allow regular expression defining quoted text to be defined by the user, in the preferences dialog. * src/pref-manager.c, src/save-restore.c: Create settings for spell checking and quoted text regex. 2000-09-07 Carlos Morgado * idl/balsa.idl: Gnome::Balsa::App, new Attachment 2000-09-07 Berend De Schouwer LDAP directory lookup. * acconfig.h: add ENABLE_LDAP * configure.in: add --enable-ldap configuration option. * src/Makefile.am: ldap-addressbook.[hc] added to the source list. * src/address-book.[hc]: Restructure and generalize the code. * src/balsa-app.[hc]: declare initialize LDAP variables. * src/expand-alias.c: move AdressData code to address-book.c * src/main.c: close LDAP on exit. * src/pref-manager.c: add LDAP page. * src/save-restore.c: save and read LDAP data. * src/ldap-addressbook.[hc]: LDAP support files. 2000-09-07 Ian Campbell * src/mailbox-conf.c: Make sure that the path has ben filled in for a local mailbox. Remove some commented out checks on the password fields, which aren't needed now. * src/information-dialog.c: Fix stupid mistake by me. 2000-09-07 Pawel Salek * src/balsa-index-page.c: bug fix for the idle_handler_cb() crashes. 2000-09-06 Ian Campbell * libbalsa/threads.h: Sync the definition of MailThreadMessage to the one in src/threads.h (really there should only be one of these...) * libbalsa/mailbox_pop3.c: Define a callback for mutt_fetchPopMail. Unlock the mutt_lock while writing to the message pipe. Prevents lockups. 2000-09-06 Carlos Morgado * idl/balsa.idl: added new idl * src/orbit-glue.c: preliminary orbit glue functions 2000-09-06 Ian Campbell * libinit_balsa/libinit.c: Add gdk_threads_{enter,leave} calls around the gtk_main here. Prevents a lock up when we do the gtk_main for the main body of the application. * libbalsa/Makefile.am, libbalsa/information.[ch]: Implement a libbalsa_information function which will call a callback provided when libbalsa is initialised. The message can include a severity level. * libbalsa/libbalsa.[ch]: Setup balsa_information from libbalsa_init, route mutt_message, mutt_yesno and mutt_error through balsa_information. * src/balsa-app.[ch], src/information-dialog.[ch]: Implement a balsa_information to pass to libbalsa as a callback, provide options of displaying certain types of message not at all, in a dialog or in a list of messages. balsa_information also replaces balsa_error and balsa_warning. * save-restore.c, src/pref-manager.c: Prefs for the above. * src/balsa-message.c, src/main-window.c: Use balsa_information instead of balsa_warning. 2000-09-06 Pawel Salek * src/Makefile.am: include libimap.a only once - and it still works! * src/balsa-index-page.c: allow expanding mailbox tree in transfer menu 2000-09-05 Pawel Salek (post-0.9.4, it's pity) * libbalsa/mailbox.c: drop dead rereading on commit, too slow. * src/balsa-app.h: MAX_QUOTE_LEVEL to 4, who reads older quotes anyway? * src/balsa-index.c: next_unread and sort function don't hide selected * src/balsa-message.c: fix regexp (thanks to Berend De Schouwer ). * src/expand-alias.c: fix misbehavior when NumLock is on (BDS, too). * src/sendmsg-window.c: connect copy, cut&paste shortcuts. 2000-09-04 Pawel Salek * src/pref-manager.c: renamed quoted colours to primary and secondary. * configure.in: bumed version number to 0.9.4 2000-09-04 Carlos Morgado * libmutt/Makefile.am: removed socket.c from files list (replaced by imap/socket.c) 2000-09-04 Pawel Salek * configure.in: Fixed GSS configuration issue (I wonder how come it worked before): CPPFLAGS set in libmutt/configure.in was overwriteen by a value set in libmutt/Makefile.am. CFLAGS is now set instead but I don't think this is the cleanest way of doing it. * balsa.spec.in: compile with GSS enabled. * libbalsa/mailbox.c: use '-' instead of '_' in signal names; first approach to fixing libbalsa_mailbox_commit_changes, return the commit's result. * libbalsa/mailbox_imap.c(mailbox_check): allow_reopen. disable checking closing mailboxes before buffy code gets fixed. * libbalsa/notify.c: disable registering imap mailboxes. * libmutt/Makefile.am: use DEFS for defining compilation constants. * libmutt/flags.c: sync with mutt 1.2.5. * libmutt/mutt.h: add M_NEW_SSL_SOCKET constant as in mutt-1.2.5. * libmutt/imap/Makefile.am: use DEFS instaed of CPPFLAGS. * libmutt/imap/imap_ssl.c: first approach. It requires more work because the code includes user interface. * src/main-window.c: check commit_changes return value. * src/balsa-message.c: don't crash on corrupted images. * src/mailbox-conf.c(conf_update_mailbox): double g_free(). * libmutt/{Makefile.am,socket.c}: removed old socket.c 2000-09-02 Pawel Salek * README: added a comment on GSS * configure.in: use --with-gss option * libbalsa/mailbox_imap.c: set ImapCRAMKey, too. * libbalsa/message.c: imap code cleanup. * libbalsa/send.c: fix deadlock on mail postpone. * libmutt/configure.in: make imap default in a right way. * libmutt-imap/Makefile.am: define LIBMUTT * libmutt/imap/auth.c: be as verbose as the original code was. * libmutt/imap/auth_gss.c: compile it. * libmutt/imap/message.c: include * src/save-restore.c: major code cleanup. 2000-09-01 Pawel Salek * libbalsa/mailbox_imap.c(open): ask for password if unknown. * libbalsa/message.c: standard input test in message_move. * libbalsa/server.[hc]: get-password signal implemented. * libmutt/imap/Makefile.am: browse.c added. * src/balsa-app.[ch]: ask_password helper function implemented, initial mailbox opening moved to an idle function. * src/balsa-index-page.c: no special exceptions for IMAP and POP3 passwords. * src/save-restore.c: connect get-password signals. * src/mailbox-conf.c: same. 2000-08-29 Ian Campbell * libbalsa/libbalsa.c: Reimplement libbalsa_error to be callable from any thread, by defering the real callback to an idle function (which will be called from the main thread..) * libbalsa/mailbox_pop3.c: We can safely release the gdk_lock for the duration of the mutt_FetchPop call (now the balsa_error is safely callable from threads). We can also remove the hack of replacing mutt_error with a non-GUI version. * libinit_balsa/Makefile.am: Tell GOB not to bother with the private headers * src/balsa-app.c: Rewrite balsa_warning to display a list of warnings, rather than popping up a new message box for each warning (which could lead to hundreds of windows if a mail server was down while you are away). * src/main.c: initialize libbalsa with balsa_warning rather than balsa_error. * libbalsa/send.c: Add #include to fix solaris build. 2000-08-29 Pawel Salek Plugged in new IMAP code. Basic testing done. IMAP folders broken, require code rewrite. * libbalsa/mailbox_imap.c(libbalsa_mailbox_imap_get_message_stream): new imap has caching encasulated, ask it to provide cached or fresh message stream. * libmutt/base64.c: added. * libbalsa/misc.c: store temporarily not used imap folder stuff. * libmutt/Makefile.am: added base64.c,removed old imap.[hc] * libmutt/buffy.c:imap_buffy_check->imap_mailbox_check * libmutt/mime.h: Base64_chars->B64Chars * libmutt/protos.h: base64 decls. * libmutt/imap/Makefile.am: fixed file list for distribution. * libmutt/imap/auth.c: removed localization translations.. * libmutt/imap/socket.c: commented out mutt_message * src/Makefile.am: linking with libimap.a - FIXME! * src/balsa-message.c: more sensible IO tests. * balsa.spec.in: apply rpm-po.patch in a better way. 2000-08-28 Pawel Salek Importing IMAP from mutt-1.2.5i * docs/README.SSL, libmutt/imap/*: added (see libmutt/ChangeLog for other details) 2000-08-27 Pawel Salek * README, NEWS, configure.in: updated for balsa-0.9.3 * docs/mh-mail-HOWTO: added. 2000-08-27 Carlos Morgado * src/save-restore.c, src/mailbox-conf.c: apop support (lacking GUI) * libmutt/pop.c: apop support merged from mutt 1.2 * libmutt/init.h, libmutt/mutt.h: APOP option * libmutt/md5c.c, libmutt/md5.h: added from mutt for apop * libbalsa/mailbox_pop3.[ch]: support for use_apop 2000-08-26 Ian Campbell * libbalsa/*.[ch]: Implemented a mutex around all libmutt calls. Updated copyright in all files. * HACKING: Add a section describing how locking should work. * balsa.spec.in: Add AUTHORS and HACKING to %doc. * src/balsa-message.c, src/print.c, src/sendmsg-window.c: make_string_from_list->libbalsa_make_string_from_list and readfile->libbalsa_readfile. * src/main.c: Initialize libbalsa earlier, so the libmutt mutes is created early on. 2000-08-25 Pawel Salek * src/balsa-app.[hc]: add attach_dir field to remember last directory files were attached from. * src/balsa-message.c: grab focus in save MIME part. * src/sendmsg-window.c: use attach_dir. 2000-08-22 Ian Campbell * libmutt/send.c: Add locking for threading. * src/main-window.c: Add gdk_threads_enter() to calls to LibBalsa within the thread. * src/main.c: call g_thread_init before calling gtk_init so the GTK sets up its threading stuff correctly. * libbalsa/mailbox.c(libbalsa_mailbox_set_unread_messages_flag): Always emit the signal, since it allows balsa-mblist to update when a second new message arrives. * src/main-window.c: Check all mailboxes even in non-threaded mode. 2000-08-22 Pawel Salek * src/quote-color.[hc]: rewrite is_a_quote() to use regexp's and allow for flexible quote prefixes. * src/balsa-message.c: use new regexp quote stuff. 2000-08-21 Ian Campbell * libbalsa/send.c: Dont send MSGSENDTHEADLOAD messages to main thread, these are done by libbalsa_mailbox_check now. * libbalsa/threads.h, src/threads.h: Remove MSGMAILTHREAD_LOAD and MSGSENDTHREADLOAD. They are no longer needed. * src/balsa-index-page.c: Remove lots of cruft. * src/balsa-index.h: Remove unused field from struct. * src/main-window.c: Don't handle MSSENDTHREADLOAD messages. This removes an include of libbalsa_private - which is nice. Remove cruft. * src/mblist-window.c: Remove cruft, cast some fields properly. * src/Makefile.am: We don't need to include libbalsa.a twice. 2000-08-21 Ian Campbell * libbalsa/mailbox.c(libbalsa_mailbox_load_messages): Clear the unread messages flag if there are no unread messages. 2000-08-21 Pawel Salek * libmutt/pop.c: fix the scary POP bug by closing spool mailbox. 2000-08-20 Ian Campbell * libbalsa/*.[ch]: Re-indent all files in libbalsa to use 8 space indentation. 2000-08-20 Ian Campbell * acconfig.h: * configure.in: * src/balsa-app.c: * src/balsa-app.h: * src/balsa-mblist.c: * src/balsa-mblist.h: * src/mblist-window.c: * src/pref-manager.c: * src/save-restore.c: * src/sendmsg-window.c: Remove the --enable-info build-time option, always build this functionality in. There is still a runtime option. 2000-08-20 Pawel Salek * src/balsa-index.c: workaround for gtk_clist_sort() bug (the bug fix has been yesterday included to gtk sources but it will take some time before people upgrade libraries). 2000-08-17 Ian Campbell * libbalsa/mailbox_imap.[ch]: Implement libbalsa_mailbox_imap_check properly. Implement libbalsa_mailbox_imap_set_path. * libbalsa/notify.c: Fix an eronious cast. * src/balsa-index-page.c(idle_handler_cb): * src/balsa-index.c(moveto_handler): Use gdk_threads_{enter/leave}. * src/mailbox_conf.c: * src/save-restore.c: Use libbalsa_mailbox_imap_set_path instead of setting directly. 2000-08-16 Ian Campbell * libbalsa/message.c (libbalsa_message_body_ref): Add support for message/rfc822, fixes bug #21128, probably some others too. 2000-08-16 Pawel Salek * libbalsa/mailbox.c, libbalsa/mailbox_local.c: fixed mailbox mutex locking. * src/main-window.c: we use (BalsaIndex*) instead of BALSA_INDEX because we don't want ugly conversion warning when balsa_window_find_current_index() returns NULL. 2000-08-15 Ian Campbell * libbalsa/Makefile.am: Add notify.[ch]. A wrapper for the mutt buffy module. * libbalsa/libbalsa.c(libbalsa_init): Call libbalsa_notify_init() * libbalsa/libbalsa.h: Include notify.h * libbalsa/mailbox.[ch]: Add two new signals, check and set_unread_messages_flag. check is a virtual function which abstracts the operation of checking a mailbox. Remove libbalsa_mailbox_check_for_new_messages and libbalsa_mailbox_ replaced both with libbalsa_mailbox_check. * libbalsa/mailbox_local.c, libbalsa/mailbox_imap.c, libbalsa/mailbox_pop.c: implement the check function, make use of libbalsa_notify where appropriate. Mailboxes now handle adding themselves for notification internally, so add_mailbox_for_checking() is no longer needed. * libbalsa/message.c: Use libbalsa_mailbox_set_unread_messages_flag instead of modifying the flag directly - emits signal. * libbalsa/send.c: Use libbalsa_mailbox_check(). * src/balsa-mblist.c: Use the set-unread-messages-flag signal instead of directly polling each mailbox on update. This also removes the need for a separate thread, since expensive work happens in the same thread as checking is done. * src/main-window.c: Update check_messages thread to work with new checking system. * src/save-restore.c: Don't put POP3 mailboxes in the list with the others, they live in balsa_app.inbox_input. Use libbalsa_set_charset not mutt_set_charset. 2000-08-15 Matthew Guenther * src/balsa-index-page.c: Fix mailbox updating, AppBar stuff. * src/balsa-mblist.c (balsa_mblist_have_new): change ...appbar_set_default to ...appbar_push. * src/balsa-mblist.c (balsa_mblist_update_mailbox): remove mailbox re-focusing code from here, move to balsa_mblist_focus_mailbox. * src/main-window.c: Install Appbar menu hints, add some menu item tooltips. * src/main-window.c: (balsa_window_real_close_mailbox): Add call to balsa_mblist_focus_mailbox. * src/main.c: Init Appbar progressbar lock. * src/quote-color.c: Change colormap to use one allocated at startup. * src/threads.h: Appbar progressbar lock defined. 2000-08-15 Ian Campbell * src/main.c: Patch from Timothy Alan Chandler to initialize GConf if needed for the experimental GtkHTML support. * configure.in: Mark GtkHTML support as experimental. 2000-08-15 Pablo Saratxaga * configure.in,po/wa.po: added Walloon file * configure.in,po.zh_CN*.po: moved zh_CN to zh_CN.GB2312; for better standardisation (po files for simplified chinese on other modules use zh_CN.GB2312) * src/main-window.c: corrected English typo * src/sendmsg-window.c: improved the heading phrase of replies (you can't translate "you" alone; most languages require it to adapt gramatically depending on the context) 2000-08-15 Pawel Salek * AUTHORS, NEWS, README, configure.in: updates for 0.9.2 * balsa.spec.in: require gnome-libs >= 1.2.0 * libbalsa/send.c: MessageQueueItem constructors/destructors, handle sending errors nicely. * libmutt/pop.c(mutt_fetchPopMail): fix for _some_ POP problems. * src/balsa-app.c(balsa_warning): shouldn't set wmclass after window is realized. * src/main-window.c: pop up a warning box on sending error. * src/sendmsg-window.c: strdup dragged file name before handing it over to add_attachment(). 2000-08-14 Ian Campbell * HACKING: Added some guidelines. 2000-08-12 Ian Campbell * configure.in: Make --enable-more-warnings and --enable-threads default to yes. 2000-08-11 Matthew Guenther * INSTALL: Add warning about older versions of egcs causing problems with Balsa. * TODO: Clean up formatting, update some items. 2000-08-11 Matthew Guenther * libbalsa/libbalsa.c: Set OPTCHECKNEW option. * src/balsa-app.[hc]: Add application colormap, visual variables. * src/balsa-index.c (balsa_index_init): Added a default sorting style; Descending by date. * src/balsa-index.[hc]: Added balsa_index_refresh for updating mailbox indexes when new messages are loaded. * src/balsa-mblist.[hc]: Added support for threaded updating of mailbox list. New function balsa_mblist_thread. Extensive changes to balsa_mblist_have_new, balsa_mblist_check_new, balsa_mblist_update_mailbox. * src/balsa-mblist.c (balsa_mblist_init): Removed setting of expander and line style, this should be set by the theme or library. Should look more consistent in HeliX Code installations. * src/main-window.c: (mail_progress_notify_cb): Removed call to balsa_mblist_have_new, doesn't work due to thread locking now. * src/main.c (main): Added calls to gdk_threads_enter/leave, moved colormap stuff around to avoid a warning. Added thread variables for mailbox updating thread. * src/threads.h: Added mblist_thread thread, updating_mblist semaphore. 2000-08-10 Ian Campbell * src/balsa-message.c: Fix save_part to properly destroy dialogs on error. Fix a memory leak in find_body_font. 2000-08-10 Ian Campbell * src/balsa-message.c: Removed obsolete FIXME * src/pref-manager.c: Use libbalsa_set_charset instead of mutt_set_charset. 2000-08-09 Ian Campbell * libbalsa/mailbox.c: Make the libbalsa_mailbox_get_message_stream a proper GTK+ signal instead of messing with the class ourselves. 2000-08-09 Ian Campbell * libbalsa/libbalsa.c, libbalsa/libbalsa.h: * libbalsa/misc.c, libbalsa/misc.h: libbalsa/misc.h: Don't pass the spoolfile to libbalsa_init anymore, instead provide libbalsa_set_spool. This is because libbalsa_init needs to be called before the mailbox information is loaded and they are created, and the Inbox isn't known until after. Move libbalsa_guess_mailspool to libbalsa.[ch] from misc.[ch] too. * src/balsa-app.c: make balsa_warning and balsa_error use gnome_warning_dialog and gnome_warning_dialog. Also format the input string using g_strdup_vprintf not vsprintf. Got rid of error_exit_cb since gnome_dialog_run_and_close() will block until the dialog is closed and we can call balsa_exit() then. balsa_error_toggle_fatality() is not needed any more since balsa_warning does non fatal messages. * src/balsa-app.h: Export balsa_error() - might be usefull.. * src/balsa-app.c: Don't call libbalsa_init from do_load_mailboxes but do call libbalsa_set_spool. Use balsa_warning instead of cantfind_notice(). * src/main.c: Call libbalsa_init. * src/save-restore.c(config_mailbox_init): Use libbalsa_server_set_* instead of filling in the fields ourselves. 2000-08-09 Ian Campbell * src/balsa-message.c: Remove two unused variables to allow -Werror compilation. 2000-08-08 Pawel Salek * src/balsa-message.c: allow external message viewers as defined in gnome MIME. * libbalsa/send.c(balsa_smtp_protocol): handle properly lines beginning with dot. 2000-08-08 Ian Campbell * libbalsa/mailbox.c: * libbalsa/mailbox.h: * libbalsa/mailbox_remote.c: * libbalsa/mailbox_remote.h: Put LibBalsaMailboxRemote into it's own file. It is a trivial object, but it helps to keep things organised if they are kept separate. * configure.in: Check for proplist.h as well as the library itself. 2000-08-08 Ian Campbell * configure.in: Add check for libgnomeui/gnome-window-icon.h * src/main.c: Only use the gnome-window-icon stuff if we have it. 2000-08-08 Pawel Salek * libbalsa/mailbox_local.c(libbalsa_mailbox_local_new): fix mailbox creation code and be more verbose on error. * libinit_balsa/balsa-druid-page-directory.gob(unconditional_mailbox): get rid of a conversion that generated confusing warnings on error. * src/save-restore.c(config_mailbox_init): same. * src/sendmsg-window.c(attachments_add): accept attachment drops to entire compose window. * src/address-book.[hc],src/expand-alias.c: multiple compose window alias expansion bug fix from Berend De Schouwer 2000-08-07 Ian Campbell * src/main-window.c: Set progress_dialog and friends to NULL in progress_dialog_destroy_cb. This solves a crash when checking after pressing the `Hide' button, fixes bug #14861. 2000-08-07 Pawel Salek * src/sendmsg-window.c: use mutt_set_charset() for setting charset. * libbalsa/send.c: add_mutt_body_plain () accepts charset as parameter 2000-08-06 Ian Campbell * libbalsa/server.c: Emit signals properly. This fixes the problem with adding/updating POP3 mailboxes. * src/balsa-mblist.c: Cast paramter to gtk_idle_add to allow compile with full warnings. 2000-08-06 Pawel Salek * src/balsa-mblist.c: use main_window as colormap source, needed for right mouse button menu. * help/C/balsa.sgml,help/C/images/example-alias.png: alias doc from Berend De Schouwer. * configure.in: increased version number to 0.9.1 2000-08-03 Berend De Schouwer Address alias expansion. * src/Makefile.am: added expand-alias.[ch] * expand-alias.[ch]: alias expansion code * src/address-book.[ch]:ab_load_addresses() added * src/balsa-app.[ch]: balsa_warning() added * src/balsa-message.c: set_wmclass(save_dialog, "save") * src/pref-manager.c,src/save-restore.c: configuration code. * src/sendmsg-window.c: alias expansion hooked. * src/balsa-message.c: quoted text marking, part1. * src/balsa-mblist.[hc]: check mailboxes only when idle. * src/pref-manager.c: use gdk_window_get_colormap() instead of gdk_colormap_get_system() which is not apriopriate in this context. 2000-08-03 Ian Campbell Window close bug fix. Renamed balsa_message_create -> balsa_message_new which is conventional - this involved renaming another balsa_message_new which sent a new message and making it static. * src/balsa-index-page.[hc]: renaming * src/balsa-message.[hc]: added destructor balsa_message_destroy() * src/main-window.c,src/message-window.c: renaming. 2000-08-03 Pawel Salek * configure.in: tested against gtkHTML 0.5 and enabled it. * src/main-window.c(send_outbox_messages_cb): menu entry and callback for sending messages queued in outbox. 2000-08-01 Peter Williams * libbalsa/mailbox.c (check_all_pop3_hosts): Compile fix for threads and Stuart's patch. 2000-07-26 Stuart Parmenter * libbalsa/Makefile.am: * libbalsa/libbalsa.h: * libbalsa/mailbox.c: * libbalsa/mailbox.h: * libbalsa/mailbox_imap.c: * libbalsa/mailbox_imap.h: * libbalsa/mailbox_pop3.c: * libbalsa/mailbox_pop3.h: * libbalsa/misc.c: * libbalsa/server.c: * libbalsa/server.h: * src/balsa-index-page.c: * src/mailbox-conf.c: * src/save-restore.c: Added LibBalsaServer object and LibBalsaMailboxRemote. IMAP and POP3 are now LibBalsaMailboxRemotes which contain a LibBalsaServer. This keeps the server information seperate from the mailbox information. Multiple mailboxes on an IMAP server for example should point to the same server (they currently create their own server object.. this should be fixed. I will add a hashtable to do this later.) This abstraction should help in added a server to the mailbox list and make things a bit more simple. LibBalsaServers should have a GNode tree of their mailboxes, but they do not currently. This will happen when I remove the current MailboxNode stuff. 2000-07-25 Stuart Parmenter * src/mailbox-conf.c Fixed crash when you cancel out of creating a mailbox due to an uninitialized pointer. 2000-07-15 Robert Brady * configure.in: added en_GB.po to ALL_LINGUAS 2000-07-12 Ian Campbell * libbalsa/libbalsa.h: * libbalsa/mailbox_imap.c: * libbalsa/mailbox_local.c: * libbalsa/mailbox_pop3.c: * src/mailbox-conf.c: * src/mailbox-conf.h: * src/mblist-window.c: * src/pref-manager.c: Fix bug where mailbox configuration warns that certain fields have not been filled in when they have. Also allow password to be blank, since there is code to check for this and prompt at runtime. Initialize fields of some mailbox types. 2000-07-11 Ian Campbell * libbalsa/body.c: * libbalsa/body.h: * libbalsa/libbalsa.c: * libbalsa/libbalsa.h: * libbalsa/libbalsa_private.h: * libbalsa/mailbox.c: * libbalsa/mailbox.h: * libbalsa/mailbox_imap.c: * libbalsa/mailbox_local.c: * libbalsa/mailbox_local.h: * libbalsa/mailbox_pop3.c: * libbalsa/message.c: * libbalsa/message.h: * libbalsa/mime.c: * libbalsa/misc.c: * libbalsa/misc.h: * libbalsa/send.c: * libinit_balsa/balsa-druid-page-directory.gob: * src/balsa-app.c: * src/balsa-app.h: * src/balsa-index-page.c: * src/balsa-mblist.c: * src/balsa-message.c: * src/local-mailbox.c: * src/mailbox-conf.c: * src/main-window.c: * src/mblist-window.c: * src/pref-manager.c: * src/save-restore.c: * src/save-restore.h: * src/sendmsg-window.c: Continued API cleanup, plus partial removal of balsa's dependency on libmutt. This involved many new functions to various classes, and lots of small changes. Changed several dialog boxes to use standard gnome dialogs. Also added an experimental GtkHTML based text/html part viewer. Configure with --enable-gtkhtml to use. Tested with GtkHTML 0.4. 2000-07-10 Matthew Guenther Applied IRIX compatibility patch by David Kaelbling to fix bug #16873 * changed to use C comments in code only, not C++ style comments * avoid use of gcc-specific switches and extensions * include neccessary system headers for threading 2000-07-08 Peter Williams * src/mailbox-conf.c: Set the page manually for new POP3 boxes as this cannot use the set_the_page "clicked" signal thingie. 2000-07-05 Pawel Salek API clean up by Ian Campbell : - removed dependencies of libbalsa on balsa. - removed all the mailbox watcher stuff and replaced it with signals - made LibBalsaMailbox make better use of the hierarchy of classes. Almost all the files are affected. I hope it will work :-). * libbalsa/send.c(libbalsa_send_message_real): quick bug fix against the original patch. 2000-07-04 Pawel Salek * src/save-restore.c: renaming 'special' mboxes fixed (PLGetString() value of later PLRelease'd Dict was used) 2000-07-03 Pawel Salek * libbalsa/{contact.h,mailbox.c}(contact_store): pass address book file name. * src/address-book.c: allow for configurable address book file, import data in two modes. * src/balsa-app.{c,h}: address book configuration: ab_location and ab_dist_list_mode. * src/balsa-index-page.c:allow for configurable address book file, * src/pref-manager.c: configurable ab_location * src/save-restore.c: saving and restoring address book settings. * src/mailbox-conf.c(conf_update_mailbox): interpret correctly check_for_blank_fields() return code. 2000-06-30 Pawel Salek * libbalsa/mailbox.c: use updated mutt API. mx_open_unref - do check the mx_close_mailbox return code. 2000-06-29 Pawel Salek * src/balsa-app.c: don't free Spoolfile. 2000-06-28 Pawel Salek * libbalsa/message.c(real_destroy): leave object in sane state. * src/sendmsg-window.c: don't crash on replying deleted message. 2000-06-27 Peter Williams * libbalsa/Makefile.am (libbalsa_a_SOURCES): Add imapdir.h to our sources so it goes into the dist. 2000-06-26 Peter Williams * src/save-restore.c (config_global_save): Check for null when saving balsa_app.open_mailbox. I squash bugs bad. 2000-06-26 Pawel Salek * src/address-book.c: show all e-mail adresses. Ian Campbell message browsing patch: The 'save as' dialog wasn't going away properly after clicking OK or Cancel. Some error dialogs were given parents. The problem with headers not being shown properly in the separate message window at first has been fixed. emacs mode hints to the top of touched files. * src/balsa-index-page.c,src/balsa-message.c, src/main-window.c,src/message-window.c 2000-06-24 Peter Williams * libbalsa/misc.c: Add proper path for 'imap.h' so we can find it. 2000-06-23 Peter Williams * libmutt/parse.c (mutt_parse_date): Add a check to provide Y2K compliancy. No shit :-) We assume messages with two-digit dates that are less than 70 are in 2000, I don't think anyone has email from before 1970.... 2000-06-21 Peter Williams * libinit_balsa/balsa-druid-page-*.gob: Whoops, don't just construct for the parent class, consturct for our class as well! * libmutt/mx.c (mx_get_magic): Make this a little more forgiving of mailboxes with newlines at the beginning * Makefile.am: put our pixmaps in gnomepixmapdir so that we can find it in the pixmap browser -- if --disable-system-install, no loss. * help/C/Makefile.am: Put our help in gnomedatadir as well. 2000-06-21 Pawel Salek Safe quitting and general clean up. * libbalsa/mailbox.c,src/sendmsg-window.c: use balsa_find_mbox_by_name(p) * src/balsa-app.[hc]: balsa_find_mbox_by_name(p) generalized, moved from src/mblist-window.c * src/main-window.c: recreate list of open mailboxes on change. * src/main.c: code clean up, use force_close_mailbox(), empty trash() doesn't try to refer to nonexisting objects. * src/save-restore.c: use pre-created open mailboxes string. * src/mailbox-conf.c: guess if the path points to dir or single folder. IMAPDir II: old mbox-conf single IMAP folder deprecated. only GUI for update is missing and IMAP speparator handling * libbalsa/imapdir.h: ignore_hidden field * libbalsa/misc.c: handle deep depth trees right. * libmutt/buffy.c: don't fail if the only watched mbox is wrong IMAP. * libmutt/imap.c: list directories only (SEPARATOR!) 2000-06-20 Pawel Salek * README: local mailbox locking configure switches explained. 2000-06-18 Pawel Salek Terence Haddock's flagging patch. * libbalsa/mailbox.{h,c}: send_watcher_mark_flag_message() implemented, MESSAGE_MARK_FLAGGED/MESSAGE_MARK_FLAGGED_MASK enums aded. * libbalsa/message.{h,c}: set_flagged signal implemented. * src/balsa-icons.{h,c}: pixmaps/flagged.xpm added. * src/balsa-index-page.{h,c}: Toggle flagged popup menu entry, balsa_message_toggle_flagged() callback. * src/balsa-index.c: flag displaying code. * src/main-window.c: main menu toggle flag entry Ian Campbell's new message window bug fix. * src/message-window.c: adjusted to the new code. 2000-06-17 Pawel Salek IMAP directory stuff, usable version. Terminology needs polishing. * libbalsa/{libbalsa.h,imapdir.h}: ImapDir structure definition * libbalsa/misc.c: imapdir_* functions. * libmutt/imap.[hc]: imap_browse_foreach() added. * src/mailbox-conf.c: adding IMAP folder sets. * src/save-restore.[ch]: saving/reading IMAP folder sets. 2000-06-16 Peter Williams * src/balsa-index-page.c (store_address_dialog_button_clicked_cb): Ditto here -- the completely confusing "No ;'s" to something more meaningful. * src/filter-edit-dialog.c (fe_run_on): Change the confusing string "Pre-Send" to "Before Sending" for the translators. 2000-06-15 Peter Williams * src/balsa-message.c (part_info_init_unknown): Increase the padding for the "save part" button, aesthetic reasons. 2000-06-15 Matthew Guenther * libbalsa/send.c: Changed balsa_lookup_mime_type to use gnome_mime_type_or_default instead of gnome_mime_type_or_default_of_file because it was having trouble with certain PDF and postscript files. 2000-06-15 Pawel Salek * libbalsa/Makefile.am: added contact.h to the list of files. New era approaching: large patch from Ian Campbell * src/balsa-app.h: some defs. * src/balsa-index-page.c: chaining destructors. * src/balsa-message.[hc]: rewritten. * src/main-window.c, src/message-window.c: extra menu options. 2000-06-14 Pawel Salek Contributed by Thomas Fitzsimmons * libbalsa/{mailbox.c, contact.h}: Contact data structure handling. * src/balsa-index-page.c: Popup menu entry for Storing address, contact dialog box implemented. * src/main-window.c: Menu entry for storing addresses. 2000-06-12 Fatih Demir * src/sendmsg-window.c ('iso_charset_menu): Removed the wrong GNOMEUIINFO_END macro call as another GNOMEUIINFO element follows up to the Russian one ( the Ukrainian one ). 2000-06-12 Pawel Salek * libbalsa/mailbox.c: redundant resetting of Spoolfile removed. * src/balsa-app.c: use balsa_guess_mail_spool for setting Spoolfile. * src/address-book.c: armoured the code against the unexpected. * libbalsa/send.c, libmutt/sendlib.c: #13708 bug fix (sending messages that contain a single dot in a line). 2000-06-11 Peter Williams * src/mblist-window.c (mblist_create_context_menu): Fix typo (to draftbox was to sentbox in context menu). * libbalsa/send.c (balsa_lookup_mime_type): Constify a pointer to quiet a compiler warning. * libbalsa/misc.{c,h}: New function, balsa_guess_mail_spool, that tries to determine the filename of the user's local mail spool. 2000-06-10 Peter Williams * libmutt/pop.c: Open the spoolbox and make sure that it works BEFORE we waste time connecting to the server, a report an error if the mailbox doesn't work. * libinit_balsa/balsa-druid-page-{user,finish,error}.gob: Fix nasty crash-causing typo (can't class an object to its class....) 2000-06-10 Pawel Salek * libbalsa/mailbox.[hc]: handling IMAP mboxes. * libbalsa/mailbox_imap.[hc]: disabled deprecated mailbox_imap_has_new_messages. * libinit_balsa/balsa-druid-page-directory.gob, * libmutt/buffy.[hc]: handling IMAP mailboxes. * src/balsa-mblist.c: call mutt_buffy_notify() less often (big win for remote mailboxes). unify handling of non- and IMAP mailboxes. * src/local-mailbox.c: code clean up. * src/mailbox-conf.c,src/save-restore.c: code clean up, IMAP watching. * src/main-window.c: simplify mailbox checking. 2000-06-08 Pawel Salek * libmutt/mbox.c(mbox_sync_mailbox): first approach to fix the silly mbox sync problem. 2000-06-05 Matthew Guenther Contributed by Alexey Kakunin : * src/balsa-message.[hc]: add get_koi_font_name to use alternate (non ISO) Cyrillic character set. * src/sendmsg-window.c: add KOi8-R to character set menu, set_koi8_charset function. 2000-06-05 Pawel Salek * libbalsa/send.c,src/main-window.c: don't delete loose messages * src/sendmsg-window.c: replying a message from a closed mailbox crashed balsa. 2000-06-02 Peter Williams * src/Makefile.am: s/GNOMEGNORBA_LIBS/GNOMEUI_LIBS/ * libinit_balsa/Makefile.am: generate the private headers now. It *should* work now :-) 2000-06-01 Pawel Salek * libinit_balsa/Makefile.am: removed private header files from the depedency list. * src/balsa-index-page.c: corrected translation macros: use '_(' not '_ (' to make marked strings show up in the .pot file. redundant string allocation, double object destroying, missing personal name, translations of VCARD keywords. * src/balsa-index.c: the index From/To information depends on the mailbox (rewritten Stephen Waters' patch). 2000-06-01 Peter Williams Remove the totally ignored IDL stuff * idl/*: Die! * configure.in: Don't check for ORBit, don't build idl/Makefile * balsa.spec.in: Don't check for installed gnorba data * Makefile.am: idl out of SUBDIRS * src/Makefile.am: Don't link with the servant libraries and don't include $(root)/idl stuff * src/main.c: Don't use ORBit init stuff * po/*.po: Sync with new gobfiles et al * libinit_balsa/balsa-druid-page-{error,finish,user}.gob: Properly access the 'construct' class function * libinit_balsa/Makefile.am: Work around gob ignoring the '--no-private-header' option; put built sources in srcdir as this is what we're supposed to do (according to people on automake-list) 2000-06-01 Peter Williams * libinit_balsa/balsa-druid-page-directory.gob: Use new GOB 1.0.0 stuff and arrays as we should. Also give away the GOB easter egg, I guess. 2000-05-30 Matthew Guenther * help/C/Makefile.am: Use stylesheet images directory. * help/C/balsa.sgml: Correct copyright dates. 2000-05-30 Pawel Salek * src/address-book.c: bug #12535 fix. * src/balsa-message.c: bug #11949 fix * src/balsa-index-page.c: bug #12606 fix. 2000-05-28 Matthew Guenther * src/balsa-index-page.[ch]: patch to add "Store Address" menu item to right-click menu in index, stores message From address in address book. From Thomas Fitzsimmons . 2000-05-28 Matthew Guenther * help/C/balsa.sgml: Fixed section levels and ids so that the Preferences dialog context-sensitive help will work properly. 2000-05-27 Fatih Demir * sounds/balsa.soundlist : Corrected a typo in the [tr]-sections. 2000-05-25 Pawel Salek * help/C/balsa.sgml: Preperties window help started. * src/mailbox-conf.c(conf_add_mailbox): plug a memory leak * src/main-window.c(send_progress_notify_cb): free properly messages sent from outbox in the MT mode. 2000-05-24 Peter Williams * help/C/balsa.sgml: Add FAQ about address book not importing. 2000-05-24 Peter Williams * configure.in (BALSA_REVISION): This is now development version 0.9.0. 2000-05-22 Matthew Guenther * src/main.c: added session management to Balsa, functions balsa_save_session and balsa_kill_session. 2000-05-22 Matthew Guenther * src/balsa-mblist.c (balsa_mblist_mailbox_style): mailbox counter fix. * src/pref-manager.c (create_misc_page): cleaned up look of color picker. 2000-05-22 Peter Williams * libinit_balsa/balsa-druid-page.gob, libinit_balsa/balsa-druid-page-welcome.gob: Enable multibyte fontsets when appropriate. I have no clue what it all means, but Yukihiro Nakai seems to know what he's talking about. 2000-05-20 Peter Williams * libinit_balsa/Makefile.am: @MAINT@ the gob rule, add a nasty dist-hook thing to pick up the generated sources. * AUTHORS README TODO INSTALL NEWS balsa.1.in help/C/balsa.sgml: Documentation updates to make this the official 0.8.0 * configure.in (BALSA_RELEASE): No longer pre1! * Makefile.am: RPM target updated to be just peachy. * Makefile.am: New balsa-dcheck target to not forget the BALSA_DISTCHECK_HACK=yes thingie. @MAINT@ some of those targets. * libinit_balsa/Makefile.am (gob rule): Put %.h in the gob mathcing rule for include dependencies. 2000-05-17 Pawel Salek Infamous safe_free bug fix. * libmutt/protos.h, libmutt/lib.c: mutt_copy_body() func added. The hdr parameter is most likely redundant. * libbalsa/send.c: copy the bodies instead of plain linking to them. delete sent messages from outbox. *libbalsa/message.c(message_delete): handle loose messages. 2000-05-16 Pawel Salek * src/sendmsg-window.c: Celtic language support fixed. * libbalsa/send.c: code cleanup on the way to fix the safe_free bug. * src/balsa-message.c: safe handling of broken images. 2000-05-15 Pawel Salek * configure.in: added pt_PT.po to ALL_LINGUAS 2000-05-15 Kjartan Maraas * TRANSLATABLE_FILES: Added list of files containing translatable strings. 2000-05-12 Peter Williams * src/balsa-message.c (part2canvas): Only print "part end: multipart" in debug mode. 2000-05-07 Pablo Saratxaga * src/address-book.c,src/filter-edit-dialog.c: i18n fixes from Gediminas Paulauskas 2000-05-12 Pawel Salek * src/balsa-message.c: #9422 bug fix. 2000-05-09 Pawel Salek * src/address-book.c: preleminary handling of gcard address lists. 2000-05-07 Pawel Salek * src/save-restore.c (config_mailbox_update): safe local mailbox properties update. 2000-05-07 Pablo Saratxaga * src/balsa-mblist.c: small i18n fix 2000-05-06 Peter Williams * src/balsa-app.[ch]: Allow toggling of whether to exit when balsa_error is called. Defaults to YES; turned off for mailbox checking. We actually need a mutex for this, but we can get away without one. * src/main.c (balsa_exit): Remove unused var. * src/main-window.c (mail_progress_notify_cb): g_free the mailbox pkey now. Include save-restore.h * src/mailbox-conf.c (mailbox_conf_close): Don't g_strdup the mailbox pkey; that is done for us now. * libbalsa/mailbox.h (struct _Server): Remove Server.name field, which is unused. * src/save-restore.[ch] (mailbox_get_pkey): Return a g_strdup string; don't user server->name, which is unused. Remove the const return type. Misc changes to accomodate this. * src/balsa-mblist.c (balsa_mblist_redraw): Check for NULL return value from gtk_ctree_insert_node (caused warnings with POP3 mailboxes) 2000-05-06 Pawel Salek * libbalsa/mailbox.c, src/save-restore.c: Carlos Morgado's fix for storing the POP port number. 2000-05-06 Pawel Salek * libmutt/configure.in: disabled fcntl locks, enabled flock. * README: pointers to locking method discussions. 2000-05-05 Pawel Salek Mailboxes in the configuration are not referred by name only any more. * libbalsa/mailbox.c,src/main-window.c,src/mailbox-conf.c: use mailbox_get_pkey() instead of mbox name. * src/balsa-app.c,src/main.c: code cleanup. * src/save-restore.c: mailbox_get_pkey() and config_get_pkey() impl'd 2000-05-04 Pawel Salek : IMAP mailbox polling to fix auto-logout bug. * libbalsa/mailbox_imap.[hc]: mailbox_imap_has_new_messages added. * libmutt/imap.c: do check the NOOP server response. * src/balsa-mblist.c: actual mailbox polling. 2000-05-03 Peter Williams * libbalsa/mailbox.c (error_in_thread): New function to replace the usual mutt_error, cause it makes GTK+ calls, which in this case happens in another thread, which makes GTK+ barf. (check_all_pop3_hosts): Fix to change mutt_error. * src/main-window.c (mail_progress_notify_cb): Handle the _ERROR message by displaying a dialog box. 2000-05-02 Pawel Salek : * libinit_balsa/balsa-druid-page-directory.gob: handle lack of MAIL environment variable properly. 2000-05-02 Pawel Salek * src/balsa-message.c, src/sendmsg-window.c: Martynas Kunigėlis patch for Baltic language support. 2000-05-01 Matthew Guenther * libbalsa/send.c (balsa_lookup_mime_type): fixed GNOME mime type lookup 2000-04-27 Pawel Salek * src/sendmsg-window.c: one g_free() too much. * src/main.c: code cleanup. 2000-04-26 Kjartan Maraas * libbalsa/mailbox.c: Use '_(' not '_ (' to make marked strings show up in the .pot file. * src/balsa-index.c: Same here 2000-04-25 Pawel Salek * src/save-restore.c: bug fix for remembering open mboxes between sessions. 2000-04-25 Pawel Salek * src/sendmsg-window.c: pasting texts containing \n to subject field lead to wrong mail headers. 2000-04-24 Pawel Salek * src/balsa-app.h,src/save-restore.c,src/main.c: remembering open mailboxes between sessions. * src/mblist-window.c: open-mailbox CLO bug fix. 2000-04-24 Fatih Demir * sounds/balsa.soundlist & sounds/email.soundlist : Added [tr] sections .. 2000-04-23 Mikael Hermansson * src/sendmsg-window.c, src/main.c: show only compose window and quit immediately after sending mail when called with --compose option. 2000-04-23 Andreas Hyden * src/pref-manager.c: Fixed a litte spellerror. 2000-04-21 Peter Williams * src/Makefile.am (INCLUDES): Include $(top_builddir)/idl for the generated headers (when srcdir != builddir) 2000-04-21 Matthew Guenther * libbalsa/message.c (message_is_multipart): changed to message_has_attachment and modified to a better way to determine message attachment status. 2000-04-20 Matthew Guenther * libbalsa/message.c: added function message_is_multipart * src/balsa-index.c (balsa_index_add): add icon to attachment column when message is multipart. * src/address-book.c: parented gnome dialogs to main and send-message windows. * src/balsa-app.h: added main_window to BalsaApplication. * src/balsa-index-page.c: * src/balsa-message.c: * src/mailbox-conf.c: * src/main-window.c: parented gnome dialogs to main window (fixes bug #4809). 2000-04-20 Pablo Saratxaga * configure.in (ALL_LINGUAS): added Lithuanian language 2000-04-20 Pawel Salek * src/pref-manager.c: #8601 bug fix. 2000-04-19 Peter Williams * libmutt/mx.c, libbalsa/send.c: Remove some leftover stderr output. * TODO, README, INSTALL: Documentation updates. * configure.in: Made this look all pretty, and added some extra 'checking' messages. * src/main-window.c (show_about_box): Added some authors. 2000-04-18 Peter Williams * balsa.spec.in: Fixes to make RPMs work. Now I understand why people say RPM sucks. * configure.in (BALSA_VERSION): Changed to reflet preview release, and to placate RPM. * README: Same. 2000-04-18 Pablo Saratxaga * configure.in (ALL_LINGUAS): added Catalan 2000-04-18 Pawel Salek * IMAP authentication error bug fix. 2000-04-17 Fatih Demir * configure.in : Added tr to ALL_LINGUAS . 2000-04-16 Matthew Guenther * libbalsa/send.c (balsa_create_msg): Added balsa mime lookup function balsa_lookup_mime_type to fix bug #4821 2000-04-12 Peter Williams * src/mailbox-conf.c (conf_update_mailbox): Address bug #8915 hopefully (check for NULL before g_frees) * src/balsa-mblist.c (balsa_widget_get_bold_font): Change function behavior to reference font, and checking for NULL font again... hopefully this ensures a nonnull style->font (see bug #7356) * src/mblist-window.c (size_allocate_cb): Fix size calculation ( + 18... yeah right ). 2000-04-12 Pawel Salek * sounds/Makefile.am, balsa.spec.in: packaging on RedHat failed. 2000-04-11 Pawel Salek * libbalsa/message.c: handle 'references' header properly * libbalsa/misc.c: wrapping misalignment * src/balsa-message.c: ':' to headers, memory leak * src/sendmsg-window.c: multiple attachment bug fix. 2000-04-10 Peter Williams * configure.in: Add check for gob when using CVS source. 2000-04-09 Matthew Guenther * src/address-book.c (ab_load): fix memory allocation bug, use more glib string functions, set ->name to ->id if no Id is present in the vcard. * src/address-book.c (ab_clist_clear): g_free'd id. (ab_okay_cb): g_free'd id. 2000-04-08 Peter Williams * AUTHORS: Made this make more sense and reflect the changes in development team over the lifecycle of Balsa. * configure.in: Print a little warning if the source is CVS source. 2000-04-08 Matthew Guenther * src/balsa-mblist.c (balsa_mblist_insert_mailbox): Fixed bug with mailbox info. 2000-04-08 Fatih Demir * balsa.desktop : Added the Turkish translation . 2000-04-07 Peter Williams * libbalsa/misc.c (wrap_string): Aborting when the input string is null is a bit excessive... * configure.in, Makefile.am: Whoopsie, forgot to remove the stuff for the website from these files. 2000-04-07 Pawel Salek * src/sendmsg-window.c: multiple attachment selection. 2000-04-07 Pawel Salek * libbalsa/message.c,libbalsa/misc.[hc],src/balsa-message.c: showing all and selected headers completed. 2000-04-06 Peter Williams * help/C/Makefile.am: better target for index.html; help now works with readonly srcdir. 2000-04-05 Pawel Salek * libmutt/socket.c,src/mblist-window.c: trying to open IMAP folder on non-existing server should not crash balsa any more. 2000-04-04 Pawel Salek * libmutt/imap.c,src/balsa-index-page.c: non-existing IMAP mailbox bug fix. 2000-04-04 Pawel Salek * src/sendmsg-window.[hc]: postpone works now with empty To field. 2000-04-04 Pawel Salek * src/address-book.c: Fellmann Joaquim's patch (with minor changes) - lookup fix. * src/balsa-index.c: removed old crust. * src/main-window.c: fix a memory leak. 2000-04-04 Ian Campbell * libbalsa/misc.[ch]: Added function 'mailbox_node_destroy' * libbalsa/send.c: Removed some unused variables * src/balsa-index-page.c: Added some #ifdef MSG_STATUS_USED around functions which are only used inside similar #ifdefs * src/balsa-mblist.c: Use mailbox_node_destory as the handler in set_row_data, fixes a memory leak * src/local-mailbox.c: Fix a memory leak * src/mblist-window.h: Fix a prototype. * src/save-restore.c: Fix memory leak. 2000-04-03 Peter Williams * src/main-window.c (wrap_message_cb): Fixed cast to GTK_WIDGET to be after test for NULL to silence GTK+ warning on startup. * libbalsa/misc.c (find_word): Fixed really nasty-looking logic and a bug where the 'to' field wouldn't show up in the compose window as a default. * src/balsa-app.c (cantfind_notice): Made Balsa gracefully handle a missing 'special mailbox' 2000-03-30 Matthew Guenther * src/main-window.c: changed reply to all to use reply_to_all.xpm, and reply_to_all_menu.xpm, pointer casting bug. * src/pref-manager.c: fixed pointer casting bug. 2000-03-30 Peter Williams * src/arrow.xpm: moved to src/pixmaps/ * src/balsa-icons.{c,h}: added new arrow pixmap; but pointless because it's currently unused! * src/Makefile.am: arrow.xpm from EXTRA_DIST 2000-03-28 Peter Williams * libbalsa/files.{c,h}: created balsa_file_finder, a *working* version of gnome_xxxx_file() * configure.in: Added system install check, testing for installs into Gnome's prefix that may require root privileges. Added website options, to generate the website files and give them a root and prefix. * src/mailbox-conf.c, src/main-windows.c, src/sendmsg-window.c, libinit-balsa/helper.c, libbalsa/mailbox.c: Use balsa_file_finder * images/Makefile.am, sounds/Makefile.am: Use appropriate installation prefex depending on sysinstall option * po/POTFILES.in: Remove src/spell-check.c, which does not compile and is not built * libbalsa/Makefile.am: Added files.{c,h} to libbalsa * website: Added directory for the Balsa website in CVS, buildable and installable with specifiable prefixes. 2000-03-27 Pawel Salek * src/balsa-app.c: auto-check explicitly checks Inbox. * src/balsa-index-page.c: bug #4805 fix * src/balsa-mblist.c: mail check bug fix. * src/main-window.c: bug #4805, #4806 fix, mail check bug fix, title bar. * src/mblist-window.c: resize mblist rehashed 2000-03-26 Pawel Salek * main.c: reorganized the initial mailbox opening code. * configure.in: mailbox info switch on by default. 2000-03-25 Matthew Guenther * src/main-window.c: fixed opening of mailboxes on startup. * src/balsa-mblist.[hc]: added balsa_mblist_open_inital() and startup_mailbox_open_list. (mailbox_nodes_to_ctree): fixed opening of mailboxes on startup. (balsa_mblist_insert_mailbox): allow for mailboxes to be opened at startup. 2000-03-24 Pawel Salek * libbalsa/mailbox.c, src/balsa-mblist.c, src/balsa-message.c: * src/main-window.c: bug hunting - message counting. 2000-03-24 Matthew Guenther * src/main-window.c: add next_unread_message_cb, associated menu and toolbar items. * src/balsa-index.[hc]: add balsa_message_next_unread * src/balsa-index-page.[hc]: add balsa_index_select_next_unread 2000-03-23 Pawel Salek * src/balsa-message.c: handling msgs w/o respective fonts * src/main-window.c: forwarding/replying multiple msgs * src/sendmsg-window.[hc]: handling multiple open compose wnds. 2000-03-22 Joaquim Fellmann * src/balsa-mblist.c: i18n and i12n update 2000-03-22 Fellmann Joaquim * src/balsa-mblist.c: make a string i18n comp. for mbox stats 2000-03-20 Pawel Salek * libbalsa/libbalsa_private.h: less verbose threaded mbox locking * libmutt/rfc822.c: de-quotation handles commas in comments * src/sendmsg-window.c: forward subject clarified. 2000-03-17 Matthew Guenther * src/sendmsg-window.c (bsmsg2message): enable In-Reply-To and References headers * libbalsa/send.c (balsa_create_message): enable In-Reply-To and References headers * libbalsa/message.h: Added references var to Message struct * libbalsa/message.c: Init and destruction of references variable * src/balsa-mblist.c: cleaner style setting, add colour * src/pref-manager.c: add colour picker for mblist unread mailbox color * src/save-restore.c: save/load colour for mblist * src/balsa-app.c: field to store colour and defaults * configure.in: change --enable-info do default yes, better (less broken) option description 2000-03-15 Pawel Salek * src/balsa-app.[hc], src/pref-manager.c,src/save-restore.c, * src/sendmsg-window.c: signature separator handling. * src/local-mailbox.c: compilation warning removed. 2000-03-14 Pawel Salek * src/sendmsg-window.c, src/balsa-app.c, src/balsa-mblist.c, * src/mailbox-conf.c, src/main-window.c: The deleting mailboxes via Balsa is expected to work properly now. Some minor bug fixes. 2000-03-14 Pawel Salek * src/balsa-app.c: handles lack of trash nicely * src/mailbox-conf.c: ultimate solution of the mailbox deletion command. Should work for any combination. * src/main-window.c: close mailbox command restored * src/sendmsg-window.c: fixed some shortcuts 2000-03-14 Pawel Salek * src/balsa-message.c, libbalsa/filter-file.c: * libbalsa/misc.c, libbalsa/mime.c: readfile() allocates place for ending '\0' character - last character of a text body in multipart message used to be eaten. * src/main.c: used to assume that balsa_app.notebook exists when empting trash. * src/main-window.c: status bar message removed when closing last mailbox. * src/sendmsg-window.c: major code clean up (uff!), finished function documentation. 2000-03-13 Alastair McKinstry * po/ChangeLog, po/ga.po: Updates 2000-03-13 hectorg * libbalsa/send.c, src/main-window.c: Some minor bugs fixed in send code 2000-03-12 birger * po/da.po: Modified Files: balsa/po/da.po 2000-03-12 Pawel Salek * src/balsa-app.c, src/balsa-index-page.c, src/balsa-index.c, * src/balsa-mblist.c, src/local-mailbox.c, src/main-window.c, * src/mblist-window.c, src/mblist-window.h: Fix for duplicate local mailboxes that were located in the local mail directory and were added at the same time to the cofiguration. Fixes also local mailbox deletion problem. 2000-03-11 alastairmck * balsa.desktop: Irish translations 2000-03-11 Matthew Guenther * libbalsa/misc.c: Added style to MailboxNode * src/mblist-window.c: Update mailbox style when changing mailboxes * src/balsa-mblist.c: Mailboxes with unread messages are now displayed without having to load the mailboxes. * src/main-window.c: Mailbox appearence are now updated when the "Check New Messages" button is pressed. 2000-03-11 Alastair McKinstry * balsa.desktop: Added Irish translation. 2000-03-08 Pawel Salek * libbalsa/message.c, libbalsa/message.h: Selection of shown headers: none, user selected or (almost) all. * libbalsa/misc.c: make_string_from_list didn't handle NULL elements. * libbalsa/misc.h: 2000-03-06 Peter Williams * libbalsa/mailbox.c (translate_message): On tip from Birger Langkjer, increase size of date buffer from an unreasonable-small 27 characters to 128. 2000-03-05 Pawel Salek * libbalsa/message.c, libbalsa/message.h: I18n support in the message window and automatic charset selection for replying and forwarding. Wrapping for message view widget. 2000-03-05 Morten Welinder * libbalsa/misc.c (make_string_from_list): Plug leak. * libbalsa/message.c (message_body_unref): Use body_free. * src/balsa-mblist.c (mailbox_nodes_to_ctree): Plug leak. * src/balsa-message.c: Include for isspace. (reflow_string): Use isspace properly. (mimetext2canvas): Initialise flags. * src/local-mailbox.c (is_mh_message): Use isdigit properly. 2000-03-03 Peter Williams * libbalsa/mailbox.c (translate_message): Uses user's preferred time format now. * src/save-restore.c, src/balsa-app.h, src/prefs-manager.c: Changes to support the new preference. 2000-2-28 Héctor García Álvarez * Some changes in SMTP to make it work right with the queue 2000-2-26 Peter Williams * Allowed the user to save the text in any message by clicking. 2000-2-26 Birger Langkjer * Integrated a patch from Mikael Hermansson 2000-2-25 Matthew Guenther * src/mblist-window.c: * src/balsa-mblist.c: Added ability to display total number of messages and number of unread messages in the mailbox list. Mailboxes with unread messages are displayed in bold, and with different icon. Mailbox list is updated when mailbox contents change (through user action). Can now sort mailboxes by name, number of unread messages, or total number of messages, in ascending or descending order. Mailbox info column width is saved between sessions. Fixed mailbox tree expand/collapse to save between sessions. * src/balsa-index-page.c: Reading messages in index will decrement message unread_messages count and update mailbox list display. * src/save-restore.c: Code to save all the mailbox list stuff. * libbalsa/mailbox.c: Fixed mailbox loading code to increment mailbox messages counter. * libbalsa/message.c: Flag changing fixed to prevent double decrement of message count. 2000-2-14 Birger Langkjer * src/sendmsg-window.c: fixed spelling error: Cyrylic->Cyrillic 2000-2-11 Tomasz Kłoczko * balsa.desktop: moved desktop file from gnome-core, * gnome-balsa2.png: moved icon file from gnome-core. 2000-2-9 Tomasz Kłoczko * balsa.desktop: * Makefile.am: added desktop file for balsa. 2000-2-1 Matthew Guenther * src/mblist-window.c: Column size saving code cleaned up, better implementation using notebook selection. Good to go. 2000-1-29 Matthew Guenther * src/balsa-app.h: * src/balsa-app.c: * src/save-restore.c: * src/balsa-index.c: Added the ability to save index column sizes between mailboxes and sessions. Rough. 2000-1-18 Joaquim Fellmann * src/pref-manager.c: i18n a forgotten string. 2000-1-14 Yun-Chung Cheng * /po/zh_CN.po: Added po file from TurboLinux Chinese Develop Team. * configure.in: Added zh_CN.po entry 2000-1-3 Ragnar Henriksen * src/pref-manager.c: Changed the helpfile location. 2000-1-1 Héctor García Álvarez * libbalsa/send.c: Added deletion on sended queued messages. SMTP support should now work properly. No known bugs in STMP support yet. 1999-12-31 Ragnar Henriksen * src/pref-manager.c: The help button are now working. 1999-12-31 Bruno Pires Marinho * .cvsignore: Removed the ABOUT-NLS from CVS because gettext adds it when the autogen.sh is called. 1999-12-30 Bruno Pires Marinho * libbalsa/mailbox.c (translate_message): * src/sendmsg-window.c: * libbalsa/send.h: * libbalsa/send.c: Added the code necessary to save the message ID of the replyed message. The mailbox name where the message is located is also saved. Added also the code to read the saved stuff. Left a TODO to find the message and set it answered. * libbalsa/mailbox.c (translate_message): Include set message_id on the Message. * src/main-window.c (continue_message_cb): Only continue on the draft mailbox. * src/sendmsg-window.c: The mailbox where the message was erased because it was sent or continued should be immediately committed. Remove the direct names of the mailboxes (like Sentbox) and put the current name instead (like balsa_app.sentbox->name). * balsa.spec.in: Improved the spec file by adding a sysconfdir=/etc, removing the man instalation because balsa does it now and adding the files on the /etc to the distribution. * Makefile.am: * .cvsignore: * balsa.1.in: * balsa.1: Removed balsa.1 and add balsa.1.in with 0.6.0 replaced by @VERSION@. The configure file now generated the balsa.1. Also made the Makefile.am install the man file. * help/C/Makefile.am: * images/Makefile.am: Removed the use_sys_install stuff and make it right. * configure.in: * acconfig.h: Normal users don't need gob to build the system so we don't check for is presence. Also removed the use_sys_install stuff because it makes no sence. * libinit_balsa/*.gob: Made the gob files compatible with the latest version 0.91.2. * libinit_balsa/Makefile.am: The built files go with the distribution and the GOB variable is gone. Also added the option --no-private-header to gob command. This way we avoing adding a lot of header files. * libinit_balsa/.cvsignore: Ignore generated files. * src/balsa-message.c: The fcc shows up if exists for postponed messages. * libbalsa/mailbox.c (translate_message): * src/sendmsg-window.c: * libbalsa/send.h: * libbalsa/send.c (balsa_postpone_message): The fcc is saved in postponed messages. 1999-12-30 Ragnar Henriksne * src/pref-manager.c - total rewrite of the layout, and new features. * src/balsa-app.h new stuff to balsa_app. (new features) * src/arrow.xpm - new file ( a dummy arrow ) until we manage to create some real stuff... * src/main.c - added the functionallity "empty trash". * src/save-restore.c - save and restore of new features. 1999-12-29 Martin Norbäck * configure.in: added "sv" to ALL_LINGUAS. 1999-12-28 Bruno Pires Marinho * src/balsa-app.h, src/balsa-app.c, src/sendmsg-window.c: Changed to read signature file every time it is needed, to let the user edit the signature without restarting Balsa. (Patch from Sverre H. Huseby ) * src/balsa-app.h, src/save-restore.c, src/balsa-app.c, src/sendmsg-window.c, src/pref-manager.c: Added user settable default Bcc field for outgoing mails. (Patch from Sverre H. Huseby ) * configure.in: Removed the detection of docbook since it is not needed now. * help/C/Makefile.am: * help/C/topic.dat: I don't know how the .htm files show up but my system generates .html files. Peter also put some section names so the files changed their names. All fixed now. Also removed the generated files from CVS and they are put on the distributed tar.gz file when the file is built. * help/C/balsa.sgml: Corrected the file. A > was missing and a . was out of a paragraph. Also changed the file from version 3.1 to 3.0. More people have the old version and I think Peter doesn't use any new feature off 3.1. * help/C/.cvsignore: Makefile.am was ignored instead of Makefile.in. 1999-12-27 Yuri Syrota * configure.in: added "uk" to ALL_LINGUAS. 1999-12-24 Héctor García Álvarez * libbalsa/send.c: Now Balsa send queued messages as it should. 1999-12-21 Bruno Pires Marinho * src/main-window.c (balsa_window_refresh): * src/pref-manager.c (apply_prefs): Added code to really change the toolbar style right after the preferences manager change it and not when balsa is restarted. 1999-12-21 Stuart Parmenter * TODO, INSTALL, AUTHORS, configure.in: Add people to AUTHORS, etc bump version to 0.6.0 1999-12-21 Héctor García Álvarez * libbalsa/send.c: Made some changes to make balsa send queued messages. Still have the bug when trying to send queued messages from a Mailbox format outbox. 1999-12-21 Bruno Pires Marinho * src/main-window.c: When the notebook changes the message preview should change accordly and when the last mailbox is closed the message preview must be cleared. * src/balsa-index-page.h: * src/balsa-index-page.c: Added function to change the message preview to the focus message of the Balsa Index given. Also when the message is unselected it is necessary to clear the message preview. * src/balsa-index.c: * src/balsa-index.h: Added new signal: unselect message. * src/balsa-message.c: Added the code for balsa_message_clear. 1999-12-20 Bruno Pires Marinho * src/balsa-message.c (headers2canvas): Changed the From field to be right after Date field. * src/pref-manager.c: Removed two warnings due to repeated gtk instructions. * src/Makefile.am: Rearranged the file. * libmutt/*: * libbalsa/message.c: * libbalsa/mailbox.c: * libbalsa/send.c: Updated libmutt to the version 1.0i with last ChangeLog entry on Wed Oct 20 14:51:57 1999. 1999-12-17 Peter Williams * libinit_balsa/balsa-druid-page-user.gob: Changed default local mail directory to ~/mail, not ~/balsa. * src/balsa-index-page.c (transfer_messages_cb): Prevent transferring a message to its own folder, which was a coredump. 1999-12-16 Peter Williams * macros/Makefile.am: uncommented "if INSIDE_GNOME_COMMON" as mentioned by Jules Bean. 1999-12-14 Peter Williams * configure.in, libinit_balsa/Makefile.am, src/Makefile.am, src/main.c, po/POTFILES.in src/main-window.c, src/balsa-init.[ch]: Made libinit_balsa mandatory and removed old init code. 1999-12-14 Ragnar Henriksen * removed a newline tag after name in addressbook. It could cause strange things, I didn't see this the first time I updated address-book.c. But after upgrading to the latest gnome-pim it showed. (Maybe they did something with the layout of GnomeGard.gcrd?) 1999-12-12 Peter Williams * libbalsa/filter-file.c: Removed compile warnings libbalsa/libbalsa.c: Ditto libbalsa/mailbox.[ch]: Ditto libbalsa/message.c: Ditto src/balsa-index-page.[ch]: Ditto src/balsa-mblist.c: Ditto src/filter-edit.h: Ditto (moved static definitions) src/filter-edit-dialog.c: Ditto src/mailbox-conf.c: Ditto src/main-window.[ch]: Ditto src/main.c: Ditto (added evil ugly uncalled hack function) src/mblist-window.c: Ditto src/pref-manager.c: Ditto src/print.c: Ditto libinit_balsa/balsa-druid-page-finish.gob: Ditto libinit_balsa/balsa-initdruid.gob: Fixed absentminded coredump on cancel 1999-12-09 Peter Williams * src/save-restore.h: Added necessary #include libbalsa.h * libinit-balsa/*.gob: Finished alpha revision. 1999-12-09 Lauris Kaplinski * configure.in: added et to ALL_LINGUAS. 1999-12-08 David Pickens * libbalsa/mailbox.c, mailbox.h, message.c, send.c, threads.h, src/main-window.c, main-window.h, main.c, threads.h Added messaging system for sending thread to communicate w/ main thread. Outbox/Sentbox now update on send. 1999-12-07 Peter Williams * libinit_balsa/balsa-druid-page-error.gob: Added nice error page * libinit_balsa/balsa-druid-page-user.gob: First real page, user settings (mailroot added to this page) 1999-12-07 David Pickens * Added multi-threaded send mail (if --enable-threads): libbalsa/send.c, libbalsa/threads.h, src/main.c, src/threads.h 1999-12-05 David Pickens * /cvs/gnome/balsa/src/balsa-app.c, * /cvs/gnome/balsa/src/balsa-app.h, * /cvs/gnome/balsa/src/main-window.c, * /cvs/gnome/balsa/src/pref-manager.c, * /cvs/gnome/balsa/src/save-restore.c: Added progress dialog options 1999-12-05 Peter Williams * src/balsa-init.c (balsa_init_window_new, druid_destroy_cb): Destroy the window owning the druid as well. 1999-12-05 Héctor García Álvarez * Rewrited send and SMTP funtions * libbalsa/send.c: Added ofline message writing funcionality 1999-12-04 David Pickens * Added mail check every x minutes option 1999-12-02 David Pickens * added ability to compile w/out threads (see 11-29) * src/main-window.c: fixed progress window 1999-12-01 Peter Williams * src/address-book.c: Fixed stray reference to MDI 1999-11-29 David Pickens *src/main.c, main-window.c, main-window.h: added multi-threaded mail checking, progress window. *libbalsa/mailbox.c, mailbox.h, libbalsa-priv.h: same *libmutt/pop.c: same 1999-11-29 Peter Williams * src/balsa-index.c (balsa_index_set_mailbox): Fixed to make message status icons work. (mailbox_listener): Same. * libbalsa/mailbox.c: Same. * libbalsa/message.c: Same. * src/balsa-index-page.c: Same. 1999-11-28 Peter Williams * src/main-window.c: Proper recording of the main window's size now. Fixed compile warnings by commenting out some unused things (search for (FIXME unused) * acconfig.h, configure.in: Updated with dummy --enable-threads argument (does nothing except define BALSA_USE_THREADS) 1999-11-28 Hector Garcia Alvarez * Added SMTP funtionalty. This should be consider alpha software. It has only been probe by me. * src/balsa-app.h : Added balsa_app.smtp to struct * src/save-restore.c : Added support to read and write config parameter about using smtp or local mail delivery * libbalsa/send.c : Added funtions balsa_smtp_send and smtp_answer. 1999-11-28 Bruno Pires Marinho * idl/Makefile.am: The auxiliary library libbalsasrv.a was installed on the system instead of the balsa.idl file. When you change the ORBit version this could break and with the balsa.idl that doesn't happen. * .cvsignore: * ABOUT-NLS: * acinclude.m4: * configure.in: * po/.cvsignore: To remove the intl module from being checked out when you check out balsa I had to change a couple of things. 1999-11-25 Ragnar Henriksen Added config parameter: * The users may now select when to include signature. 1999-11-23 Ragnar Henriksen * new file: address-book.h * rewrote ab_load(). * added name search. * removed al comp. warningsi for address-book.c. 1999-11-22 Peter Williams * src/balsa-app.h (DEFAULT_MESSAGE_FONT): This font should now exist. * src/balsa-init.c (generic_back_cb): Fixed problem with buttons disabled? Problem even existed? 1999-11-21 Peter Williams * src/balsa-init.c: Complete rewrite with GnomeDruid! Yahoo! * src/balsa-init.c: Fixed it so it really works :-) 1999-11-20 Ragnar Henriksen * new files: print.h print.c -> the beginning of printing. * save-restore.c added saveing and loading of print setup. * pref-manager.c added print notebook. * balsa-app.h/c added print setup to balsa struct. * main-window.c added print icon. 1999-11-18 Stuart Parmenter * libbalsa/mailbox.[ch] Changed mailbox code to act as GtkObjects * libbalsa/mailbox_local.[ch] libbalsa/mailbox_pop3.[ch] libbalsa/mailbox_imap.[ch] added new files * libbalsa/mailbox.c (mailbox_new): now returns a GtkObject instead of a Mailbox (mailbox_free) removed. * src/* wrap mailbox_new in BALSA_MESSAGE() src/* change mailbox_free to gtk_object_destroy() 1999-11-15 Peter Williams * src/balsa-index-page.c (create_menu): Fixed size of Transfer mblist; now that balsa_app.mblist_width means something, we use it for the usize. * src/sendmsg-window.c (add_attachment): Clean up attachment code a little bit. * configure.in, images/Makefile.am: Fixed to install pixmaps in the correct location. * src/main-window.c (balsa_window_new): Added callback to record changes in 'notebook_height' and set the default position. * src/balsa-app.h, src/save-restore.c (config_global_load): Changed from deprecated 'mblist_height' to shiny new 'notebook_height'. 1999-11-14 Peter Williams * src/main-window.c (balsa_window_new), src/balsa-index-page.c, balsa-mblist.c: Replaced gtk_widget_set_usize()'s with code that properly sets the position of the large paned widget. * src/mblist-window.c (balsa_mailbox_list_window_new): Added signal handle on size_allocate to set balsa_app.mblist_width. * src/balsa-mblist.c (balsa_mblist_destroy): Fixed erroneous setting mblist_width/height to 1x1 1999-11-13 Peter Williams * src/mailbox-conf.c (mailbox_conf_set_values): Fixed typo in IMAP configuration. * src/save-restore.c (rot): Fixed bad assertions. 1999-11-12 Peter Williams * src/main-window.c (balsa_window_real_close_mailbox): Implemented real_close_mailbox(). * src/balsa-index-page.[ch] (balsa_index_page_close_and_destroy): Added a delete function for BalsaIndexPage. Hooks up to destroy signal so you should call gtk_object_destroy() on it. * src/mblist-window.c (mblist_open_mailbox): Prevent multiple windows of the same MB opened. * src/main-window.c (file_menu): Add the 'Exit' menu item back, hooked to balsa_exit(). * src/balsa-app.c (read_signature): Fix off-by-one on .signature loading. 1999-07-28 Tomasz Kłoczko * po/pl.po, configure.in Sync with PLD cvs tree: - added pl translation (translation by Paweł Dziekoński and fixes by Zbigniew Chyla ) 1999-04-08 Jesse Sightler * src/balsa-message.c: Added keyboard navigation. * src/sendmsg-window.c: Improved general layout and added drag'n'drop of addresses from Gnomecard. * libbalsa/mime.c: Fixed failure to traverse all nodes of multipart msg. Wed Mar 31 18:14:00 1999 Manish Vachharajani * src/mailbox_conf.c: Show the config notebook widget before changing pages so pages actually change. Is this a gtk+ bug? Fri Mar 19 03:32:49 1999 Timur Bakeyev * src/Makefile.am: Change set of "GNOMEUI_LIBS -lgnorba ORB_LIBS" to GNOMEGNORBA_LIBS, which is more correct and clean. And prevent from linker errors. 1999-02-24 Sergey Panov * src/filter-edit-dialog.c, src/pref-manager.c: added missed _() macros 1999-02-11 Sergey Panov * src/main.c, src/Makefile.am: turn on internationalization 1999-02-01 Jaka Mocnik * src/filter-edit-dialog.c (build_left_side): pass it a GtkWidget ** parameter to get the clist pointer in. (build_right_side): accept a GtkWidget * parameter in order to pass it a clist for apply/revert callbacks userdata. (filter_edit_dialog): utilize the above. * src/filter-edit-callbacks.c (unique_filter_name): actually increment row. 1999-01-20 Nat Friedman * src/pref-manager.c (open_preferences_manager): Connect the help signal of the GnomePropertyBox to gnome_help_pbox_display. 1999-01-19 Jeff Garzik * src/balsa-app.c, src/balsa-init.c, src/filter-edit-dialog.c, src/index-child.c, src/mailbox-conf.c: Renamed deprecated Gtk+ functions. 1999-01-18 bertrand * src/save-restore.c: add a new property key ("ShowMailboxContentInfo") * src/pref-manager.c: add a preference item (show/hide mailbox content information) * src/balsa-mblist.c (balsa_mblist_redraw): (balsa_mblist_init): show/hide the clist colums titles depending on the pref setting. * src/balsa-mblist.c (balsa_mblist_class_init): cntent information disabled for the moment. New argument ("show_content_info") to th emblist object. Have to store it in the prop list. 1999-01-15 bertrand * src/index-child.c (index_button_press_cb): new function to handle double click properly regarding to new gtk+ code. (index_select_cb): no more double click handling code. (index_child_create_view): connect scrolled windows adjustments to the canvas adjustments. Set the step increment. 1999-01-14 bertrand * src/mblist-window.c (mblist_open_window): take the "MailboxListHeight" into account. * src/save-restore.c (config_global_save): new property: "MailboxListHeight" (config_global_load): idem. * src/balsa-app.h: new kember to store the mailbox list height. (useful only when the window is floatting) * src/mblist-window.c (mblist_menu_open_cb): (mblist_menu_close_cb): src/main-window.c (mailbox_menu): two new items to open/close a selected mailbox from the menubar. 1999-01-14 bertrand * src/mblist-window.c (mb_close_cb): new func (mblist_create_context_menu): new context menu item: close the mb. * src/mblist-window.c (mblist_create_context_menu): s/mblist_create_menu/mblist_create_context_menu (mblist_create_context_menu): new context menu item (open mailbox) (mb_open_cb): corresponding callback. (mblist_open_mailbox): new func. Use this to open a mailbox. * src/mblist-window.c (mblist_button_press_cb): removed the mblist_clicked_cb function and replaced it by this new one. All mouse press events are handled in this callback now. Before this, things were not very clear. For example, the double-click left button was handled in the mailbox_select callback. 1999-01-13 bertrand * src/mailbox-conf.c (mailbox_conf_delete): bug when removing the firts pop mailbox. Fix submitted by Ian Campbell * src/main.c (config_init): commented out the return keyword after .balsarc initialisation. It prevented the config to be loaded and in particular the mailbox list window size to be set correctly when a .balsarc did not exist. * src/mblist-window.c (mblist_clicked_cb): new function to handle contextual menus more precisely and in particular, allowing the menu to appear even when the mouse does not click on one mailbox row. 1999-01-12 bertrand * src/filter-edit-callbacks.c * src/mailbox-conf.c * src/pref-manager.c : s/gtk_toggle_button_set_state/gtk_toggle_button_set_active/ to conform to changes in gtk+. 1999-01-11 bertrand * src/mblist-window.c (mblist_drag_data_received): check if the source mailbox is not the dest mailbox. (mblist_drag_motion): when the drag pointer is not on a valid row, deselect all. (mblist_drag_leave): when the drag pointer leave the window, unselect all * removed the dnd trace * src/index-child.c (index_child_setup_dnd): changed the drag icon (index_child_create_view): unset "use_drag_icons" & "reorderable" clist flags. * src/pref-manager.c (apply_prefs): replyto field chages were not saved. fixed. * src/index-child.c src/mblist-window.c : add some dnd trace code cause dnd does not work anymore. * src/sendmsg-window.c (sendmsg_window_new): bugfix when replying to a message with subject begining with Re: 1999-01-11 bertrand added the code to commit the changes which are flagged (generally deletion). The code is OK, but some general issues remain to be fixed. (in particular, the problem which open_unref automatically syncing mailboxes and thus freeing delete-flagged messages ) * src/main-window.c (mailbox_commit_changes): new menu for this ("Mailboxes" -> "commit current") * libbalsa/mailbox.c (mailbox_commit_flagged_changes): new function to commit the changes which are only flagged. * src/balsa-index.c (balsa_index_del): new functino to delete a message from the index list. (mailbox_listener): proper answer to the delete watcher message. 1999-01-10 bertrand added the code to view infos about the mailboxes in the mailbox list it roughly works but the possibility to show or not show info fields must still be added. * src/balsa-mblist.c (balsa_mblist_set_row_info_fields): new function to display informations about a mailbox. (balsa_mblist_release_watchers): free the list of mailbox the mailbox list is watching. (balsa_mblist_add_watched_mailbox): add a mailbox to the list of watched mailboxes. (balsa_mblist_redraw): when creating the mailbox row, add the info fields (mailbox_nodes_to_ctree): idem on normal mailboxes. (mailbox_listener): when notified there is a change, upadte the information field of the concerned row. * libbalsa/mailbox.c: new function (mailbox_gather_content_info) the name tells everything about it. (message_copy): update the mailbox info fields (message_move): idem (message_read): idem (message_unread): idem (mailbox_check_new_messages): idem * libbalsa/mailbox.h: added the unread_message field. also added the total_messages field. 1999-01-08 bertrand * src/balsa-mblist.c (balsa_mblist_redraw): start to add mailbox info in the mailbox list window (number of messages, number of unread messages). This should be configurable cause I guess not everybody likes this. 1999-01-08 Nat Friedman * src/main-window.c (settings_menu): No separator before Preferences. (main_menu): Added N_() around "Message" and "Mailboxes" 1999-01-08 bertrand * src/index-child.c (index_child_new): when the mailbox already exists, set it as the active view. 1999-01-08 bertrand messages can be moved even when the destination is already opened :-)) * libbalsa/mailbox.h: added a new mailbox watcher message to tell a watcher a message has been appended but that it is not a new message. * libbalsa/mailbox.c (send_watcher_append_message): new function to send an APEND message. (message_copy): send an append message to the dest mailbox (message_move): idem. (_mailbox_open_ref): when the mailbox was already opened but not in append mode, close it first. 1999-01-08 Nat Friedman * src/message-window.c (forward_message_cb): Get the messagewindow from the window's gtk data. (replytoall_message_cb): Likewise. 1999-01-08 Nat Friedman * src/sendmsg-window.c (file_menu): Standardized. (close_window): Fixed signature. (send_message_cb): Likewise. (attach_clicked): Likewise. (close_window): Likewise. (attach_dialog_cancel): Likewise. 1999-01-08 Nat Friedman * src/message-window.c: Include sendmsg-window.h and message-window.h Added a prototype for destroy_message_window. (message_menu): A new menu. (replyto_message_cb): Calback for the new menu. (replytoall_message_cb): Likewise. (forward_message_cb): Likewise. (message_window_new): gtk_object_set_data stores the MessageWindow, not the window. 1999-01-08 Nat Friedman * src/main-window.c (APPBAR_KEY): Changed the PROGRESSBAR_KEY to APPBAR_KEY. (main_window_set_cursor): Use the GnomeAppBar's progress meter. (main_window_init): Removed all the code to create a GtkProgressBar. Use the GnomeAppBar progress meter instead. 1999-01-07 Nat Friedman * src/index-child.c: Updated the copyright 1999-01-07 Nat Friedman * src/message-window.c: Updated the menu items for the message window to reflect the standard. Added the 'message' field to the MessageWindow structure. Added the 'displayed_messages' hash table. (message_window_new): Check to see if the specified message is already displayed, and if so, gdk_window_raise() the window containing it. If not, add it to the hash table. (destroy_message_window): Remove the hash-table entry corresponding to this message window. 1999-01-07 Nat Friedman * src/main-window.c (main_menu): Updated to use the SETTINGS standard menu, and moved Preferences back to there. 1999-01-07 Nat Friedman * src/main-window.c (app_created): Use the GnomeAppBar instead of the GtkStatusBar. 1999-01-07 Nat Friedman * src/main-window.c (file_menu): Use GNOMEUIINFO_MENU_PREFERENCES_ITEM. (mailbox_menu): Added menu hints to the custom menu items. 1999-01-07 Nat Friedman * src/main-window.c (main_window_init): Install the menu hints. (show_about_box): Updated the copyright dates. Move the preferences menu item to the File menu. 1999-01-07 bertrand * libbalsa/mailbox.c (_mailbox_open_ref): unlock the mailbox even if it was already opened before. (message_move): test if we actually opened the mailbox or if it was opened before. When it was already opened, don't unref it. --> the dnd move works now, yeepeeh ! 1999-01-07 Nat Friedman * src/main-window.c (help_menu): Use GNOMEUIINFO_MENU_ABOUT_ITEM and the standard GNOMEUIINFO menu trees. 1999-01-06 Nat Friedman * src/main-window.c (file_menu): Use the GNOMEUIINFO standard menu item for exit. 1999-01-06 Nat Friedman * src/main-window.c (file_menu): Use the gnome-uidefs.h macros. 1999-01-06 Nat Friedman * src/main-window.c (file_menu): Use Ctrl-Q as the exit-app accelerator. 1998-12-28 bertrand * src/mblist-window.c (mblist_open_window): added the dnd reception callback. (mblist_drag_data_received): handle the received messages. For the moment, when a list of messages is dropped on a mailbox, it is moved to that mailbox. Other actions should be easy to add. * src/index-child.c (index_child_create_view): moved the dnd code to a specific function : index_child_setup_dnd() (index_child_setup_dnd): new function. (index_child_drag_data_get): new function, pass the selected messages in the clist to the X selection mechanism. This should be reviewed by a gtk+ expert. However, this does not work with the current version of gtk+ (1.1.9). I had to remove the dnd class functions in gtkclist to make all this work correctly. * src/balsa-index.c (balsa_index_get_selected_rows): added this function to get the currently selected messages. This is useful to the dnd stuff. * src/main-window.c (main_window_set_cursor): removed a warning 1998-12-27 Jaka Mocnik * src/main-window.c (destroy_window_cb): only save window size. attached to destroy signal of each app in app_create(). (destroy_mdi_cb): call balsa_exit(). attached to mdi destroy signal. savin window size here makes no sense as mdi might not have an active_window on destruction! (app_created): set the pointer to pbar as data to each GnomeApp with key PROCESSBAR_KEY. (main_window_set_cursor): use the pbar set as data to the GnomeApp. using a global static var won't work if someone drags a page out to create multiple notebooks. 1998-12-26 bertrand * src/mblist-window.[ch]: new files. * src/main-windo.c: moved the mailbox list window code to the new two above files. * src/balsa-message.c (balsa_message_new): corrected the bug that made some widget background white instead of their normal background. * src/sendmsg-window.c (create_info_pane): idem as above. 1998-12-19 Joel Becker * src/filter-edit-dialog.c: Enabled the neat new dnd reordering of the filter clist. Yay. 1998-12-19 pavlov@pavlov.net Modified files: libbalsa : misc.c misc.h src : balsa-mblist.c main-window.c Log message: make mailbox folders closed by default.. will do saving of their status shortly 1998-12-18 Jeff Garzik * po/de.po: big update from Michael Glauche 1998-12-18 Jeff Garzik * libbalsa/mailbox.c, libmutt/commands.c, libmutt/curs_main.c, libmutt/flaglib.c, libmutt/flags.c, libmutt/mutt.h, libmutt/mx.c, libmutt/pager.c, libmutt/pattern.c: s/M_READ/MFLAG_READ/ - Solaris system defines M_READ * libbalsa/misc.c: call g_malloc instead of malloc, because we call g_free in the allocated memory later on. From wmorgan@syntony.org. 1998-12-17 Jeff Garzik * libmutt/sendlib.c: one-liner from wmorgan@syntony.org that fixes msg bodies w/o a trailing newline 1998-12-16 Jeff Garzik * src/pref-manager.c: Outgoing mail is now a table, allowing you to select 'remote smtp server' or 'local mail agent' for mail delivery. Greyed out because it doesn't actually work yet. 1998-12-16 Joel Becker * libbalsa/filter-error.c, libbalsa/filter-file.c, libbalsa/filter-funcs.c, libbalsa/filter-private.h, src/filter-edit-callbacks.c, src/filter-edit-dialog.c: Lots of little things, especially gui workings. It's not perfect yet. Nor is it working. But it compiles clean, and should cause no harm. 1998-12-15 Jeff Garzik * src/pref-manager.c: Added protocol column to server list. * src/spell-check.[ch]: Spell checking module for mail compose window. 1998-12-15 Ettore Perazzoli * src/main-window.c (refresh_main_window): Retrieve the toolbar with `gnome_app_get_dock_widget_by_name()'. (mblist_open_window): Make the behavior of the dock item `EXCLUSIVE'. Use `gnome_app_add_dock_item' instead of `gnome_dock_add_item()'. * src/sendmsg-window.c (sendmsg_window_new): Likewise. 1998-12-14 Stuart Parmenter ./ : INSTALL README balsa.1 balsa.spec configure.in, po/ : de.po es.po fi.po fr.po ga.po ko.po no.po, libbalsa/ : Makefile.am libbalsa.c mime.c send.c, idl/Makefile.am, sounds/Makefile.am, src/Makefile.am: - Now passes 'make distcheck' it.po: - added the italian translation. 1998-12-14 Jeff Garzik * src/main-window.c: - Re-enabled Mailbox/Delete menu item; it takes into account lack of selection now. - Updated for new gnome-dock-item-new args. * src/message-window.c: - Continued futile efforts to close the message window via File/Close. 1998-12-14 Jeff Garzik * libbalsa/mailbox.[ch]: Added simple IMAP support stubs. * src/main-window.c: - include mailbox-conf.h to avoid warnings. - Added menu items to add, edit, and delete mailboxes. - Corrected typo. - Pop up error dialogs if no item is selected, and edit/delete is chosen. * src/message-window.c: - added menu to message window, just File|Close right now. 1998-12-13 Jeff Garzik * src/main-window.c: - Exported 'mdi' var, so we can grab it from other modules. - Reordered check-new-mail action to check regardless of whether we check locally or not. * src/pref-manager.c: - Properly parent the prop box, so it minimizes when other windows are minimized. - Select first item in POP3 server list. FIXME: needs to select "proper" item based on previous action, add, delete, and modify. - Internationalize a few strings. Rename "POP3 Servers" frame to "Remote Mailbox Servers" * src/sendmsg-window.c: Change menu item "Exit" to "Close". We do not exit the app. 1998-12-09 Herbert Valerio Riedel * src/filter-edit.h, libbalsa/filter-funcs.h: added missing prototypes * libbalsa/filter-funcs.c (filter_init): initialize var to shut up compiler 1998-12-12 Jaka Mocnik * src/main-window.c (app_created): connected set_icon() to realize signal handler for app as MDI does not explicitly realize GnomeApps anymore. 1998-12-10 Miguel de Icaza * src/sendmsg-window.c (attachments_add): Add drag and drop support for the attachments. 1998-12-09 Jeff Garzik * src/balsa-message.c, src/index-child.c: Fixed gnome-dialog-run-and-close breakage. 1998-12-08 Jaka Mocnik * src/index-child.c, src/balsa-message.c: changed gnome_dialog_set_modal() to gtk_window_set_modal() and use gnome_dialog_run_close() instead of gnome_dialog_run_and_hide() and gtk_widget_destroy(). * main-window.c (refresh_main_window): DON'T use gnome_mdi_set_mode() to refresh display. this gets you into trouble and would look butt ugly anyway. 1998-11-29 Miguel de Icaza * src/sendmsg-window.c (create_info_pane): GnomeIconList no longer starts in frozen state. 1998-11-29 Herbert Valerio Riedel * src/balsa-index.c (balsa_index_init): fixed superflous re-allocation of scrolled window * src/main-window.c (create_toolbar): added GTK_WINDOW()-cast 1998-11-28 Michael Lausch * changed gtk_container_border_with to gtk_container_set_border_width 1998-11-25 Herbert Valerio Riedel * src/sendmsg-window.c: add #include and cast-macros * src/pref-manager.c: added cast-macros * src/main.c: fixed declaration of balsa_init() * src/main-window.c: added cast-macros * src/local-mailbox.c: added #include * src/index-child.c: see next * src/filter-edit-dialog.c: see next * src/balsa-index.c: added cast-macros * src/balsa-app.c: added const modifier to balsa_error() * libbalsa/misc.c: fixed return value checking of malloc in readfile() 1998-11-18 Richard Hestilow * src/main-window.c: Added underscore accelerators, no longer right justify "Help" menu either. 1998-09-23 Michael Lausch * libbalse/mime.c (Mailbox): reorganized the translation of MIME messages into HTML. Some things in gtkXmHTML aren't working, so i use a table approach now. Better multipart handling which is necessary for PGP support. 1998-09-15 Robert Wilhelm * src/balsa-index.c (numeric_compare): new function to get sorting by message number right. (clist_click_column): use it here. 1998-09-11 Michael Lausch * src/balsa-message.c: Start of saving MIME parts (aka Attachments) to files. More on this topic will follow. 1998-09-02 Nuno Ferreira * src/Makefile.am (INCLUDES): Added ${top_builddir}/libmutt so that muttconfig.h is found when srcdir != builddir. * libbalsa/Makefile.am (INCLUDES): Likewise. 1998-08-25 Nat Friedman * src/balsa-init.c (next_cb): Try to create the specified mailboxes if they do not exist (create_mailbox_if_not_present): new function to do the above 1998-08-23 Nat Friedman * src/save-restore.c: This file has been completely rewritten. libPropList based configuration loading and storing is now functional. The configuration function names have all been made sane, also, and several files, including balsa-app.c, balsa-init.c, main.c, and pref-manager.c had to be modified to call the new routines. * src/mailbox-conf.c: Added some casts to the gtk_signal_connect() calls so that passing non-pointer closures doesn't generate a warning. 1998-08-07 Michael Lausch * src/main.c (balsa_exit): fix crash when exiting without selecting a mailbox. 1998-08-06 Michael Lausch * libbalsa/mailbox.c (content_type2str): new function. Returns String representation of MIME content. (text2html): Temproarily moved to mailbox.c from balsa-message. Will be moved back when MIME part handling is fixed. (other2html): new function. Formats an unknown MIME part into HTML. Should use a tag, currently prints the part as text which is _wrong_. (audio2html): new function. Formats a `audio' part in HTML. Should use a tag. Currently just prints AUDIO (application2html): new function. Formats an `applicaton' in HTML. Should use a tag. Currently just prints APPLICATION. (image2html): new function. Formats a `image' part in HTML. Should use a tag or a tag. Currently just prints IMAGE. (message2html): new function. Formats a `message' in HTML. Should render the message like a top level message. Currently just prints MESSAGE. (multipart2html): new function. Should render a MULITPART part. Currently just prints MULTIPART. (video2html): new function. Formats a `video' in HTML. Should use a tag. Currently just prints VIDEO. (mimetext2html): new function. Renders a text message into HTML. subtype html is unchanged, all oethers are passed to text2html. (part2html): calls one of the part formatting functions depending on the type attribute of the MIME part. Subtype handling is done by the correspodning functions. (message_body_ref): Now renders the message in HTML with MIME handling. THIS WILL CHANGE. Next version will only put the type/subtype attributes into the balsa message structure. * src/balsa-message.c (message2html): message body is already HTML'ized. not further formating necessary. THIS WILL BE CHANGED very soon. temporarily moved ther text2html function into the mailbox file. * libmutt/mx.c (mx_get_magic): fixed M_MH recognition semantics. .xmhcache file only exists of exmh was used. * libbalsa/misc.c (readfile): fixed readfile function. 1998-08-03 Michael Lausch * src/local-mailbox.c (read_dir): changed isnumname to is_mh_message. MH messages filenames are a lot more variable then expected. (read_folders_from_file): new function. Reads the folder cache file and add mailboxes. (is_mh_message): new function. Applies some heuristics on the filename to find out if it is a MH message name (,[0-9]+ and [0-9].~[0-9]+~) are considered to be MH messages. new variable folder_cache_name. Sat Aug 01 20:25:23 1998 George Lebl * src/index-child.c: fixed up the destroy handler * src/main-window.c: user remove instead of destroy to close a child Thu Jul 30 21:26:22 EDT 1998 Stuart Parmenter * libmutt/configure.in, mx.c, parse.c, pop.c, send.c Updated to mutt v0.93.2 * libbalsa/mailbox.c, src/index-child.c Initial work on IMAP and POP3 support with mutt. It doesn't seem to work very well right now. I am still working on this. Thu Jul 30 17:21:32 EDT 1998 Stuart Parmenter * libbalsa/mailbox.c, src/local-mailbox.c Balsa now should read in mailboxes properly. i.e. check to make sure its valid, as well as check its type. I believe it should load mh folders now as well, although I havn't tested this yet, since I don't have any mh folders. Balsa will not open any files with characters that are all numbers (i.e. mh messages), nor any files that start with a '.'. Wed Jul 29 08:05:28 EDT 1998 Stuart Parmenter * src/balsa-init.c Changed Balsa Init to use a gtk_dialog instead of a gnome_app window. I'll probibly change this to a gnome_dialog later. This should make it look a little bit nicer. *src/pref-manager.c Changed the button box layout to SPREAD instead of END Tue Jul 28 21:43:58 EDT 1998 Stuart Parmenter * src/balsa-init.c More work, should save your settings now. Mailbox addition inside the balsa-init still not there. Balsa-app now uses balsa-init.c since its pretty:) Tue Jul 28 21:19:38 EDT 1998 Stuart Parmenter * src/balsa-init.c Started making balsa-init do something useful. It is almost complete. Once complete, it will be what is started when Balsa is run for the first time. It will setup all the information that Balsa needs to run correctly. Tue Jul 28 14:00:35 EDT 1998 Stuart Parmenter * src/pref-manager.c Removed open_main_window() call from pref manager if balsa_app.current_index_child was NULL. This was causing lots of opened windows on startup. Tue Jul 28 04:01:40 1998 Stuart Parmenter * TODO, INSTALL, README: Update of the documentation (or sad excuse for that). Added the INSTALL file to replace the one thats automagically generated if it doesn't exist. This way we get a file that accually applies to the installation of balsa, and not generic stuff. This should help, not that its hard to do now that c-client is removed. Updated the TODO file to note that local mailbox dir recursion now is implimented but lacks a way to store the mailboxes in something other than a list currently. This will be GForest's use. Updated README to remove INSTALL file info, and such. Added a description, etc. balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/HACKING000066400000000000000000000065341477646064400214210ustar00rootroot00000000000000The following are some general guidelines for adding code to Balsa: ------------------------------------------------------------------- The prefered address for reaching Balsa developers is balsa-maintainer@theochem.kth.se The prefered place to discuss general Balsa development is balsa-list@gnome.org Refer to AUTHORS for the list of active developers. The code has generally three layers: |--------------------| | src | | |---------------| | | libbalsa | | | |------------| | | | libmutt | ---------------------- - src contains balsa specific code. - libbalsa contains object definitions code that in principle can be reused. Good examples are address books, or AddressEntries. - libmutt is a mailbox backend code. Use FIXME in comments to make a note of things which need looking at. All GtkObject derivatives should live in there own .c and .h files. In general functionality should be split in a sensible way amoung files. respect the libbalsa_ namespace. commited code should compile with --enable-more-warnings - this enables some extra warnings and -Werror which makes warnings into errors. libmutt ------- All changes to libmutt/* should be marked with a comment beginning BALSA: and describing the change and the reason for it. Source files ------------ All files should have a magic emacs mode line at the top (note older files will have c-basic-offset as 2 or 8): /* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ following this a GPL copyright header. Copyright should be attributed as: (c) 1997-2000 Stuart Parmenter and others, see AUTHORS for a list of people Following this should be a brief description of what the file contains. See existing source for a general idea. Threads ------- Their are three locks which are important to balsa: 1) The GDK lock - this protects GDK and GTK+. 2) The lock on each mailbox. 3) The libmutt lock - this is maintained by libbalsa and is used because libmutt is not threadsafe. libbalsa API functions expect to always be called with the GDK lock held and the mutt lock not held (remember this when calling API funcs from within libbalsa). The GDK lock may be released, but you must be careful and should relock it before returning. You must be careful when the GDK lock is not held that libmutt doesn't call mutt_error or anything which calls GTK functions. In order to avoid deadlocks it is important that the locks are always taken in the same order. That is gdk lock first, then any mailbox lock, then libmutt lock. Note that this doesn't mean you must take all those locks - but if you do take them it must be in that order. If you want just the mutt lock and not the GDK lock this is OK - but you may not try to take the GDK lock whilst holding the mutt lock - you must release the mutt lock first. Be careful to avoid deadlock when locking multiple mailboxes (FIXME: This sentance isn't much help to anyone ;-) Coding Style ------------ The coding style used in Balsa currently is a bit of a mess. When adding a new file to Balsa, please use the standard GNOME indentation style, rather than the one used in the rest of Balsa. A good place to read is the file HACKING included with Gnumeric. The magin emacs comment (as mentioned above) should help you to follow the formatting guidelines but you can indent explicitly your file with indent -kr -i4 -psl balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/INSTALL000066400000000000000000000053151477646064400214570ustar00rootroot00000000000000Please see README for latest installation information --- Balsa E-Mail Client 2.0.x Copyright (C) 1997-2002 Stuart Parmenter and others, see AUTHORS file. See 'COPYING' for license information. Please note linking against OpenSSL libraries is explicitely allowed. See 'AUTHORS' for a list of contributors. Please make sure you have the following things: Glib >= 2.6.0 GTK >= 2.6.0 gnome-libs >= 2.0.0 (see notes below) gnome-print >= 0.25 libpspell >= 0.11.2 (and at least one spell check module) alternatively libapsell >= 0.50 libesmtp >= 0.8.11 http://www.stafford.uklinux.net/libesmtp/ If you do not have these, please check: http://balsa.gnome.org/download.html for links to these packages. Or try http://www.gnome.org, http://www.gtk.org, and http://www.enlightenment.org. Note that some of these modules have their own requirements. Installation of pspell is known to be troublesome, make sure you have read - and understood - all the details. Feedback should to to pspell team, not balsa team. It is highly recommended to install and use the Perl Compatible Regular Expression library (PCRE), version 3.0 or higher. Further information about this library is available from http://www.pcre.org/ Some pre-built PCRE rpm's can be found at http://www.rpmfind.net/linux/rpm2html/search.php?query=pcre You need also gnome-doc-tools for building the help system. They are available from http://people.redhat.com/dcm/software.html Since version 2.0.10 balsa has EXPERIMENTAL support for gpg signed and encrypted MIME messages according to RFC 3156. Further information is available at http://www.mynetcologne.de/~nc-dreszal/balsa/balsa23-secure-mail.html Build Instructions: For more information and configuration options see 'README'. You need libtool, pspell-devel (obligatory) and gnome-print-devel (recommended) packages installed. Balsa works also very nicely with gtkhtml >= 0.8 and openldap. # ./configure # make Installation: Do the above then # make install Notes: Balsa does not play nice with older versions of egcs, if you are using an earlier version than 2.95 of this compiler and have troubles with segfaults, try compiling with optimizations turned off or upgrading. Some versions of libgnome is known to have bugs that lead to balsa crash on startup. Read http://mail.gnome.org/archives/balsa-list/2000-October/msg00101.html and make sure you have at least /usr/lib/libgnome.so.32.3.11. Experimental gcc 2.96 distributed with RedHat 7.0 generates spurious warning messages. You have to update your compiler (strongly recommended!) or configure balsa with explicitely specified --disable-more-warnings option. balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/MAINTAINERS000066400000000000000000000002301477646064400221120ustar00rootroot00000000000000Author list is in AUTHORS. This is just to keep bugzilla.gnome.org happy Full Name Balsa Maintainer E-mail: balsa-maint theochem kth se Userid: pawels balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/Makefile.am000066400000000000000000000052531477646064400224630ustar00rootroot00000000000000#intl dir needed for tarball --disable-nls build. DISTCHECK_CONFIGURE_FLAGS="--disable-extra-mimeicons" SUBDIRS = . sounds po images doc libnetclient libbalsa libinit_balsa src ui # set tar in case it is not set by automake or make man_MANS=balsa.1 pixmapdir = $(datadir)/pixmaps pixmap_DATA = gnome-balsa2.png desktopdir = $(datadir)/applications desktop_in_files = org.desktop.Balsa.desktop.in balsa-mailto-handler.desktop.in desktop_DATA = org.desktop.Balsa.desktop balsa-mailto-handler.desktop # Appdata files appdatadir = $(datarootdir)/metainfo appdata_in_files = balsa.appdata.xml.in dist_appdata_DATA = balsa.appdata.xml balsa_extra_dist = \ HACKING \ balsa-mail-style.xml \ balsa-mail.lang \ balsa.1.in \ balsa.spec.in \ bootstrap.sh \ docs/mh-mail-HOWTO \ docs/pine2vcard \ docs/vconvert.awk \ $(desktop_in_files) \ $(appdata_in_files) \ gnome-balsa2.png \ meson.build \ meson_options.txt \ balsa-mailto-handler.desktop.meson \ org.desktop.Balsa.desktop.meson \ po/meson.build \ README-CardDAV.md EXTRA_DIST = \ $(balsa_extra_dist) if BUILD_WITH_GTKSOURCEVIEW gtksourceviewdir = $(BALSA_DATA_PREFIX)/gtksourceview-3.0 gtksourceview_DATA = balsa-mail.lang \ balsa-mail-style.xml endif DISTCLEANFILES = $(desktop_DATA) $(server_DATA) $(dist_appdata_DATA) %.desktop: %.desktop.in $(AM_V_GEN)$(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@ %.xml: %.xml.in $(AM_V_GEN)$(MSGFMT) --xml --template $< -d $(top_srcdir)/po -o $@ dist-hook: balsa.spec cp balsa.spec $(distdir) @MAINT@RPM: balsa.spec @MAINT@ rm -f *.rpm @MAINT@ $(MAKE) distdir="$(PACKAGE)-$(PACKAGE_VERSION)" dist @MAINT@ cp $(top_srcdir)/rpm-po.patch $(top_builddir)/rpm-po.patch @MAINT@ rpm -ta "./$(PACKAGE)-$(PACKAGE_VERSION).tar.gz" @MAINT@ rm $(top_builddir)/rpm-po.patch @MAINT@ -test -f "/usr/src/redhat/SRPMS/$(PACKAGE)-$(PACKAGE_VERSION)-@BALSA_RELEASE@.src.rpm" \ @MAINT@ && cp -f "/usr/src/redhat/SRPMS/$(PACKAGE)-$(PACKAGE_VERSION)-@BALSA_RELEASE@.src.rpm" . @MAINT@ -for ping in /usr/src/redhat/RPMS/* ; do \ @MAINT@ if test -d $$ping ; then \ @MAINT@ arch=`echo $$ping |sed -e 's,/.*/\([^/][^/]*\),\1,'` ; \ @MAINT@ f="$$ping/$(PACKAGE)-$(PACKAGE_VERSION)-@BALSA_RELEASE@.$$arch.rpm" ; \ @MAINT@ test -f $$f && cp -f $$f . ; \ @MAINT@ fi ; \ @MAINT@ done @MAINT@snapshot: @MAINT@ $(MAKE) distdir=$(PACKAGE)-`date +"%y%m%d"` dist @MAINT@balsa-dcheck: @MAINT@ $(MAKE) BALSA_DISTCHECK_HACK=yes distcheck ## to automatically rebuild aclocal.m4 if any of the macros in ## `macros/' change xzdist: distdir @test -n "$(AMTAR)" || { echo "AMTAR undefined. Run make bzdist AMTAR=gtar"; false; } -chmod -R a+r $(distdir) $(AMTAR) choJf $(distdir).tar.xz $(distdir) -rm -rf $(distdir) balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/NEWS000066400000000000000000000575051477646064400211350ustar00rootroot00000000000000* Balsa-2.6.5 release. Release date 2025-04-12 - fix connection issues with broken IMAP servers - add limited support for CardDAV address books - always store user credentials in the Secret Service if possible - improve dealing with user credentials iff the Secret Service is unusable - improve saving attachments - improved setup wizard with server probing - add support for Web Key Directory (WKD) GnuPG keys - improve crypto user interface - add optional DKIM and DMARC checks - prefer TLS connections over STARTTLS - Webkit 4.1 support - use XDG-compliant user data folder layout - remove deprecated stuff (SQLite2, Rubrica, ige-mac-integration) - lots of bug fixes - documentation updates (yet incomplete) * Balsa-2.6.4 release. Release date 2022-09-20 - Fix display/printout with nondefault HTML preferences. - HTML context meny improments, integration with Webkit HTML privacy filter. - Header edition in GNOME editor fixed. - Some MDN, iCalendar issues fixed. - More informative error messages. - Notification improvements. - Show UI for opening download location after download. - Minor memory leaks plugged. - code refactoring and lceanup. - Library and build system deprecation cleanups. - Translation updates. * Balsa-2.6.3 release. Release date 2021-08-18 - Improve Autocrypt-related error messages. - Improvements to communication with GnuPG key servers. - Create standard-compatible HTML messages. - Implement sender-dependent HTML message preferences. - Reuse HTTP connections when rendering HTML messages. - Do not send empty Reply-To, Cc, etc headers. - More robust IMAP parser and response handling. - Code cleanups, platform-dependent build fixes * Balsa-2.6.2 release. Release date 2020-12-21 - Webkit widgets are now sandboxed. - Improved desktop notifications. - iTIP calendar reply are improved. - Handling of multiple crypto keys for the same recipient. - build cleanups and improvements, e.g. application logging. - code cleanups and simplifications as enabled by moving to more modern libraries. - bug fixes: draft with message/external-body attachments; do not crash on importing half-broken keys - improved translations. * Balsa-2.6.1 release. Release date 2020-05-10 - fix server identity verification. * Balsa-2.6.0 release. Release date 2020-04-11 This release switches to gmime3 library for MIME processing. * Balsa-2.5.9 release. Release date 2019-10-19 - fix HTML message layout issues. * Balsa-2.5.8 release. Release date 2019-10-11 Change with respect to 2.5.7 - i18n improvements. - improved display of HTML messages. - handling of calendar (vcal) attachments. - LDAP address book improvements / error handling. - message presentation refactoring. - GPGME is a hard requirement now. - misc bug fixes and code health updates. * Balsa-2.5.7 release. Release date 2019-05-25 Changes with respect to 2.5.6 tag: - mitigate “Re: What's Up Johnny?” vulnerabilities - code cleanup and adaptations to changing libraries. New minimal requirements are: GLib - 2.48, Gtk3 - 3.18 - fix bugs in referencing images from HTML emails - encryption: key selection improvements - printing HTML parts - menu tree UI improvements - improved IMAP folder configuration - IMAP and POP code ported to use glib / gio - other bug fixes * Balsa-2.5.6 release. Release date 2018-06-01 Changes wrt to 2.5.5 tag: - fix scroll on click issue - display time stamps of date-only RFC 5545 iCalendar events - disable reply-to-group when the message is not from an RFC-2369-compliant mail list - Mitigate EFail vulnerability for Webkit2 * Balsa-2.5.5 release. Release date 2018-02-26 Changes wrt to 2.5.4 tag: - crypto performance improvements - updates to match glib-2.56 API changes. - fix use-after-free bugs. - improve replying to HTML-only messages. - low level networking re-done. - multiple bugfixes. * Balsa-2.5.1 release. Release date 2013-04-27 - new message header widget - WebkitGtk2 widget integration - ported to GNetworkMonitor - yet another documentation port - initial config assistant improvements. * Balsa-2.5.0 release. Release date 2013-02-28 - making gtk3 build the official one. * Balsa-2.4.9 release. Release date 2010-11-19 - compile against new GTK, libnotify libs. * Balsa-2.4.8 release. Release date 2010-08-21 - QUOTA and MYRIGHTS IMAP extension support. - bug fixes: #625695, #620221, #623910, #623740, #618979, #579479, #613998 - various memory leaks plugged. * Balsa-2.4.7 release. Release date 2010-02-13 - infinite loop (debian #568298). - avoid crashes when manually verifing GPG signature. * Balsa-2.4.6 release. Release date 2010-01-27 Clearly, 2.4.3 to 2.4.5 were of a release-candidate quality... - add forgotten part of filter comparison patch. - fix occasional IMAP failures on compressed connections. * Balsa-2.4.5 release. Release date 2010-01-24 - fix building with GNOME. * Balsa-2.4.3 release. Release date 2010-01-23 - IMAP compression (COMPRESS=DEFLATE) when supported by server - making opening attachment easier by saving them in a directory - downloadable images when using Webkit html widget - faster opening of the compose window. - text searching enabled in the WebKit html viewer. - options to hide toolbars and other parts of the UI (useful on netbooks etc). - For laptop/wifi users: not trying to reach POP3 servers while disconnected, and instead checking immediately on reconnection. * Balsa-2.4.2 release. Release date 2009-12-06 - searching in HTML parts. - improved webkit support. - NetworkManager events intercepted to reconnect to IMAP servers. - compatibility with recent openssl. - compatibility with gtk version >= 2.18 - improved Mac OS X integration. - bug fixes! - better translations! * Balsa-2.4.1 release. Release date 2009-08-09 - Continuing cleanup work: removing obsolete library calls. - partial workaround for the deadlock in xcb library code. - experimental use of libcanberra for sound. - many small bugfixes. * Balsa-2.4.0 release. Release date 2009-05-25 - GMime-2.4, GLib-2.16, and Gtk-2.14 required. - use libunique as an alternative to BonoboActivation, whenever available. - compile and run on Mac OSX. - VCALENDAR and VEVENT handling. - deprecation cleanup. - message threading improvements (eg. thread selection) and fixes. * Balsa-2.3.28 release. Release date 2009-01-18 - Fix the IMAP message threading regression. - Use GIO library when available. - Improve GMail IMAP compatibility. - Bug fixes for 509434, 567323, 566426, 566420, 566415. * Balsa-2.3.27 release. Release date 2008-12-30 - porting to most recent GTK versions. - documentation ported to gnome-doc format. (#559825) - partial translations of the manual to German and Spanish. - gnome-keyring is used if available (experimental). - disable deprecated apis only in svn tree (#561875). - initial experimental support for WebKit. * Balsa-2.3.26 release. Release date 2008-09-07 - composing format=flowed messages with spaces pasted in works better. - allow to explicitly specify a GPG key id for an identity. * Balsa-2.3.25 release. Release date 2008-06-14 - GMail compatibility. - notification icon in GNOME panel is optional now. - wrapping of flowed text improved. - lots of various bug fixes. * Balsa-2.3.24 release. Release date 2008-05-31 - Support for accessing files over gnome-vfs (smb, ssh mounts, etc.) - maildir tree scanning fixes. - Rudimentary support for sending text/html messages. - UIDPLUS IMAP extension support. * Balsa-2.3.23 release. Release date 2008-03-20 - Suppport for IMAP MULTIAPPEND extension for faster uploading of message batches to and from IMAP servers. - improved scanning of mailbox trees. - GtkSourceView2 support. * Balsa-2.3.22 release. Release date 2007-12-23 - new address edition widget in the compose window. - compose window displays languages available for spell checking. - more new icons. * Balsa-2.3.21 release. Release date 2007-12-08 - migration from GnomeUI to GtkUIManager - Rubrica address book support. - bugs fixed: GNOME: 481842, 488432, 496316; Redhat: 414361. * Balsa-2.3.20 release. Release date 2007-09-07 - fix buffer overflow (#474366). - avoid sending messages twice under certain conditions. * Balsa-2.3.19 release. Release date 2007-08-25 - more build fixes. * Balsa-2.3.18 release. Release date 2007-08-22 - reflow improvements. - Build problems against steaming-hot GNOME fixed. - Make BINARY and ESEARCH IMAP extensions usage more robust. * Balsa-2.3.17 release. Release date 2007-07-04 - check validity of server APOP challenge. - add ability to store VCARD signatures. - use ESEARCH IMAP extension if available. - message wrapping fixes. - and an usual bunch of bugfixes. * Balsa-2.3.16 release. Release date 2007-05-27 - fix message threading regression. - reorganize "Identity" dialog. - code cleanup. * Balsa-2.3.15 release. Release date 2007-05-01 - Use GtkPrint infrastructure if available. - handle LDAP referrals. - nicer citation marks. - initial libnotify support. - IMAP BINARY support. * Balsa-2.3.14 release. Release date 2006-12-12 - deferred population of the mailbox index. - client-side IMAP sorting. - be compatible with recent gtk2 releases. - mailbox tabs reorderable with d&d. - enhanced mailto: URL handling. * Balsa-2.3.13 release. Release date 2006-06-26 - many small fixes - nicer icons. * Balsa-2.3.12 release. Release date 2006-03-04 - do not reference freed memory in mbox driver. * Balsa-2.3.11 release. Release date 2006-02-28 - assure messages are properly signed after identity change. - Ctrl-N goes over unread messages in all mailboxes. - Redone Preference Manager. - support better slow LDAP servers. - use better real estate when displaying message counts. - fixed bugs: 330085, 330093, 332980. * Balsa-2.3.10 release. Release date 2006-01-29 - local mailbox opening acceleration. - composed message saving and postponing UI improvements. * Balsa-2.3.9 release. Release date 2006-01-06 - fix mailbox locking regressions. - GtkSpell improvements. * Balsa-2.3.8 release. Release date 2005-12-27 - improved local mailbox opening performance. - fix gtk2-2.8.9 compatibility (324516). - fixed 323442, 323458, 323618, 323617, 323448, 323871, 323871, * Balsa-2.3.7 release. Release date 2005-12-04 - few ready quick filters added to "Subject or Sender" one. - optional GtkSpell support. - POP3 delivery speedup. - Face and X-Face: header support. * Balsa-2.3.6 release. Release date 2005-10-23 - improved support for splitting messages. - fix bugs 318171, 317240. * Balsa-2.3.5 release. Release date 2005-09-20 - improve error handling. - doc updates. - bugs fixes: 309574, 312091 and 312105. * Balsa-2.3.4 release. Release date 2005-07-06 - fixed regression in message encryption. - working address book edition. - possible buffer overflow in IMAP code fixed. - double free occuring when user rejects POP3 TLS certificate fixed. * Balsa-2.3.3 release. Release date 2005-06-06 - preserve local mailbox statistics between sessions. - SQLite v.3 support (#305152). - default inbox location (#305659). - better mailbox popup menu (#305668). - fix imap scanning on 64-bit machines. - fix unlikely crash in initial configuration (#30666). * Balsa-2.3.2 release. Release date 2005-05-08 - fix bugs 302782, 303421, 303422. * Balsa-2.3.1 release. Release date 2005-05-02 - build with GNOME-2.10, OSX, SuSE, gcc4. - omit self from cc addresses. - cache message counts between sessions. - allow sending messages through a pipe to an external program. - support for multiple esmtp servers. - allow using STATUS for checking IMAP mailboxes. - reimplement message duplicate deletion. - bugs fixed 123765, 153386, 168732, 168733, 168353, 171388, 170456, 170512, 171415, 172005, 172145. * Balsa-2.3.0 release. Release date 2005-02-23 - require GTK+ >= 2.4.0 - new address completion widget. - new themeable icon scheme. - new composer attachment handling widget. - migrate from GnomeFileEntry to GtkFileChooser. - IMAP IDLE support. * Balsa-2.2.6 release. Release date 2004-11-19 - fixed MBOX driver over NFS problem. - use ISO-2022-JP for composing Japanese messages. - yet more exceptions caught. - S/MIME support. - improved identity selection and address book completions. - IMAP optimizations. * Balsa-2.2.5 release. Release date 2004-10-02 - sent messages saved to sentbox only after being sent. - use of fixed-height with gtk2>=2.4.9 to speed up large mailboxes. - GPG is expected to be fully functional now. - mbox mailbox driver fixes. * Balsa-2.2.4 release. Release date 2004-08-28 - periodic expunge configurable. - cleanup IMAP password quering code. - GPE address book support - http://gpe.handhelds.org/projects/GPE-address.shtml - new configuration druid. * Balsa-2.2.3 release. Release date 2004-08-15 - periodic expunge code crash fixed. - fixed recovery from broken IMAP connections. - startup speedup. - some memory leaks fixed. * Balsa-2.2.2 release. Release date 2004-08-08 - configurable hiding of deleted messages. - keyboard navigation fixes. - message counting in some edge cases fixed. - GPG fixes. * Balsa-2.2.1 release. Release date 2004-07-30 - IMAP mailboxes could be incorrectly marked as read-only. - message selection behaves more sanely. - 64-bit fixes. - memory leaks fixed. - handle better imap servers without server-side threading and limits on number of concurent connections. - quick "Sender or Subject" message index filtering. - various UI improvements. * Balsa-2.2.0 release. Release date 2004-07-06 - fix 143322, 143263, 145701. - GPGME updates. - GSSAPI IMAP authentication. - more build fixes. * Balsa-2.1.91 release. Release date 2004-07-06 - multiple build fixes. - few crashes fixed. * Balsa-2.1.90 release. Release date 2004-07-03 - mailbox scanning improvements. - Edit/Find UI more user-friendly. - message filtering fixes. - reset TLS status of broken IMAP sessions. * Balsa-2.1.3 release. Release date 2004-05-22 - GPGME fixes. - Reduce memory usage of local mailbox drivers. - numerous i18n fixes. - more careful error checking. - user configuration of TLS, APOP settings to work around broken servers. * Balsa-2.1.2 release. Release date 2004-04-05 - POP3 with TLS and PIPELINING. - mbox driver performance improvements. - numerous other performance improvements. - filters reenabled. - memory leaks plugged. * Balsa-2.1.1 release. Release date 2004-02-29 Numerous fixes, most prominent are: - reduce memory usage of mbox driver. - major cleanup of local and remote drivers. - searching re-enabled again. - SSL/TLS re-enabled again. - Use bonobo to bring up already running instances. * Balsa-2.1.0 release. Release date 2004-01-11 - entirely new backend and message index. * Balsa-2.0.14 release. Release date 2003-08-26 - message wrapping improvements, RFC 2646 support. - experimental LDAP write support (feedback and patches appreciated). - number of bugs fixed. * Balsa-2.0.13 release. Release date 2003-07-27 - more flexible printing configuration. - l10n improvements. - number of bug fixes. * Balsa-2.0.12 release. Release date 2003-07-06 - Added Undo and Redo in the message composer. - occasional mangling of text attachments fixed. - more information about attached messages is shown. - further GPG improvements. * Balsa-2.0.11 release. Release date 2003-05-11 - text wrapping improvements. - charset encoding validation and conversion improvements. - several message signing and encryption improvelemts. - minor LDAP fixes (large directories, non-US-ASCII characters). * Balsa-2.0.10 release. Release date 2003-03-24 - GPG support. - translation fixes and enhancements. - large set of UI fixes. - wrapping cleanups. - autocommit improvements. - (lib)mutt buffer overflow fix. - ...and lots of other bugs fixed. * Balsa-2.0.9 release. Release date 2003-02-23 - some crashes and deadlocks fixed. - bugs in --without-esmtp build fixed. - autocommit feature misbehaviors fixed. - filtering in presence of deleted messages fixed. * Balsa-2.0.8 release. Release date 2003-02-16 - infinite loops in message threading fixed. - bug fixed: 105763, 105871, 105605. * Balsa-2.0.7 release. Release date 2003-02-09 - message threading improvements. - IMAP connections pinged to prevent timeouts. - configurable procmail commands used for POP filtering. * Balsa-2.0.6 release. Release date 2003-01-29 - authenticated LDAP binding. Option to use TLS for LDAP. - persistent mailbox sorting and threading. - search improvements. - multiple UI fixes. - printing font and paper selection fixed. * Balsa-2.0.5 release. Release date 2003-01-05 - IMAP message caching fixed. - use images attached to HTML messages. - make identity dialogs non-modal. - do charset conversion (if needed) on including files to compose windows. - do not allow to send messages with wrong charset. - number of other bugs fixed. * Balsa-2.0.4 release. Release date 2002-12-24 - do not use any deprecated GNOME API. - compile against aspell>=0.50 and gnome-2.2 - do not crash on concurrent access to local mailboxes. - finally working help. - update titles of compose windows. - numerous bug fixes. * Balsa-2.0.3 release. Release date 2002-10-28 - preference manager adapted to HIG. - new translations. - IMAP and LDAP fixes. - filter fixes. - printing fixes. * Balsa-2.0.2 release. Release date 2002-09-15 - lot of deprected coe removed. - internationalization problems nailed down. - many bug fixes and improvements ported from the main trunk. * Balsa-2.0.1 release. Release date 2002-06-10 This is a second release of GNOME2 port. It shares many improvements with the main branch. The changes unique to this port are: - port objects to GObjects whenever possible. - replace GtkCTree with GtkTreeView. - redesign identities dialog from scratch. * Balsa-2.0.0 release. Release date 2002-04-24 This is first release of GNOME2 port. * Balsa-1.3.1 release. Release date 2002-02-07 - fixes for printing of multipart messages with different content-types (AD). - rescanning local directories. - delayed message deletion (and undeletion) (PB). - highlight bad addresses in compose window (PB). - external editor support (Jelmer Vernooij). - imap message caching. - imap password handling fixes. * Balsa-1.3.0 release. Release date 2001-12-16 - first step to searching and filters. - require gnome-1.4 or newer: gdk_pixbuf, gnome-vfs and some other. - delayed IMAP tree scanning. - "reply to group" functional. * Balsa-1.2.3 release. Release date 2001-11-05 - improved address extraction from messages. - new tools for the toolbar. - improved handling of mail threading. - other UI fixes. - make building from the tarball easier. * Balsa-1.2.2 release. Release date 2001-10-31 - few crash opportunities removed. - few UI improvements. - better handling of IMAP connection problems. * Balsa-1.2.1 release. Release date 2001-10-21 - new icons (Ali Akcaagac). - handling MIME external-body types: receiving and sending. - forwarding messages as attachement (Albrecht Dreß). - handling format=flowed messages (Peter Bloomfield, rfc2646). - improved handling of collapsed threads (Toralf Lund, Carlos). - handling of distribution lists for LDIF address books (Toralf Lund). - extended D&D compose mail handling (Peter Bloomfield, Toralf Lund). - many new functions added to the toolbar. - multiple UI improvements. - several bugs fixed. * Balsa-1.2.0 release. Release date 2001-09-18 - exit clean up cleaned up. - message D&D improved. - final POP3 fixes. * Balsa-1.2.pre3 release. Release date 2001-08-31 - POP3 code armoured (hopefully) - selective IMAP check fixed. - ESMTP TLS support. - fix some nasty bugs, including gnome_exec_async() and gnome_show_url() ones. * Balsa-1.2.pre2 release. Release date 2001-08-23 - download pop3 mail to arbirary box. - numerous memory leaks plugged. - SSL roughly functional. - new nice icons. - paper selection implemented. - LDIF address book format added (this is the recommended format). - LDAP address book functional for large LDAP servers. - numerous bugs fixed, including: #52384, #55416, #55437, #58473, #59326, #59331 and 34 other less interesting (duplicated, packaging errors, older versions). * Balsa-1.2.pre1 release. Release date 2001-08-08 - bug fixes. * Balsa-1.1.7 pre-release. Release date 2001-07-13 - several improvements in IMAP folder handling (Peter Bloomfield). - message size column in index (Maciej Golebiewski). - numerous UI improvements (christophe barbe, M. Thielker, Manuel McLure) - some new command line options. - several bugs fixed. * Balsa-1.1.6 development release. Release date 2001-06-21 - multiple identity support (Matthew Guenther). - message deletion optimizations. - mailbox index flipping on message deletion or transfer fixed. - more IMAP Cyrus fixes (Peter Bloomfield) - MH nested mailboxes support (Gordon Oliver). * Balsa-1.1.5 development release. Release date 2001-05-21 - libESMTP used for message submission: AUTH and PIPELINE extension available. - active URLs in text messages. (Albrecht Dreß) - pipe signature support. (Julian M Catchen) - printing rewritten: printing images etc. (Albrecht Dreß) * Balsa-1.1.4 development release. Release date 2001-04-20 - GDK locking problems resolved. - printing non-english texts enabled. - extended quoted text and reply string configuration. - occasional attachment corruption problem fixed. - SGI compatibility fixes. * Balsa-1.1.3 development release. Release date 2001-03-29 - minor optimization work. - MDN reply suport (Albrecht Dress ). - IMAP timeout handled (bit over-verbosely, IMO). - maildir and MH mailboxes creation. * Balsa-1.1.2 development release. Release date 2001-03-03 - IMAP folders - IMAP mailbox checking tested. Pings connections properly. - initial subscribe support IMAP mailboxes. - MT-enabled mailbox opening. * Balsa-1.1.1 development release. Release date 2001-02-06 - IMAP folders semi-ofically working. - IMAP code considerably improved. - IMAP mailbox checking functional. - preferences dialog improvements. - numerous bug fixes. * Balsa-1.1.0 development release. Release date 2001-01-22 - aliases support improved A LOT. - DnD support. don't stress it too much, it sometimes crashes unexpectedly. - sends Disposition Notification requests. - give a choice to prepend or append the signature. - lot of internal mailbox node restructure and bug fixes. * Balsa-1.0.pre2 test release. Release date 2000-10-06. This is a second official pre-release. No new features, only bugs have been fixed: - don't crash on replying empty mails - fixes solaris build. - updated doc. - make install prefix=xxx should work now. - cancelled spell check outputting garbage bug. The interface has been polished a bit, too. * Balsa-1.0.pre1 test release. Release date 2000-09-27. This is the first official pre-release. The list of changes since 0.9.5 includes mostly bug fixes and interface changes. - new context-sensitive main window menu. - gnome-print-0.22 compatibility. - memory leaks. - spell check improvements and compose message language selection. - improved line wrapping. * Balsa-0.9.5 development release. Release date 2000-09-18. We are in a feature freeze state. The features implemented since 0.9.4 are: - improved multi-threading. - new warning/error reporting code. - LDAP support. - spell check (pspell package required tu compile and use balsa). - gnome-config used for storing/reading configuration. - multiple address book support. vCard- and LDAP-types implemented. - manual updates - gnome-print used for printing. * Balsa-0.9.4 development release. elease date 2000-09-05. - IMAP CRAM-MD5 and GSSAPI authorization methods - POP3 APOP authorization method. * Balsa-0.9.3 development release. Release date 2000-08-28. This is a developement release with unfinished features. POP downloading seem to be finally solved. Crash when deleting the last message from a mailbox has been identified and terminated. Do not report bugs with GtkHTML - it is quite unstable. Patches are welcome. * Balsa-0.9.2 development release. Release date 2000-08-15. - some bug fixes. * Balsa-0.9.1 development release. Release date 2000-08-06. - new message browser. - user defined location of the address book. - alias expansion support. - quoted text highlighting. - gtkHTML experimental support. balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/README-CardDAV.md000066400000000000000000000134441477646064400231110ustar00rootroot00000000000000# CardDAV support in Balsa Balsa can be configured to include limited support for remote CardDAV ([RFC 6352](https://www.rfc-editor.org/rfc/rfc6352)) address books: * it is possible to read the address book and to *add* new items, but not to *modify* or *delete* entries; * the remote server *must* support Basic authentication. Note that this requirement excludes inter alia GMail which requires OAuth authentication. CardDAV support in Balsa requires `libsoup` (version 2.4 or 3.0, which is also a dependency of HTML supprt) and `libxml-2.0`. Configure Balsa with `--with-webdav` to enable it. ## Supported features The implementation in Balsa supports the following features: * [RFC 6764](https://www.rfc-editor.org/rfc/rfc6764) auto-detection, not supported by all servers, sometimes broken; * HTTP Basic authentication. The credentials are stored in the *Secret Service* if balsa has been configured to support it (recommended); * automatic detection of address books; * reading address data using *addressbook-query* or *addressbook-multiget* reports; * VCard 3.0 and 4.0 address book items; * filtering *addressbook-query* for VCard's containing an email address (RFC 6352, sect. 10.5), and limitation of returned VCard attributes for both *addressbook-query* and *addressbook-multiget* reports (RFC 6352, sect. 10.4.2) in order to reduce bandwith (not supported by most servers); * detection of remote address book changes using *sync-token* ([RFC 6578](https://www.rfc-editor.org/rfc/rfc6578)) or *CTag* (“[CTag in CalDAV](https://github.com/apple/ccs-calendarserver/blob/master/doc/Extensions/caldav-ctag.txt)”), both not supported by all servers; ## Configuration The configuration of a CardDAV address book requires two steps, as after the first one Balsa tries to retrieve more information from the remote server. 1. In the first step, fill in the *Domain or URL*, *User Name* and *Pass Phrase* entries. If the remote server supports DNS SRV service labels (RFC 6764, sect. 3), it is sufficient to enter the domain name for the first item. If it implements Well-Known URI support (RFC 6764, sect. 5), enter the `https://` URI of the CardDAV server *without a path*. If it doesn't support either, enter full URI of the CaddDAV service. Then click *probe…* to check the settings. 2. Balsa reads the list of address books available on the remote server. Select the proper one from the *CardDAV address book name* combo box. 3. As reading the addresses from the remote server may be slow and they typically change rarely, Balsa caches them locally. The period for re-checking for changes is configurable; if supported by the remote server, Balsa will use the *sync-token* or *CTag* to detect changes which is a lot cheaper than always reading the whole address book. The *addressbook-query* report seems to be broken on some servers (which is a violation of RFC 6352). If you know your CardDAV address book contains items, but none appears in Balsa, check *Force Multiget for non-standard server* which tries to work around these bugs. ## Debug output Calling `balsa` with the environment variable `G_MESSAGES_DEBUG` including `webdav` or `all` prints debug messages about the WebDAV/CardDAV operation. ## Tested Configurations The following sections include a few tested configurations (mostly German providers). ### Apple iCloud Enter `icould.com` as *Domain or URL*, the email address as *User Name*, and the app-specific password as *Pass Phrase*. Notes: * DNS SRV service label auto-detection is half-broken as no context path (RFC 6764, sect. 4) is provided and the Well-Known URI request fails. Balsa contains code to work around this bug. * Although required by RFC 6352, the server does not support *addressbook-query* reports, i.e. Balsa always must use the more costly *addressbook-multiget* report. * Supports *sync-token* and *CTag* synchronisation. * VCard attribute limitation does not work. ### Posteo Enter `posteo.de` as *Domain or URL*, the email address as *User Name*, and the usual password as *Pass Phrase*. Notes: * Fully functional DNS SRV service label auto-detection. * Supports *CTag* synchronisation. * The server is rather slow. * *addressbook-query* filtering works, VCard attribute limitation doesn't. ### Deutsche Telekom Enter the URL `https://spica.t-online.de` as *Domain or URL*, the email address as *User Name*, and the usual password as *Pass Phrase*. As the server is broken (see below), the option *Force Multiget for non-standard server* must be activated. Notes: * Well-Known URI detection is supported. * The server claims to support *addressbook-query*, but doesn't return anything. However, *addressbook-multiget* works just fine. * Only `t-online.de` accounts have been tested, but `magenta.de` *should* also work. * VCard attribute limitation does not work. ### Arcor/Vodafone Enter the URL `https://webdav.vodafonemail.de/carddav` as *Domain or URL*, the email address as *User Name*, and the usual password as *Pass Phrase*. Notes: * A Well-Known URI access (i.e. `https://webdav.vodafonemail.de` as *Domain or URL*) returns a `301: Moved Permanently` response, but without giving the real target, i.e. the implementation is broken. * Only (very old) `arcor.de` accounts have been tested, other Vodafone ones *may* also work. * *addressbook-query* is supported, but neither filtering nor VCard attribute limitation work. * The server does not support *sync-token* or *CTag* synchronisation, i.e. every update reads the complete address book. ### Freenet Enter `freenet.de` as *Domain or URL*, the email address as *User Name*, and the usual password as *Pass Phrase*. Notes: * Fully functional DNS SRV service label auto-detection. * Supports *CTag* synchronisation. * The server is rather slow. * *addressbook-query* filtering and VCard attribute limitation work. balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/README.md000066400000000000000000000247411477646064400217110ustar00rootroot00000000000000# Balsa An E-Mail Client, version 2.6.x See [ChangeLog](./ChangeLog) for the list of the recent changes and [NEWS](./NEWS) for highlights. Copyright (C) 1997-2020 Stuart Parmenter and others See [COPYING](./COPYING) for license information. See [AUTHORS](./AUTHORS) for a list of contributors ## Authors: See [AUTHORS](./AUTHORS) ## Website: https://pawsa.fedorapeople.org/balsa/ ## Description: Balsa is an e-mail reader. This client is part of the GNOME desktop environment. It supports local mailboxes, POP3 and IMAP. ## Configuration: Balsa can be built using either Autotools (configure, make, and so on) or using Meson and an appropriate backend such as Ninja. Details of the autotools configure script follow; the corresponding Meson files, meson.build and meson_options.txt, provide exactly the same configuration options, in a more Mesonish way. Balsa has a lot of options to its configure script; you should run `./configure --help` to get an idea of them. More complete descriptions are here. Basically, Balsa requires - glib-2.0 >= 2.48.0 - gtk+-3.0 >= 3.18.0 - gmime-3.0 >= 3.2.6 - gio-2.0 - gthread-2.0 - gnutls >= 3.0 - gpgme >= 1.6.0 - libical >= 2.0.0 - fribidi `--disable-more-warnings` Balsa by default is very sensitive to compilation warnings which often mean simply programming or configuration errors. If you are sure this is not the case, or you cannot change your system setup use this option to compile the code and hope for the best. (some Solaris setups require this). `--with-gnome` Add "GNOME;" to Balsa's categories in the two .desktop files. `--with-libsecret` Link to libsecret to store credentials in the Secret Service instead of the obfuscated text file `~/.config/balsa/config-private`. See also section _Credentials_ below. `--with-gss[=/usr/kerberos]` This enables GSSAPI Kerberos based authentication scheme. Specify the kerberos directory as the argument. `--with-html-widget=(no|webkit2)` When using webkit2, in order to quote html-only messages it is recommended to install a html-to-text conversion tool. Supported tools are python-html2text, html2markdown, html2markdown.py2, html2markdown.py3 and html2text. Additionally, sqlite3 is required for managing sender-dependent HTML preferences. `--with-spell-checker=(internal|gtkspell|gspell)` Select the spell checker for the message composer. The internal spell checker depends on the enchant library (any version except 1.6.1). `--with-ldap` Use ldap libraries for a read-only address book. The read/write address book is in the works but needs some finishing touches. `--with-gpe` Include support for GPE address books (requires sqlite3). `--with-osmo` Enable experimental support for read-only DBus access to the Osmo contacts. Note that Osmo svn rev. 1099 or later is required. `--with-canberra` Use libcanberra-gtk3 for filter sounds. `--with-compface` Use Compface for rendering X-Face format thumbnails of email authors in a mail header. `--with-gtksourceview` Use GtkSourceview for highlighting structured phrases in messages, and for syntax highlighting in attachments. `--with-gcr` Use the GCR library for displaying certificates and crypto UI. `--enable-autocrypt` Build with Autocrypt support to simplify GnuPG key exchange (see https://autocrypt.org/, requires sqlite3). `--enable-systray` Enable Freedesktop System Tray Icon support (requires libxapp). `--with-webdav` Enable limited support for CardDAV address books (see README-CardDAV.md, requires libsoup and libxml). `--disable-nls` Do not use Native Language Support (Localization). ## Libraries: If you use the autotools build system, make sure you have libtool installed (if you get some error messages during compilation or when running precompiled binaries saying that libtdl is missing it means you need to install just that package). ## Balsa GIT: Balsa is hosted on the Gnome GitLab server. To get the latest source, get the module 'balsa': git clone https://gitlab.gnome.org/GNOME/balsa.git ## End-to-End Encryption (E2EE): Balsa supports E2EE using the multipart OpenPGP (RFC 3156) or S/MIME (RFC RFC 8551) standards as well as single-part OpenPGP (RFC 4880). Messages can be signed, encrypted, or both. The GpgME library (https://gnupg.org/software/gpgme/) must be installed. For the cryptographic operations, suitable backends like gnupg for the OpenPGP protocols and/or gpgsm for S/MIME are required. Optionally, Balsa can be configured to include Autocrypt support (https://autocrypt.org/index.html). ## Specifying the SMTP Server: Remote SMTP Server: Specify the domain name and optionally the port for of the SMTP server you use for submitting mail. Please note that the default port number is 587 or 465 for SMTPS (see below). The syntax is hostname[:port]. Port can be a decimal number or the name of the service as specified in /etc/services. Just click the *probe...* button to let Balsa detect the best port and security (see below) combination. If like system is running a local MTA (e.g. Postfix or Exim), you can just set this to localhost:25 without encryption.. Security: Specify the security level. For an ISP, this is typically "SMTP over SSL (SMTPS)" (default port 465) or "TLS required" (default 587, but many ISP's listen on port 25). If your ISP does not support either, choose a different ISP. For a local connection (i.e. to localhost), an unencrypted connection is fine. Note that Balsa will not use the PLAIN or LOGIN authentication mechanisms if the connection is not encrypted. User: If the remote SMTP server requires authentication, enter your user name here. Note that the exact format depends on the MTA in use. For example, some systems expect a user name, others may require an email address. Pass Phrase: If the remote SMTP server requires authentication, enter your pass phrase here. Some systems refer to the pass phrase as a password. Limitations on the length of the pass phrase depend on the SMTP server. Client Certificate and Pass Phrase: Few ISP's hand over a client certificate Balsa must present when connecting. Choose the PEM-encoded certificate file and -if it has an encrypted private key- set the key's pass phrase. Split large messages: Some ISP's impose a message size limit. In this case, enter the appropriate value here. ## Credentials Balsa uses the desktop environment's Secret Service (using the org.freedesktop.Secret.Service D-Bus service) to safely store credentials if support for `libsecret` has been included (see _Configuration_ above). The Secret Service is implemented by, inter alia, GNOME keyring, Kwallet and KeePassXC. Otherwise, the credentials are stored obfuscated in the file `~/.config/balsa/config-private`. **This method is not recommended, though.** If a password cannot be loaded from the Secret Service, Balsa tries to read it from the config file as fallback, and to store it in the Secret Service. On success, it is removed from the config file for security. Note that Balsa will never _store_ any credentials in the config file unless using the Secret Service is explicitly disabled. In the unlikely case of a desktop environment which does not provide any usable Secret Service D-Bus service, using the config file can be enforced for Balsa binaries including `libsecret` support by setting the environment variable BALSA_DISABLE_LIBSECRET=1 ## Gtk+-3 Dialog Header Bars: If the Gtk+ version is >= 3.12.0, Balsa uses the new Gtk header bars instead of the traditional action areas. As this may look ugly when using other desktop environments than Gnome (e.g. XFCE), Balsa can be switched to the old style by defining the environment variable BALSA_DIALOG_HEADERBAR=0 ## Help System: In order to compile the help files, you need to have the Mallard documentation system. Very good documentation can be found at: http://projectmallard.org/ ## Balsa as mailto protocol handler: Balsa can be used as mailto protocol handler; by default, a desktop file that declares this capability is installed. ## Mailbox locking: Balsa uses flock+dotfile for mailbox file locking. It does not use fcntl (although it can be enabled) since this locking method is very fragile and often not portable (see for example https://web.pa.msu.edu/reference/pine-tech-notes/low-level.html#locking). Make sure that your spool directory has drwxrwxrwt (01777) access privileges. Presently, dotfile locking requires this unconditionally In the future, we may relax this requirement and will allow you to shoot yourself in your leg. ## POP3 mail filtering: When the respective POP3 'mailbox' has the 'filter' box checked, the downloaded mail is passed on to procmail which will use ~/.procmailrc file as its configuration, so you can share it between Balsa and fetchmail and get consistent behavior no matter you use Balsa or fetchmail for downloading. Simple example ~/.procmailrc file: ``` --------- cut here ---------------- :0H: * ^Subject:.*balsa mail/balsa-related-mail --------- cut here ---------------- ``` It is recommended to read procmail(1) and procmailrc(1) for more real-life examples and syntax explanation. ## Debugging: Set the environment variable G_MESSAGES_DEBUG to print debugging information to the console. The value shall be either a space- separated list of log domains, or the special value "all". The following custom domains are implemented in Balsa: - libnetclient: low-level network IO. Warning: the output may contain plain-text passwords. - imap: IMAP server interaction. Warning: the output may contain plain-text passwords. - crypto: GnuPG and S/MIME crypto operations - autocrypt: Autocrypt operations - html: HTML rendering with webkit2 - address-book: address book backend operations (GPE, LDAP, …) - icons: - mbox-imap: IMAP mailbox operations - mbox-local: local mailbox operations - mbox-maildir: Maildir mailbox operations - mbox-mbox: MBox mailbox operations - mbox-mh: MH mailbox operations - mbox-pop3: POP3 mailbox operations - send: message transmission - spell-check: internal spell checker - webdav: WebDAV (CardDAV) operation - dkim: DKIM/DMARC processing (enable DKIM/DMARC checks in *Preferences -> Settings -> Miscellaneous*). ## Reporting Bugs: To report a bug, please create an issue at https://gitlab.gnome.org/GNOME/balsa/issues. Patches are welcome! ## Known issues: * When dotlocking is not possible (Wrong access privilieges for the mailbox file) Balsa will open mailbox for reading only. Verify that Balsa can create dot file in the mailbox directory. Recommended access privileges to /var/spool/mail are rwxrwxrwxt (01777) balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/TODO000066400000000000000000000015631477646064400211170ustar00rootroot00000000000000TODO LIST: Milestone 1.4 targets: ---------------------- - Merge upcoming stable mutt into libmutt - Filters - have pop3 mailbox indexes on servers that support it - split server/mailbox configuration logically, redo secure connection settings - decent mailing list support at address book and alias expansion levels. (LDIF/LDAP seems to be the most apriopriate file format). New features/unfinished things: ------------------------------- - [PARTIAL] Filters (patches semi-ready) - [PARTIAL] CORBA (for intelligent handling of multiple instances of balsa). - IMAP - update message flags immediately. Client-side caching - migrate to gnome-vfs, currently used gnome-mime is buggy. UI: --- - Incorporate use of GNOME Docklet to indicate status of unread mail, status, etc. - inline images (patch in bugzilla) - Split Preferences window into several more managable chunks. balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/TRANSLATABLE_FILES000066400000000000000000000001031477646064400231350ustar00rootroot00000000000000sounds/balsa.soundlist balsa.desktop README NEWS help/C/balsa.sgml balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/acinclude.m4000066400000000000000000000011411477646064400226100ustar00rootroot00000000000000AC_DEFUN([AM_HDR_SIGACTION], [AC_CACHE_CHECK([for sigaction.h], am_cv_hdr_sigaction, [AC_TRY_LINK([#include ], [int i = 0;], am_cv_hdr_sigaction=yes, am_cv_hdr_sigaction=no)]) if test $am_cv_hdr_sigaction = yes; then AC_DEFINE(HAVE_SIGACTION_H) fi ]) AC_DEFUN([AM_HDR_SIGSET], [AC_CACHE_CHECK([for sigset.h], am_cv_hdr_sigset, [AC_TRY_LINK([#include ], [int i = 0;], am_cv_hdr_sigset=yes, am_cv_hdr_sigset=no)]) if test $am_cv_hdr_sigset = yes; then AC_DEFINE(HAVE_SIGSET_H) fi ]) balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/autogen.sh000077500000000000000000000011371477646064400224250ustar00rootroot00000000000000#! /bin/sh # bootstrap file to be used when autogen.sh fails. test -n "$srcdir" || srcdir=`dirname "$0"` test -n "$srcdir" || srcdir=. olddir=`pwd` cd $srcdir echo "Running gettextize... Ignore non-fatal messages." gettextize --force --no-changelog || exit 1 echo "Running libtoolize..." libtoolize --force || exit 1 echo "Running aclocal..." aclocal || exit 1 echo "Running autoconf..." autoconf || exit 1 echo "Running autoheader..." autoheader || exit 1 echo "Running automake..." automake --gnu --add-missing --copy || exit 1 cd $olddir echo "Running configure $* ..." exec $srcdir/configure "$@" balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/balsa-mail-style.xml000066400000000000000000000027501477646064400243100ustar00rootroot00000000000000 Albrecht Dreß <_description>Colour scheme for Balsa messages structured phrases \n\n" "\n", html_lang, html_subject); g_free(html_subject); g_free(html_lang); /* add the lines of the message body */ while (*start) { const gchar * eol = strchr(start, '\n'); const gchar * p = start; gboolean is_rtl = FALSE; GString * html; gsize idx; if (!eol) eol = start + strlen(start); /* find the first real char to determine the paragraph direction */ /* Use the same logic as fribidi_get_par_direction(), but * without allocating memory for all the gunichars and * FriBidiCharTypes: */ while (p < eol) { FriBidiCharType char_type; char_type = fribidi_get_bidi_type(g_utf8_get_char(p)); if (FRIBIDI_IS_LETTER(char_type)) { is_rtl = FRIBIDI_IS_RTL(char_type); break; } p = g_utf8_next_char(p); } /* html escape the line */ html = g_string_new_len(start, eol - start); /* encode hyperlinks */ html = libbalsa_html_encode_hyperlinks(html); /* replace a series of n spaces by (n - 1)   and one space */ idx = 0; while (idx < html->len) { if (html->str[idx] == ' ' && (idx == 0 || html->str[idx + 1] == ' ')) { html->str[idx++] = '&'; html = g_string_insert(html, idx, "nbsp;"); idx += 5; } else idx = g_utf8_next_char(html->str + idx) - html->str; } /* append the paragraph, always stating the proper direction */ g_string_append_printf(html_body, "

%s

\n", is_rtl ? "rtl" : "ltr", *html->str ? html->str : " "); g_string_free(html, TRUE); /* next line */ start = eol; if (*start) start++; } /* close the html context */ html_body = g_string_append(html_body, "\n\n"); /* return the utf-8 encoded text/html */ return g_string_free(html_body, FALSE); } /* * libbalsa_wrap_quoted string * Wraps the string, prefixing wrapped lines with any quote string * Uses the same wrapping strategy as libbalsa_wrap_string() * Returns a newly allocated string--deallocate with g_free() when done */ char * libbalsa_wrap_quoted_string(const char *str, unsigned width, GRegex *quote_regex) { char **lines; char **line; GString *wrapped; PangoLogAttr *log_attrs = NULL; g_return_val_if_fail(str != NULL, NULL); g_return_val_if_fail(quote_regex != NULL, NULL); lines = g_strsplit(str, "\n", -1); wrapped = g_string_new(NULL); for (line = lines; *line != NULL; line++) { unsigned quote_len, quote_len_utf8; const char *start_ptr, *break_ptr, *ptr; const unsigned minl = width / 2; unsigned ptr_offset, start_offset, break_offset; int num_chars; int attrs_len; unsigned cursor; num_chars = g_utf8_strlen(*line, -1); attrs_len = num_chars + 1; log_attrs = g_renew(PangoLogAttr, log_attrs, attrs_len); pango_get_log_attrs(*line, -1, -1, pango_language_get_default(), log_attrs, attrs_len); libbalsa_match_regex(*line, quote_regex, NULL, "e_len); g_string_append_len(wrapped, *line, quote_len); ptr = *line + quote_len; ptr_offset = g_utf8_pointer_to_offset(*line, ptr); cursor = quote_len_utf8 = ptr_offset; start_ptr = break_ptr = ptr; start_offset = break_offset = ptr_offset; while (*ptr != '\0') { gunichar c = g_utf8_get_char(ptr); if (c == '\t') cursor += 8 - cursor % 8; else cursor++; if (log_attrs[ptr_offset].is_line_break) { break_ptr = ptr; break_offset = ptr_offset; } if (cursor >= width && break_offset >= start_offset + minl && !g_unichar_isspace(c)) { const char *end_ptr, *test_ptr; gunichar test_char; /* Back up over whitespace */ test_ptr = break_ptr; do { end_ptr = test_ptr; test_ptr = g_utf8_prev_char(test_ptr); test_char = g_utf8_get_char(test_ptr); } while (test_ptr > start_ptr && g_unichar_isspace(test_char)); g_string_append_len(wrapped, start_ptr, end_ptr - start_ptr); g_string_append_c(wrapped, '\n'); g_string_append_len(wrapped, *line, quote_len); start_ptr = break_ptr; start_offset = break_offset; cursor = quote_len_utf8 + ptr_offset - start_offset; } ptr = g_utf8_next_char(ptr); ptr_offset++; } g_string_append(wrapped, start_ptr); g_string_append_c(wrapped, '\n'); } g_free(log_attrs); g_strfreev(lines); return (char *) g_string_free(wrapped, FALSE); } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/mime.h000066400000000000000000000025351477646064400233000ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __LIBBALSA_MIME_H__ #define __LIBBALSA_MIME_H__ #include #include "libbalsa.h" typedef void (*LibBalsaCharsetFunc) (const gchar * charset, gpointer data); GString *process_mime_part(LibBalsaMessage * message, LibBalsaMessageBody * body, gchar * reply_prefix_str, gint llen, gboolean ignore_html, gboolean flow); GString *content2reply(LibBalsaMessageBody *root, gchar * reply_prefix_str, gint llen, gboolean ignore_html, gboolean flow); #endif /* __LIBBALSA_MIME_H__ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/misc.c000066400000000000000000001064141477646064400233000ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ /* The routines that go here should depend only on common libraries - so that this file can be linked against the address book program balsa-ab without introducing extra dependencies. External library dependencies should go to libbalsa.c */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "misc.h" #define _SVID_SOURCE 1 #include #include #ifdef USE_FCNTL # include #endif #include #include #include #include #include #include #include #include "libbalsa.h" #include "libbalsa_private.h" #include "html.h" #include #include static const gchar *permanent_prefixes[] = { BALSA_DATA_PREFIX, "src", "." }; static const gchar *libbalsa_get_codeset_name(const gchar *txt, LibBalsaCodeset Codeset); #ifndef HAVE_STRUCT_UTSNAME_DOMAINNAME static int getdnsdomainname(char *s, size_t l); static int getdnsdomainname (char *s, size_t l) { FILE *f; char tmp[1024]; char *p = NULL; char *q; if ((f = fopen ("/etc/resolv.conf", "r")) == NULL) return (-1); tmp[sizeof (tmp) - 1] = 0; l--; /* save room for the terminal \0 */ while (fgets (tmp, sizeof (tmp) - 1, f) != NULL) { p = tmp; while ( g_ascii_isspace (*p)) p++; if (strncmp ("domain", p, 6) == 0 || strncmp ("search", p, 6) == 0) { p += 6; for (q = strtok (p, " \t\n"); q; q = strtok (NULL, " \t\n")) if (strcmp (q, ".")) break; if (q) { char *a = q; for (; *q; q++) a = q; if (*a == '.') *a = '\0'; g_stpcpy (s, q); fclose (f); return 0; } } } fclose (f); return (-1); } #endif /* !HAVE_STRUCT_UTSNAME_DOMAINNAME */ gchar * libbalsa_get_domainname(void) { struct utsname utsname; #ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME uname(&utsname); return g_strdup(utsname.domainname); #else /* HAVE_STRUCT_UTSNAME_DOMAINNAME */ char domainname[256]; /* arbitrary length */ gchar *d; uname(&utsname); d = strchr( utsname.nodename, '.' ); if(d) { return g_strdup( d+1 ); } if ( getdnsdomainname(domainname, sizeof(domainname)) == 0 ) { return g_strdup(domainname); } return NULL; #endif /* HAVE_STRUCT_UTSNAME_DOMAINNAME */ } /* libbalsa_find_word: searches given word delimited by blanks or string boundaries in given string. IS NOT case-sensitive. Returns TRUE if the word is found. */ gboolean libbalsa_find_word(const gchar * word, const gchar * str) { const gchar *ptr = str; int len = strlen(word); while (*ptr) { if (g_ascii_strncasecmp(word, ptr, len) == 0) return TRUE; /* skip one word */ while (*ptr && !isspace((int)*ptr)) ptr++; while (*ptr && isspace((int) *ptr)) ptr++; } return FALSE; } /* libbalsa_wrap_string wraps given string replacing spaces with '\n'. do changes in place. lnbeg - line beginning position, sppos - space position, te - tab's extra space. */ void libbalsa_wrap_string(gchar * str, int width) { const int minl = width / 2; gchar *space_pos, *ptr; gint te = 0; gint ptr_offset, line_begin_offset, space_pos_offset; g_return_if_fail(str != NULL); line_begin_offset = ptr_offset = space_pos_offset = 0; space_pos = ptr = str; while (*ptr) { switch (*ptr) { case '\t': te += 7; break; case '\n': line_begin_offset = ptr_offset + 1; te = 0; break; case ' ': space_pos = ptr; space_pos_offset = ptr_offset; break; } if (ptr_offset - line_begin_offset >= width - te && space_pos_offset >= line_begin_offset + minl) { *space_pos = '\n'; line_begin_offset = space_pos_offset + 1; te = 0; } ptr=g_utf8_next_char(ptr); ptr_offset++; } } /* Delete the contents of a directory and the directory itself. Return TRUE if everything was OK. If FALSE is returned then error will be set to some useful value. */ gboolean libbalsa_delete_directory(const gchar *path, GError **error) { GDir *dir; gboolean result; g_return_val_if_fail(path != NULL, FALSE); dir = g_dir_open(path, 0, error); if (dir == NULL) { result = FALSE; } else { const gchar *item; result = TRUE; item = g_dir_read_name(dir); while (result && (item != NULL)) { gchar *full_path; full_path = g_build_filename(path, item, NULL); if (g_file_test(full_path, G_FILE_TEST_IS_DIR)) { result = libbalsa_delete_directory(full_path, error); } else { if (g_unlink(full_path) != 0) { g_set_error(error, LIBBALSA_ERROR_QUARK, errno, _("cannot delete “%s”: %s"), full_path, g_strerror(errno)); result = FALSE; } } g_free(full_path); item = g_dir_read_name(dir); } g_dir_close(dir); if (g_rmdir(path) != 0) { g_set_error(error, LIBBALSA_ERROR_QUARK, errno, _("cannot delete “%s”: %s"), path, g_strerror(errno)); result = FALSE; } } return result; } /* libbalsa_expand_path: We handle only references to ~/. */ gchar* libbalsa_expand_path(const gchar * path) { const gchar *home = g_get_home_dir(); if(path[0] == '~') { if(path[1] == '/') return g_strconcat(home, path+1, NULL); else if(path[1] == '\0') return g_strdup(home); /* else: unrecognized combination */ } return g_strdup(path); } /* create a uniq directory, resulting name should be freed with g_free */ gboolean libbalsa_mktempdir (char **s) { g_return_val_if_fail(s != NULL, FALSE); *s = g_build_filename(g_get_tmp_dir(), "balsa-tmpdir-XXXXXX", NULL); return g_mkdtemp_full(*s, 0700) != NULL; } /* libbalsa_set_fallback_codeset: sets the codeset for incorrectly * encoded characters. * Returns the previous codeset. */ static LibBalsaCodeset sanitize_fallback_codeset = WEST_EUROPE; LibBalsaCodeset libbalsa_set_fallback_codeset(LibBalsaCodeset codeset) { LibBalsaCodeset ret = sanitize_fallback_codeset; const gchar *charsets[] = { "UTF-8", libbalsa_get_codeset_name(NULL, codeset), NULL }; g_mime_parser_options_set_fallback_charsets(libbalsa_parser_options(), charsets); sanitize_fallback_codeset = codeset; return ret; } /* libbalsa_utf8_sanitize * * Validate utf-8 text, and if validation fails, replace each offending * byte with either '?' or assume a reasonable codeset for conversion. * * Arguments: * text The text to be sanitized; NULL is OK. * fallback if TRUE and *text is not clean, convert using codeset * codeset the codeset to use for fallback conversion * target if not NULL filled with the name of the used codeset or NULL * or error/"?" conversion * * Return value: * TRUE if *text was clean and FALSE otherwise * * NOTE: The text is either modified in place or replaced and freed. */ gboolean libbalsa_utf8_sanitize(gchar **text, gboolean fallback, gchar const **target) { gchar *p; if (target) *target = NULL; if (!*text || g_utf8_validate(*text, -1, NULL)) return TRUE; if (fallback) { gsize b_written; GError *conv_error = NULL; const gchar *use_enc = libbalsa_get_codeset_name(*text, sanitize_fallback_codeset); p = g_convert(*text, strlen(*text), "utf-8", use_enc, NULL, &b_written, &conv_error); if (p) { g_free(*text); *text = p; if (target) *target = use_enc; return FALSE; } g_debug("conversion %s -> utf8 failed: %s", use_enc, conv_error->message); g_error_free(conv_error); } p = *text; while (!g_utf8_validate(p, -1, (const gchar **) &p)) *p++ = '?'; return FALSE; } /* libbalsa_utf8_strstr() returns TRUE if s2 is a substring of s1. * libbalsa_utf8_strstr is case insensitive * this functions understands utf8 strings (as you might have guessed ;-) */ gboolean libbalsa_utf8_strstr(const gchar *s1, const gchar *s2) { const gchar * p,* q; /* convention : NULL string is contained in anything */ if (!s2) return TRUE; /* s2 is non-NULL, so if s1==NULL we return FALSE :)*/ if (!s1) return FALSE; /* OK both are non-NULL now*/ /* If s2 is the empty string return TRUE */ if (!*s2) return TRUE; while (*s1) { /* We look for the first char of s2*/ for (;*s1 && g_unichar_toupper(g_utf8_get_char(s2))!=g_unichar_toupper(g_utf8_get_char(s1)); s1 = g_utf8_next_char(s1)); if (*s1) { /* We found the first char let see if this potential match is an actual one */ s1 = g_utf8_next_char(s1); q = s1; p = g_utf8_next_char(s2); while (*q && *p && g_unichar_toupper(g_utf8_get_char(p)) ==g_unichar_toupper(g_utf8_get_char(q))) { p = g_utf8_next_char(p); q = g_utf8_next_char(q); } /* We have a match if p has reached the end of s2, ie *p==0 */ if (!*p) return TRUE; } } return FALSE; } /* The LibBalsaCodeset enum is not used for anything currently, but this * list must be the same length, and should probably be kept consistent: */ LibBalsaCodesetInfo libbalsa_codeset_info[LIBBALSA_NUM_CODESETS] = { {N_("West European"), /* WEST_EUROPE */ "iso-8859-1", "windows-1252"} , {N_("East European"), /* EAST_EUROPE */ "iso-8859-2", "windows-1250"} , {N_("South European"), /* SOUTH_EUROPE */ "iso-8859-3"} , {N_("North European"), /* NORTH_EUROPE */ "iso-8859-4"} , {N_("Cyrillic"), /* CYRILLIC */ "iso-8859-5", "windows-1251"} , {N_("Arabic"), /* ARABIC */ "iso-8859-6", "windows-1256"} , {N_("Greek"), /* GREEK */ "iso-8859-7", "windows-1253"} , {N_("Hebrew"), /* HEBREW */ "iso-8859-8", "windows-1255"} , {N_("Turkish"), /* TURKISH */ "iso-8859-9", "windows-1254"} , {N_("Nordic"), /* NORDIC */ "iso-8859-10"} , {N_("Thai"), /* THAI */ "iso-8859-11"} , {N_("Baltic"), /* BALTIC */ "iso-8859-13", "windows-1257"} , {N_("Celtic"), /* CELTIC */ "iso-8859-14"} , {N_("West European (euro)"), /* WEST_EUROPE_EURO */ "iso-8859-15"} , {N_("Russian"), /* RUSSIAN */ "koi-8r"} , {N_("Ukrainian"), /* UKRAINE */ "koi-8u"} , {N_("Japanese"), /* JAPAN */ "iso-2022-jp"} , {N_("Korean"), /* KOREA */ "euc-kr"} , {N_("East European"), /* EAST_EUROPE_WIN */ "windows-1250"} , {N_("Cyrillic"), /* CYRILLIC_WIN */ "windows-1251"} , {N_("Greek"), /* GREEK_WIN */ "windows-1253"} , {N_("Hebrew"), /* HEBREW_WIN */ "windows-1255"} , {N_("Arabic"), /* ARABIC_WIN */ "windows-1256"} , {N_("Baltic"), /* BALTIC_WIN */ "windows-1257"} , }; /* * Return the name of a codeset according to Codeset. If txt is not NULL, is * is scanned for chars between 0x80 and 0x9f. If such a char is found, this * usually means that txt contains windows (not iso) characters. */ static const gchar * libbalsa_get_codeset_name(const gchar * txt, LibBalsaCodeset Codeset) { LibBalsaCodesetInfo *info = &libbalsa_codeset_info[Codeset]; if (txt && info->win) { LibBalsaTextAttribute attr = libbalsa_text_attr_string(txt); if (attr & LIBBALSA_TEXT_HI_CTRL) return info->win; } return info->std; } /* Create a GtkComboBox with the national charsets as options; * called when some text is found to be neither US-ASCII nor UTF-8, so * the list includes neither of these. */ GtkWidget * libbalsa_charset_button_new(void) { GtkWidget *combo_box; LibBalsaCodeset n, active = WEST_EUROPE; const gchar *locale_charset; combo_box = gtk_combo_box_text_new(); locale_charset = g_mime_locale_charset(); for (n = 0; n < LIBBALSA_NUM_CODESETS; n++) { LibBalsaCodesetInfo *info = &libbalsa_codeset_info[n]; gchar *tmp = g_strdup_printf("%s (%s)", _(info->label), info->std); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), tmp); g_free(tmp); if (!g_ascii_strcasecmp(info->std, locale_charset)) active = n; } /* locale_charset may be UTF-8, in which case it was not found, * and the initial choice will be WEST_EUROPE (= 0). */ gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), active); return combo_box; } /* Helper */ static void lb_text_attr(const gchar * text, gssize len, gboolean * has_esc, gboolean * has_hi_bit, gboolean * has_hi_ctrl) { if (len < 0) len = strlen(text); for (; --len >= 0; text++) { guchar c = *text; if (c == 0x1b) *has_esc = TRUE; if (c >= 0x80) { *has_hi_bit = TRUE; if (c <= 0x9f) *has_hi_ctrl = TRUE; } } } /* Return text attributes of a string. */ LibBalsaTextAttribute libbalsa_text_attr_string(const gchar * string) { LibBalsaTextAttribute attr; gboolean has_esc = FALSE; gboolean has_hi_bit = FALSE; gboolean has_hi_ctrl = FALSE; gboolean is_utf8; lb_text_attr(string, -1, &has_esc, &has_hi_bit, &has_hi_ctrl); is_utf8 = g_utf8_validate(string, -1, NULL); attr = 0; if (has_esc) attr |= LIBBALSA_TEXT_ESC; if (has_hi_bit) attr |= LIBBALSA_TEXT_HI_BIT; if (has_hi_ctrl) attr |= LIBBALSA_TEXT_HI_CTRL; if (is_utf8 && has_hi_bit) attr |= LIBBALSA_TEXT_HI_UTF8; return attr; } /* Return text attributes of the contents of a file; * filename is in URI form; * returns -1 on error. */ LibBalsaTextAttribute libbalsa_text_attr_file(const gchar * filename) { GFile *file; GFileInputStream *stream; gssize bytes; LibBalsaTextAttribute attr; gchar buf[80]; gchar *new_chars = buf; gboolean has_esc = FALSE; gboolean has_hi_bit = FALSE; gboolean has_hi_ctrl = FALSE; gboolean is_utf8 = TRUE; file = g_file_new_for_uri(filename); stream = g_file_read(file, NULL, NULL); g_object_unref(file); if (!stream) return -1; while ((bytes = g_input_stream_read(G_INPUT_STREAM(stream), new_chars, (sizeof buf) - (new_chars - buf), NULL, NULL)) > 0) { gboolean test_bits; test_bits = !has_esc || !has_hi_bit || !has_hi_ctrl; if (!test_bits && !is_utf8) break; if (test_bits) lb_text_attr(new_chars, bytes, &has_esc, &has_hi_bit, &has_hi_ctrl); if (is_utf8) { const gchar *end; bytes += new_chars - buf; new_chars = buf; if (!g_utf8_validate(buf, bytes, &end)) { bytes -= (end - buf); if (g_utf8_get_char_validated(end, bytes) == (gunichar) (-1)) { is_utf8 = FALSE; } else { /* copy remaining bytes to start of buffer */ memmove(buf, end, bytes); new_chars += bytes; } } } } g_object_unref(stream); if (bytes < 0) return -1; attr = 0; if (has_esc) attr |= LIBBALSA_TEXT_ESC; if (has_hi_bit) attr |= LIBBALSA_TEXT_HI_BIT; if (has_hi_ctrl) attr |= LIBBALSA_TEXT_HI_CTRL; if (is_utf8 && has_hi_bit) attr |= LIBBALSA_TEXT_HI_UTF8; return attr; } #define compare_stat(osb, nsb) ( (osb.st_dev != nsb.st_dev || osb.st_ino != nsb.st_ino || osb.st_rdev != nsb.st_rdev) ? -1 : 0 ) /* * This function is supposed to do nfs-safe renaming of files. * * Warning: We don't check whether src and target are equal. */ int libbalsa_safe_rename (const char *src, const char *target) { struct stat ssb, tsb; if (!src || !target) return -1; if (link (src, target) != 0) { /* * Coda does not allow cross-directory links, but tells * us it's a cross-filesystem linking attempt. * * However, the Coda rename call is allegedly safe to use. * * With other file systems, rename should just fail when * the files reside on different file systems, so it's safe * to try it here. * */ if (errno == EXDEV) return rename (src, target); return -1; } /* * Stat both links and check if they are equal. */ if (stat (src, &ssb) == -1) { return -1; } if (stat (target, &tsb) == -1) { return -1; } /* * pretend that the link failed because the target file * did already exist. */ if (compare_stat (ssb, tsb) == -1) { errno = EEXIST; return -1; } /* * Unlink the original link. Should we really ignore the return * value here? XXX */ unlink (src); return 0; } #define MAXLOCKATTEMPT 5 /* Args: * excl if excl != 0, request an exclusive lock * dot if dot != 0, try to dotlock the file * timeout should retry locking? */ int libbalsa_lock_file (const char *path, int fd, int excl, int dot, int timeout) { #if defined (USE_FCNTL) || defined (USE_FLOCK) int count; int attempt; struct stat prev_sb = { 0 }; #endif int r = 0; #ifdef USE_FCNTL struct flock lck; memset (&lck, 0, sizeof (struct flock)); lck.l_type = excl ? F_WRLCK : F_RDLCK; lck.l_whence = SEEK_SET; count = 0; attempt = 0; while (fcntl (fd, F_SETLK, &lck) == -1) { struct stat sb; g_debug("%s(): fcntl errno %d.", __func__, errno); if (errno != EAGAIN && errno != EACCES) { libbalsa_information (LIBBALSA_INFORMATION_MESSAGE, _("fcntl failed: %s."), g_strerror(errno)); return -1; } if (fstat (fd, &sb) != 0) sb.st_size = 0; if (count == 0) prev_sb = sb; /* only unlock file if it is unchanged */ if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0)) { if (timeout) libbalsa_information (LIBBALSA_INFORMATION_WARNING, _("Timeout exceeded while attempting fcntl lock!")); return (-1); } prev_sb = sb; libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, _("Waiting for fcntl lock… %d"), ++attempt); sleep (1); } #endif /* USE_FCNTL */ #ifdef USE_FLOCK count = 0; attempt = 0; while (flock (fd, (excl ? LOCK_EX : LOCK_SH) | LOCK_NB) == -1) { struct stat sb; if (errno != EWOULDBLOCK) { libbalsa_information(LIBBALSA_INFORMATION_WARNING, "flock: %s", g_strerror(errno)); r = -1; break; } if (fstat(fd,&sb) != 0 ) sb.st_size=0; if (count == 0) prev_sb=sb; /* only unlock file if it is unchanged */ if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0)) { if (timeout) libbalsa_information(LIBBALSA_INFORMATION_WARNING, _("Timeout exceeded while attempting flock lock!")); r = -1; break; } prev_sb = sb; libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, _("Waiting for flock attempt… %d"), ++attempt); sleep (1); } #endif /* USE_FLOCK */ #ifdef USE_DOTLOCK if (r == 0 && dot) r = dotlock_file (path, fd, timeout); #endif /* USE_DOTLOCK */ if (r == -1) { /* release any other locks obtained in this routine */ #ifdef USE_FCNTL lck.l_type = F_UNLCK; fcntl (fd, F_SETLK, &lck); #endif /* USE_FCNTL */ #ifdef USE_FLOCK flock (fd, LOCK_UN); #endif /* USE_FLOCK */ return (-1); } return 0; } int libbalsa_unlock_file (const char *path, int fd, int dot) { #ifdef USE_FCNTL struct flock unlockit = { F_UNLCK, 0, 0, 0 }; memset (&unlockit, 0, sizeof (struct flock)); unlockit.l_type = F_UNLCK; unlockit.l_whence = SEEK_SET; fcntl (fd, F_SETLK, &unlockit); #endif #ifdef USE_FLOCK flock (fd, LOCK_UN); #endif #ifdef USE_DOTLOCK if (dot) undotlock_file (path, fd); #endif return 0; } /* libbalsa_ia_rfc2821_equal compares two addresses according to rfc2821: local-part@domain is equal, if the local-parts are case sensitive equal, but the domain case-insensitive */ gboolean libbalsa_ia_rfc2821_equal(const InternetAddress * a, const InternetAddress * b) { const gchar *a_atptr, *b_atptr; const gchar *a_addr, *b_addr; gint a_atpos, b_atpos; if (!INTERNET_ADDRESS_IS_MAILBOX(a) || !INTERNET_ADDRESS_IS_MAILBOX(b)) return FALSE; /* first find the "@" in the two addresses */ a_addr = INTERNET_ADDRESS_MAILBOX(a)->addr; b_addr = INTERNET_ADDRESS_MAILBOX(b)->addr; a_atptr = strchr(a_addr, '@'); b_atptr = strchr(b_addr, '@'); if (!a_atptr || !b_atptr) return FALSE; a_atpos = a_atptr - a_addr; b_atpos = b_atptr - b_addr; /* now compare the strings */ if (!a_atpos || !b_atpos || a_atpos != b_atpos || strncmp(a_addr, b_addr, a_atpos) || g_ascii_strcasecmp(a_atptr, b_atptr)) return FALSE; else return TRUE; } /* * Utilities for making consistent dialogs. */ #define LB_PADDING 12 /* per HIG */ GtkWidget * libbalsa_create_grid(void) { GtkWidget *grid; grid = gtk_grid_new(); gtk_grid_set_row_spacing(GTK_GRID(grid), LB_PADDING); gtk_grid_set_column_spacing(GTK_GRID(grid), LB_PADDING); return grid; } /* create_label: Create a label and add it to a table in the first column of given row, setting the keyval to found accelerator value, that can be later used in create_entry. */ GtkWidget * libbalsa_create_grid_label(const gchar * text, GtkWidget * grid, gint row) { GtkWidget *label; label = gtk_label_new_with_mnemonic(text); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_label_set_xalign(GTK_LABEL(label), 0.0F); gtk_grid_attach(GTK_GRID(grid), label, 0, row, 1, 1); return label; } /** \brief Create a properly aligned label with line wrap * * \param text label text * \param markup TRUE if the label text contains markup * \return the new label widget * * Create a new label, enable word wrap, and set set xalign property. */ GtkWidget * libbalsa_create_wrap_label(const gchar *text, gboolean markup) { GtkWidget *label; if (markup) { label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), text); } else { label = gtk_label_new(text); } gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_label_set_xalign(GTK_LABEL(label), 0.0F); return label; } /* create_check: creates a checkbox with a given label and places them in given array. */ GtkWidget * libbalsa_create_grid_check(const gchar * text, GtkWidget * grid, gint row, gboolean initval) { GtkWidget *check_button; check_button = gtk_check_button_new_with_mnemonic(text); gtk_grid_attach(GTK_GRID(grid), check_button, 0, row, 2, 1); if (initval) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), TRUE); return check_button; } /* Create a text entry and add it to the table */ GtkWidget * libbalsa_create_grid_entry(GtkWidget * grid, GCallback changed_func, gpointer data, gint row, const gchar * initval, GtkWidget * hotlabel) { GtkWidget *entry; entry = gtk_entry_new(); gtk_widget_set_hexpand(entry, TRUE); gtk_grid_attach(GTK_GRID(grid), entry, 1, row, 1, 1); if (initval) gtk_entry_set_text(GTK_ENTRY(entry), initval); gtk_label_set_mnemonic_widget(GTK_LABEL(hotlabel), entry); /* Watch for changes... */ if (changed_func) g_signal_connect(entry, "changed", changed_func, data); return entry; } /* Create a GtkSizeGroup and add to it any GtkLabel packed in a GtkGrid * inside the chooser widget; size_group will be unreffed when the * chooser widget is finalized. */ static void lb_create_size_group_func(GtkWidget * widget, gpointer data) { if (GTK_IS_LABEL(widget) && GTK_IS_GRID(gtk_widget_get_parent(widget))) gtk_size_group_add_widget(GTK_SIZE_GROUP(data), widget); else if (GTK_IS_CONTAINER(widget)) gtk_container_foreach(GTK_CONTAINER(widget), lb_create_size_group_func, data); } GtkSizeGroup * libbalsa_create_size_group(GtkWidget * chooser) { GtkSizeGroup *size_group; size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); g_object_weak_ref(G_OBJECT(chooser), (GWeakNotify) g_object_unref, size_group); lb_create_size_group_func(chooser, size_group); return size_group; } static void on_view_pwd_icon_press(GtkWidget *widget, gpointer data) { gboolean visible = gtk_entry_get_visibility(GTK_ENTRY(widget)); gtk_entry_set_visibility(GTK_ENTRY(widget), !visible); gtk_entry_set_icon_from_icon_name(GTK_ENTRY(widget), GTK_ENTRY_ICON_SECONDARY, visible ? "view-reveal-symbolic" : "view-conceal-symbolic"); } void libbalsa_entry_config_passwd(GtkEntry *entry) { g_return_if_fail(GTK_IS_ENTRY(entry)); gtk_entry_set_visibility(entry, FALSE); g_object_set(entry, "input-purpose", GTK_INPUT_PURPOSE_PASSWORD, NULL); gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, "view-reveal-symbolic"); gtk_entry_set_icon_activatable(entry, GTK_ENTRY_ICON_SECONDARY, TRUE); g_signal_connect(entry, "icon-press", G_CALLBACK (on_view_pwd_icon_press), NULL); } void libbalsa_assure_balsa_dirs(void) { const gchar *(*dir_fn[3])(void) = { g_get_user_config_dir, g_get_user_state_dir, g_get_user_cache_dir }; guint n; for (n = 0U; n < G_N_ELEMENTS(dir_fn); n++) { gchar *folder; folder = g_build_filename(dir_fn[n](), "balsa", NULL); if (g_mkdir_with_parents(folder, S_IRWXU) == -1) { g_error("cannot create folder %s: %s", folder, g_strerror(errno)); } g_free(folder); } } /* Some more "guess" functions symmetric to libbalsa_guess_mail_spool()... */ #define POP_SERVER "pop" #define IMAP_SERVER "mx" #define LDAP_SERVER "ldap" static gchar* qualified_hostname(const char *name) { gchar *domain=libbalsa_get_domainname(); if(domain) { gchar *host=g_strdup_printf("%s.%s", name, domain); g_free(domain); return host; } else return g_strdup(name); } gchar *libbalsa_guess_ldap_server() { return qualified_hostname(LDAP_SERVER); } gchar *libbalsa_guess_ldap_base() { gchar *server = libbalsa_guess_ldap_server(); /* Note: Assumes base dn is "o=". Somewhat speculative... */ if(server) { gchar *base=NULL, *domain; if((domain=strchr(server, '.'))) base = g_strdup_printf("o=%s", domain+1); g_free(server); return base; } return NULL; } gchar *libbalsa_guess_ldap_name() { gchar *base = libbalsa_guess_ldap_base(); if(base) { gchar *name = strchr(base, '='); gchar *dir_name = g_strdup_printf(_("LDAP Directory for %s"), (name?name+1:base)); g_free(base); return dir_name; } return NULL; } gboolean libbalsa_path_is_below_dir(const gchar * path, const gchar * dir) { gsize len; if (!path || !dir || !g_str_has_prefix(path, dir)) return FALSE; len = strlen(dir); return dir[len - 1] == G_DIR_SEPARATOR || path[len] == G_DIR_SEPARATOR; } #define LIBBALSA_RADIX 1024.0 #define MAX_WITHOUT_SUFFIX 9999 gchar * libbalsa_size_to_gchar(guint64 size) { if (size > MAX_WITHOUT_SUFFIX) { gdouble displayed_size = (gdouble) size; gchar *s, suffix[] = "KMGT"; for (s = suffix; /* *s != '\0' */; s++) { displayed_size /= LIBBALSA_RADIX; if (displayed_size < 9.995) return g_strdup_printf("%.2f%c", displayed_size, *s); if (displayed_size < 99.95) return g_strdup_printf("%.1f%c", displayed_size, *s); if (displayed_size < LIBBALSA_RADIX - 0.5 || !s[1]) return g_strdup_printf("%" G_GUINT64_FORMAT "%c", ((guint64) (displayed_size + 0.5)), *s); } } return g_strdup_printf("%" G_GUINT64_FORMAT, size); } /* * libbalsa_font_string_to_css: construct CSS text corresponding to a * PangoFontDescription string. * * font_string: the PangoFontDescription string; * name: the name of the widget to which the font is to be applied. * * Returns: a newly allocated string with the CSS text; * g_free() when no longer needed. */ gchar * libbalsa_font_string_to_css(const gchar * font_string, const gchar * name) { PangoFontDescription *desc; PangoFontMask mask; GString *string; g_return_val_if_fail(font_string != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); desc = pango_font_description_from_string(font_string); mask = pango_font_description_get_set_fields(desc); string = g_string_new(NULL); g_string_printf(string, "#%s {\n", name); if (mask & PANGO_FONT_MASK_FAMILY) { g_string_append_printf(string, "font-family: \"%s\";\n", pango_font_description_get_family(desc)); } if (mask & PANGO_FONT_MASK_STYLE) { PangoStyle style; /* An enum with default values, * so use it to index the array. */ static const gchar *styles[] = { "normal", "oblique", "italic" }; style = pango_font_description_get_style(desc); g_string_append_printf(string, "font-style: %s;\n", styles[style]); } if (mask & PANGO_FONT_MASK_VARIANT) { PangoVariant variant; /* An enum with default values, * so use it to index the array. */ static const gchar *variants[] = { "normal", "small-caps" }; variant = pango_font_description_get_variant(desc); g_string_append_printf(string, "font-variant: %s;\n", variants[variant]); } if (mask & PANGO_FONT_MASK_WEIGHT) { PangoWeight weight; /* An enum with weight values, so use the value. */ weight = pango_font_description_get_weight(desc); g_string_append_printf(string, "font-weight: %d;\n", weight); } if (mask & PANGO_FONT_MASK_STRETCH) { PangoStretch stretch; /* An enum with default values, * so use it to index the array. */ static const gchar *stretches[] = { "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", "normal", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded" }; stretch = pango_font_description_get_stretch(desc); g_string_append_printf(string, "font-stretch: %s;\n", stretches[stretch]); } if (mask & PANGO_FONT_MASK_SIZE) { gdouble size; const gchar *units; size = (gdouble) pango_font_description_get_size(desc) / PANGO_SCALE; units = pango_font_description_get_size_is_absolute(desc) ? "px" : "pt"; g_string_append_printf(string, "font-size: %.1f%s;\n", size, units); } g_string_append_c(string, '}'); pango_font_description_free(desc); return g_string_free(string, FALSE); } GMimeParserOptions * libbalsa_parser_options(void) { static GMimeParserOptions *parser_options = NULL; if (g_once_init_enter(&parser_options)) { GMimeParserOptions *tmp = g_mime_parser_options_new(); g_mime_parser_options_set_rfc2047_compliance_mode(tmp, GMIME_RFC_COMPLIANCE_LOOSE); g_once_init_leave(&parser_options, tmp); } return parser_options; } /* * libbalsa_add_mnemonic_button_to_box * * Create a button widget and add it to a GtkBox with the same * look as a regular button in a GtkButtonBox; returns the button. * * markup: mnemonic text for the button; * box: the box; * align: how to align the button in its allocated space. * * To replace a GtkButtonBox with the default GTK_BUTTONBOX_EDGE style, * align should be GTK_ALIGN_START for the first button, GTK_ALIGN_END * for the last button, and GTK_ALIGN_CENTER for other buttons. * To replace a GtkButtonBox with style GTK_BUTTONBOX_SPREAD, * align should be GTK_ALIGN_CENTER for all buttons; * To replace a GtkButtonBox with style GTK_BUTTONBOX_EXPAND, * align should be GTK_ALIGN_FILL for all buttons. * * In the EDGE case with more than three buttons, and in the SPREAD case, * the spacing is not identical to GtkButtonBox's. */ /* Margin to increase the width of the button, to approximate the look * of a GtkButtonBox; may be a pixel or two too small: */ #define LIBBALSA_LABEL_MARGIN 12 #define LIBBALSA_SIZE_GROUP_KEY "libbalsa-size-group-key" GtkWidget * libbalsa_add_mnemonic_button_to_box(const gchar *markup, GtkWidget *box, GtkAlign align) { GtkSizeGroup *size_group; GtkWidget *label; GtkWidget *button; size_group = g_object_get_data(G_OBJECT(box), LIBBALSA_SIZE_GROUP_KEY); if (size_group == NULL) { size_group = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); g_object_set_data_full(G_OBJECT(box), LIBBALSA_SIZE_GROUP_KEY, size_group, g_object_unref); } label = gtk_label_new(NULL); gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), markup); gtk_widget_set_margin_start(label, LIBBALSA_LABEL_MARGIN); gtk_widget_set_margin_end(label, LIBBALSA_LABEL_MARGIN); gtk_widget_show(label); gtk_size_group_add_widget(size_group, label); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), label); gtk_widget_set_hexpand(button, TRUE); gtk_widget_set_halign(button, align); gtk_widget_show(button); gtk_container_add(GTK_CONTAINER(box), button); return button; } /* filename is the filename (naw!) * We ignore proper slashing of names. Ie, /prefix//pixmaps//file won't be caught. */ gchar * libbalsa_pixmap_finder(const gchar * filename) { gchar *cat; guint i; g_return_val_if_fail(filename, NULL); for (i = 0; i < G_N_ELEMENTS(permanent_prefixes); i++) { cat = g_build_filename(permanent_prefixes[i], "pixmaps", filename, NULL); if (g_file_test(cat, G_FILE_TEST_IS_REGULAR)) return cat; g_free(cat); } cat = g_build_filename("images", "pixmaps", NULL); if (g_file_test(cat, G_FILE_TEST_IS_REGULAR)) return cat; g_free(cat); g_warning("Cannot find expected pixmap file “%s”", filename); return NULL; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/misc.h000066400000000000000000000165421477646064400233070ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __LIBBALSA_MISC_H__ #define __LIBBALSA_MISC_H__ #ifndef BALSA_VERSION # error "Include config.h before this file." #endif #include #include #include typedef enum _LibBalsaCodeset LibBalsaCodeset; enum _LibBalsaCodeset { WEST_EUROPE, /* iso-8859-1 or windows-1252 */ EAST_EUROPE, /* iso-8859-2 or windows-1250 */ SOUTH_EUROPE, /* iso-8859-3 */ NORTH_EUROPE, /* iso-8859-4 */ CYRILLIC, /* iso-8859-5 or windows-1251 */ ARABIC, /* iso-8859-6 or windows-1256 */ GREEK, /* iso-8859-7 or windows-1253 */ HEBREW, /* iso-8859-8 or windows-1255 */ TURKISH, /* iso-8859-9 or windows-1254 */ NORDIC, /* iso-8859-10 */ THAI, /* iso-8859-11 */ BALTIC, /* iso-8859-13 or windows-1257 */ CELTIC, /* iso-8859-14 */ WEST_EUROPE_EURO, /* iso-8859-15 */ RUSSIAN, /* koi-8r */ UKRAINE, /* koi-8u */ JAPAN, /* iso-2022-jp */ KOREA, /* euc-kr */ EAST_EUROPE_WIN, /* windows-1250 */ CYRILLIC_WIN, /* windows-1251 */ GREEK_WIN, /* windows-1253 */ HEBREW_WIN, /* windows-1255 */ ARABIC_WIN, /* windows-1256 */ BALTIC_WIN, /* windows-1257 */ LIBBALSA_NUM_CODESETS }; typedef enum _LibBalsaTextAttribute LibBalsaTextAttribute; enum _LibBalsaTextAttribute { LIBBALSA_TEXT_ESC = 1 << 0, /* ESC char(s) */ LIBBALSA_TEXT_HI_BIT = 1 << 1, /* 8-bit char(s) */ LIBBALSA_TEXT_HI_CTRL = 1 << 2, /* 0x80 - 0x9f */ LIBBALSA_TEXT_HI_UTF8 = 1 << 3 /* 8-bit utf-8 */ }; typedef struct _LibBalsaCodesetInfo LibBalsaCodesetInfo; struct _LibBalsaCodesetInfo { const gchar *label; const gchar *std; const gchar *win; }; typedef void (*libbalsa_url_cb_t) (GtkTextBuffer *, GtkTextIter *, const gchar *, guint, gpointer); typedef struct _LibBalsaUrlInsertInfo LibBalsaUrlInsertInfo; struct _LibBalsaUrlInsertInfo { libbalsa_url_cb_t callback; gpointer callback_data; gboolean buffer_is_flowed; GString *ml_url_buffer; }; #define LIBBALSA_ERROR_QUARK (g_quark_from_static_string("libbalsa")) extern LibBalsaCodesetInfo libbalsa_codeset_info[]; GtkWidget *libbalsa_charset_button_new(void); LibBalsaTextAttribute libbalsa_text_attr_string(const gchar * string); LibBalsaTextAttribute libbalsa_text_attr_file(const gchar * filename); gchar *libbalsa_get_domainname(void); #define libbalsa_urlencode(str) (g_uri_escape_string((str), NULL, FALSE)) #define libbalsa_urldecode(str) (g_uri_unescape_string((str), NULL)) gboolean libbalsa_find_word(const gchar * word, const gchar * str); void libbalsa_wrap_string(gchar * str, int width); char *libbalsa_wrap_quoted_string(const char *str, unsigned width, GRegex *quote_regex); GString *libbalsa_process_text_rfc2646(gchar * par, gint width, gboolean from_screen, gboolean to_screen, gboolean quote, gboolean delsp); gchar *libbalsa_wrap_rfc2646(gchar * par, gint width, gboolean from_screen, gboolean to_screen, gboolean delsp); void libbalsa_unwrap_buffer(GtkTextBuffer * buffer, GtkTextIter * iter, gint lines); gboolean libbalsa_delete_directory(const gchar *path, GError **error); gchar *libbalsa_expand_path(const gchar *path); gboolean libbalsa_mktempdir(gchar ** name); LibBalsaCodeset libbalsa_set_fallback_codeset(LibBalsaCodeset codeset); gboolean libbalsa_utf8_sanitize(gchar ** text, gboolean fallback, gchar const **target); gboolean libbalsa_utf8_strstr(const gchar *s1,const gchar *s2); gboolean libbalsa_insert_with_url(GtkTextBuffer * buffer, const char *chars, guint len, GtkTextTag * tag, LibBalsaUrlInsertInfo *url_info); void libbalsa_unwrap_selection(GtkTextBuffer * buffer, GRegex * rex); gboolean libbalsa_match_regex(const gchar * line, GRegex * rex, guint * count, guint * index); int libbalsa_lock_file (const char *path, int fd, int excl, int dot, int timeout); int libbalsa_unlock_file (const char *path, int fd, int dot); int libbalsa_safe_rename (const char *src, const char *target); gboolean libbalsa_ia_rfc2821_equal(const InternetAddress * a, const InternetAddress * b); GtkWidget *libbalsa_create_grid(void); GtkWidget *libbalsa_create_grid_label(const gchar * label, GtkWidget * grid, gint row); GtkWidget *libbalsa_create_grid_entry(GtkWidget * grid, GCallback func, gpointer data, gint row, const gchar * initval, GtkWidget * hotlabel); GtkWidget *libbalsa_create_grid_check(const gchar * label, GtkWidget * grid, gint row, gboolean initval); GtkSizeGroup *libbalsa_create_size_group(GtkWidget * chooser); GtkWidget *libbalsa_create_wrap_label(const gchar *text, gboolean markup); void libbalsa_entry_config_passwd(GtkEntry *entry); void libbalsa_assure_balsa_dirs(void); gchar *libbalsa_guess_ldap_base(void); gchar *libbalsa_guess_ldap_name(void); gboolean libbalsa_path_is_below_dir(const gchar * path, const gchar * dir); gchar *libbalsa_size_to_gchar(guint64 length); gchar * libbalsa_text_to_html(const gchar * title, const gchar * body, const gchar * lang); GString * libbalsa_html_encode_hyperlinks(GString * paragraph); gchar *libbalsa_font_string_to_css(const gchar * font_string, const gchar * name); GMimeParserOptions *libbalsa_parser_options(void); /* Some margin helpers */ #define HIG_PADDING 6 static inline void libbalsa_set_hmargins(GtkWidget *widget, int margin) { gtk_widget_set_margin_start(widget, margin); gtk_widget_set_margin_end(widget, margin); } static inline void libbalsa_set_vmargins(GtkWidget *widget, int margin) { gtk_widget_set_margin_top(widget, margin); gtk_widget_set_margin_bottom(widget, margin); } static inline void libbalsa_set_margins(GtkWidget *widget, int margin) { libbalsa_set_hmargins(widget, margin); libbalsa_set_vmargins(widget, margin); } GtkWidget * libbalsa_add_mnemonic_button_to_box(const gchar *markup, GtkWidget *box, GtkAlign align); gchar * libbalsa_pixmap_finder(const gchar * filename); #endif /* __LIBBALSA_MISC_H__ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/missing.h000066400000000000000000000020631477646064400240160ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ #ifndef __MISSING_H__ #define __MISSING_H__ 1 /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #include #ifndef BALSA_VERSION # error "Include config.h before this file." #endif #if (HAVE_DECL_CTIME_R == 0) char * ctime_r(const time_t *clock, char *buf); #endif #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/missing_time.c000066400000000000000000000023271477646064400250320ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #if !defined(HAVE_CTIME_R) #include "missing.h" #include #ifndef HAVE_CTIME_R char * ctime_r(const time_t *clock, char *buf) { static GMutex time_lock; g_mutex_lock(&mutex); strcpy(buf, ctime(clock)); g_mutex_unlock(&mutex); return buf; } #endif #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/padlock-keyhole.xpm000066400000000000000000000244051477646064400260010ustar00rootroot00000000000000/* XPM */ static const char * padlock_keyhole_xpm[] = { "48 48 352 2", " c None", ". c #000000", "+ c #010101", "@ c #9B9B9B", "# c #D0D0D0", "$ c #E3E3E3", "% c #E9E9E9", "& c #DDDDDD", "* c #C6C6C6", "= c #919191", "- c #BEBEBE", "; c #EAEAEA", "> c #F1F1F1", ", c #F3F3F3", "' c #EDEDED", ") c #E6E6E6", "! c #E2E2E2", "~ c #D8D8D8", "{ c #9C9C9C", "] c #606060", "^ c #F0F0F0", "/ c #ECECEC", "( c #E4E4E4", "_ c #E1E1E1", ": c #D6D6D6", "< c #B7B7B7", "[ c #454545", "} c #858585", "| c #D9D9D9", "1 c #CECECE", "2 c #C2C2C2", "3 c #CCCCCC", "4 c #D5D5D5", "5 c #DCDCDC", "6 c #E0E0E0", "7 c #C8C8C8", "8 c #B9B9B9", "9 c #626262", "0 c #5E5E5E", "a c #E8E8E8", "b c #BCBCBC", "c c #585858", "d c #141414", "e c #7B7B7B", "f c #DFDFDF", "g c #C3C3C3", "h c #BBBBBB", "i c #4C4C4C", "j c #979797", "k c #B6B6B6", "l c #EBEBEB", "m c #8A8A8A", "n c #929292", "o c #DBDBDB", "p c #B3B3B3", "q c #939393", "r c #C0C0C0", "s c #020202", "t c #A2A2A2", "u c #E5E5E5", "v c #A0A0A0", "w c #818181", "x c #D1D1D1", "y c #AEAEAE", "z c #767676", "A c #F2F2F2", "B c #2F2F2F", "C c #828282", "D c #EEEEEE", "E c #B5B5B5", "F c #9F9F9F", "G c #0F0F0F", "H c #1F1F1F", "I c #A8A8A8", "J c #EFEFEF", "K c #CBCBCB", "L c #C5C5C5", "M c #DADADA", "N c #CACACA", "O c #ABABAB", "P c #ADACAA", "Q c #371908", "R c #9C5217", "S c #B86E25", "T c #B96B26", "U c #A75A1C", "V c #A55E1F", "W c #BC732A", "X c #B86F27", "Y c #97551A", "Z c #C99C62", "` c #F4E1CB", " . c #F4E0C9", ".. c #EFDBBE", "+. c #ECD5B7", "@. c #EBD2B4", "#. c #EAD2B3", "$. c #EBCFB0", "%. c #E9CEAE", "&. c #E8CCAB", "*. c #E7CCA8", "=. c #E8C7A1", "-. c #E6C6A1", ";. c #E5C5A0", ">. c #E3C29A", ",. c #E0C09B", "'. c #E0BD93", "). c #DFBA92", "!. c #DFBA8E", "~. c #DDB386", "{. c #D5AC7C", "]. c #A2611B", "^. c #F5E6D0", "/. c #EAD3AF", "(. c #EACFAF", "_. c #DAB88B", ":. c #DAB687", "<. c #D8B081", "[. c #D6AE7F", "}. c #D3AB7C", "|. c #D1A974", "1. c #CFA56E", "2. c #CCA36D", "3. c #CA9F67", "4. c #C89E67", "5. c #C69B63", "6. c #C29861", "7. c #C2935B", "8. c #BF9052", "9. c #BC884B", "0. c #BD8440", "a. c #BA7E3D", "b. c #B37634", "c. c #A76A22", "d. c #8D5314", "e. c #F5E4CE", "f. c #E7CDA8", "g. c #DFBD90", "h. c #D8B183", "i. c #D5AD7E", "j. c #D2AA7B", "k. c #D2A677", "l. c #D0A771", "m. c #CDA36C", "n. c #C89F68", "o. c #C59B64", "p. c #C49961", "q. c #C59A62", "r. c #C2985D", "s. c #C1945A", "t. c #BF9054", "u. c #BE8E4F", "v. c #BC8749", "w. c #BA823F", "x. c #B17432", "y. c #8B5214", "z. c #E0BF97", "A. c #DBB486", "B. c #D7AF80", "C. c #D2AC7B", "D. c #D0A66F", "E. c #B58E5C", "F. c #A07E50", "G. c #9A794D", "H. c #B28C59", "I. c #C79C64", "J. c #C2975F", "K. c #BC8441", "L. c #B57C38", "M. c #AF732C", "N. c #A3661E", "O. c #875014", "P. c #E8CDA9", "Q. c #DFBC92", "R. c #D2AB7D", "S. c #D0AB75", "T. c #B38E5D", "U. c #94744A", "V. c #775E3C", "W. c #201910", "X. c #79603E", "Y. c #C79D66", "Z. c #BF9156", "`. c #BE8645", " + c #BC833F", ".+ c #B67C37", "++ c #AA6C23", "@+ c #8D5514", "#+ c #E8CEA9", "$+ c #E1BC94", "%+ c #DAB487", "&+ c #D8B281", "*+ c #D0A873", "=+ c #92744D", "-+ c #7A603E", ";+ c #79603F", ">+ c #BE8F51", ",+ c #BA813D", "'+ c #B77E3A", ")+ c #B37934", "!+ c #A66921", "~+ c #E5C9A4", "{+ c #DDBA90", "]+ c #D2A575", "^+ c #D1A770", "/+ c #95754C", "(+ c #201A10", "_+ c #211A10", ":+ c #D7B78E", "<+ c #BD8C4C", "[+ c #BC8845", "}+ c #BB823E", "|+ c #A96B22", "1+ c #E9CDAC", "2+ c #E7CBA6", "3+ c #D1A572", "4+ c #96774E", "5+ c #E1CBAD", "6+ c #C09359", "7+ c #BC8543", "8+ c #B37832", "9+ c #E8CCA7", "0+ c #E5CAA4", "a+ c #DCB98F", "b+ c #CAA16B", "c+ c #20190F", "d+ c #DEC6A7", "e+ c #C19256", "f+ c #BD8D4E", "g+ c #B57D3A", "h+ c #B57836", "i+ c #AD722C", "j+ c #A4661D", "k+ c #D2AB79", "l+ c #D1A872", "m+ c #755C38", "n+ c #755B37", "o+ c #DDC7A7", "p+ c #B77F3C", "q+ c #B0752F", "r+ c #A46821", "s+ c #895114", "t+ c #E9CEAA", "u+ c #DAB385", "v+ c #201A11", "w+ c #927E63", "x+ c #E3CFB3", "y+ c #D4B388", "z+ c #BB8444", "A+ c #B67A39", "B+ c #B17630", "C+ c #D2AC77", "D+ c #CDA46E", "E+ c #A57D4D", "F+ c #D9BF9E", "G+ c #CAA371", "H+ c #B77D38", "I+ c #AD6F26", "J+ c #BA935E", "K+ c #95744A", "L+ c #C5B39B", "M+ c #B57938", "N+ c #AD762E", "O+ c #AF722A", "P+ c #E1BD96", "Q+ c #CAA069", "R+ c #B58F5D", "S+ c #836641", "T+ c #8F7554", "U+ c #BC8947", "V+ c #BD8242", "W+ c #DBB88E", "X+ c #D1A776", "Y+ c #CCA26B", "Z+ c #B48D59", "`+ c #6C5433", " @ c #6D5536", ".@ c #B47B37", "+@ c #C08D51", "@@ c #894E14", "#@ c #DCB387", "$@ c #D1AB76", "%@ c #B28B57", "&@ c #AC834E", "*@ c #3F301C", "=@ c #40321E", "-@ c #D2BD9F", ";@ c #C8A271", ">@ c #B8803D", ",@ c #AF742E", "'@ c #864C13", ")@ c #E6CAA5", "!@ c #B28753", "~@ c #9A7545", "{@ c #89683E", "]@ c #DAC1A0", "^@ c #BD8E50", "/@ c #B17732", "(@ c #AD712A", "_@ c #CA9D63", ":@ c #874D14", "<@ c #E4C8A3", "[@ c #DAB88D", "}@ c #CBA26C", "|@ c #B78F5B", "1@ c #7F633F", "2@ c #725938", "3@ c #D3B389", "4@ c #CC9F69", "5@ c #B87F3B", "6@ c #BC823D", "7@ c #CEA16B", "8@ c #E8CBA5", "9@ c #C1975C", "0@ c #C09257", "a@ c #B9813E", "b@ c #BC8545", "c@ c #CDA06A", "d@ c #E6C9A3", "e@ c #D9B888", "f@ c #D3A676", "g@ c #BC8C4D", "h@ c #BE8A4D", "i@ c #BE8B4F", "j@ c #C79D60", "k@ c #E6C8A1", "l@ c #E1C39C", "m@ c #C2995F", "n@ c #D2AA77", "o@ c #D4A773", "p@ c #BF8A4C", "q@ c #B17330", "r@ c #331707", "s@ c #B2752D", "t@ c #C49A5D", "u@ c #B87E39", "v@ c #B37532", "w@ c #AF772E", "x@ c #AC742B", "y@ c #AA7229", "z@ c #AE7129", "A@ c #A96D26", "B@ c #A56922", "C@ c #A36720", "D@ c #A2651D", "E@ c #9E6119", "F@ c #9B5F18", "G@ c #995D16", "H@ c #925615", "I@ c #58300D", "J@ c #261105", "K@ c #311607", " ", " ", " ", " ", " . . . + . . . ", " . . + @ # $ % & * = + . . ", " . + - ; > , > ' ; ) ! ~ { + . ", " . ] $ , ^ / ) ( $ ! ! ! _ : < [ . ", " . } / , ; $ | 1 2 2 3 4 5 6 & 7 8 9 . ", " . 0 / , a 5 b c d . . . e - 6 f 5 g h i . ", " . + ! , % ~ j . . . { & 6 ~ h k + ", " . 8 , l ~ m . . n o f 1 p q . ", " + ; > & r s . . t u & r k + ", " v > a * w . s 5 ; x y z . ", " . # A | r B . C D 5 E F . ", " . _ > 3 r G H / ! r I . ", " . ) J K < . . % u L y . ", " . M l N O . . ( $ N P . ", " Q Q Q R S T U Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q V W X Y Q Q Q Q ", " Q Z ` ...+.@.#.$.%.&.*.=.-.-.-.-.-.=.=.-.;.;.>.,.'.).!.~.{.].Q ", " Q ^./.(.>._.:.<.[.}.|.1.2.3.3.3.3.3.3.3.4.5.6.7.8.9.0.a.b.c.d.Q ", " Q e.%.f.g.h.i.j.k.l.m.n.o.p.p.p.q.q.q.q.p.r.s.t.u.v.w.a.x.c.y.Q ", " Q ^.$.%.z.A.<.B.C.k.D.2.E.F.G.G.H.I.I.I.q.J.7.t.u.K.w.L.M.N.O.Q ", " Q e.(.P.Q.i.R.j.S.D.m.T.U.V.W.. W.X.n.3.Y.o.p.r.Z.u.`. +.+++@+Q ", " Q e.%.#+$+%+&+B.j.*+1.=+-+. . . . . ;+3.o.q.J.s.>+v.,+'+)+!+y.Q ", " Q ` P.~+{+i.j.j.]+^+2./+(+. . . . . _+:+4.5.p.J.Z.<+[+}+.+|+d.Q ", " Q e.1+2+Q.<.[.R.j.3+m.4+. . . . . . . 5+Y.p.J.6+>+<+7+a.8+c.y.Q ", " Q ` 9+0+a+[.}.j.]+1.b+/+W.. . . . . c+d+6.e+t.f+v.w.g+h+i+j+O.Q ", " Q e.1+2+{+i.k+l+1.b+n.q.m+. . . . . n+o+7.e+8.u.9. +p+.+q+r+s+Q ", " Q ^.(.t+$+A.u+u+[.k+*+1.2.-+_+. v+w+x+y+5.r.s.t.<+z+p+A+B+r+y.Q ", " Q ` t+~+_.C+]+l+D+b+4.p.r.E+. . . F+G+p.6.7.Z.t.<+[+w.H+8+I+s+Q ", " Q e.t+2+a+[.}.j.]+D.b+4.J+K+. . . L+p.p.6.e+Z.u.v. +'+M+N+O+O.Q ", " Q ^.(.t+P+A.<.[.C.*+m.Q+R+S+. . . T+d+p.r.e+t.f+U+ +'+M+M.V+O.Q ", " Q ` *.-.W+}.k+X+D.Y+3.q.Z+`+. . . @d+p.6.7.e+8.9.z+a..@B++@@@Q ", " Q .2+-.#@$@3+D.m.n.p.%@&@*@. . . =@-@;@7.Z.t.f+U+>@L.h+,@+@'@Q ", " Q ` )@-.A.$@l.1.b+4.p.!@~@*@. . . *@{@]@^@f+9.z+w.'+.@/@(@_@:@Q ", " Q ` 9+<@[@}.k.S.D.}@n.|@1@. . . . . 2@3@6.e+Z.>+9.K.g+L.B+4@s+Q ", " Q e.P.~+a+i.j.k+^+1.b+n.q.q.q.q.q.q.q.q.p.7.Z.8.v. +'+5@6@7@@@Q ", " Q ` 8@~+_.j.]+^+D+3.I.p.9@6+0@0@0@0@0@0@Z.8.u.U+z+a@L.5@b@c@O.Q ", " Q .d@;.e@f@l.1.}@3.5.q.p.r.6.6.p.p.q.q.p.s.6+t.g@U+h@p.i@j@@@Q ", " Q .k@l@u+3+1.m.n.o.m@7.0@Z.Z.0@7.9@q.4.m.m.7@7@k+n@3+o@p@q@:@Q ", " r@s@j@t@<+a.u@A+h+v@w@i+x@y@y@y@z@z@z@z@y@A@++B@C@D@E@F@G@H@I@J@ ", " K@Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q J@ ", " ", " ", " ", " ", " "}; balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/rfc2445.c000066400000000000000000001077071477646064400234440ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* * VCalendar (RFC 5545 and 5546) stuff * Copyright (C) 2009-2020 Albrecht Dreß * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include "libbalsa.h" #include "rfc2445.h" struct _LibBalsaVCal { GObject parent; /* method */ icalproperty_method method; /* VCALENDAR object */ icalcomponent *vcalendar; /* linked list of VEVENT entries */ GList *vevent; }; G_DEFINE_TYPE(LibBalsaVCal, libbalsa_vcal, G_TYPE_OBJECT) struct _LibBalsaVEvent { GObject parent; LibBalsaAddress *organizer; GList *attendee; icaltimetype stamp; icaltimetype start; icaltimetype end; icaltimetype recurrence_id; struct icaldurationtype duration; struct icalrecurrencetype rrule; icalproperty_status status; gchar *uid; int sequence; gchar *summary; gchar *location; gchar *description; GList *categories; }; G_DEFINE_TYPE(LibBalsaVEvent, libbalsa_vevent, G_TYPE_OBJECT) /* LibBalsaAddress extra object data */ typedef struct { icalparameter_role role; icalparameter_partstat part_stat; icalparameter_rsvp rsvp; } LibBalsaVCalInfo; #define RFC2445_INFO "RFC2445:Info" static void libbalsa_vcal_finalize(GObject *self); static void libbalsa_vevent_finalize(GObject *self); /* conversion helpers */ static LibBalsaVCal *vcalendar_extract(const gchar *vcal_buf); static LibBalsaAddress *cal_address_5545_to_lbaddress(icalproperty *prop, gboolean is_organizer); static const gchar *vcal_role_to_str(icalparameter_role role); static gchar *icaltime_str(icaltimetype ical_time, const gchar *format_str); /* --- VCal GObject stuff --- */ static void libbalsa_vcal_class_init(LibBalsaVCalClass *klass) { GObjectClass *gobject_klass = G_OBJECT_CLASS(klass); gobject_klass->finalize = libbalsa_vcal_finalize; } static void libbalsa_vcal_init(LibBalsaVCal *self) { self->method = ICAL_METHOD_NONE; } static void libbalsa_vcal_finalize(GObject *self) { LibBalsaVCal *vcal = LIBBALSA_VCAL(self); const GObjectClass *parent_class = G_OBJECT_CLASS(libbalsa_vcal_parent_class); if (vcal->vevent != NULL) { g_list_free_full(vcal->vevent, g_object_unref); } if (vcal->vcalendar != NULL) { icalcomponent_free(vcal->vcalendar); } (*parent_class->finalize)(self); } /* --- VEvent GObject stuff --- */ static void libbalsa_vevent_class_init(LibBalsaVEventClass * klass) { GObjectClass *gobject_klass = G_OBJECT_CLASS(klass); gobject_klass->finalize = libbalsa_vevent_finalize; } static void libbalsa_vevent_init(LibBalsaVEvent *self) { self->start = icaltime_null_time(); self->end = icaltime_null_time(); self->stamp = icaltime_null_time(); self->duration = icaldurationtype_null_duration(); self->rrule.freq = ICAL_NO_RECURRENCE; self->status = ICAL_STATUS_NONE; } static void libbalsa_vevent_finalize(GObject *self) { LibBalsaVEvent *vevent = LIBBALSA_VEVENT(self); const GObjectClass *parent_class = G_OBJECT_CLASS(libbalsa_vevent_parent_class); if (vevent->organizer) { g_object_unref(vevent->organizer); } if (vevent->attendee) { g_list_free_full(vevent->attendee, g_object_unref); } g_free(vevent->uid); g_free(vevent->summary); g_free(vevent->location); g_free(vevent->description); g_list_free_full(vevent->categories, g_free); (*parent_class->finalize)(self); } /* parse a text/calendar part and convert it into a LibBalsaVCal object */ LibBalsaVCal * libbalsa_vcal_new_from_body(LibBalsaMessageBody * body) { LibBalsaVCal *retval = NULL; gchar *vcal_buf; g_return_val_if_fail(body != NULL, NULL); /* get the body buffer */ if (libbalsa_message_body_get_content(body, &vcal_buf, NULL) > 0) { gchar *charset; /* check if the body has a charset (default is utf-8, see '2445, sect 4.1.4) */ charset = libbalsa_message_body_get_parameter(body, "charset"); if ((charset != NULL) && (g_ascii_strcasecmp(charset, "utf-8") != 0)) { gchar *conv_buf; conv_buf = g_convert(vcal_buf, -1, "utf-8", charset, NULL, NULL, NULL); g_free(vcal_buf); vcal_buf = conv_buf; } g_free(charset); if (vcal_buf != NULL) { /* o.k., create a new object */ retval = vcalendar_extract(vcal_buf); g_free(vcal_buf); } } return retval; } /* return a rfc 2445 attendee (i.e. a LibBalsaAddress w/ extra information) * as a human-readable string */ gchar * libbalsa_vcal_attendee_to_str(LibBalsaAddress *person) { GString *retval; gchar *str; LibBalsaVCalInfo *info; g_return_val_if_fail(LIBBALSA_IS_ADDRESS(person), NULL); retval = g_string_new(""); info = g_object_get_data(G_OBJECT(person), RFC2445_INFO); if (info->role != ICAL_ROLE_NONE) { g_string_printf(retval, "%s ", vcal_role_to_str(info->role)); } str = libbalsa_address_to_gchar(person, -1); retval = g_string_append(retval, str); g_free(str); if (info->part_stat != ICAL_PARTSTAT_NONE) { g_string_append_printf(retval, " (%s)", libbalsa_vcal_part_stat_to_str(info->part_stat)); } return g_string_free(retval, FALSE); } /* check if a rfc 2445 attendee (i.e. a LibBalsaAddress w/ extra information) * has the RSVP flag ("please reply") set */ gboolean libbalsa_vcal_attendee_rsvp(LibBalsaAddress * person) { LibBalsaVCalInfo *info; g_return_val_if_fail(LIBBALSA_IS_ADDRESS(person), FALSE); info = g_object_get_data(G_OBJECT(person), RFC2445_INFO); return info->rsvp == ICAL_RSVP_TRUE; } LibBalsaAddress * libbalsa_vevent_organizer(LibBalsaVEvent *event) { g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), NULL); return event->organizer; } const gchar * libbalsa_vevent_summary(LibBalsaVEvent *event) { g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), NULL); return event->summary; } const gchar * libbalsa_vevent_location(LibBalsaVEvent *event) { g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), NULL); return event->location; } const gchar * libbalsa_vevent_description(LibBalsaVEvent *event) { g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), NULL); return event->description; } gchar * libbalsa_vevent_time_str(LibBalsaVEvent *event, LibBalsaVEventTimestamp which, const gchar *format_str) { gchar *result = NULL; g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), NULL); switch (which) { case VEVENT_DATETIME_STAMP: result = icaltime_str(event->stamp, format_str); break; case VEVENT_DATETIME_START: result = icaltime_str(event->start, format_str); break; case VEVENT_DATETIME_END: result = icaltime_str(event->end, format_str); break; default: g_assert_not_reached(); } return result; } guint libbalsa_vevent_attendees(LibBalsaVEvent *event) { g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), 0U); return g_list_length(event->attendee); } LibBalsaAddress * libbalsa_vevent_attendee(LibBalsaVEvent *event, guint nth_attendee) { g_return_val_if_fail(LIBBALSA_IS_VEVENT(event) && (nth_attendee < g_list_length(event->attendee)), NULL); return (LibBalsaAddress *) g_list_nth_data(event->attendee, nth_attendee); } guint libbalsa_vevent_category_count(LibBalsaVEvent *event) { g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), 0U); return g_list_length(event->categories); } gchar * libbalsa_vevent_category_str(LibBalsaVEvent *event) { gchar *res = NULL; g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), NULL); if (event->categories != NULL) { GString *buffer; GList *p; buffer = g_string_new((const gchar *) event->categories->data); for (p = event->categories->next; p != NULL; p = p->next) { g_string_append_c(buffer, '\n'); g_string_append(buffer, (const gchar *) p->data); } res = g_string_free(buffer, FALSE); } return res; } gchar * libbalsa_vevent_duration_str(LibBalsaVEvent *event) { gchar *res = NULL; g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), NULL); if (icaldurationtype_is_null_duration(event->duration) == 0) { GString *buffer = g_string_new(NULL); if (event->duration.weeks > 0) { g_string_append_printf(buffer, "%d %s", event->duration.weeks, ngettext("week", "weeks", event->duration.weeks)); } if (event->duration.days > 0) { if (buffer->len > 0U) { g_string_append(buffer, ", "); } g_string_append_printf(buffer, "%d %s", event->duration.days, ngettext("day", "days", event->duration.days)); } if (event->duration.hours > 0) { if (buffer->len > 0U) { g_string_append(buffer, ", "); } g_string_append_printf(buffer, "%d %s", event->duration.hours, ngettext("hour", "hours", event->duration.hours)); } if (event->duration.minutes > 0) { if (buffer->len > 0U) { g_string_append_c(buffer, ' '); } g_string_append_printf(buffer, "%d %s", event->duration.minutes, ngettext("minute", "minutes", event->duration.minutes)); } if (event->duration.seconds > 0) { if (buffer->len > 0U) { g_string_append_c(buffer, ' '); } g_string_append_printf(buffer, "%d %s", event->duration.seconds, ngettext("second", "seconds", event->duration.seconds)); } res = g_string_free(buffer, FALSE); } return res; } icalproperty_status libbalsa_vevent_status(LibBalsaVEvent *event) { g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), ICAL_STATUS_NONE); return event->status; } const gchar * libbalsa_vevent_status_str(LibBalsaVEvent *event) { static struct { icalproperty_status status; gchar *status_str; } status[] = { { ICAL_STATUS_NONE, NC_("ical_status", "unknown") }, { ICAL_STATUS_TENTATIVE, NC_("ical_status", "event is tentative") }, { ICAL_STATUS_CONFIRMED, NC_("ical_status", "event is definite") }, { ICAL_STATUS_CANCELLED, NC_("ical_status", "event was cancelled") } }; guint n; g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), NULL); for (n = 0U; (n < G_N_ELEMENTS(status)) && (status[n].status != event->status); n++) { /* nothing to do */ } return (n < G_N_ELEMENTS(status)) ? status[n].status_str : status[0].status_str; } icalproperty_method libbalsa_vcal_method(LibBalsaVCal *vcal) { g_return_val_if_fail(LIBBALSA_IS_VCAL(vcal), ICAL_METHOD_NONE); return vcal->method; } const gchar * libbalsa_vcal_method_str(LibBalsaVCal *vcal) { static struct { icalproperty_method method; gchar *meth_str; } methods[] = { { ICAL_METHOD_NONE, NC_("ical_method", "unknown") }, { ICAL_METHOD_PUBLISH, NC_("ical_method", "Event Notification") }, { ICAL_METHOD_REQUEST, NC_("ical_method", "Event Request") }, { ICAL_METHOD_REPLY, NC_("ical_method", "Reply to Event Request") }, { ICAL_METHOD_CANCEL, NC_("ical_method", "Event Cancellation") } }; guint n; for (n = 0U; (n < G_N_ELEMENTS(methods)) && (methods[n].method != vcal->method); n++) { /* nothing to do */ } return (n < G_N_ELEMENTS(methods)) ? methods[n].meth_str : methods[0].meth_str; } /* return a rfc 2445 participant status as human-readable string */ const gchar * libbalsa_vcal_part_stat_to_str(icalparameter_partstat pstat) { static struct { icalparameter_partstat partstat; gchar *partstat_str; } partstats[] = { { ICAL_PARTSTAT_NONE, NC_("ical_partstat", "unknown") }, { ICAL_PARTSTAT_NEEDSACTION, NC_("ical_partstat", "needs action") }, { ICAL_PARTSTAT_ACCEPTED, NC_("ical_partstat", "accepted") }, { ICAL_PARTSTAT_DECLINED, NC_("ical_partstat", "declined") }, { ICAL_PARTSTAT_TENTATIVE, NC_("ical_partstat", "tentatively accepted") }, { ICAL_PARTSTAT_DELEGATED, NC_("ical_partstat", "delegated") } }; guint n; for (n = 0U; (n < G_N_ELEMENTS(partstats)) && (partstats[n].partstat != pstat); n++) { /* nothing to do */ } return (n < G_N_ELEMENTS(partstats)) ? partstats[n].partstat_str : partstats[0].partstat_str; } guint libbalsa_vcal_vevent_count(LibBalsaVCal *vcal) { g_return_val_if_fail(LIBBALSA_IS_VCAL(vcal), 0U); return g_list_length(vcal->vevent); } LibBalsaVEvent * libbalsa_vcal_vevent(LibBalsaVCal *vcal, guint nth_event) { g_return_val_if_fail(LIBBALSA_IS_VCAL(vcal) && (nth_event < g_list_length(vcal->vevent)), NULL); return (LibBalsaVEvent *) g_list_nth_data(vcal->vevent, nth_event); } /* -- recurrence strings -- * According to RFC 5545, Sect. 3.3.1, these rules can be extremely complex. The following functions basically implement the same * features als Thunderbird's "Lightning" extension, which should be fine for the majority of cases in the wild. However, there * /may/ (and will) be cases where these function just fail... */ static inline gboolean ical_ar_empty(const short *array) { return array[0] == ICAL_RECURRENCE_ARRAY_MAX; } static inline const gchar * day_name(gint day) { static const gchar * day_names[7] = { NC_("day_of_week", "Sunday"), NC_("day_of_week", "Monday"), NC_("day_of_week", "Tuesday"), NC_("day_of_week", "Wednesday"), NC_("day_of_week", "Thursday"), NC_("day_of_week", "Friday"), NC_("day_of_week", "Saturday") }; return ((day >= 0) && (day < 7)) ? day_names[day] : "???"; } /** \brief Check for "BYDAY" items in any order * * \param rrule recurrence rule * \param want_days bit mask of expected items in "BYDAY" (bit 1 = Sunday, bit 7 = Saturday) * \return TRUE if the "BYDAY" item contains exactly all requested week days in any order */ static gboolean ical_check_bydays(const struct icalrecurrencetype *rrule, guint want_days) { guint have_days = 0U; guint n; for (n = 0U; (n < ICAL_BY_DAY_SIZE) && (rrule->by_day[n] != ICAL_RECURRENCE_ARRAY_MAX); n++) { have_days |= (1U << rrule->by_day[n]); } return want_days == have_days; } static GString * vevent_recurrence_daily(const struct icalrecurrencetype *rrule) { GString *result = g_string_new(NULL); if (ical_check_bydays(rrule, 0x7cU)) { g_string_append(result, _("every weekday")); } else if (rrule->interval == 1) { g_string_append(result, _("every day")); } else { /* #1: interval */ g_string_append_printf(result, _("every %d days"), rrule->interval); } return result; } static GString * vevent_recurrence_weekly(const struct icalrecurrencetype *rrule) { GString *result = g_string_new(NULL); if (!ical_ar_empty(rrule->by_day)) { gint n; if (rrule->interval == 1) { g_string_append(result, _("every ")); } else { /* #1: interval */ g_string_append_printf(result, _("every %d weeks on "), rrule->interval); } g_string_append(result, day_name(rrule->by_day[0] - 1)); for (n = 1; (n < ICAL_BY_DAY_SIZE) && (rrule->by_day[n] != ICAL_RECURRENCE_ARRAY_MAX); n++) { if ((n < (ICAL_BY_DAY_SIZE - 1)) && (rrule->by_day[n + 1] != ICAL_RECURRENCE_ARRAY_MAX)) { g_string_append_printf(result, ", %s", day_name(rrule->by_day[n] - 1)); } else { /* #1: the day of week (defined in the day_of_week context) */ g_string_append_printf(result, _(" and %s"), day_name(rrule->by_day[n] - 1)); } } } else { if (rrule->interval == 1) { g_string_append(result, _("every week")); } else { /* #1: interval */ g_string_append_printf(result, _("every %d weeks"), rrule->interval); } } return result; } static void day_ordinal_append(GString *buffer, int day, const gchar *last_append, const gchar *ordinal_append) { if (day == -1) { g_string_append(buffer, _("the last")); if (last_append != NULL) { g_string_append_printf(buffer, " %s", last_append); } } else { switch (day % 10) { case 1: /* #1: the day of month */ g_string_append_printf(buffer, _("%dst"), day); break; case 2: /* #1: the day of month */ g_string_append_printf(buffer, _("%dnd"), day); break; case 3: /* #1: the day of month */ g_string_append_printf(buffer, _("%drd"), day); break; default: /* #1: the day of month */ g_string_append_printf(buffer, _("%dth"), day); } if (ordinal_append != NULL) { g_string_append_printf(buffer, " %s", ordinal_append); } } } static GString * vevent_recurrence_monthly(const struct icalrecurrencetype *rrule, const icaltimetype *start) { GString *result = g_string_new(NULL); if (!ical_ar_empty(rrule->by_day)) { /* we have a "BYDAY" rule */ if (ical_check_bydays(rrule, 0xfeU)) { if (rrule->interval == 1) { g_string_append(result, _("every day of every month")); } else { /* #1: interval */ g_string_append_printf(result, _("every day of the month every %d months"), rrule->interval); } return result; /* eject here so we don't append the month interval again... */ } else { guint n; guint every_mask = 0U; GList *days = NULL; GList *p; /* collect all days repeating every week */ for (n = 0U; (n < ICAL_BY_DAY_SIZE) && (rrule->by_day[n] != ICAL_RECURRENCE_ARRAY_MAX); n++) { int day_pos; day_pos = icalrecurrencetype_day_position(rrule->by_day[n]); if ((day_pos < -1) || (day_pos > 5)) { return g_string_assign(result, _("rule too complex")); } else if (day_pos == 0) { int day_of_week; day_of_week = icalrecurrencetype_day_day_of_week(rrule->by_day[n]); every_mask |= 1U << day_of_week; /* #1: the day of week (defined in the day_of_week context) */ days = g_list_append(days, g_strdup_printf(_("every %s"), day_name(day_of_week - 1))); } else { /* handled below... */ } } /* collect specific ones, but avoid something like "Monday and the last Monday" */ for (n = 0U; (n < ICAL_BY_DAY_SIZE) && (rrule->by_day[n] != ICAL_RECURRENCE_ARRAY_MAX); n++) { int day_of_week; day_of_week = icalrecurrencetype_day_day_of_week(rrule->by_day[n]); if ((every_mask & (1U << day_of_week)) == 0U) { int day_pos; GString *buffer = g_string_new(NULL); day_pos = icalrecurrencetype_day_position(rrule->by_day[n]); day_ordinal_append(buffer, day_pos, day_name(day_of_week - 1), day_name(day_of_week - 1)); days = g_list_append(days, g_string_free(buffer, FALSE)); } } /* glue the string together */ g_string_append(result, (const gchar *) days->data); for (p = days->next; p != NULL; p = p->next) { if (p->next != NULL) { g_string_append_printf(result, ", %s", (const gchar *) p->data); } else { /* #1: recurrence expression */ g_string_append_printf(result, _(" and %s"), (const gchar *) p->data); } } g_list_free_full(days, g_free); } } else if (!ical_ar_empty(rrule->by_month_day)) { /* we have a "BYMONTHDAY" rule */ guint n; for (n = 0; (n < ICAL_BY_MONTHDAY_SIZE) && (rrule->by_month_day[n] != ICAL_RECURRENCE_ARRAY_MAX); n++) { if (rrule->by_month_day[n] < -1) { return g_string_assign(result, _("rule too complex")); } else { if (n > 0) { if (rrule->by_month_day[n + 1] != ICAL_RECURRENCE_ARRAY_MAX) { g_string_append(result, ", "); } else { g_string_append(result, _(" and ")); } } day_ordinal_append(result, rrule->by_month_day[n], _("day"), NULL); } } } else { day_ordinal_append(result, start->day, _("day"), NULL); } if (rrule->interval == 1) { g_string_append(result, _(" of every month")); } else { /* #1: interval */ g_string_append_printf(result, _(" of every %d months"), rrule->interval); } return result; } static GString * vevent_recurrence_yearly(const struct icalrecurrencetype *rrule, const icaltimetype *start) { static const gchar *mon_name[12] = { NC_("name_of_month", "January"), NC_("name_of_month", "February"), NC_("name_of_month", "March"), NC_("name_of_month", "April"), NC_("name_of_month", "May"), NC_("name_of_month", "June"), NC_("name_of_month", "July"), NC_("name_of_month", "August"), NC_("name_of_month", "September"), NC_("name_of_month", "October"), NC_("name_of_month", "November"), NC_("name_of_month", "December") }; GString *result = g_string_new(NULL); /* rules which are too complex for Lightning, so ignore them here, too... */ if ((rrule->by_month[1] != ICAL_RECURRENCE_ARRAY_MAX) || (rrule->by_month_day[1] != ICAL_RECURRENCE_ARRAY_MAX) || (rrule->by_month_day[0] < -1)) { return g_string_assign(result, _("rule too complex")); } if (ical_ar_empty(rrule->by_day)) { /* RRULE:FREQ=YEARLY;BYMONTH=x;BYMONTHDAY=y. * RRULE:FREQ=YEARLY;BYMONTHDAY=x (takes the month from the start date) * RRULE:FREQ=YEARLY;BYMONTH=x (takes the day from the start date) * RRULE:FREQ=YEARLY (takes month and day from the start date) */ const gchar *month; GString *day = g_string_new(NULL); if (ical_ar_empty(rrule->by_month)) { month = mon_name[start->month - 1]; } else { month = mon_name[rrule->by_month[0] - 1]; } if (ical_ar_empty(rrule->by_month_day)) { day_ordinal_append(day, start->day, NULL, NULL); } else { day_ordinal_append(day, rrule->by_month_day[0], _("day"), NULL); } if (rrule->interval == 1) { /* #1: name of month (defined in the name_of_month context) */ /* #2: day of week (defined in the day_of_week context) */ g_string_append_printf(result, _("every %s %s"), month, day->str); } else { /* #1: interval */ /* #2: name of month (defined in the name_of_month context) */ /* #3: day of week (defined in the day_of_week context) */ g_string_append_printf(result, _("every %d years on %s %s"), rrule->interval, month, day->str); } g_string_free(day, TRUE); } else if (!ical_ar_empty(rrule->by_month) && !ical_ar_empty(rrule->by_day)) { /* RRULE:FREQ=YEARLY;BYMONTH=x;BYDAY=y1,y2,... */ const gchar *month = mon_name[rrule->by_month[0] - 1]; if (ical_check_bydays(rrule, 0x7cU)) { /* every day of the month */ if (rrule->interval == 1) { /* #1: name of month (defined in the name_of_month context) */ g_string_append_printf(result, _("every day of %s"), month); } else { /* #1: interval */ /* #2: name of month (defined in the name_of_month context) */ g_string_append_printf(result, _("every %d years every day of %s"), rrule->interval, month); } } else if (rrule->by_day[1] == ICAL_RECURRENCE_ARRAY_MAX) { int day_pos; int day_of_week; day_pos = icalrecurrencetype_day_position(rrule->by_day[0]); day_of_week = icalrecurrencetype_day_day_of_week(rrule->by_day[0]); if (day_pos == 0) { if (rrule->interval == 1) { /* #1: day of week (defined in the day_of_week context) */ /* #2: name of month (defined in the name_of_month context) */ g_string_append_printf(result, _("every %s of %s"), day_name(day_of_week - 1), month); } else { /* #1: interval */ /* #2: day of week (defined in the day_of_week context) */ /* #3: name of month (defined in the name_of_month context) */ g_string_append_printf(result, _("every %d years on every %s of %s"), rrule->interval, day_name(day_of_week - 1), month); } } else if ((day_pos >= -1) && (day_pos <= 5)) { GString *day = g_string_new(NULL); day_ordinal_append(day, day_pos, day_name(day_of_week - 1), day_name(day_of_week - 1)); if (rrule->interval == 1) { /* #1: day of week (defined in the day_of_week context) */ /* #2: name of month (defined in the name_of_month context) */ g_string_append_printf(result, _("the %s of every %s"), day->str, month); } else { /* #1: interval */ /* #2: day of week (defined in the day_of_week context) */ /* #3: name of month (defined in the name_of_month context) */ g_string_append_printf(result, _("every %d years on the %s of %s"), rrule->interval, day->str, month); } g_string_free(day, TRUE); } else { g_string_assign(result, _("rule too complex")); } } else { /* currently we don't support yearly rules with more than one BYDAY element or exactly 7 elements with all the weekdays * (the "every day" case) */ g_string_assign(result, _("rule too complex")); } } else { return g_string_assign(result, _("rule too complex")); } return result; } gchar * libbalsa_vevent_recurrence_str(LibBalsaVEvent *event, const gchar *format_str) { gchar *result = NULL; g_return_val_if_fail(LIBBALSA_IS_VEVENT(event), NULL); if ((event->rrule.freq >= ICAL_SECONDLY_RECURRENCE) && (event->rrule.freq <= ICAL_YEARLY_RECURRENCE)) { GString *buffer; switch (event->rrule.freq) { case ICAL_SECONDLY_RECURRENCE: buffer = g_string_new(C_("ical_recurrence", "secondly")); break; case ICAL_MINUTELY_RECURRENCE: buffer = g_string_new(C_("ical_recurrence", "minutely")); break; case ICAL_HOURLY_RECURRENCE: buffer = g_string_new(C_("ical_recurrence", "hourly")); break; case ICAL_DAILY_RECURRENCE: buffer = vevent_recurrence_daily(&event->rrule); break; case ICAL_WEEKLY_RECURRENCE: buffer = vevent_recurrence_weekly(&event->rrule); break; case ICAL_MONTHLY_RECURRENCE: buffer = vevent_recurrence_monthly(&event->rrule, &event->start); break; case ICAL_YEARLY_RECURRENCE: buffer = vevent_recurrence_yearly(&event->rrule, &event->start); break; default: g_assert_not_reached(); } /* end timestamp or count */ if (event->rrule.count > 0) { g_string_append(buffer, ngettext(", %d occurrence", ", %d occurrences", event->rrule.count)); } else if (icaltime_is_null_time(event->rrule.until) == 0) { gchar *timestr; timestr = icaltime_str(event->rrule.until, format_str); /* #1: time string */ g_string_append_printf(buffer, _(" until %s"), timestr); g_free(timestr); } else { /* nothing to do */ } result = g_string_free(buffer, FALSE); } return result; } /* return a new buffer containing a proper reply to an event for a new * participant status * * According to RFC 5546, Sect. 3.2.3., the REPLY shall include the following components and properties: * METHOD: MUST be REPLY * VEVENT: ATTENDEE, DTSTAMP, ORGANIZER, RECURRENCE-ID (if present in the request), UID, SEQUENCE (if present in the request) * * However, M$ Outlook/Exchange is broken and does not process these standard-compliant parts correctly. The trivial fix is to add * several optional fields (I did not figure out which are needed to work around the issue, so we just add them all...). */ gchar * libbalsa_vevent_reply(const LibBalsaVEvent *event, InternetAddress *sender, icalparameter_partstat new_stat) { icalcomponent *reply; icalcomponent *ev_data; icalproperty *prop; gchar *buf; gchar *reply_str; /* check for allowed new state and sender */ g_return_val_if_fail((new_stat == ICAL_PARTSTAT_ACCEPTED || new_stat == ICAL_PARTSTAT_DECLINED || new_stat == ICAL_PARTSTAT_TENTATIVE) && sender != NULL, NULL); reply = icalcomponent_new(ICAL_VCALENDAR_COMPONENT); icalcomponent_add_property(reply, icalproperty_new_version("2.0")); icalcomponent_add_property(reply, icalproperty_new_prodid("-//GNOME//Balsa " BALSA_VERSION "//EN")); icalcomponent_add_property(reply, icalproperty_new_method(ICAL_METHOD_REPLY)); /* create the VEVENT */ ev_data = icalcomponent_new(ICAL_VEVENT_COMPONENT); icalcomponent_add_component(reply, ev_data); /* add ATTENDEE */ buf = g_strconcat("mailto:", internet_address_mailbox_get_addr(INTERNET_ADDRESS_MAILBOX(sender)), NULL); prop = icalproperty_new_attendee(buf); g_free(buf); icalproperty_add_parameter(prop, icalparameter_new_cn(internet_address_get_name(sender))); icalproperty_add_parameter(prop, icalparameter_new_partstat(new_stat)); icalcomponent_add_property(ev_data, prop); /* add DTSTAMP */ icalcomponent_add_property(ev_data, icalproperty_new_dtstamp(icaltime_current_time_with_zone(NULL))); /* add ORGANIZER - /should/ be present */ if ((event->organizer != NULL) && (libbalsa_address_get_addr(event->organizer) != NULL)) { prop = icalproperty_new_organizer(libbalsa_address_get_addr(event->organizer)); if (libbalsa_address_get_full_name(event->organizer) != NULL) { icalproperty_add_parameter(prop, icalparameter_new_cn(libbalsa_address_get_full_name(event->organizer))); } icalcomponent_add_property(ev_data, prop); } /* add RECURRENCE-ID (if present) */ if (icaltime_is_null_time(event->recurrence_id) == 0) { icalcomponent_add_property(ev_data, icalproperty_new_recurrenceid(event->recurrence_id)); } /* add UID - /should/ be present */ if (event->uid != NULL) { icalcomponent_add_property(ev_data, icalproperty_new_uid(event->uid)); } /* add SEQUENCE (if present) */ if (event->sequence > 0) { icalcomponent_add_property(ev_data, icalproperty_new_sequence(event->sequence)); } /* the following fields are *optional* in a reply according to RFC 5546, Sect. 3.2.3, but are apparently required by broken * software like Exchange/Outlook */ if (icaltime_is_null_time(event->start) == 0) { icalcomponent_add_property(ev_data, icalproperty_new_dtstart(event->start)); } if (icaltime_is_null_time(event->end) == 0) { icalcomponent_add_property(ev_data, icalproperty_new_dtend(event->end)); } if (event->summary != NULL) { icalcomponent_add_property(ev_data, icalproperty_new_summary(event->summary)); } if (event->description != NULL) { icalcomponent_add_property(ev_data, icalproperty_new_description(event->description)); } if (event->status != ICAL_STATUS_NONE) { icalcomponent_add_property(ev_data, icalproperty_new_status(event->status)); } if (event->location != NULL) { icalcomponent_add_property(ev_data, icalproperty_new_location(event->location)); } reply_str = icalcomponent_as_ical_string_r(reply); icalcomponent_free(reply); return reply_str; } /* -- rfc 2445 parser helper functions -- */ static LibBalsaVCal * vcalendar_extract(const gchar *vcal_buf) { LibBalsaVCal *retval = NULL; icalcomponent *component; component = icalparser_parse_string(vcal_buf); if (component == NULL) { return NULL; } /* verify - icalrestriction_check() seems to produce False Positives for some Thunderbird events, so do *not* use it here */ if (icalcomponent_isa(component) == ICAL_VCALENDAR_COMPONENT) { icalcomponent *item; retval = LIBBALSA_VCAL(g_object_new(LIBBALSA_TYPE_VCAL, NULL)); retval->method = icalcomponent_get_method(component); retval->vcalendar = component; /* loop over all VEVENT items (if any) */ for (item = icalcomponent_get_first_component(component, ICAL_VEVENT_COMPONENT); item != NULL; item = icalcomponent_get_next_component(component, ICAL_VEVENT_COMPONENT)) { LibBalsaVEvent *event; icalproperty *prop; event = LIBBALSA_VEVENT(g_object_new(LIBBALSA_TYPE_VEVENT, NULL)); retval->vevent = g_list_append(retval->vevent, event); /* extract properties - DTSTAMP, DTSTART, DTEND * note: there is no need to get the DURATION, as libical calculates the proper DTEND if necessary. However, in * particular for all-day events, the duration is sometimes easier to understand than the (exclusive) end. */ event->stamp = icalcomponent_get_dtstamp(item); event->start = icalcomponent_get_dtstart(item); event->end = icalcomponent_get_dtend(item); event->duration = icalcomponent_get_duration(item); if (icaldurationtype_is_bad_duration(event->duration)) { event->duration = icaldurationtype_null_duration(); } /* RECURRENCE-ID */ event->recurrence_id = icalcomponent_get_recurrenceid(item); /* STATUS */ event->status = icalcomponent_get_status(item); if (event->status == (icalproperty_status) 0) { event->status = ICAL_STATUS_NONE; } /* RRULE (only one is allowed, see RFC 5546, Sect. 3.2.2) */ prop = icalcomponent_get_first_property(item, ICAL_RRULE_PROPERTY); if (prop != NULL) { event->rrule = icalproperty_get_rrule(prop); } /* UID, SUMMARY, LOCATION, DESCRIPTION */ event->uid = g_strdup(icalcomponent_get_uid(item)); event->summary = g_strdup(icalcomponent_get_summary(item)); event->location = g_strdup(icalcomponent_get_location(item)); event->description = g_strdup(icalcomponent_get_description(item)); /* ORGANIZER */ prop = icalcomponent_get_first_property(item, ICAL_ORGANIZER_PROPERTY); if (prop != NULL) { event->organizer = cal_address_5545_to_lbaddress(prop, TRUE); } /* ATTENDEE */ for (prop = icalcomponent_get_first_property(item, ICAL_ATTENDEE_PROPERTY); prop != NULL; prop = icalcomponent_get_next_property(item, ICAL_ATTENDEE_PROPERTY)) { LibBalsaAddress *attendee; attendee = cal_address_5545_to_lbaddress(prop, FALSE); if (attendee != NULL) { event->attendee = g_list_prepend(event->attendee, attendee); } } /* SEQUENCE (if present) */ event->sequence = icalcomponent_get_sequence(item); /* CATEGORIES */ for (prop = icalcomponent_get_first_property(item, ICAL_CATEGORIES_PROPERTY); prop != NULL; prop = icalcomponent_get_next_property(item, ICAL_CATEGORIES_PROPERTY)) { event->categories = g_list_append(event->categories, g_strdup(icalproperty_get_categories(prop))); } } } return retval; } /* extract a rfc 5545 mailto address and into a LibBalsaAddress and add the * rfc 5545 attributes as data to the returned object. */ static LibBalsaAddress * cal_address_5545_to_lbaddress(icalproperty *prop, gboolean is_organizer) { const gchar *uri; LibBalsaAddress *retval = NULL; if (is_organizer) { uri = icalproperty_get_organizer(prop); } else { uri = icalproperty_get_attendee(prop); } /* must be a mailto: uri */ if (g_ascii_strncasecmp("mailto:", uri, 7) == 0) { LibBalsaVCalInfo *info; icalparameter *param; retval = libbalsa_address_new(); libbalsa_address_append_addr(retval, &uri[7]); info = g_new0(LibBalsaVCalInfo, 1); g_object_set_data_full(G_OBJECT(retval), RFC2445_INFO, info, g_free); if (!is_organizer) { info->role = ICAL_ROLE_REQPARTICIPANT; } else { info->role = ICAL_ROLE_NONE; } info->part_stat = ICAL_PARTSTAT_NONE; info->rsvp = ICAL_RSVP_NONE; for (param = icalproperty_get_first_parameter(prop, ICAL_ANY_PARAMETER); param != NULL; param = icalproperty_get_next_parameter(prop, ICAL_ANY_PARAMETER)) { switch (icalparameter_isa(param)) { case ICAL_CN_PARAMETER: libbalsa_address_set_full_name(retval, icalparameter_get_cn(param)); break; case ICAL_PARTSTAT_PARAMETER: info->part_stat = icalparameter_get_partstat(param); break; case ICAL_ROLE_PARAMETER: info->role = icalparameter_get_role(param); break; case ICAL_RSVP_PARAMETER: info->rsvp = icalparameter_get_rsvp(param); break; default: /* nothing to do, make gcc happy */ break; } } } return retval; } /* return a rfc 2445 role as human-readable string */ static const gchar * vcal_role_to_str(icalparameter_role role) { static struct { icalparameter_role role; gchar *role_str; } roles[] = { { ICAL_ROLE_NONE, NC_("ical_role", "unknown") }, { ICAL_ROLE_CHAIR, NC_("ical_role", "chair") }, { ICAL_ROLE_REQPARTICIPANT, NC_("ical_role", "required participant") }, { ICAL_ROLE_OPTPARTICIPANT, NC_("ical_role", "optional participant") }, { ICAL_ROLE_NONPARTICIPANT, NC_("ical_role", "non-participant, information only") } }; guint n; for (n = 0U; (n < G_N_ELEMENTS(roles)) && (roles[n].role != role); n++) { /* nothing to do */ } return (n < G_N_ELEMENTS(roles)) ? roles[n].role_str : roles[0].role_str; } static gchar * icaltime_str(icaltimetype ical_time, const gchar *format_str) { gchar *result = NULL; if (icaltime_is_null_time(ical_time) == 0) { time_t unix_time; unix_time = icaltime_as_timet_with_zone(ical_time, ical_time.zone); if (ical_time.is_date == 0) { result = libbalsa_date_to_utf8(unix_time, format_str); } else { result = libbalsa_date_to_utf8(unix_time, "%x"); } } return result; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/rfc2445.h000066400000000000000000000061671477646064400234470ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* * VCalendar (RFC 5545 and 5546) stuff * Copyright (C) 2009-2020 Albrecht Dreß * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __RFC2445_H__ #define __RFC2445_H__ #include #include #include #include #include "body.h" #include "address.h" G_BEGIN_DECLS /* a VCalendar object description as GObject */ #define LIBBALSA_TYPE_VCAL (libbalsa_vcal_get_type()) G_DECLARE_FINAL_TYPE(LibBalsaVCal, libbalsa_vcal, LIBBALSA, VCAL, GObject) /* a VEvent object description as GObject */ #define LIBBALSA_TYPE_VEVENT (libbalsa_vevent_get_type()) G_DECLARE_FINAL_TYPE(LibBalsaVEvent, libbalsa_vevent, LIBBALSA, VEVENT, GObject) typedef enum { VEVENT_DATETIME_STAMP, VEVENT_DATETIME_START, VEVENT_DATETIME_END } LibBalsaVEventTimestamp; LibBalsaVCal *libbalsa_vcal_new_from_body(LibBalsaMessageBody * body); gchar *libbalsa_vevent_reply(const LibBalsaVEvent *event, InternetAddress *sender, icalparameter_partstat new_stat); gchar *libbalsa_vcal_attendee_to_str(LibBalsaAddress *person); gboolean libbalsa_vcal_attendee_rsvp(LibBalsaAddress *person); icalproperty_method libbalsa_vcal_method(LibBalsaVCal *vcal); const gchar *libbalsa_vcal_method_str(LibBalsaVCal *vcal); const gchar *libbalsa_vcal_part_stat_to_str(icalparameter_partstat pstat); guint libbalsa_vcal_vevent_count(LibBalsaVCal *vcal); LibBalsaVEvent *libbalsa_vcal_vevent(LibBalsaVCal *vcal, guint nth_event); LibBalsaAddress *libbalsa_vevent_organizer(LibBalsaVEvent *event); const gchar *libbalsa_vevent_summary(LibBalsaVEvent *event); const gchar *libbalsa_vevent_location(LibBalsaVEvent *event); const gchar *libbalsa_vevent_description(LibBalsaVEvent *event); icalproperty_status libbalsa_vevent_status(LibBalsaVEvent *event); gchar *libbalsa_vevent_time_str(LibBalsaVEvent *event, LibBalsaVEventTimestamp which, const gchar *format_str); guint libbalsa_vevent_attendees(LibBalsaVEvent *event); LibBalsaAddress *libbalsa_vevent_attendee(LibBalsaVEvent *event, guint nth_attendee); guint libbalsa_vevent_category_count(LibBalsaVEvent *event); gchar *libbalsa_vevent_category_str(LibBalsaVEvent *event); gchar *libbalsa_vevent_duration_str(LibBalsaVEvent *event); const gchar *libbalsa_vevent_status_str(LibBalsaVEvent *event); gchar *libbalsa_vevent_recurrence_str(LibBalsaVEvent *event, const gchar *format_str); G_END_DECLS #endif /* __RFC2445_H__ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/rfc3156.c000066400000000000000000000407561477646064400234440ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "rfc3156.h" #include #include #include "libbalsa.h" #include "libbalsa_private.h" #include "libbalsa-gpgme-widgets.h" #include "libbalsa-gpgme-keys.h" #include "libbalsa-gpgme.h" #include "gmime-multipart-crypt.h" #include "gmime-gpgme-signature.h" #include "gmime-part-rfc2440.h" #include "gmime-application-pkcs7.h" #include #ifdef G_LOG_DOMAIN # undef G_LOG_DOMAIN #endif #define G_LOG_DOMAIN "crypto" /* ==== public functions =================================================== */ /* return TRUE if we can encrypt for every recipient in the recipients list * using protocol */ gboolean libbalsa_can_encrypt_for_all(InternetAddressList * recipients, gpgme_protocol_t protocol) { gpgme_ctx_t gpgme_ctx; gboolean result; /* silent paranoia checks */ if (!recipients) return TRUE; /* we can of course encrypt for nobody... */ /* create the gpgme context and set the protocol */ gpgme_ctx = libbalsa_gpgme_new_with_proto(protocol, NULL, NULL, NULL); if (gpgme_ctx == NULL) { result = FALSE; } else { /* loop over all recipients and try to find valid keys */ result = libbalsa_gpgme_have_all_keys(gpgme_ctx, recipients, NULL); gpgme_release(gpgme_ctx); } return result; } /* === RFC 2633/ RFC 3156 crypto routines === */ /* * Signs the MIME object *content with the private key of rfc822_for using * protocol. Return TRUE on success (in which case *content is replaced by the * new MIME object). * Note: In RFC 2633 mode (GPGME_PROTOCOL_CMS), this function creates a * multipart/signed instead of an application/pkcs7-mime, as the latter one * doesn't contain a cleartext also readable for MUA's without S/MIME support. */ gboolean libbalsa_sign_mime_object(GMimeObject ** content, const gchar * rfc822_for, gpgme_protocol_t protocol, GtkWindow * parent, GError ** error) { GMimeMultipartSigned *mps; /* paranoia checks */ g_return_val_if_fail(rfc822_for != NULL, FALSE); g_return_val_if_fail(content != NULL, FALSE); /* call gpgme to create the signature */ if (!(mps = g_mime_multipart_signed_new())) { return FALSE; } if (!g_mime_gpgme_mps_sign(mps, *content, rfc822_for, protocol, parent, error)) { g_object_unref(mps); return FALSE; } g_object_unref(*content); *content = GMIME_OBJECT(mps); return TRUE; } /* * Encrypts MIME object *content for every recipient in the array rfc822_for * using protocol. If successful, return TRUE and replace *content by the new * MIME object. */ gboolean libbalsa_encrypt_mime_object(GMimeObject ** content, GList * rfc822_for, gpgme_protocol_t protocol, gboolean always_trust, GtkWindow * parent, GError ** error) { GMimeObject *encrypted_obj = NULL; GPtrArray *recipients; gboolean result = FALSE; /* paranoia checks */ g_return_val_if_fail(rfc822_for != NULL, FALSE); g_return_val_if_fail(content != NULL, FALSE); /* convert the key list to a GPtrArray */ recipients = g_ptr_array_new(); while (rfc822_for) { g_ptr_array_add(recipients, rfc822_for->data); rfc822_for = g_list_next(rfc822_for); } /* encrypt: multipart/encrypted for RFC 3156, application/pkcs7-mime for RFC 2633 */ if (protocol == GPGME_PROTOCOL_OpenPGP) { GMimeMultipartEncrypted *mpe = g_mime_multipart_encrypted_new(); encrypted_obj = GMIME_OBJECT(mpe); result = g_mime_gpgme_mpe_encrypt(mpe, *content, recipients, always_trust, parent, error); } else { GMimePart *pkcs7 = g_mime_part_new_with_type("application", "pkcs7-mime"); encrypted_obj = GMIME_OBJECT(pkcs7); result = g_mime_application_pkcs7_encrypt(pkcs7, *content, recipients, always_trust, parent, error); } g_ptr_array_unref(recipients); /* error checking */ if (!result) { g_object_unref(encrypted_obj); } else { g_object_unref(*content); *content = GMIME_OBJECT(encrypted_obj); } return result; } /* * Signs the MIME object *content with the private key of rfc822_signer and * then encrypt the result for all recipients in rfc822_for using protocol. * Return TRUE on success (in which case *content is replaced by the new * MIME object). */ gboolean libbalsa_sign_encrypt_mime_object(GMimeObject ** content, const gchar * rfc822_signer, GList * rfc822_for, gpgme_protocol_t protocol, gboolean always_trust, GtkWindow * parent, GError ** error) { GMimeObject *signed_object; /* paranoia checks */ g_return_val_if_fail(rfc822_signer != NULL, FALSE); g_return_val_if_fail(rfc822_for != NULL, FALSE); g_return_val_if_fail(content != NULL, FALSE); /* we want to be able to restore */ signed_object = g_object_ref(*content); if (!libbalsa_sign_mime_object(&signed_object, rfc822_signer, protocol, parent, error)) return FALSE; if (!libbalsa_encrypt_mime_object(&signed_object, rfc822_for, protocol, always_trust, parent, error)) { g_object_unref(signed_object); return FALSE; } g_object_unref(*content); *content = signed_object; return TRUE; } /* * Check the signature of body (which must be a multipart/signed). On * success, set the sig_info field of the signature part. It succeeds * if all the data needed to verify the signature (gpg database, the * complete signed part itself) were available and the verification * was attempted. Please observe that failure means in this context a * temporary one. Information about failed signature verifications are * passed through LibBalsaBody::sig_info. */ gboolean libbalsa_body_check_signature(LibBalsaMessageBody * body, gpgme_protocol_t protocol) { LibBalsaMailbox *mailbox; GError *error = NULL; GMimeGpgmeSigstat *result; /* paranoia checks */ g_return_val_if_fail(body, FALSE); g_return_val_if_fail(body->mime_part != NULL, FALSE); g_return_val_if_fail(body->message, FALSE); /* check if the body is really a multipart/signed */ if (!GMIME_IS_MULTIPART_SIGNED(body->mime_part) || (g_mime_multipart_get_count (GMIME_MULTIPART(body->mime_part)) < 2)) return FALSE; if (body->parts->next->sig_info) g_object_unref(body->parts->next->sig_info); /* verify the signature */ mailbox = libbalsa_message_get_mailbox(body->message); libbalsa_mailbox_lock_store(mailbox); result = g_mime_gpgme_mps_verify(GMIME_MULTIPART_SIGNED(body->mime_part), &error); if (!result) { if (error) { libbalsa_information(LIBBALSA_INFORMATION_ERROR, "%s: %s", _("signature verification failed"), error->message); g_error_free(error); } else libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("signature verification failed")); } body->parts->next->sig_info = result; libbalsa_mailbox_unlock_store(mailbox); return TRUE; } /* * Body points to an application/pgp-encrypted body. If decryption is * successful, it is freed, and the routine returns a pointer to the chain of * decrypted bodies. Otherwise, the original body is returned. */ LibBalsaMessageBody * libbalsa_body_decrypt(LibBalsaMessageBody *body, gpgme_protocol_t protocol, GtkWindow *parent) { LibBalsaMailbox *mailbox; GMimeObject *mime_obj = NULL; GError *error = NULL; LibBalsaMessage *message; GMimeGpgmeSigstat *sig_state = NULL; gboolean smime_encrypted = FALSE; /* paranoia checks */ g_return_val_if_fail(body != NULL, body); g_return_val_if_fail(body->mime_part != NULL, body); g_return_val_if_fail(body->message != NULL, body); /* sanity checks... */ if (protocol == GPGME_PROTOCOL_OpenPGP) { if (!GMIME_IS_MULTIPART_ENCRYPTED(body->mime_part)) return body; } else { const char * smime_type = g_mime_object_get_content_type_parameter(body->mime_part, "smime-type"); if (!smime_type || !GMIME_IS_PART(body->mime_part)) return body; if (!g_ascii_strcasecmp(smime_type, "enveloped-data")) smime_encrypted = TRUE; else smime_encrypted = body->was_encrypted; } mailbox = libbalsa_message_get_mailbox(body->message); libbalsa_mailbox_lock_store(mailbox); if (protocol == GPGME_PROTOCOL_OpenPGP) { mime_obj = g_mime_gpgme_mpe_decrypt(GMIME_MULTIPART_ENCRYPTED(body->mime_part), &sig_state, parent, &error); } else { mime_obj = g_mime_application_pkcs7_decrypt_verify(GMIME_PART(body->mime_part), &sig_state, parent, &error); } libbalsa_mailbox_unlock_store(mailbox); /* check the result */ if (mime_obj == NULL) { if (error) { if (error->code != GPG_ERR_CANCELED) libbalsa_information(LIBBALSA_INFORMATION_ERROR, "%s: %s", _("decryption failed"), error->message); g_error_free(error); } else libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("decryption failed")); return body; } message = body->message; libbalsa_message_body_free(body); body = libbalsa_message_body_new(message); /* remember that is was encrypted */ if (protocol == GPGME_PROTOCOL_OpenPGP) { body->was_encrypted = TRUE; } else { body->was_encrypted = smime_encrypted; } if (body->was_encrypted) libbalsa_message_set_crypt_mode(body->message, LIBBALSA_PROTECT_ENCRYPT); libbalsa_message_body_set_mime_body(body, mime_obj); if (sig_state) { if (g_mime_gpgme_sigstat_status(sig_state) != GPG_ERR_NOT_SIGNED) body->sig_info = sig_state; else g_object_unref(sig_state); } return body; } /* routines dealing with RFC2440 */ gboolean libbalsa_rfc2440_sign_encrypt(GMimePart *part, const gchar *sign_for, GList *encrypt_for, gboolean always_trust, GtkWindow *parent, GError **error) { GPtrArray *recipients; gboolean result; /* paranoia checks */ g_return_val_if_fail(part != NULL, FALSE); g_return_val_if_fail(sign_for != NULL || encrypt_for != NULL, FALSE); /* convert the key list to a GPtrArray */ if (encrypt_for) { recipients = g_ptr_array_new(); while (encrypt_for) { g_ptr_array_add(recipients, encrypt_for->data); encrypt_for = g_list_next(encrypt_for); } } else recipients = NULL; /* sign and/or encrypt */ result = g_mime_part_rfc2440_sign_encrypt(part, sign_for, recipients, always_trust, parent, error); /* clean up */ if (recipients) g_ptr_array_unref(recipients); return result; } /* * Check the signature of part and return the result of the crypto process. If * sig_info is not NULL, return the signature info object there. */ gpgme_error_t libbalsa_rfc2440_verify(GMimePart * part, GMimeGpgmeSigstat ** sig_info) { GMimeGpgmeSigstat *result; GError *error = NULL; gpgme_error_t retval; /* paranoia checks */ g_return_val_if_fail(part != NULL, FALSE); /* free any old signature */ if (sig_info && *sig_info) { g_object_unref(*sig_info); *sig_info = NULL; } /* verify */ result = g_mime_part_rfc2440_verify(part, &error); if (!result) { if (error) { libbalsa_information(LIBBALSA_INFORMATION_ERROR, "%s: %s", _("signature verification failed"), error->message); retval = error->code; g_error_free(error); } else { libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("signature verification failed")); retval = GPG_ERR_GENERAL; } } else retval = g_mime_gpgme_sigstat_status(result); /* return the signature info if requested */ if (result) { if (sig_info) *sig_info = result; else g_object_unref(result); } return retval; } /* * Decrypt part, if possible check the signature, and return the result of the * crypto process. If sig_info is not NULL and the part is signed, return the * signature info object there. */ gpgme_error_t libbalsa_rfc2440_decrypt(GMimePart * part, GMimeGpgmeSigstat ** sig_info, GtkWindow * parent) { GError *error = NULL; GMimeGpgmeSigstat *result; gpgme_error_t retval; /* paranoia checks */ g_return_val_if_fail(part != NULL, FALSE); /* free any old signature */ if (sig_info && *sig_info) { g_object_unref(*sig_info); *sig_info = NULL; } /* decrypt */ result = g_mime_part_rfc2440_decrypt(part, parent, &error); if (result == NULL) { if (error) { if (error->code != GPG_ERR_CANCELED) libbalsa_information(LIBBALSA_INFORMATION_ERROR, "%s: %s", _("decryption and signature verification failed"), error->message); retval = error->code; g_error_free(error); } else { libbalsa_information(LIBBALSA_INFORMATION_ERROR, _ ("decryption and signature verification failed")); retval = GPG_ERR_GENERAL; } } else { if (g_mime_gpgme_sigstat_status(result) == GPG_ERR_NOT_SIGNED) retval = GPG_ERR_NO_ERROR; else retval = g_mime_gpgme_sigstat_status(result); /* return the signature info if requested */ if (sig_info && g_mime_gpgme_sigstat_status(result) != GPG_ERR_NOT_SIGNED) *sig_info = result; else g_object_unref(result); } return retval; } /* conversion of status values to human-readable messages */ gchar * libbalsa_gpgme_sig_stat_to_gchar(gpgme_error_t stat) { switch (stat) { case GPG_ERR_NO_ERROR: return g_strdup(_("The signature is valid.")); case GPG_ERR_SIG_EXPIRED: return g_strdup(_("The signature is valid but expired.")); case GPG_ERR_KEY_EXPIRED: return g_strdup(_("The signature is valid but the key used to verify the signature has expired.")); case GPG_ERR_CERT_REVOKED: return g_strdup(_("The signature is valid but the key used to verify the signature has been revoked.")); case GPG_ERR_BAD_SIGNATURE: return g_strdup(_("The signature is invalid.")); case GPG_ERR_NO_PUBKEY: return g_strdup(_("The signature could not be verified due to a missing key.")); case GPG_ERR_NO_DATA: return g_strdup(_("This part is not a real signature.")); case GPG_ERR_INV_ENGINE: return g_strdup(_("The signature could not be verified due to an invalid crypto engine.")); case GPG_ERR_MULT_SIGNATURES: return g_strdup(_("The signature contains multiple signers, this may be a forgery.")); default: { gchar errbuf[4096]; /* should be large enough... */ gpgme_strerror_r(stat, errbuf, sizeof(errbuf)); if (gpgme_err_source(stat) != GPG_ERR_SOURCE_UNKNOWN) { /* Translators: #1 error source; #2 error message */ return g_strdup_printf(_("An error prevented the signature verification: %s: %s"), gpgme_strsource(stat), errbuf); } else { /* Translators: #1 error message */ return g_strdup_printf(_("An error prevented the signature verification: %s"), errbuf); } } } } const gchar * libbalsa_gpgme_validity_to_gchar(gpgme_validity_t validity) { switch (validity) { case GPGME_VALIDITY_UNKNOWN: return _("The user ID is of unknown validity."); case GPGME_VALIDITY_UNDEFINED: return _("The validity of the user ID is undefined."); case GPGME_VALIDITY_NEVER: return _("The user ID is never valid."); case GPGME_VALIDITY_MARGINAL: return _("The user ID is marginally valid."); case GPGME_VALIDITY_FULL: return _("The user ID is fully valid."); case GPGME_VALIDITY_ULTIMATE: return _("The user ID is ultimately valid."); default: return _("bad validity"); } } const gchar * libbalsa_gpgme_validity_to_gchar_short(gpgme_validity_t validity) { switch (validity) { case GPGME_VALIDITY_UNKNOWN: return _("unknown"); case GPGME_VALIDITY_UNDEFINED: return _("undefined"); case GPGME_VALIDITY_NEVER: return _("never"); case GPGME_VALIDITY_MARGINAL: return _("marginal"); case GPGME_VALIDITY_FULL: return _("full"); case GPGME_VALIDITY_ULTIMATE: return _("ultimate"); default: return _("bad validity"); } } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/rfc3156.h000066400000000000000000000054621477646064400234440ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __RFC3156_H__ #define __RFC3156_H__ #include #include "libbalsa.h" #include "misc.h" #include "gmime-gpgme-signature.h" gboolean libbalsa_can_encrypt_for_all(InternetAddressList * recipients, gpgme_protocol_t protocol); /* routines dealing with RFC 2633 and RFC 3156 stuff */ gboolean libbalsa_sign_mime_object(GMimeObject ** content, const gchar * rfc822_for, gpgme_protocol_t protocol, GtkWindow * parent, GError ** error); gboolean libbalsa_encrypt_mime_object(GMimeObject ** content, GList * rfc822_for, gpgme_protocol_t protocol, gboolean always_trust, GtkWindow * parent, GError ** error); gboolean libbalsa_sign_encrypt_mime_object(GMimeObject ** content, const gchar * rfc822_signer, GList * rfc822_for, gpgme_protocol_t protocol, gboolean always_trust, GtkWindow * parent, GError ** error); gboolean libbalsa_body_check_signature(LibBalsaMessageBody * body, gpgme_protocol_t protocol); LibBalsaMessageBody *libbalsa_body_decrypt(LibBalsaMessageBody * body, gpgme_protocol_t protocol, GtkWindow * parent); /* routines dealing with RFC 2440 stuff */ gboolean libbalsa_rfc2440_sign_encrypt(GMimePart * part, const gchar * sign_for, GList * encrypt_for, gboolean always_trust, GtkWindow * parent, GError ** error); gpgme_error_t libbalsa_rfc2440_verify(GMimePart * part, GMimeGpgmeSigstat ** sig_info); gpgme_error_t libbalsa_rfc2440_decrypt(GMimePart * part, GMimeGpgmeSigstat ** sig_info, GtkWindow * parent); /* helper functions to convert states to human-readable form */ gchar *libbalsa_gpgme_sig_stat_to_gchar(gpgme_error_t stat) G_GNUC_WARN_UNUSED_RESULT; const gchar *libbalsa_gpgme_validity_to_gchar(gpgme_validity_t validity); const gchar *libbalsa_gpgme_validity_to_gchar_short(gpgme_validity_t validity); #endif /* __RFC3156_H__ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/rfc6350.c000066400000000000000000000333001477646064400234260ustar00rootroot00000000000000/* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, see the file AUTHORS for a list. * * This module provides a simple RFC 6350 (aka VCard 4.0, see https://tools.ietf.org/html/rfc6350) parser which extracts a single * VCard from a GDataInputStream and returns it as LibBalsaAddress. * * Written by Copyright (C) 2016 Albrecht Dreß . * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, 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 * . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #if defined(HAVE_OSMO) || defined(HAVE_WEBDAV) #include #include "rfc6350.h" /* define GError stuff for the RFC 6350/VCard parser */ #define RFC6350_ERROR_QUARK (g_quark_from_static_string("rfc6350-parser")) #define RFC6350_ERROR_NO_COLON 1 #define RFC6350_ERROR_EMPTY 2 #define RFC6350_ERROR_BEGIN 3 #define RFC6350_ERROR_END 4 #define CRLF "\r\n" static gboolean rfc6350_eval_line(gchar *line, LibBalsaAddress *address, GError **error); static gchar **rfc6350_strsplit(const gchar *item, guint count); static gchar *rfc6350_get_name(gchar *name); static void rfc6350_unescape(gchar *item); static gchar *rfc6350_fn_from_n(gchar **n_items); static gchar *rfc6350_escape(const gchar *value) G_GNUC_WARN_UNUSED_RESULT; static void rfc6350_add_folded(GString *strbuf, const gchar *label, const gchar *value); LibBalsaAddress * rfc6350_parse_from_stream(GDataInputStream *stream, gboolean *eos, GError **error) { gchar *line; LibBalsaAddress *result = NULL; line = g_data_input_stream_read_line_utf8(stream, NULL, NULL, error); if (line == NULL) { if (*error == NULL) { *eos = TRUE; } } else if (g_ascii_strcasecmp(line, "BEGIN:VCARD") != 0) { g_set_error(error, RFC6350_ERROR_QUARK, RFC6350_ERROR_BEGIN, _("malformed card, BEGIN:VCARD expected")); g_free(line); } else { gboolean parse_done = FALSE; result = libbalsa_address_new(); while (result && (line != NULL) && !parse_done) { if (g_ascii_strcasecmp(line, "END:VCARD") == 0) { parse_done = TRUE; g_free(line); } else { gchar *nextline; /* perform unfolding (RFC 6350, sect. 3.2. "Line Delimiting and Folding") */ nextline = g_data_input_stream_read_line_utf8(stream, NULL, NULL, error); while ((nextline) != NULL && ((nextline[0] == ' ') || (nextline[0] == '\t'))) { gchar *unfold; unfold = g_strconcat(line, &nextline[1], NULL); g_free(line); g_free(nextline); line = unfold; nextline = g_data_input_stream_read_line_utf8(stream, NULL, NULL, error); } /* evaluate unfolded line, drop address on error */ if (!rfc6350_eval_line(line, result, error)) { g_object_unref(result); result = NULL; } /* process next line */ g_free(line); line = nextline; } } if (!parse_done) { g_set_error(error, RFC6350_ERROR_QUARK, RFC6350_ERROR_END, _("malformed card, END:VCARD missing")); g_object_unref(result); result = NULL; } } /* ignore items without an Email address, fill empty full name if necessary */ if (result != NULL) { if (libbalsa_address_get_addr(result) == NULL) { g_object_unref(result); result = NULL; } else if (libbalsa_address_get_full_name(result) == NULL) { libbalsa_address_set_full_name(result, _("No-Name")); } } return result; } gchar * rfc6350_from_address(LibBalsaAddress *address, gboolean vcard4, gboolean add_uuid) { GString *vcbuf; const gchar *first_name; const gchar *last_name; gchar *buf; gchar *n_last_buf; gchar *n_first_buf; guint addr_idx; g_return_val_if_fail(LIBBALSA_IS_ADDRESS(address), NULL); /* header */ vcbuf = g_string_new("BEGIN:VCARD" CRLF "VERSION:"); g_string_append_c(vcbuf, vcard4 ? '4' : '3'); g_string_append(vcbuf, ".0" CRLF); /* UUID if requested */ if (add_uuid) { buf = g_uuid_string_random(); g_string_append_printf(vcbuf, "UID:urn:uuid:%s" CRLF, buf); g_free(buf); } /* FN field, must be present */ first_name = libbalsa_address_get_first_name(address); last_name = libbalsa_address_get_last_name(address); if (libbalsa_address_get_full_name(address) != NULL) { buf = rfc6350_escape(libbalsa_address_get_full_name(address)); } else { gchar *fn_buf; if ((first_name != NULL) && (last_name != NULL)) { fn_buf = g_strconcat(first_name, " ", last_name, NULL); } else if (first_name != NULL) { fn_buf = g_strdup(first_name); } else if (last_name != NULL) { fn_buf = g_strdup(last_name); } else { fn_buf = g_strdup(_("unknown")); } buf = rfc6350_escape(fn_buf); g_free(fn_buf); } rfc6350_add_folded(vcbuf, "FN", buf); g_free(buf); /* N field, should be present */ if (last_name != NULL) { n_last_buf = rfc6350_escape(last_name); } else { n_last_buf = g_strdup(""); } if (first_name != NULL) { n_first_buf = rfc6350_escape(first_name); } else { n_first_buf = g_strdup(""); } buf = g_strconcat(n_last_buf, ";", n_first_buf, ";;;", NULL); g_free(n_first_buf); g_free(n_last_buf); rfc6350_add_folded(vcbuf, "N", buf); g_free(buf); /* ORG field (optional) */ if (libbalsa_address_get_organization(address) != NULL) { buf = rfc6350_escape(libbalsa_address_get_organization(address)); rfc6350_add_folded(vcbuf, "ORG", buf); g_free(buf); } /* EMAIL fields */ for (addr_idx = 0U; addr_idx < libbalsa_address_get_n_addrs(address); addr_idx++) { buf = rfc6350_escape(libbalsa_address_get_nth_addr(address, addr_idx)); rfc6350_add_folded(vcbuf, "EMAIL", buf); g_free(buf); } /* footer */ g_string_append(vcbuf, "END:VCARD" CRLF); return g_string_free(vcbuf, FALSE); } /** \brief Extract a VCard name item * * \param name input name field, modified in place * \return the name field, with group and parameters stripped * * Remove the \em group and \em param parts of the VCard \em name field (see RFC 6350, sect. 3.3. "ABNF Format Definition"). * * \note Do \em not free the returned value. */ static gchar * rfc6350_get_name(gchar *name) { gchar *result; gchar *semicolon; /* skip group */ result = strchr(name, '.'); if (result == NULL) { result = name; } else { result = &result[1]; } /* drop any name parameters */ semicolon = strchr(result, ';'); if (semicolon != NULL) { semicolon[0] = '\0'; } return result; } /** \brief RFC 6350 unescape a string * * \param item VCard item, modified in place * * Unescape a string according to RFC 6350, sect. 3.4. "Property Value Escaping". Note that all other escaped characters than those * defined in RFC 6350 are simply ignored, although they \em should be regarded as errors. * * \note Do \em not free the returned value. */ static void rfc6350_unescape(gchar *item) { gchar *p; gchar *bslash; g_assert(item != NULL); p = item; do { bslash = strchr(p, '\\'); if (bslash != NULL) { if (strchr(",;\\nN", bslash[1]) != NULL) { if (g_ascii_tolower(bslash[1]) == 'n') { bslash[1] = '\n'; } memmove(bslash, &bslash[1], strlen(bslash)); } p = &bslash[1]; } else { p = NULL; } } while (p != NULL); } /** \brief Split a ';' delimited list into items * * \param item value string consisting of ';' delimited items * \param count maximum number of fields to split into * \return a newly allocated NULL-terminated array of unescaped fields * * Split the passed value string into fields, and unescape the resulting values. If the \em item contains more than \em count * fields, the extra delimiters are ignored. * * \note Free the returned value by calling g_strfreev() on it. */ static gchar ** rfc6350_strsplit(const gchar *item, guint count) { gchar **result; const gchar *start; guint index; result = g_new0(gchar *, count + 1U); start = item; index = 0U; while ((start != NULL) && (index < count)) { if (start[0] == ';') { result[index] = g_strdup(""); start = &start[1]; } else { const gchar *delim; delim = strchr(start, ';'); while ((delim != NULL) && (delim[-1] == '\\')) { delim = strchr(&delim[1], ';'); } if (delim != NULL) { result[index] = g_strndup(start, delim - start); start = &delim[1]; } else { result[index] = g_strdup(start); start = NULL; } rfc6350_unescape(result[index]); } index++; } return result; } /** \brief Evaluate a VCard line * * \param line VCard line * \param address target address object * \param error filled with error information on error * \return TRUE on success, or FALSE is the VCard line is malformed * * Evaluate the VCard line, extract a N, FN, NICKNAME, ORG or EMAIL item and assign it to the appropriate fields in the target * address item. */ static gboolean rfc6350_eval_line(gchar *line, LibBalsaAddress *address, GError **error) { gchar *value; gboolean result; /* split into name and value */ value = strchr(line, ':'); if (value == NULL) { g_set_error(error, RFC6350_ERROR_QUARK, RFC6350_ERROR_NO_COLON, _("malformed line “%s”, missing “:”"), line); result = FALSE; } else { gchar *namepart; gchar *name; /* get the name and make sure that neither name nor value are empty */ namepart = g_strndup(line, value - line); name = rfc6350_get_name(namepart); value = &value[1]; if ((name[0] == '\0') || (value[0] == '\0')) { g_set_error(error, RFC6350_ERROR_QUARK, RFC6350_ERROR_EMPTY, _("malformed line “%s”, empty name or value"), line); } else { g_debug("%s: line='%s' name='%s', value='%s'", __func__, line, name, value); if (g_ascii_strcasecmp(name, "FN") == 0) { rfc6350_unescape(value); libbalsa_address_set_full_name(address, value); } else if (g_ascii_strcasecmp(name, "N") == 0) { gchar **n_items; n_items = rfc6350_strsplit(value, 5U); libbalsa_address_set_first_name(address, n_items[1]); libbalsa_address_set_last_name(address, n_items[0]); if (libbalsa_address_get_full_name(address) == NULL) { libbalsa_address_set_full_name (address, rfc6350_fn_from_n(n_items)); } g_strfreev(n_items); } else if (g_ascii_strcasecmp(name, "NICKNAME") == 0) { rfc6350_unescape(value); libbalsa_address_set_nick_name(address, value); } else if (g_ascii_strcasecmp(name, "ORG") == 0) { gchar **n_items; n_items = rfc6350_strsplit(value, 2U); libbalsa_address_set_organization(address, n_items[0]); g_strfreev(n_items); } else if (g_ascii_strcasecmp(name, "EMAIL") == 0) { rfc6350_unescape(value); libbalsa_address_append_addr(address, value); } else { /* ignore any other items */ } } g_free(namepart); result = TRUE; } return result; } /** \brief Create a full name from VCard "N" items * * \param n_items extracted VCard N items * \return the full name * * Construct a full name by concatenating -in this order- the VCard "N" elements Honorific Prefixes, Given Names, Additional Names, * Family Names and Honorific Suffixes, separated by a single space each. */ static gchar * rfc6350_fn_from_n(gchar **n_items) { GString *fn; static const guint add_idx[5] = { 3U, 1U, 2U, 0U, 4U }; guint n; fn = g_string_new(NULL); for (n = 0; n < 5U; n++) { if ((n_items[add_idx[n]] != NULL) && (n_items[add_idx[n]][0] != '\0')) { if (fn->len > 0U) { fn = g_string_append_c(fn, ' '); } fn = g_string_append(fn, n_items[add_idx[n]]); } } return g_string_free(fn, FALSE); } /** \brief RFC 6350 escape a string * * \param[in] value string to escape * \return the newly allocated, escaped string * * Escape a string according to RFC 6350, sect. 3.4. "Property Value Escaping". */ static gchar * rfc6350_escape(const gchar *value) { GString *buf; const gchar *p; buf = g_string_sized_new(strlen(value)); p = value; do { size_t chunk; chunk = strcspn(p, ";,\\\n"); if (chunk > 0U) { g_string_append_len(buf, p, chunk); p = &p[chunk]; } if (*p != '\0') { g_string_append_c(buf, '\\'); g_string_append_c(buf, *p); p = &p[1]; } } while (*p != '\0'); return g_string_free(buf, FALSE); } /** \brief RFC 6350 fold a VCard entry * * \param[in,out] strbuf VCard buffer * \param[in] label VCard item label * \param[in] value VCard item value * * Append the passed label and value to the VCard string buffer, folding it according to RFC 6350, sect. 3.2. "Line Delimiting and * Folding". */ static void rfc6350_add_folded(GString *strbuf, const gchar *label, const gchar *value) { long int label_offs; const gchar *p; p = value; g_string_append_printf(strbuf, "%s:", label); label_offs = strlen(label) + 1L; do { const gchar *chunk_end; chunk_end = g_utf8_next_char(p); do { chunk_end = g_utf8_next_char(chunk_end); } while ((*chunk_end != '\0') && ((chunk_end - p) <= (71 - label_offs))); g_string_append_len(strbuf, p, chunk_end - p); if (*chunk_end != '\0') { g_string_append(strbuf, CRLF " "); } label_offs = 0; p = chunk_end; } while (*p != '\0'); g_string_append(strbuf, CRLF); } #endif /* HAVE_OSMO || HAVE_WEBDAV */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/rfc6350.h000066400000000000000000000043471477646064400234440ustar00rootroot00000000000000/* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, see the file AUTHORS for a list. * * This module provides a simple RFC 6350 (aka VCard 4.0, see https://tools.ietf.org/html/rfc6350) parser which extracts a single * VCard from a GDataInputStream and returns it as LibBalsaAddress. * * Written by Copyright (C) 2016 Albrecht Dreß . * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, 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 * . */ #ifndef LIBBALSA_RFC6350_H_ #define LIBBALSA_RFC6350_H_ #include "address.h" /** \brief Extract a single VCard 4.0 * * \param stream VCard input stream * \param eos filled with TRUE is the end of the input stream has been reached * \param error filled with error information on error * \return a new address object on success * * Read a VCard from the input stream and extract all relevant fields into a LibBalsaAddress. A LibBalsaAddress is returned only if * it contains any email address. The caller shall distinguish this case from an error by checking if the error argument is filled. * The input stream is positioned immediately after the card read. * * \note The caller shall unref the returned address object. */ LibBalsaAddress *rfc6350_parse_from_stream(GDataInputStream *stream, gboolean *eos, GError **error); /** \brief Create a VCard from an address * * \param[in] address address object * \param[in] vcard4 \c TRUE to create a VCard version 4.0, \c FALSE to use version 3.0 * \param[in] add_uuid \c TRUE to add a \c UID item * \return the VCard */ gchar *rfc6350_from_address(LibBalsaAddress *address, gboolean vcard4, gboolean add_uuid); #endif /* LIBBALSA_RFC6350_H_ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/send.c000066400000000000000000002122501477646064400232720ustar00rootroot00000000000000/* -*-mode:c; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #define _DEFAULT_SOURCE 1 #define _POSIX_C_SOURCE 199309L #include "send.h" #include #include #include #include #include "libbalsa.h" #include "libbalsa_private.h" #include "server.h" #include "misc.h" #include "missing.h" #include "information.h" #include "net-client-smtp.h" #include "gmime-filter-header.h" #include "smtp-server.h" #include "identity.h" #include "libbalsa-progress.h" #include "libbalsa-gpgme.h" #include #ifdef G_LOG_DOMAIN # undef G_LOG_DOMAIN #endif #define G_LOG_DOMAIN "send" typedef struct _MessageQueueItem MessageQueueItem; typedef struct _SendMessageInfo SendMessageInfo; struct _MessageQueueItem { SendMessageInfo *smsg_info; LibBalsaMessage *orig; GMimeStream *stream; NetClientSmtpMessage *smtp_msg; }; struct _SendMessageInfo { LibBalsaSmtpServer *smtp_server; LibBalsaMailbox *outbox; NetClientSmtp *session; LibBalsaFccboxFinder finder; GList *items; /* of MessageQueueItem */ gboolean no_dialog; gchar *progress_id; gint64 total_size; gint64 total_sent; gint last_report; guint msg_count; guint curr_msg; }; typedef struct _SendQueueInfo SendQueueInfo; struct _SendQueueInfo { LibBalsaMailbox *outbox; LibBalsaFccboxFinder finder; GtkWindow *parent; }; static GMutex send_messages_lock; static gint sending_threads = 0; /* how many sending threads are active, access via g_atomic_* */ static GSourceFunc auto_send_cb = NULL; static gboolean send_mail_auto = FALSE; static guint send_mail_time = 0U; static guint send_mail_timer_id = 0U; static gint retrigger_send = 0; /* # of messages added to outbox while the smtp server was locked, access via g_atomic_* */ static ProgressDialog send_progress_dialog; /* end of state variables section */ /* Stop the the auto-send timer, and start it if start and send_mail_auto are TRUE, and a callback is defined. In order to catch * weird cases (e.g. user unflags or undeletes a message in the outbox) we ignore if the outbox is actually empty or does not * contain any ready-to-send messages, and start the timer anyway. The overhead of the callback just doing nothing should be * insignificant. */ static void update_send_timer(gboolean start) { if (send_mail_timer_id != 0U) { g_source_remove(send_mail_timer_id); send_mail_timer_id = 0U; } if (start && send_mail_auto && (auto_send_cb != NULL)) { send_mail_timer_id = g_timeout_add_seconds(send_mail_time, auto_send_cb, NULL); } } void libbalsa_auto_send_init(GSourceFunc auto_send_handler) { auto_send_cb = auto_send_handler; update_send_timer(FALSE); } void libbalsa_auto_send_config(gboolean enable, guint timeout_minutes) { send_mail_auto = enable; send_mail_time = timeout_minutes * 60U; update_send_timer(enable); } gboolean libbalsa_is_sending_mail(void) { return g_atomic_int_get(&sending_threads) > 0; } static MessageQueueItem * msg_queue_item_new(SendMessageInfo *smi) { MessageQueueItem *mqi; mqi = g_new0(MessageQueueItem, 1U); mqi->smsg_info = smi; return mqi; } static void msg_queue_item_destroy(MessageQueueItem *mqi) { if (mqi->smtp_msg != NULL) { net_client_smtp_msg_free(mqi->smtp_msg); } if (mqi->stream != NULL) { g_object_unref(mqi->stream); } if (mqi->orig != NULL) { g_object_unref(mqi->orig); } g_free(mqi); } static SendMessageInfo * send_message_info_new(LibBalsaSmtpServer *smtp_server, LibBalsaMailbox *outbox, LibBalsaFccboxFinder finder, NetClientSmtp *session) { SendMessageInfo *smi; smi = g_new0(SendMessageInfo, 1); smi->session = session; smi->outbox = g_object_ref(outbox); smi->finder = finder; smi->smtp_server = g_object_ref(smtp_server); smi->progress_id = g_strdup_printf(_("SMTP server %s"), libbalsa_smtp_server_get_name(smtp_server)); return smi; } static void send_message_info_destroy(SendMessageInfo *smi) { if (smi->outbox != NULL) { g_object_unref(smi->outbox); } if (smi->session != NULL) { g_object_unref(smi->session); } if (smi->items != NULL) { g_list_free_full(smi->items, (GDestroyNotify) msg_queue_item_destroy); } if (smi->progress_id != NULL) { g_free(smi->progress_id); } g_object_unref(smi->smtp_server); g_free(smi); } static LibBalsaMsgCreateResult libbalsa_create_rfc2440_buffer(LibBalsaMessage *message, GMimePart *mime_part, GtkWindow *parent, GError **error); static LibBalsaMsgCreateResult do_multipart_crypto(LibBalsaMessage *message, GMimeObject **mime_root, GtkWindow *parent, GError **error); static GMimePart *lb_create_pubkey_part(LibBalsaMessage *message, GtkWindow *parent, GError **error); static gpointer balsa_send_message_real(SendMessageInfo *info); static LibBalsaMsgCreateResult create_mime_message(LibBalsaMessage *message, gboolean flow, gboolean postponing, GMimeMessage **return_message, GError **error); static LibBalsaMsgCreateResult libbalsa_create_msg(LibBalsaMessage *message, gboolean flow, GError **error); static LibBalsaMsgCreateResult libbalsa_fill_msg_queue_item_from_queu(LibBalsaMessage *message, MessageQueueItem *mqi); static void lbs_set_content(GMimePart *mime_part, gchar *content) { GMimeStream *stream; GMimeDataWrapper *wrapper; stream = g_mime_stream_mem_new(); g_mime_stream_write(stream, content, strlen(content)); wrapper = g_mime_data_wrapper_new_with_stream(stream, GMIME_CONTENT_ENCODING_DEFAULT); g_object_unref(stream); g_mime_part_set_content(mime_part, wrapper); g_object_unref(wrapper); } static GMimeObject * add_mime_body_plain(LibBalsaMessageBody *body, gboolean flow, gboolean postpone, guint use_gpg_mode, LibBalsaMsgCreateResult *crypt_res, GError **error) { GMimePart *mime_part; const gchar *charset; GtkWindow *parent = g_object_get_data(G_OBJECT(body->message), "parent-window"); g_return_val_if_fail(body, NULL); charset = body->charset; if (body->content_type != NULL) { /* Use the supplied mime type */ gchar *type, *subtype; /* FIXME: test sending with different mime types */ g_debug("path active"); type = g_strdup (body->content_type); if ((subtype = strchr (type, '/')) != NULL) { *subtype++ = 0; mime_part = g_mime_part_new_with_type(type, subtype); } else { mime_part = g_mime_part_new_with_type("text", "plain"); } g_free (type); } else { mime_part = g_mime_part_new_with_type("text", "plain"); } g_mime_object_set_disposition(GMIME_OBJECT(mime_part), GMIME_DISPOSITION_INLINE); g_mime_part_set_content_encoding(mime_part, GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE); g_mime_object_set_content_type_parameter(GMIME_OBJECT(mime_part), "charset", charset != NULL ? charset : "us-ascii"); if (flow) { g_mime_object_set_content_type_parameter(GMIME_OBJECT(mime_part), "DelSp", "Yes"); g_mime_object_set_content_type_parameter(GMIME_OBJECT(mime_part), "Format", "Flowed"); } if ((charset != NULL) && (g_ascii_strcasecmp(charset, "UTF-8") != 0) && (g_ascii_strcasecmp(charset, "UTF8") != 0)) { GMimeStream *stream, *filter_stream; GMimeFilter *filter; GMimeDataWrapper *wrapper; stream = g_mime_stream_mem_new(); filter_stream = g_mime_stream_filter_new(stream); filter = g_mime_filter_charset_new("UTF-8", charset); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filter_stream), filter); g_object_unref(filter); g_mime_stream_write(filter_stream, body->buffer, strlen(body->buffer)); g_object_unref(filter_stream); wrapper = g_mime_data_wrapper_new_with_stream(stream, GMIME_CONTENT_ENCODING_DEFAULT); g_object_unref(stream); g_mime_part_set_content(mime_part, wrapper); g_object_unref(wrapper); } else { lbs_set_content(mime_part, body->buffer); } /* rfc 2440 sign/encrypt if requested */ if (use_gpg_mode != 0) { *crypt_res = libbalsa_create_rfc2440_buffer(body->message, GMIME_PART(mime_part), parent, error); if (*crypt_res != LIBBALSA_MESSAGE_CREATE_OK) { g_object_unref(mime_part); return NULL; } } /* if requested, add a text/html version in a multipart/alternative */ if (body->html_buffer && !postpone) { GMimeMultipart *mpa = g_mime_multipart_new_with_subtype("alternative"); g_mime_multipart_add(mpa, GMIME_OBJECT(mime_part)); g_object_unref(mime_part); mime_part = g_mime_part_new_with_type("text", "html"); g_mime_multipart_add(mpa, GMIME_OBJECT(mime_part)); g_object_unref(mime_part); g_mime_object_set_disposition(GMIME_OBJECT(mime_part), GMIME_DISPOSITION_INLINE); g_mime_part_set_content_encoding(mime_part, GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE); g_mime_object_set_content_type_parameter(GMIME_OBJECT(mime_part), "charset", "UTF-8"); lbs_set_content(mime_part, body->html_buffer); if ((use_gpg_mode != 0) && ((use_gpg_mode & LIBBALSA_PROTECT_MODE) != LIBBALSA_PROTECT_SIGN)) { *crypt_res = libbalsa_create_rfc2440_buffer(body->message, GMIME_PART(mime_part), parent, error); if (*crypt_res != LIBBALSA_MESSAGE_CREATE_OK) { g_object_unref(mpa); return NULL; } } return GMIME_OBJECT(mpa); } else { return GMIME_OBJECT(mime_part); } } #if 0 /* you never know when you will need this one... */ static void dump_queue(const char *msg) { MessageQueueItem *mqi = message_queue; g_debug("dumping message queue at %s:", msg); while (mqi) { g_debug("item: %p", mqi); mqi = mqi->next_message; } } #endif /* libbalsa_message_queue: places given message in the outbox. */ static void libbalsa_set_message_id(GMimeMessage *mime_message); static LibBalsaMsgCreateResult lbs_message_queue_real(LibBalsaMessage *message, LibBalsaMailbox *outbox, LibBalsaMailbox *fccbox, LibBalsaSmtpServer *smtp_server, gboolean flow, GError **error) { LibBalsaMsgCreateResult result; GMimeMessage *mime_msg; guint big_message; gboolean rc; g_assert(error != NULL); g_return_val_if_fail(message, LIBBALSA_MESSAGE_CREATE_ERROR); if ((result = libbalsa_create_msg(message, flow, error)) != LIBBALSA_MESSAGE_CREATE_OK) { return result; } mime_msg = libbalsa_message_get_mime_message(message); if (fccbox != NULL) { g_mime_object_set_header(GMIME_OBJECT(mime_msg), "X-Balsa-Fcc", libbalsa_mailbox_get_url(fccbox), NULL); } g_mime_object_set_header(GMIME_OBJECT(mime_msg), "X-Balsa-DSN", libbalsa_message_get_request_dsn(message) ? "1" : "0", NULL); g_mime_object_set_header(GMIME_OBJECT(mime_msg), "X-Balsa-SmtpServer", libbalsa_smtp_server_get_name(smtp_server), NULL); big_message = libbalsa_smtp_server_get_big_message(smtp_server); if (big_message > 0) { GMimeMessage **mime_msgs; size_t nparts; guint i; mime_msgs = g_mime_message_partial_split_message(mime_msg, big_message, &nparts); g_object_ref(mime_msg); rc = TRUE; for (i = 0; i < nparts; ++i) { if (nparts > 1) { /* RFC 2046, 5.2.2: "...it is specified that entities of * type "message/partial" must always have a content- * transfer-encoding of 7bit (the default)" */ g_mime_part_set_content_encoding(GMIME_PART (mime_msgs[i]->mime_part), GMIME_CONTENT_ENCODING_7BIT); libbalsa_set_message_id(mime_msgs[i]); } if (rc) { /* Temporarily modify message by changing its mime_msg: */ libbalsa_message_set_mime_message(message, mime_msgs[i]); rc = libbalsa_message_copy(message, outbox, error); } g_object_unref(mime_msgs[i]); } g_free(mime_msgs); /* Restore message's original mime_msg: */ libbalsa_message_set_mime_message(message, mime_msg); g_object_unref(mime_msg); } else { rc = libbalsa_message_copy(message, outbox, error); } return rc ? LIBBALSA_MESSAGE_CREATE_OK : LIBBALSA_MESSAGE_QUEUE_ERROR; } LibBalsaMsgCreateResult libbalsa_message_queue(LibBalsaMessage *message, LibBalsaMailbox *outbox, LibBalsaMailbox *fccbox, LibBalsaSmtpServer *smtp_server, gboolean flow, GError **error) { LibBalsaMsgCreateResult result; update_send_timer(FALSE); result = lbs_message_queue_real(message, outbox, fccbox, smtp_server, flow, error); if (g_atomic_int_get(&sending_threads) == 0) { update_send_timer(TRUE); } return result; } /* libbalsa_message_send: send the given messsage (if any, it can be NULL) and all the messages in given outbox. */ static void lbs_process_queue(LibBalsaMailbox *outbox, LibBalsaFccboxFinder finder, LibBalsaSmtpServer *smtp_server, GtkWindow *parent); static gboolean lbs_process_queue_real(LibBalsaSmtpServer *smtp_server, SendQueueInfo *send_info); LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage *message, LibBalsaMailbox *outbox, LibBalsaMailbox *fccbox, LibBalsaFccboxFinder finder, LibBalsaSmtpServer *smtp_server, gboolean show_progress, GtkWindow *parent, gboolean flow, GError **error) { LibBalsaMsgCreateResult result = LIBBALSA_MESSAGE_CREATE_OK; g_return_val_if_fail(smtp_server != NULL, LIBBALSA_MESSAGE_SERVER_ERROR); if (message != NULL) { update_send_timer(FALSE); result = lbs_message_queue_real(message, outbox, fccbox, smtp_server, flow, error); if (result == LIBBALSA_MESSAGE_CREATE_OK) { if (libbalsa_smtp_server_trylock(smtp_server)) { lbs_process_queue(outbox, finder, smtp_server, show_progress ? parent : NULL); } else { g_atomic_int_inc(&retrigger_send); } } else if (g_atomic_int_get(&sending_threads) == 0) { update_send_timer(TRUE); } else { /* nothing to do */ } } return result; } static void add_recipients(NetClientSmtpMessage *message, InternetAddressList *recipient_list, gboolean request_dsn) { if (recipient_list != NULL) { const InternetAddress *ia; NetClientSmtpDsnMode dsn_mode; int i; /* XXX - It would be cool if LibBalsaAddress could contain DSN options for a particular recipient. For the time being, just use a switch */ if (request_dsn) { dsn_mode = NET_CLIENT_SMTP_DSN_SUCCESS + NET_CLIENT_SMTP_DSN_FAILURE + NET_CLIENT_SMTP_DSN_DELAY; } else { dsn_mode = NET_CLIENT_SMTP_DSN_NEVER; } for (i = 0; i < internet_address_list_length(recipient_list); i++) { ia = internet_address_list_get_address(recipient_list, i); if (INTERNET_ADDRESS_IS_MAILBOX(ia)) { net_client_smtp_msg_add_recipient(message, INTERNET_ADDRESS_MAILBOX(ia)->addr, dsn_mode); } else { add_recipients(message, INTERNET_ADDRESS_GROUP(ia)->members, request_dsn); } } } } static gssize send_message_data_cb(gchar *buffer, gsize count, gpointer user_data, GError **error) { ssize_t read_res; MessageQueueItem *mqi = (MessageQueueItem *) user_data; SendMessageInfo *smi = mqi->smsg_info; read_res = g_mime_stream_read(mqi->stream, buffer, count); if (!smi->no_dialog && (smi->total_size > 0) && (read_res > 0)) { gdouble fraction; gint ipercent; smi->total_sent += read_res; fraction = (gdouble) smi->total_sent / (gdouble) smi->total_size; g_debug("%s: s=%lu t=%lu %g", __func__, (unsigned long) smi->total_sent, (unsigned long) smi->total_size, fraction); if (fraction > 1.0) { fraction = 1.0; } ipercent = (gint) (100.0 * (fraction + 0.5)); if (!smi->no_dialog && (ipercent > smi->last_report)) { libbalsa_progress_dialog_update(&send_progress_dialog, smi->progress_id, FALSE, fraction, _("Message %u of %u"), smi->curr_msg, smi->msg_count); smi->last_report = ipercent; } } return read_res; } static void lbs_check_reachable_cb(GObject *object, gboolean can_reach, gpointer cb_data) { LibBalsaSmtpServer *smtp_server = LIBBALSA_SMTP_SERVER(object); SendQueueInfo *send_info = (SendQueueInfo *) cb_data; gboolean thread_started = FALSE; if (can_reach) { thread_started = lbs_process_queue_real(smtp_server, send_info); } else { libbalsa_information(LIBBALSA_INFORMATION_WARNING, _("Cannot reach SMTP server %s (%s), any queued message will remain in %s."), libbalsa_smtp_server_get_name(smtp_server), libbalsa_server_get_host(LIBBALSA_SERVER(smtp_server)), libbalsa_mailbox_get_name(send_info->outbox)); } if (!thread_started) { /* if the thread has been started, it will take care of unlocking the server and re-starting the timer */ libbalsa_smtp_server_unlock(smtp_server); update_send_timer(TRUE); } g_object_unref(send_info->outbox); if (send_info->parent != NULL) { g_object_unref(send_info->parent); } g_free(send_info); } /* note: the following function is called with the passed smtp server being locked * parent != NULL indicates that the progress dialogue shall be shown */ static void lbs_process_queue(LibBalsaMailbox *outbox, LibBalsaFccboxFinder finder, LibBalsaSmtpServer *smtp_server, GtkWindow *parent) { SendQueueInfo *send_info; send_info = g_new(SendQueueInfo, 1U); send_info->outbox = g_object_ref(outbox); send_info->finder = finder; if (parent != NULL) { send_info->parent = g_object_ref(parent); } else { send_info->parent = NULL; } libbalsa_server_test_can_reach(LIBBALSA_SERVER(smtp_server), lbs_check_reachable_cb, send_info); } static void lbs_process_queue_msg(guint msgno, SendMessageInfo *send_message_info) { MessageQueueItem* new_message; LibBalsaMessage* msg; const gchar* smtp_server_name; LibBalsaMsgCreateResult created; const gchar *dsn_header; /* Skip this message if it either FLAGGED or DELETED: */ if (!libbalsa_mailbox_msgno_has_flags(send_message_info->outbox, msgno, 0, (LIBBALSA_MESSAGE_FLAG_FLAGGED | LIBBALSA_MESSAGE_FLAG_DELETED))) { return; } msg = libbalsa_mailbox_get_message(send_message_info->outbox, msgno); if (!msg) { /* error? */ return; } /* check the smtp server */ libbalsa_message_body_ref(msg, TRUE); smtp_server_name = libbalsa_message_get_user_header(msg, "X-Balsa-SmtpServer"); if (!smtp_server_name) { smtp_server_name = libbalsa_smtp_server_get_name(NULL); } if (strcmp(smtp_server_name, libbalsa_smtp_server_get_name(send_message_info->smtp_server)) != 0) { libbalsa_message_body_unref(msg); g_object_unref(msg); return; } dsn_header = libbalsa_message_get_user_header(msg, "X-Balsa-DSN"); libbalsa_message_set_request_dsn(msg, dsn_header != NULL ? atoi(dsn_header) != 0 : FALSE); new_message = msg_queue_item_new(send_message_info); created = libbalsa_fill_msg_queue_item_from_queu(msg, new_message); libbalsa_message_body_unref(msg); if (created != LIBBALSA_MESSAGE_CREATE_OK) { msg_queue_item_destroy(new_message); } else { gboolean request_dsn; LibBalsaMessageHeaders *headers; InternetAddressList *from; const InternetAddress* ia; const gchar* mailbox; libbalsa_message_change_flags(msg, LIBBALSA_MESSAGE_FLAG_FLAGGED, 0); send_message_info->items = g_list_prepend(send_message_info->items, new_message); new_message->smtp_msg = net_client_smtp_msg_new(send_message_data_cb, new_message); request_dsn = libbalsa_message_get_request_dsn(msg); if (request_dsn) { const gchar *message_id = libbalsa_message_get_message_id(msg); net_client_smtp_msg_set_dsn_opts(new_message->smtp_msg, message_id, FALSE); } /* Add the sender info */ headers = libbalsa_message_get_headers(msg); from = headers->from; if (from != NULL && (ia = internet_address_list_get_address(from, 0)) != NULL) { while (ia != NULL && INTERNET_ADDRESS_IS_GROUP(ia)) { ia = internet_address_list_get_address(INTERNET_ADDRESS_GROUP( ia)->members, 0); } mailbox = ia ? INTERNET_ADDRESS_MAILBOX(ia)->addr : ""; } else { mailbox = ""; } net_client_smtp_msg_set_sender(new_message->smtp_msg, mailbox); /* Now need to add the recipients to the message. */ add_recipients(new_message->smtp_msg, headers->to_list, request_dsn); add_recipients(new_message->smtp_msg, headers->cc_list, request_dsn); add_recipients(new_message->smtp_msg, headers->bcc_list, request_dsn); /* Estimate the size of the message. This need not be exact but it's better to err * on the large side since some message headers may be altered during the transfer. */ send_message_info->total_size += g_mime_stream_length(new_message->stream); send_message_info->msg_count++; } g_object_unref(msg); } static NetClientSmtp * lbs_process_queue_init_session(LibBalsaServer* server) { NetClientCryptMode security; const gchar *host; NetClientSmtp* session; security = libbalsa_server_get_security(server); host = libbalsa_server_get_host(server); if (security == NET_CLIENT_CRYPT_ENCRYPTED) { session = net_client_smtp_new(host, 465U, security); } else { // FIXME - submission (587) is the standard, but most isp's use 25... session = net_client_smtp_new(host, 587U, security); } net_client_smtp_set_auth_mode(session, libbalsa_server_get_auth_mode(server)); /* connect signals */ g_signal_connect(session, "cert-check", G_CALLBACK(libbalsa_server_check_cert), session); g_signal_connect(session, "auth", G_CALLBACK(libbalsa_server_get_auth), server); /* load client certificate if configured */ if (libbalsa_server_get_client_cert(server)) { const gchar *cert_file = libbalsa_server_get_cert_file(server); GError* error = NULL; g_signal_connect(session, "cert-pass", G_CALLBACK(libbalsa_server_get_cert_pass), server); if (!net_client_set_cert_from_file(NET_CLIENT(session), cert_file, &error)) { libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("Cannot load certificate file %s: %s"), cert_file, error->message); /* bad certificate private key password: clear it */ if (error->code == NET_CLIENT_ERROR_CERT_KEY_PASS) { libbalsa_server_set_password(server, NULL, TRUE); } g_error_free(error); g_object_unref(session); session = NULL; } } return session; } /* libbalsa_process_queue: treats given mailbox as a set of messages to send. Loads them up and launches sending thread/routine. NOTE that we do not close outbox after reading. send_real/thread message handler does that. Returns if the thread has been launched Note: the function is always called with the respective SMTP server being locked, so unlock if we don't start the sending thread */ static gboolean lbs_process_queue_real(LibBalsaSmtpServer *smtp_server, SendQueueInfo *send_info) { gboolean thread_started = FALSE; g_mutex_lock(&send_messages_lock); if (libbalsa_mailbox_open(send_info->outbox, NULL)) { NetClientSmtp *session; /* create the SMTP session */ session = lbs_process_queue_init_session(LIBBALSA_SERVER(smtp_server)); if (session != NULL) { SendMessageInfo *send_message_info; guint msgno; send_message_info = send_message_info_new(smtp_server, send_info->outbox, send_info->finder, session); for (msgno = libbalsa_mailbox_total_messages(send_info->outbox); msgno > 0U; msgno--) { lbs_process_queue_msg(msgno, send_message_info); } /* launch the thread for sending the messages only if we collected any */ if (send_message_info->items != NULL) { GThread *send_mail; if (send_info->parent != NULL) { libbalsa_progress_dialog_ensure(&send_progress_dialog, _("Sending Mail"), send_info->parent, send_message_info->progress_id); send_message_info->no_dialog = FALSE; } else { send_message_info->no_dialog = TRUE; } g_atomic_int_inc(&sending_threads); send_mail = g_thread_new("balsa_send_message_real", (GThreadFunc) balsa_send_message_real, send_message_info); g_thread_unref(send_mail); thread_started = TRUE; } else { send_message_info_destroy(send_message_info); } } if (!thread_started) { libbalsa_mailbox_close(send_info->outbox, TRUE); } } g_mutex_unlock(&send_messages_lock); return thread_started; } void libbalsa_process_queue(LibBalsaMailbox *outbox, LibBalsaFccboxFinder finder, GSList *smtp_servers, gboolean show_progress, GtkWindow *parent) { if (libbalsa_mailbox_open(outbox, NULL)) { guint msgno; guint pending = 0U; update_send_timer(FALSE); for (msgno = libbalsa_mailbox_total_messages(outbox); msgno > 0U; msgno--) { if (libbalsa_mailbox_msgno_has_flags(outbox, msgno, 0, (LIBBALSA_MESSAGE_FLAG_FLAGGED | LIBBALSA_MESSAGE_FLAG_DELETED))) { pending++; } } if (pending > 0U) { for (; smtp_servers; smtp_servers = smtp_servers->next) { LibBalsaSmtpServer *smtp_server = LIBBALSA_SMTP_SERVER(smtp_servers->data); if (libbalsa_smtp_server_trylock(smtp_server)) { lbs_process_queue(outbox, finder, smtp_server, show_progress ? parent : NULL); } } } else { update_send_timer(TRUE); g_debug("%s: no messages pending", __func__); } libbalsa_mailbox_close(outbox, FALSE); } } /* balsa_send_message_real: does the actual message sending. This function may be called as a thread. Also, structure info should be freed before exiting. */ static gboolean balsa_send_message_real_idle_cb(LibBalsaMailbox *outbox) { if (g_atomic_int_and(&retrigger_send, 0U) != 0U) { g_idle_add(auto_send_cb, GINT_TO_POINTER(1)); } else { update_send_timer(TRUE); } libbalsa_mailbox_close(outbox, TRUE); g_object_unref(outbox); return FALSE; } #define ERROR_IS_TRANSIENT(error) \ (g_error_matches((error), NET_CLIENT_ERROR_QUARK, NET_CLIENT_ERROR_CONNECTION_LOST) || \ g_error_matches((error), NET_CLIENT_SMTP_ERROR_QUARK, NET_CLIENT_ERROR_SMTP_TRANSIENT)) static inline void balsa_send_message_success(MessageQueueItem *mqi, SendMessageInfo *info) { LibBalsaMailbox *mailbox; mailbox = mqi->orig != NULL ? libbalsa_message_get_mailbox(mqi->orig) : NULL; /* sending message successful */ if (mailbox != NULL) { gboolean remove = TRUE; const gchar *fccurl = libbalsa_message_get_user_header(mqi->orig, "X-Balsa-Fcc"); if (fccurl != NULL) { LibBalsaMailbox *fccbox = info->finder(fccurl); const gchar *fccname = libbalsa_mailbox_get_name(fccbox); GError *err = NULL; if (!info->no_dialog) { libbalsa_progress_dialog_update(&send_progress_dialog, info->progress_id, FALSE, NAN, _("Save message in %s…"), fccname); } libbalsa_message_change_flags(mqi->orig, 0, LIBBALSA_MESSAGE_FLAG_NEW | LIBBALSA_MESSAGE_FLAG_FLAGGED); libbalsa_mailbox_sync_storage(mailbox, FALSE); remove = libbalsa_message_copy(mqi->orig, fccbox, &err); if (!remove) { libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("Saving sent message to %s failed: %s"), fccname, err != NULL ? err->message : "?"); g_clear_error(&err); } } /* If copy failed, mark the message again as flagged - otherwise it will get * resent again. And again, and again... */ libbalsa_message_change_flags(mqi->orig, remove ? LIBBALSA_MESSAGE_FLAG_DELETED : LIBBALSA_MESSAGE_FLAG_FLAGGED, 0); } } static inline void balsa_send_message_error(MessageQueueItem *mqi, GError *error) { LibBalsaMailbox *mailbox; mailbox = mqi->orig != NULL ? libbalsa_message_get_mailbox(mqi->orig) : NULL; /* sending message failed */ if (mailbox != NULL) { if (ERROR_IS_TRANSIENT(error)) { /* Mark it as: * - neither flagged nor deleted, so it can be resent later * without changing flags. */ libbalsa_message_change_flags(mqi->orig, 0, LIBBALSA_MESSAGE_FLAG_FLAGGED | LIBBALSA_MESSAGE_FLAG_DELETED); } else { /* Mark it as: * - flagged, so it will not be sent again until the error is fixed * and the user manually clears the flag; * - undeleted, in case it was already deleted. */ libbalsa_message_change_flags(mqi->orig, LIBBALSA_MESSAGE_FLAG_FLAGGED, LIBBALSA_MESSAGE_FLAG_DELETED); } } libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("Sending message to SMTP server %s failed: %s\nMessage left in your outbox."), libbalsa_smtp_server_get_name(mqi->smsg_info->smtp_server), error->message); } static void balsa_send_message_syslog(const gchar *smtp_server, const MessageQueueItem *mqi, gboolean result, const gchar *server_response, const GError *server_error) { GString *syslog_msg; syslog_msg = g_string_new(NULL); g_string_append_printf(syslog_msg, "[%d:%s] SMTP=%s Message-ID=%s", (int) getpid(), g_get_user_name(), smtp_server, libbalsa_message_get_message_id(mqi->orig)); if (result) { syslog(LOG_MAIL | LOG_INFO, "%s Result='%s'", syslog_msg->str, server_response); } else { syslog(LOG_MAIL | LOG_NOTICE, "%s Error='%s'", syslog_msg->str, (server_error != NULL) ? server_error->message : "unknown"); } g_string_free(syslog_msg, TRUE); } static gpointer balsa_send_message_real(SendMessageInfo *info) { gboolean result; GError *error = NULL; gchar *greeting = NULL; g_debug("%s: starting", __func__); /* connect the SMTP server */ if (!info->no_dialog) { libbalsa_progress_dialog_update(&send_progress_dialog, info->progress_id, FALSE, INFINITY, _("Connecting %s…"), net_client_get_host(NET_CLIENT(info->session))); } result = net_client_smtp_connect(info->session, &greeting, &error); g_debug("%s: connect = %d [%p]: '%s'", __func__, result, info->items, greeting); g_free(greeting); if (result) { GList *this_msg; if (!info->no_dialog) { libbalsa_progress_dialog_update(&send_progress_dialog, info->progress_id, FALSE, 0.0, _("Connected to %s"), net_client_get_host(NET_CLIENT(info->session))); } for (this_msg = info->items; this_msg != NULL; this_msg = this_msg->next) { MessageQueueItem *mqi = (MessageQueueItem *) this_msg->data; gboolean send_res; gchar *server_reply = NULL; LibBalsaMailbox *mailbox; mailbox = mqi->orig != NULL ? libbalsa_message_get_mailbox(mqi->orig) : NULL; info->curr_msg++; g_debug("%s: %u/%u mqi = %p", __func__, info->msg_count, info->curr_msg, mqi); /* send the message */ send_res = net_client_smtp_send_msg(info->session, mqi->smtp_msg, &server_reply, &error); balsa_send_message_syslog(net_client_get_host(NET_CLIENT(info->session)), mqi, send_res, server_reply, error); g_free(server_reply); g_mutex_lock(&send_messages_lock); if (mailbox != NULL) { libbalsa_message_change_flags(mqi->orig, 0, LIBBALSA_MESSAGE_FLAG_FLAGGED); } else { g_debug("mqi: %p mqi->orig: %p mailbox: %p", mqi, mqi->orig, mailbox); } if (send_res) { /* sending message successful */ balsa_send_message_success(mqi, info); } else { /* sending message failed */ balsa_send_message_error(mqi, error); g_clear_error(&error); result = FALSE; } /* free data */ g_mutex_unlock(&send_messages_lock); } } else { if (ERROR_IS_TRANSIENT(error) || (error->code == NET_CLIENT_ERROR_SMTP_AUTHFAIL)) { GList *this_msg; /* Mark all messages as neither flagged nor deleted, so they can be resent later * without changing flags. */ for (this_msg = info->items; this_msg != NULL; this_msg = this_msg->next) { MessageQueueItem *mqi = (MessageQueueItem *) this_msg->data; LibBalsaMailbox *mailbox; mailbox = mqi->orig != NULL ? libbalsa_message_get_mailbox(mqi->orig) : NULL; if (mailbox != NULL) { libbalsa_message_change_flags(mqi->orig, 0, LIBBALSA_MESSAGE_FLAG_FLAGGED | LIBBALSA_MESSAGE_FLAG_DELETED); } } if (error->code == NET_CLIENT_ERROR_SMTP_AUTHFAIL) { /* authentication failed: clear password */ libbalsa_server_set_password(LIBBALSA_SERVER(info->smtp_server), NULL, FALSE); } } libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("Connecting SMTP server %s (%s) failed: %s"), libbalsa_smtp_server_get_name(info->smtp_server), net_client_get_host(NET_CLIENT(info->session)), error->message); g_error_free(error); } /* close outbox in an idle callback, as it might affect the display */ g_idle_add((GSourceFunc) balsa_send_message_real_idle_cb, g_object_ref(info->outbox)); /* finalise the SMTP session (which may be slow) */ g_object_unref(info->session); info->session = NULL; /* clean up */ if (!info->no_dialog) { libbalsa_progress_dialog_update(&send_progress_dialog, info->progress_id, TRUE, 1.0, _("Finished")); } else if (result) { libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, ngettext("Transmitted %u message to %s", "Transmitted %u messages to %s", info->msg_count), info->msg_count, libbalsa_smtp_server_get_name(info->smtp_server)); } else { /* no dialogue and error: information already displayed, nothing to do */ } libbalsa_smtp_server_unlock(info->smtp_server); send_message_info_destroy(info); (void) g_atomic_int_dec_and_test(&sending_threads); return NULL; } static void message_add_references(LibBalsaMessage *message, GMimeMessage *msg) { GList *list; /* If the message has references set, add them to the envelope */ list = libbalsa_message_get_references(message); if (list != NULL) { GString *str = g_string_new(NULL); do { if (str->len > 0) { g_string_append_c(str, ' '); } g_string_append_printf(str, "<%s>", (gchar *) list->data); } while ((list = list->next) != NULL); g_mime_object_set_header(GMIME_OBJECT(msg), "References", str->str, NULL); g_string_free(str, TRUE); } list = libbalsa_message_get_in_reply_to(message); if (list != NULL) { /* There's no specific header function for In-Reply-To */ g_mime_object_set_header(GMIME_OBJECT(msg), "In-Reply-To", list->data, NULL); } } static GList * get_mailbox_names(GList *list, InternetAddressList *address_list) { gint i, len; len = internet_address_list_length(address_list); for (i = 0; i < len; i++) { InternetAddress *ia = internet_address_list_get_address(address_list, i); if (INTERNET_ADDRESS_IS_MAILBOX(ia)) { list = g_list_append(list, g_strdup(((InternetAddressMailbox *) ia)->addr)); } else { list = get_mailbox_names(list, ((InternetAddressGroup *) ia)->members); } } return list; } static inline gboolean ia_list_not_empty(InternetAddressList *ial) { return (ial != NULL) && (internet_address_list_length(ial) > 0); } static LibBalsaMsgCreateResult create_mime_message(LibBalsaMessage *message, gboolean flow, gboolean postponing, GMimeMessage **return_message, GError **error) { GMimeObject *mime_root = NULL; GMimeMessage *mime_message; LibBalsaMessageBody *body; LibBalsaMessageHeaders *headers; gchar *tmp; GList *list; gboolean attach_pubkey = FALSE; GtkWindow *parent = g_object_get_data(G_OBJECT(message), "parent-window"); #ifdef ENABLE_AUTOCRYPT LibBalsaIdentity *identity; #endif /* ENABLE_AUTOCRYPT */ GDateTime *datetime; /* attach the public key only if we send the message, not if we just postpone it */ if (!postponing && libbalsa_message_get_attach_pubkey(message) && ((libbalsa_message_get_crypt_mode(message) & LIBBALSA_PROTECT_PROTOCOL) != 0)) { attach_pubkey = TRUE; } body = libbalsa_message_get_body_list(message); if ((body != NULL) && ((body->next != NULL) || attach_pubkey)) { mime_root = GMIME_OBJECT(g_mime_multipart_new_with_subtype(libbalsa_message_get_subtype(message))); } while (body != NULL) { GMimeObject *mime_part; mime_part = NULL; if ((body->file_uri != NULL) || (body->filename != NULL)) { gchar **mime_type; if (body->content_type != NULL) { mime_type = g_strsplit_set(body->content_type, "/;", 3); } else { const gchar *mt = libbalsa_vfs_get_mime_type(body->file_uri); mime_type = g_strsplit(mt, "/", 2); } if (body->attach_mode == LIBBALSA_ATTACH_AS_EXTBODY) { GMimeContentType *content_type = g_mime_content_type_new("message", "external-body"); mime_part = g_mime_object_new_type(libbalsa_parser_options(), "message", "external-body"); g_mime_object_set_content_type(mime_part, content_type); g_mime_part_set_content_encoding(GMIME_PART(mime_part), GMIME_CONTENT_ENCODING_7BIT); if (body->filename && !strncmp(body->filename, "URL", 3)) { g_mime_object_set_content_type_parameter(mime_part, "access-type", "URL"); g_mime_object_set_content_type_parameter(mime_part, "URL", body->filename + 4); } else { g_mime_object_set_content_type_parameter(mime_part, "access-type", "local-file"); g_mime_object_set_content_type_parameter(mime_part, "name", libbalsa_vfs_get_uri_utf8(body-> file_uri)); } lbs_set_content(GMIME_PART(mime_part), "Note: this is _not_ the real body!\n"); } else if (g_ascii_strcasecmp(mime_type[0], "message") == 0) { GMimeStream *stream; GMimeParser *parser; GMimeMessage *mime_msg; GError *err = NULL; stream = libbalsa_vfs_create_stream(body->file_uri, 0, FALSE, &err); if (!stream) { if (err != NULL) { gchar *msg = err->message ? g_strdup_printf(_("Cannot read %s: %s"), libbalsa_vfs_get_uri_utf8(body->file_uri), err->message) : g_strdup_printf(_("Cannot read %s"), libbalsa_vfs_get_uri_utf8(body->file_uri)); g_set_error(error, err->domain, err->code, "%s", msg); g_clear_error(&err); g_free(msg); } g_strfreev(mime_type); return LIBBALSA_MESSAGE_CREATE_ERROR; } parser = g_mime_parser_new_with_stream(stream); g_mime_parser_set_format(parser, GMIME_FORMAT_MESSAGE); g_object_unref(stream); mime_msg = g_mime_parser_construct_message(parser, libbalsa_parser_options()); g_object_unref(parser); mime_part = GMIME_OBJECT(g_mime_message_part_new_with_message (mime_type[1], mime_msg)); g_object_unref(mime_msg); } else { const gchar *charset = NULL; GMimeStream *stream; GMimeDataWrapper *content; GError *err = NULL; if ((g_ascii_strcasecmp(mime_type[0], "text") == 0) && ((charset = body->charset) == NULL)) { charset = libbalsa_vfs_get_charset(body->file_uri); if (charset == NULL) { static const gchar default_type[] = "application/octet-stream"; libbalsa_information(LIBBALSA_INFORMATION_WARNING, _("Cannot determine character set " "for text file “%s”; " "sending as MIME type “%s”"), libbalsa_vfs_get_uri_utf8(body->file_uri), default_type); g_strfreev(mime_type); mime_type = g_strsplit(default_type, "/", 2); } } /* use BASE64 encoding for non-text mime types use 8BIT for message */ mime_part = GMIME_OBJECT(g_mime_part_new_with_type(mime_type[0], mime_type[1])); g_mime_object_set_disposition(mime_part, body->attach_mode == LIBBALSA_ATTACH_AS_INLINE ? GMIME_DISPOSITION_INLINE : GMIME_DISPOSITION_ATTACHMENT); if (g_ascii_strcasecmp(mime_type[0], "text") != 0) { g_mime_part_set_content_encoding(GMIME_PART(mime_part), GMIME_CONTENT_ENCODING_BASE64); } else { /* is text */ g_mime_object_set_content_type_parameter(mime_part, "charset", charset); } g_mime_part_set_filename(GMIME_PART(mime_part), libbalsa_vfs_get_basename_utf8(body->file_uri)); stream = libbalsa_vfs_create_stream(body->file_uri, 0, FALSE, &err); if (!stream) { if (err != NULL) { gchar *msg = err->message ? g_strdup_printf(_("Cannot read %s: %s"), libbalsa_vfs_get_uri_utf8(body->file_uri), err->message) : g_strdup_printf(_("Cannot read %s"), libbalsa_vfs_get_uri_utf8(body->file_uri)); g_set_error(error, err->domain, err->code, "%s", msg); g_clear_error(&err); g_free(msg); } g_object_unref(mime_part); g_strfreev(mime_type); return LIBBALSA_MESSAGE_CREATE_ERROR; } content = g_mime_data_wrapper_new_with_stream(stream, GMIME_CONTENT_ENCODING_DEFAULT); g_object_unref(stream); g_mime_part_set_content(GMIME_PART(mime_part), content); g_object_unref(content); } g_strfreev(mime_type); } else if (body->buffer != NULL) { guint gpg_mode; guint use_gpg_mode; LibBalsaMsgCreateResult crypt_res = LIBBALSA_MESSAGE_CREATE_OK; /* in '2440 mode, touch *only* the first body! */ if (!postponing && (body == libbalsa_message_get_body_list(body->message)) && ((gpg_mode = libbalsa_message_get_crypt_mode(message)) != 0) && ((gpg_mode & LIBBALSA_PROTECT_OPENPGP) != 0)) { use_gpg_mode = gpg_mode; } else { use_gpg_mode = 0; } mime_part = add_mime_body_plain(body, flow, postponing, use_gpg_mode, &crypt_res, error); if (!mime_part) { if (mime_root != NULL) { g_object_unref(mime_root); } return crypt_res; } } if (mime_root != NULL) { g_mime_multipart_add(GMIME_MULTIPART(mime_root), GMIME_OBJECT(mime_part)); g_object_unref(mime_part); } else { mime_root = mime_part; } body = body->next; } if (attach_pubkey) { GMimePart *pubkey_part; pubkey_part = lb_create_pubkey_part(message, parent, error); if (pubkey_part == NULL) { if (mime_root != NULL) { g_object_unref(mime_root); } return LIBBALSA_MESSAGE_CREATE_ERROR; } if (mime_root != NULL) { g_mime_multipart_add(GMIME_MULTIPART(mime_root), GMIME_OBJECT(pubkey_part)); g_object_unref(pubkey_part); } else { mime_root = GMIME_OBJECT(pubkey_part); } } if ((libbalsa_message_get_body_list(message) != NULL) && !postponing) { LibBalsaMsgCreateResult crypt_res = do_multipart_crypto(message, &mime_root, parent, error); if (crypt_res != LIBBALSA_MESSAGE_CREATE_OK) { return crypt_res; } } mime_message = g_mime_message_new(TRUE); if (mime_root != NULL) { GList *param = libbalsa_message_get_parameters(message); while (param != NULL) { gchar **vals = (gchar **)param->data; g_mime_object_set_content_type_parameter(GMIME_OBJECT(mime_root), vals[0], vals[1]); param = param->next; } g_mime_message_set_mime_part(mime_message, mime_root); g_object_unref(mime_root); } message_add_references(message, mime_message); headers = libbalsa_message_get_headers(message); if (ia_list_not_empty(headers->from)) { InternetAddressList *from; from = g_mime_message_get_from(mime_message); internet_address_list_append(from, headers->from); } if (ia_list_not_empty(headers->reply_to)) { InternetAddressList *reply_to; reply_to = g_mime_message_get_reply_to(mime_message); internet_address_list_append(reply_to, headers->reply_to); } if (LIBBALSA_MESSAGE_GET_SUBJECT(message)) { g_mime_message_set_subject(mime_message, LIBBALSA_MESSAGE_GET_SUBJECT(message), NULL); } datetime = g_date_time_new_from_unix_local(headers->date); g_mime_message_set_date(mime_message, datetime); g_date_time_unref(datetime); if (ia_list_not_empty(headers->to_list)) { InternetAddressList *addresses = g_mime_message_get_addresses(mime_message, GMIME_ADDRESS_TYPE_TO); internet_address_list_append(addresses, headers->to_list); } if (ia_list_not_empty(headers->cc_list)) { InternetAddressList *addresses = g_mime_message_get_addresses(mime_message, GMIME_ADDRESS_TYPE_CC); internet_address_list_append(addresses, headers->cc_list); } if (ia_list_not_empty(headers->bcc_list)) { InternetAddressList *addresses = g_mime_message_get_addresses(mime_message, GMIME_ADDRESS_TYPE_BCC); internet_address_list_append(addresses, headers->bcc_list); } if (ia_list_not_empty(headers->dispnotify_to)) { tmp = internet_address_list_to_string(headers->dispnotify_to, NULL, TRUE); if (tmp != NULL) { g_mime_object_append_header(GMIME_OBJECT(mime_message), "Disposition-Notification-To", tmp, NULL); g_free(tmp); } } for (list = headers->user_hdrs; list; list = list->next) { gchar **pair = list->data; g_strchug(pair[1]); g_mime_object_append_header(GMIME_OBJECT(mime_message), pair[0], pair[1], NULL); g_debug("adding header '%s:%s'", pair[0], pair[1]); } tmp = g_strdup_printf("Balsa %s", VERSION); g_mime_object_append_header(GMIME_OBJECT(mime_message), "X-Mailer", tmp, NULL); g_free(tmp); #ifdef ENABLE_AUTOCRYPT /* add Autocrypt header if requested */ if (!postponing && ((identity = libbalsa_message_get_identity(message)) != NULL) && (libbalsa_identity_get_autocrypt_mode(identity) != AUTOCRYPT_DISABLE) && !autocrypt_ignore(g_mime_object_get_content_type(mime_root))) { tmp = autocrypt_header(identity, error); if (tmp == NULL) { g_object_unref(mime_message); return LIBBALSA_MESSAGE_CREATE_ERROR; } g_mime_object_append_header(GMIME_OBJECT(mime_message), "Autocrypt", tmp, NULL); g_free(tmp); } #endif libbalsa_message_set_mime_message(message, mime_message); /* message now holds a reference to mime_message, so we do not add one here: */ if (return_message != NULL) *return_message = mime_message; g_object_unref(mime_message); return LIBBALSA_MESSAGE_CREATE_OK; } /* When we postpone a message in the compose window, we lose track of * the message we were replying to. We *could* save some identifying * information in a dummy header, but it could still be hard to track it * down: it might have been filed in another mailbox, for instance. For * now, we'll just let it go... */ gboolean libbalsa_message_postpone(LibBalsaMessage *message, LibBalsaMailbox *draftbox, gchar **extra_headers, gboolean flow, GError **error) { GMimeMessage *mime_message; mime_message = libbalsa_message_get_mime_message(message); if (mime_message == NULL) { LibBalsaMsgCreateResult res = create_mime_message(message, flow, TRUE, &mime_message, error); if (res != LIBBALSA_MESSAGE_CREATE_OK) return FALSE; } if (extra_headers != NULL) { GMimeObject *object = GMIME_OBJECT(mime_message); gint i; for (i = 0; extra_headers[i] && extra_headers[i + 1]; i += 2) g_mime_object_set_header(object, extra_headers[i], extra_headers[i + 1], NULL); } return libbalsa_message_copy(message, draftbox, error); } static inline gchar base32_char(guint8 val) { val &= 0x1f; if (val <= 25) { return val + 'A'; } else { return val + '2' - 26; } } /* Create a message-id and set it on the mime message. */ static void libbalsa_set_message_id(GMimeMessage *mime_message) { static GMutex mutex; /* as to make me thread-safe... */ static GRand *rand = NULL; static struct { gint64 now_monotonic; gdouble randval; char user_name[16]; char host_name[16]; } id_data; GHmac *msg_id_hash; guint8 buffer[32]; gsize buflen; gchar *message_id; guint8 *src; gchar *dst; g_mutex_lock(&mutex); if (rand == NULL) { /* initialise some stuff on first-time use... */ rand = g_rand_new_with_seed((guint32) time(NULL)); strncpy(id_data.user_name, g_get_user_name(), sizeof(id_data.user_name) - 1); id_data.user_name[sizeof(id_data.user_name) - 1] = '\0'; strncpy(id_data.host_name, g_get_host_name(), sizeof(id_data.host_name) - 1); id_data.host_name[sizeof(id_data.host_name) - 1] = '\0'; } /* get some randomness... */ id_data.now_monotonic = g_get_monotonic_time(); id_data.randval = g_rand_double(rand); /* hash the buffer */ msg_id_hash = g_hmac_new(G_CHECKSUM_SHA256, (const guchar *) &id_data, sizeof(id_data)); buflen = sizeof(buffer); g_hmac_get_digest(msg_id_hash, buffer, &buflen); g_hmac_unref(msg_id_hash); g_mutex_unlock(&mutex); /* create a msg id string as base32-encoded string from the first * 30 bytes of the hashed result, and separate the groups by '.' * or '@' */ message_id = dst = g_malloc0(54U); /* = (32 / 5) * 9 */ src = buffer; while (buflen >= 5U) { *dst++ = base32_char(src[0] >> 3); *dst++ = base32_char((src[0] << 2) + (src[1] >> 6)); *dst++ = base32_char(src[1] >> 1); *dst++ = base32_char((src[1] << 4) + (src[2] >> 4)); *dst++ = base32_char((src[2] << 1) + (src[3] >> 7)); *dst++ = base32_char(src[3] >> 2); *dst++ = base32_char((src[3] << 3) + (src[4] >> 5)); *dst++ = base32_char(src[4]); src = &src[5]; buflen -= 5U; if (dst == &message_id[(54U / 2U) - 1U]) { *dst++ = '@'; } else if (buflen >= 5U) { *dst++ = '.'; } } g_mime_message_set_message_id(mime_message, message_id); g_free(message_id); } /* balsa_create_msg: copies message to msg. */ static LibBalsaMsgCreateResult libbalsa_create_msg(LibBalsaMessage *message, gboolean flow, GError **error) { GMimeMessage *mime_message; mime_message = libbalsa_message_get_mime_message(message); if (mime_message == NULL) { LibBalsaMsgCreateResult res = create_mime_message(message, flow, FALSE, &mime_message, error); if (res != LIBBALSA_MESSAGE_CREATE_OK) return res; } libbalsa_set_message_id(mime_message); return LIBBALSA_MESSAGE_CREATE_OK; } static LibBalsaMsgCreateResult libbalsa_fill_msg_queue_item_from_queu(LibBalsaMessage *message, MessageQueueItem *mqi) { GMimeStream *msg_stream; LibBalsaMsgCreateResult result = LIBBALSA_MESSAGE_CREATE_ERROR; mqi->orig = message; if (libbalsa_message_get_mime_message(message) != NULL) { LibBalsaMailbox *mailbox = libbalsa_message_get_mailbox(message); msg_stream = g_mime_stream_mem_new(); libbalsa_mailbox_lock_store(mailbox); g_mime_object_write_to_stream(GMIME_OBJECT(libbalsa_message_get_mime_message(message)), NULL, msg_stream); libbalsa_mailbox_unlock_store(mailbox); g_mime_stream_reset(msg_stream); } else { msg_stream = libbalsa_message_stream(message); } if (msg_stream != NULL) { GMimeStream *filter_stream; GMimeFilter *filter; filter_stream = g_mime_stream_filter_new(msg_stream); /* filter out unwanted headers */ filter = g_mime_filter_header_new(); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filter_stream), filter); g_object_unref(filter); /* add CRLF */ filter = g_mime_filter_unix2dos_new(FALSE); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filter_stream), filter); g_object_unref(filter); /* encode dot */ filter = g_mime_filter_smtp_data_new(); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filter_stream), filter); g_object_unref(filter); /* write to a new stream */ mqi->stream = g_mime_stream_mem_new(); g_mime_stream_write_to_stream(filter_stream, mqi->stream); g_object_unref(filter_stream); g_mime_stream_reset(mqi->stream); g_object_unref(msg_stream); g_object_ref(mqi->orig); result = LIBBALSA_MESSAGE_CREATE_OK; } return result; } /* * If the identity contains a forced key ID for the passed protocol, return the key ID. Otherwise, return the email address of the * "From:" address list to let GpeME automagically select the proper key. */ static const gchar * lb_send_from(LibBalsaMessage * message, gpgme_protocol_t protocol) { const gchar *from_id; const gchar *key_id; if ((protocol == GPGME_PROTOCOL_OpenPGP) && ((key_id = libbalsa_identity_get_force_gpg_key_id(libbalsa_message_get_identity(message))) != NULL) && (key_id[0] != '\0')) { from_id = key_id; } else if ((protocol == GPGME_PROTOCOL_CMS) && ((key_id = libbalsa_identity_get_force_smime_key_id(libbalsa_message_get_identity(message))) != NULL) && (key_id[0] != '\0')) { from_id = key_id; } else { InternetAddress *ia = internet_address_list_get_address(libbalsa_message_get_headers(message)->from, 0); while (INTERNET_ADDRESS_IS_GROUP(ia)) { ia = internet_address_list_get_address(((InternetAddressGroup *) ia)->members, 0); } from_id = ((InternetAddressMailbox *) ia)->addr; } return from_id; } static GMimePart * lb_create_pubkey_part(LibBalsaMessage *message, GtkWindow *parent, GError **error) { const gchar *key_id; gchar *keybuf; GMimePart *mime_part = NULL; key_id = lb_send_from(message, GPGME_PROTOCOL_OpenPGP); keybuf = libbalsa_gpgme_get_pubkey(GPGME_PROTOCOL_OpenPGP, key_id, parent, error); if (keybuf != NULL) { GMimeStream *stream; GMimeDataWrapper *wrapper; gchar *filename; mime_part = g_mime_part_new_with_type("application", "pgp-keys"); filename = g_strconcat(key_id, ".asc", NULL); g_mime_object_set_content_type_parameter(GMIME_OBJECT(mime_part), "name", filename); g_mime_object_set_disposition(GMIME_OBJECT(mime_part), GMIME_DISPOSITION_ATTACHMENT); g_mime_object_set_content_disposition_parameter(GMIME_OBJECT(mime_part), "filename", filename); g_free(filename); g_mime_part_set_content_encoding(mime_part, GMIME_CONTENT_ENCODING_7BIT); stream = g_mime_stream_mem_new(); g_mime_stream_write(stream, keybuf, strlen(keybuf)); g_free(keybuf); wrapper = g_mime_data_wrapper_new(); g_mime_data_wrapper_set_stream(wrapper, stream); g_object_unref(stream); g_mime_part_set_content(mime_part, wrapper); g_object_unref(wrapper); } return mime_part; } static LibBalsaMsgCreateResult libbalsa_create_rfc2440_buffer(LibBalsaMessage *message, GMimePart *mime_part, GtkWindow *parent, GError **error) { guint mode = libbalsa_message_get_crypt_mode(message); gboolean always_trust = libbalsa_message_get_always_trust(message); switch (mode & LIBBALSA_PROTECT_MODE) { case LIBBALSA_PROTECT_SIGN: /* sign only */ if (!libbalsa_rfc2440_sign_encrypt(mime_part, lb_send_from(message, GPGME_PROTOCOL_OpenPGP), NULL, FALSE, parent, error)) { return LIBBALSA_MESSAGE_SIGN_ERROR; } break; case LIBBALSA_PROTECT_ENCRYPT: case LIBBALSA_PROTECT_SIGN | LIBBALSA_PROTECT_ENCRYPT: { LibBalsaMessageHeaders *headers = libbalsa_message_get_headers(message); GList *encrypt_for = NULL; gboolean result; /* build a list containing the addresses of all to:, cc: and the from: address. Note: don't add bcc: addresses as they would be visible in the encrypted block. */ encrypt_for = get_mailbox_names(encrypt_for, headers->to_list); encrypt_for = get_mailbox_names(encrypt_for, headers->cc_list); encrypt_for = get_mailbox_names(encrypt_for, headers->from); if ((headers->bcc_list != NULL) && (internet_address_list_length(headers->bcc_list) > 0)) { libbalsa_information (LIBBALSA_INFORMATION_WARNING, ngettext("This message will not be encrypted " "for the BCC: recipient.", "This message will not be encrypted " "for the BCC: recipients.", internet_address_list_length (headers->bcc_list))); } if (mode & LIBBALSA_PROTECT_SIGN) { result = libbalsa_rfc2440_sign_encrypt(mime_part, lb_send_from(message, GPGME_PROTOCOL_OpenPGP), encrypt_for, always_trust, parent, error); } else { result = libbalsa_rfc2440_sign_encrypt(mime_part, NULL, encrypt_for, always_trust, parent, error); } g_list_free_full(encrypt_for, g_free); if (!result) { return LIBBALSA_MESSAGE_ENCRYPT_ERROR; } } break; default: g_assert_not_reached(); } return LIBBALSA_MESSAGE_CREATE_OK; } /* handle rfc2633 and rfc3156 signing and/or encryption of a message */ static LibBalsaMsgCreateResult do_multipart_crypto(LibBalsaMessage *message, GMimeObject **mime_root, GtkWindow *parent, GError **error) { guint mode; gpgme_protocol_t protocol; gboolean always_trust; mode = libbalsa_message_get_crypt_mode(message); /* check if we shall do any protection */ if ((mode & LIBBALSA_PROTECT_MODE) == 0) { return LIBBALSA_MESSAGE_CREATE_OK; } /* check which protocol should be used */ if (mode & LIBBALSA_PROTECT_RFC3156) { protocol = GPGME_PROTOCOL_OpenPGP; } else if (mode & LIBBALSA_PROTECT_SMIME) { protocol = GPGME_PROTOCOL_CMS; } else if (mode & LIBBALSA_PROTECT_OPENPGP) { return LIBBALSA_MESSAGE_CREATE_OK; /* already done... */ } else { return LIBBALSA_MESSAGE_ENCRYPT_ERROR; /* hmmm.... */ } always_trust = libbalsa_message_get_always_trust(message); /* sign and/or encrypt */ switch (mode & LIBBALSA_PROTECT_MODE) { case LIBBALSA_PROTECT_SIGN: /* sign message */ if (!libbalsa_sign_mime_object(mime_root, lb_send_from(message, protocol), protocol, parent, error)) { return LIBBALSA_MESSAGE_SIGN_ERROR; } break; case LIBBALSA_PROTECT_ENCRYPT: case LIBBALSA_PROTECT_ENCRYPT | LIBBALSA_PROTECT_SIGN: { LibBalsaMessageHeaders *headers = libbalsa_message_get_headers(message); GList *encrypt_for = NULL; gboolean success; /* build a list containing the addresses of all to:, cc: and the from: address. Note: don't add bcc: addresses as they would be visible in the encrypted block. */ encrypt_for = get_mailbox_names(encrypt_for, headers->to_list); encrypt_for = get_mailbox_names(encrypt_for, headers->cc_list); encrypt_for = g_list_append(encrypt_for, g_strdup(lb_send_from(message, protocol))); if (headers->bcc_list && (internet_address_list_length(headers-> bcc_list) > 0)) { libbalsa_information (LIBBALSA_INFORMATION_WARNING, ngettext("This message will not be encrypted " "for the BCC: recipient.", "This message will not be encrypted " "for the BCC: recipients.", internet_address_list_length (headers->bcc_list))); } if ((libbalsa_message_get_crypt_mode(message) & LIBBALSA_PROTECT_SIGN) != 0) { success = libbalsa_sign_encrypt_mime_object(mime_root, lb_send_from(message, protocol), encrypt_for, protocol, always_trust, parent, error); } else { success = libbalsa_encrypt_mime_object(mime_root, encrypt_for, protocol, always_trust, parent, error); } g_list_free_full(encrypt_for, (GDestroyNotify) g_free); if (!success) { return LIBBALSA_MESSAGE_ENCRYPT_ERROR; } break; } default: g_error("illegal gpg_mode %d (" __FILE__ " line %d)", mode, __LINE__); } return LIBBALSA_MESSAGE_CREATE_OK; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/send.h000066400000000000000000000056571477646064400233120ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __SEND_H__ #define __SEND_H__ #ifndef BALSA_VERSION # error "Include config.h before this file." #endif #include "libbalsa.h" typedef LibBalsaMailbox* (*LibBalsaFccboxFinder)(const gchar *url); typedef enum _LibBalsaMsgCreateResult LibBalsaMsgCreateResult; enum _LibBalsaMsgCreateResult { LIBBALSA_MESSAGE_CREATE_OK, LIBBALSA_MESSAGE_SIGN_ERROR, LIBBALSA_MESSAGE_ENCRYPT_ERROR, LIBBALSA_MESSAGE_CREATE_ERROR, LIBBALSA_MESSAGE_QUEUE_ERROR, LIBBALSA_MESSAGE_SAVE_ERROR, LIBBALSA_MESSAGE_SEND_ERROR, LIBBALSA_MESSAGE_SERVER_ERROR }; gboolean libbalsa_message_postpone(LibBalsaMessage * message, LibBalsaMailbox * draftbox, gchar ** extra_headers, gboolean flow, GError **error); LibBalsaMsgCreateResult libbalsa_message_queue(LibBalsaMessage* message, LibBalsaMailbox* outbox, LibBalsaMailbox* fccbox, LibBalsaSmtpServer * smtp_server, gboolean flow, GError ** error); LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage *message, LibBalsaMailbox *outbox, LibBalsaMailbox *fccbox, LibBalsaFccboxFinder finder, LibBalsaSmtpServer *smtp_server, gboolean show_progress, GtkWindow *parent, gboolean flow, GError **error); void libbalsa_process_queue(LibBalsaMailbox *outbox, LibBalsaFccboxFinder finder, GSList *smtp_servers, gboolean show_progress, GtkWindow *parent); void libbalsa_auto_send_init(GSourceFunc auto_send_cb); void libbalsa_auto_send_config(gboolean enable, guint timeout_minutes); #endif /* __SEND_H__ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/server-config.c000066400000000000000000000552761477646064400251270ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2018 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include "misc.h" #include "net-client-smtp.h" #include "net-client-pop.h" #include "imap-handle.h" #include "libbalsa-conf.h" #include "server-config.h" #ifdef G_LOG_DOMAIN # undef G_LOG_DOMAIN #endif #define G_LOG_DOMAIN "libbalsa-server" struct _LibBalsaServerCfg { GtkNotebook parent; /* "Basic" notebook page */ GtkWidget *basic_grid; /* grid */ guint basic_rows; /* count of rows */ GtkWidget *name; /* descriptive name */ GtkWidget *host_port; /* host and optionally port */ GtkWidget *probe_host; /* button for probing the host */ GtkWidget *security; /* security (SSL/TLS/...) */ GtkWidget *auth_mode; /* authentication mode */ GtkWidget *username; /* user name for authentication */ GtkWidget *password; /* password for authentication */ GtkWidget *remember_pass; /* remember password */ /* "Advanced" notebook page */ GtkWidget *advanced_grid; /* grid */ guint advanced_rows; /* count of rows */ GtkWidget *require_cert; /* require a client certificate */ GtkWidget *cert_file; /* client certificate file name */ GtkWidget *cert_pass; /* client certificate pass phrase */ GtkWidget *remember_cert_pass; /* remember certificate pass phrase */ /* function for probing a server's capabilities */ gboolean (*probe_fn)(const gchar *, guint, NetClientProbeResult *, GCallback, GError **); gboolean cfg_valid; /* whether the config options are valid (parent may enable OK) */ }; G_DEFINE_TYPE(LibBalsaServerCfg, libbalsa_server_cfg, GTK_TYPE_NOTEBOOK) static GtkWidget *server_cfg_add_entry(GtkWidget *grid, guint row, const gchar *label, const gchar *value, GCallback callback, GtkWidget *button, gpointer cb_data) G_GNUC_WARN_UNUSED_RESULT; static GtkWidget *server_cfg_add_check(GtkWidget *grid, guint row, const gchar *label, gboolean value, GCallback callback, gpointer cb_data) G_GNUC_WARN_UNUSED_RESULT; static void server_cfg_add_widget(GtkWidget *grid, guint row, const gchar *text, GtkWidget *widget); static GtkWidget *server_cfg_security_widget(LibBalsaServer *server); static GtkWidget *server_cfg_auth_widget(LibBalsaServer *server); static void on_server_cfg_changed(GtkWidget *widget, LibBalsaServerCfg *server_cfg); static void on_server_probe(GtkWidget *widget, LibBalsaServerCfg *server_cfg); static guint changed_sig; static const gchar *remember_password_message[4] = { N_("_Remember user password in Secret Service"), N_("_Remember certificate pass phrase in Secret Service"), N_("_Remember user password"), N_("_Remember certificate pass phrase") }; LibBalsaServerCfg * libbalsa_server_cfg_new(LibBalsaServer *server, const gchar *name) { LibBalsaServerCfg *server_cfg; const gchar *protocol; const gchar *cert_file; int pwd_msg_offs; g_return_val_if_fail(LIBBALSA_IS_SERVER(server), NULL); #if defined(HAVE_LIBSECRET) pwd_msg_offs = libbalsa_conf_use_libsecret() ? 0 : 2; #else pwd_msg_offs = 2; #endif server_cfg = LIBBALSA_SERVER_CFG(g_object_new(libbalsa_server_cfg_get_type(), NULL)); /* notebook page with basic options */ server_cfg->basic_grid = libbalsa_create_grid(); server_cfg->basic_rows = 0U; gtk_container_set_border_width(GTK_CONTAINER(server_cfg->basic_grid), 2 * HIG_PADDING); gtk_notebook_append_page(GTK_NOTEBOOK(server_cfg), server_cfg->basic_grid, gtk_label_new_with_mnemonic(_("_Basic"))); /* server descriptive name */ server_cfg->name = server_cfg_add_entry(server_cfg->basic_grid, server_cfg->basic_rows++, _("_Descriptive Name:"), name, G_CALLBACK(on_server_cfg_changed), NULL, server_cfg); /* probe button */ server_cfg->probe_host = gtk_button_new_from_icon_name("system-run", GTK_ICON_SIZE_MENU); gtk_button_set_label(GTK_BUTTON(server_cfg->probe_host), _("probe…")); gtk_button_set_always_show_image(GTK_BUTTON(server_cfg->probe_host), TRUE); g_signal_connect(server_cfg->probe_host, "clicked", G_CALLBACK(on_server_probe), server_cfg); protocol = libbalsa_server_get_protocol(server); if (strcmp(protocol, "smtp") == 0) { server_cfg->probe_fn = net_client_smtp_probe; } else if (strcmp(protocol, "pop3") == 0) { server_cfg->probe_fn = net_client_pop_probe; } else if (strcmp(protocol, "imap") == 0) { server_cfg->probe_fn = imap_server_probe; } else { g_assert_not_reached(); } /* host and port */ server_cfg->host_port = server_cfg_add_entry(server_cfg->basic_grid, server_cfg->basic_rows++, _("_Server:"), libbalsa_server_get_host(server), G_CALLBACK(on_server_cfg_changed), server_cfg->probe_host, server_cfg); /* security settings */ server_cfg->security = server_cfg_security_widget(server); server_cfg_add_widget(server_cfg->basic_grid, server_cfg->basic_rows++, _("Se_curity:"), server_cfg->security); g_signal_connect(server_cfg->security, "changed", G_CALLBACK(on_server_cfg_changed), server_cfg); /* authentication mode */ server_cfg->auth_mode = server_cfg_auth_widget(server); server_cfg_add_widget(server_cfg->basic_grid, server_cfg->basic_rows++, _("_Authentication:"), server_cfg->auth_mode); g_signal_connect(server_cfg->auth_mode, "changed", G_CALLBACK(on_server_cfg_changed), server_cfg); /* user name and password */ server_cfg->username = server_cfg_add_entry(server_cfg->basic_grid, server_cfg->basic_rows++, _("_User Name:"), libbalsa_server_get_user(server), G_CALLBACK(on_server_cfg_changed), NULL, server_cfg); server_cfg->password = server_cfg_add_entry(server_cfg->basic_grid, server_cfg->basic_rows++, _("_Pass Phrase:"), libbalsa_server_get_password(server), G_CALLBACK(on_server_cfg_changed), NULL, server_cfg); libbalsa_entry_config_passwd(GTK_ENTRY(server_cfg->password)); server_cfg->remember_pass = server_cfg_add_check(server_cfg->basic_grid, server_cfg->basic_rows++, remember_password_message[pwd_msg_offs], libbalsa_server_get_remember_password(server), G_CALLBACK(on_server_cfg_changed), server_cfg); /* notebook page with advanced options */ server_cfg->advanced_grid = libbalsa_create_grid(); server_cfg->advanced_rows = 0U; gtk_container_set_border_width(GTK_CONTAINER(server_cfg->advanced_grid), 2 * HIG_PADDING); gtk_notebook_append_page(GTK_NOTEBOOK(server_cfg), server_cfg->advanced_grid, gtk_label_new_with_mnemonic(_("_Advanced"))); /* client certificate and passphrase */ server_cfg->require_cert = server_cfg_add_check(server_cfg->advanced_grid, server_cfg->advanced_rows++, _("Server _requires client certificate"), libbalsa_server_get_client_cert(server), G_CALLBACK(on_server_cfg_changed), server_cfg); server_cfg->cert_file = gtk_file_chooser_button_new(_("Choose Client Certificate"), GTK_FILE_CHOOSER_ACTION_OPEN); server_cfg_add_widget(server_cfg->advanced_grid, server_cfg->advanced_rows++, _("Certificate _File:"), server_cfg->cert_file); cert_file = libbalsa_server_get_cert_file(server); if (cert_file != NULL) { gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(server_cfg->cert_file), cert_file); } g_signal_connect(server_cfg->cert_file, "file-set", G_CALLBACK(on_server_cfg_changed), server_cfg); server_cfg->cert_pass = server_cfg_add_entry(server_cfg->advanced_grid, server_cfg->advanced_rows++, _("Certificate _Pass Phrase:"), libbalsa_server_get_cert_passphrase(server), G_CALLBACK(on_server_cfg_changed), NULL, server_cfg); libbalsa_entry_config_passwd(GTK_ENTRY(server_cfg->cert_pass)); server_cfg->remember_cert_pass = server_cfg_add_check(server_cfg->advanced_grid, server_cfg->advanced_rows++, remember_password_message[pwd_msg_offs + 1], libbalsa_server_get_remember_cert_passphrase(server), G_CALLBACK(on_server_cfg_changed), server_cfg); /* initially run the validity check */ on_server_cfg_changed(NULL, server_cfg); return server_cfg; } gboolean libbalsa_server_cfg_valid(LibBalsaServerCfg *server_cfg) { g_return_val_if_fail(LIBBALSA_IS_SERVER_CFG(server_cfg), FALSE); return server_cfg->cfg_valid; } GtkWidget * libbalsa_server_cfg_add_check(LibBalsaServerCfg *server_cfg, gboolean basic, const gchar *label, gboolean initval, GCallback callback, gpointer cb_data) { GtkWidget *new_check; g_return_val_if_fail(LIBBALSA_IS_SERVER_CFG(server_cfg) && (label != NULL), NULL); if (basic) { new_check = server_cfg_add_check(server_cfg->basic_grid, server_cfg->basic_rows++, label, initval, callback, cb_data); } else { new_check = server_cfg_add_check(server_cfg->advanced_grid, server_cfg->advanced_rows++, label, initval, callback, cb_data); } return new_check; } GtkWidget * libbalsa_server_cfg_add_entry(LibBalsaServerCfg *server_cfg, gboolean basic, const gchar *label, const gchar *initval, GCallback callback, gpointer cb_data) { GtkWidget *new_entry; g_return_val_if_fail(LIBBALSA_IS_SERVER_CFG(server_cfg) && (label != NULL), NULL); if (basic) { new_entry = server_cfg_add_entry(server_cfg->basic_grid, server_cfg->basic_rows++, label, initval, callback, NULL, cb_data); } else { new_entry = server_cfg_add_entry(server_cfg->advanced_grid, server_cfg->advanced_rows++, label, initval, callback, NULL, cb_data); } return new_entry; } void libbalsa_server_cfg_add_item(LibBalsaServerCfg *server_cfg, gboolean basic, const gchar *label, GtkWidget *widget) { g_return_if_fail(LIBBALSA_IS_SERVER_CFG(server_cfg) && (label != NULL) && (widget != NULL)); if (basic) { server_cfg_add_widget(server_cfg->basic_grid, server_cfg->basic_rows++, label, widget); } else { server_cfg_add_widget(server_cfg->advanced_grid, server_cfg->advanced_rows++, label, widget); } } void libbalsa_server_cfg_add_row(LibBalsaServerCfg *server_cfg, gboolean basic, GtkWidget *left, GtkWidget *right) { GtkGrid *dest; guint *dest_row; g_return_if_fail(LIBBALSA_IS_SERVER_CFG(server_cfg) && (left != NULL)); if (basic) { dest = GTK_GRID(server_cfg->basic_grid); dest_row = &server_cfg->basic_rows; } else { dest = GTK_GRID(server_cfg->advanced_grid); dest_row = &server_cfg->advanced_rows; } if (right != NULL) { gtk_grid_attach(GTK_GRID(dest), left, 0, *dest_row, 1, 1); gtk_grid_attach(GTK_GRID(dest), right, 1, *dest_row, 2, 1); } else { gtk_grid_attach(GTK_GRID(dest), left, 0, *dest_row, 2, 1); } *dest_row += 1; } const gchar * libbalsa_server_cfg_get_name(LibBalsaServerCfg *server_cfg) { g_return_val_if_fail(LIBBALSA_IS_SERVER_CFG(server_cfg), FALSE); return gtk_entry_get_text(GTK_ENTRY(server_cfg->name)); } /* note: name is special, see libbalsa_server_cfg_get_name() */ void libbalsa_server_cfg_assign_server(LibBalsaServerCfg *server_cfg, LibBalsaServer *server) { gchar *cert_file; g_return_if_fail(LIBBALSA_IS_SERVER_CFG(server_cfg) && LIBBALSA_IS_SERVER(server)); /* host, post and security */ libbalsa_server_set_security(server, (NetClientCryptMode) (gtk_combo_box_get_active(GTK_COMBO_BOX(server_cfg->security)) + 1)); libbalsa_server_set_host(server, gtk_entry_get_text(GTK_ENTRY(server_cfg->host_port)), libbalsa_server_get_security(server)); /* authentication stuff */ libbalsa_server_set_auth_mode(server, atoi(gtk_combo_box_get_active_id(GTK_COMBO_BOX(server_cfg->auth_mode)))); libbalsa_server_set_username(server, gtk_entry_get_text(GTK_ENTRY(server_cfg->username))); libbalsa_server_set_password(server, gtk_entry_get_text(GTK_ENTRY(server_cfg->password)), FALSE); libbalsa_server_set_remember_password(server, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(server_cfg->remember_pass))); /* client certificate */ libbalsa_server_set_client_cert(server, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(server_cfg->require_cert))); cert_file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(server_cfg->cert_file)); libbalsa_server_set_cert_file(server, cert_file); g_free(cert_file); libbalsa_server_set_password(server, gtk_entry_get_text(GTK_ENTRY(server_cfg->cert_pass)), TRUE); libbalsa_server_set_remember_cert_passphrase(server, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(server_cfg->remember_cert_pass))); } /* -- local stuff --------------------------------------------------------------------------------------------------------------- */ static void libbalsa_server_cfg_class_init(LibBalsaServerCfgClass *klass) { changed_sig = g_signal_new("changed", LIBBALSA_TYPE_SERVER_CFG, G_SIGNAL_RUN_LAST, 0U, NULL, NULL, NULL, G_TYPE_NONE, 0U); } static void libbalsa_server_cfg_init(LibBalsaServerCfg *self) { /* Nothing to do */ } static GtkWidget * server_cfg_add_entry(GtkWidget *grid, guint row, const gchar *label, const gchar *value, GCallback callback, GtkWidget *button, gpointer cb_data) { GtkWidget *new_entry; new_entry = gtk_entry_new(); if (button != NULL) { GtkWidget *hbox; hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, HIG_PADDING); server_cfg_add_widget(grid, row, label, hbox); gtk_widget_set_hexpand(new_entry, TRUE); gtk_widget_set_halign(new_entry, GTK_ALIGN_FILL); gtk_container_add(GTK_CONTAINER(hbox), new_entry); gtk_container_add(GTK_CONTAINER(hbox), button); } else { server_cfg_add_widget(grid, row, label, new_entry); } if (value != NULL) { gtk_entry_set_text(GTK_ENTRY(new_entry), value); } if (callback != NULL) { g_signal_connect(new_entry, "changed", callback, cb_data); } return new_entry; } static GtkWidget * server_cfg_add_check(GtkWidget *grid, guint row, const gchar *label, gboolean value, GCallback callback, gpointer cb_data) { GtkWidget *new_check; new_check = libbalsa_create_grid_check(label, grid, row, value); if (callback != NULL) { g_signal_connect(new_check, "toggled", callback, cb_data); } return new_check; } static void server_cfg_add_widget(GtkWidget *grid, guint row, const gchar *text, GtkWidget *widget) { GtkWidget *label; label = libbalsa_create_grid_label(text, grid, row); gtk_widget_set_hexpand(widget, TRUE); gtk_grid_attach(GTK_GRID(grid), widget, 1, row, 1, 1); gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget); } /** * \note Make sure that the order of entries in the combo matches the order of enum _NetClientCryptMode items. If calling * gtk_combo_box_get_active() on the returned widget, remember it starts with 0, so compensate for the offset of * NET_CLIENT_CRYPT_ENCRYPTED. */ static GtkWidget * server_cfg_security_widget(LibBalsaServer *server) { GtkWidget *combo_box = gtk_combo_box_text_new(); gchar *proto_upper; gchar *ssl_label; proto_upper = g_ascii_strup(libbalsa_server_get_protocol(server), -1); ssl_label = g_strdup_printf(_("%s over SSL (%sS)"), proto_upper, proto_upper); g_free(proto_upper); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), ssl_label); g_free(ssl_label); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), _("TLS required")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), _("TLS if possible (not recommended)")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), _("None (not recommended)")); gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), (gint) libbalsa_server_get_security(server) - 1); return combo_box; } static GtkWidget * server_cfg_auth_widget(LibBalsaServer *server) { const gchar *protocol; GtkWidget *combo_box = gtk_combo_box_text_new(); gchar id_buf[8]; protocol = libbalsa_server_get_protocol(server); if ((strcmp(protocol, "pop3") == 0) || (strcmp(protocol, "imap") == 0)) { gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box), "1", _("anonymous access")); /* RFC 4505 */ } else { gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box), "1", _("none required")); } gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box), "2", _("user name and pass phrase")); #if defined(HAVE_GSSAPI) gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box), "4", _("Kerberos (GSSAPI)")); #endif snprintf(id_buf, sizeof(id_buf), "%d", (gint) libbalsa_server_get_auth_mode(server)); gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo_box), id_buf); return combo_box; } static void on_server_cfg_changed(GtkWidget *widget, LibBalsaServerCfg *server_cfg) { const gchar *active_auth; gboolean sensitive; NetClientAuthMode auth_mode; /* valid configuration only if a name and a host have been given */ server_cfg->cfg_valid = (*gtk_entry_get_text(GTK_ENTRY(server_cfg->name)) != '\0') && (*gtk_entry_get_text(GTK_ENTRY(server_cfg->host_port)) != '\0'); /* can probe only if name and host/port are given */ gtk_widget_set_sensitive(server_cfg->probe_host, server_cfg->cfg_valid); /* user name/password depend upon auth mode */ active_auth = gtk_combo_box_get_active_id(GTK_COMBO_BOX(server_cfg->auth_mode)); if (active_auth != 0) { auth_mode = atoi(active_auth); } else { auth_mode = 0; } gtk_widget_set_sensitive(server_cfg->username, auth_mode != NET_CLIENT_AUTH_NONE_ANON); gtk_widget_set_sensitive(server_cfg->password, auth_mode == NET_CLIENT_AUTH_USER_PASS); gtk_widget_set_sensitive(server_cfg->remember_pass, auth_mode == NET_CLIENT_AUTH_USER_PASS); /* invalid configuration if authentication is required, but no user name given */ if ((auth_mode != NET_CLIENT_AUTH_NONE_ANON) && (*gtk_entry_get_text(GTK_ENTRY(server_cfg->username)) == '\0')) { server_cfg->cfg_valid = FALSE; } /* client certificate and passphrase stuff only if TLS/SSL is enabled */ sensitive = (NetClientCryptMode) (gtk_combo_box_get_active(GTK_COMBO_BOX(server_cfg->security)) + 1) != NET_CLIENT_CRYPT_NONE; gtk_widget_set_sensitive(server_cfg->require_cert, sensitive); if (sensitive) { sensitive = sensitive && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(server_cfg->require_cert)); } gtk_widget_set_sensitive(server_cfg->cert_file, sensitive); gtk_widget_set_sensitive(server_cfg->cert_pass, sensitive); gtk_widget_set_sensitive(server_cfg->remember_cert_pass, sensitive); /* invalid configuration if a certificate is required, but no file name given */ if (sensitive) { gchar *cert_file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(server_cfg->cert_file)); if ((cert_file == NULL) || (cert_file[0] == '\0')) { server_cfg->cfg_valid = FALSE; } g_free(cert_file); } g_signal_emit(server_cfg, changed_sig, 0); } typedef struct { LibBalsaServerCfg *server_cfg; char *server_name; NetClientProbeResult probe_res; } on_server_probe_data_t; static void on_server_probe_response(GtkDialog *self, gint response_id, gpointer user_data); static void on_server_probe(GtkWidget *widget, LibBalsaServerCfg *server_cfg) { const gchar *server_name; gboolean success; NetClientProbeResult probe_res; GError *error = NULL; GtkWidget *msgdlg; on_server_probe_data_t *data; server_name = gtk_entry_get_text(GTK_ENTRY(server_cfg->host_port)); g_assert(server_cfg->probe_fn != NULL); success = server_cfg->probe_fn(server_name, 5, &probe_res, G_CALLBACK(libbalsa_server_check_cert), &error); if (success) { const gchar *crypt_str; const gchar *auth_str; GtkDialogFlags flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | libbalsa_dialog_flags(); switch (probe_res.crypt_mode) { case NET_CLIENT_CRYPT_ENCRYPTED: crypt_str = _("yes (SSL/TLS)"); break; case NET_CLIENT_CRYPT_STARTTLS: crypt_str = _("yes (STARTTLS)"); break; default: crypt_str = _("no"); } if ((probe_res.auth_mode & NET_CLIENT_AUTH_KERBEROS) != 0) { auth_str = _("Kerberos (GSSAPI)"); probe_res.auth_mode = NET_CLIENT_AUTH_KERBEROS; } else if ((probe_res.auth_mode & NET_CLIENT_AUTH_USER_PASS) != 0) { auth_str = _("user name and pass phrase"); probe_res.auth_mode = NET_CLIENT_AUTH_USER_PASS; } else { auth_str = _("none"); probe_res.auth_mode = NET_CLIENT_AUTH_NONE_ANON; } msgdlg = gtk_message_dialog_new(NULL, flags, GTK_MESSAGE_INFO, GTK_BUTTONS_NONE, _("Probe results for server %s\n" "\342\200\242 Port: %u\n" "\342\200\242 Encryption: %s\n" "\342\200\242 Authentication: %s\n"), server_name, probe_res.port, crypt_str, auth_str); gtk_dialog_add_button(GTK_DIALOG(msgdlg), _("_Apply"), GTK_RESPONSE_APPLY); gtk_dialog_add_button(GTK_DIALOG(msgdlg), _("_Close"), GTK_RESPONSE_CLOSE); } else { msgdlg = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT | libbalsa_dialog_flags(), GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Error probing server %s: %s"), server_name, (error != NULL) ? error->message : _("unknown")); } g_clear_error(&error); data = g_new(on_server_probe_data_t, 1); data->server_cfg = g_object_ref(server_cfg); data->server_name = g_strdup(server_name); data->probe_res = probe_res; g_signal_connect(msgdlg, "response", G_CALLBACK(on_server_probe_response), data); gtk_widget_show_all(msgdlg); } static void on_server_probe_response(GtkDialog *self, gint response_id, gpointer user_data) { on_server_probe_data_t *data = user_data; gtk_widget_destroy(GTK_WIDGET(self)); if (response_id == GTK_RESPONSE_APPLY) { gchar *buffer; gchar id_buf[8]; const gchar *colon; colon = strchr(data->server_name, ':'); if (colon == NULL) { buffer = g_strdup_printf("%s:%u", data->server_name, data->probe_res.port); } else { buffer = g_strdup_printf("%.*s:%u", (int) (colon - data->server_name), data->server_name, data->probe_res.port); } gtk_entry_set_text(GTK_ENTRY(data->server_cfg->host_port), buffer); g_free(buffer); gtk_combo_box_set_active(GTK_COMBO_BOX(data->server_cfg->security), data->probe_res.crypt_mode - 1); snprintf(id_buf, sizeof(id_buf), "%d", data->probe_res.auth_mode); gtk_combo_box_set_active_id(GTK_COMBO_BOX(data->server_cfg->auth_mode), id_buf); } g_object_unref(data->server_cfg); g_free(data->server_name); g_free(data); } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/server-config.h000066400000000000000000000114731477646064400251230ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2018 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef LIBBALSA_SERVER_CONFIG_H_ #define LIBBALSA_SERVER_CONFIG_H_ #include #include "server.h" #ifndef BALSA_VERSION # error "Include config.h before this file." #endif #define LIBBALSA_TYPE_SERVER_CFG (libbalsa_server_cfg_get_type()) G_DECLARE_FINAL_TYPE(LibBalsaServerCfg, libbalsa_server_cfg, LIBBALSA, SERVER_CFG, GtkNotebook) /** @brief Create a new server configuration widget * @param server server data, must not be NULL * @param name name, may be NULL * @return a newly allocated and populated server configuration notebook widget */ LibBalsaServerCfg *libbalsa_server_cfg_new(LibBalsaServer *server, const gchar *name) G_GNUC_WARN_UNUSED_RESULT; /** @brief Check if the server configuration is valid * @param server_cfg server configuration widget * @return TRUE if the configuration is valid, i.e. all mandatory fields are filled in */ gboolean libbalsa_server_cfg_valid(LibBalsaServerCfg *server_cfg); /** @brief Add a custom widget to the server configuration * @param server_cfg server configuration widget * @param basic TRUE to append the widget to the @em Basic or FALSE to the @em Advanced page * @param label widget label, must not be NULL * @param widget widget to append, must not be NULL */ void libbalsa_server_cfg_add_item(LibBalsaServerCfg *server_cfg, gboolean basic, const gchar *label, GtkWidget *widget); /** @brief Add custom widgets to the server configuration * @param server_cfg server configuration widget * @param basic TRUE to append the widget to the @em Basic or FALSE to the @em Advanced page * @param left widget in the left grid column, must not be NULL * @param right widget in the right grid column, may be NULL if the left widget shall span over both grid columns */ void libbalsa_server_cfg_add_row(LibBalsaServerCfg *server_cfg, gboolean basic, GtkWidget *left, GtkWidget *right); /** @brief Add a custom check box to the server configuration * @param server_cfg server configuration widget * @param basic TRUE to append the widget to the @em Basic or FALSE to the @em Advanced page * @param label widget label, must not be NULL * @param initval initial check box value * @param callback callback function for the @em toggled signal, may be NULL * @param cb_data data to pass to the callback * @return a new GtkCheckButton */ GtkWidget *libbalsa_server_cfg_add_check(LibBalsaServerCfg *server_cfg, gboolean basic, const gchar *label, gboolean initval, GCallback callback, gpointer cb_data) G_GNUC_WARN_UNUSED_RESULT; /** @brief Add a custom entry to the server configuration * @param server_cfg server configuration widget * @param basic TRUE to append the widget to the @em Basic or FALSE to the @em Advanced page * @param label widget label, must not be NULL * @param initval initial entry value, may be NULL * @param callback callback function for the @em changed signal, may be NULL * @param cb_data data to pass to the callback * @return a new GtkEntry */ GtkWidget *libbalsa_server_cfg_add_entry(LibBalsaServerCfg *server_cfg, gboolean basic, const gchar *label, const gchar *initval, GCallback callback, gpointer cb_data) G_GNUC_WARN_UNUSED_RESULT; /** @brief Get the name of the server configuration * @param server_cfg server configuration widget * @return the name entered in the Descriptive Name GtkEntry */ const gchar *libbalsa_server_cfg_get_name(LibBalsaServerCfg *server_cfg); /** @brief Get the server configuration * @param server_cfg server configuration widget * @param server server data, must not be NULL */ void libbalsa_server_cfg_assign_server(LibBalsaServerCfg *server_cfg, LibBalsaServer *server); #endif /* LIBBALSA_SERVER_CONFIG_H_ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/server.c000066400000000000000000000641271477646064400236570ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "server.h" #include #include #if defined(HAVE_LIBSECRET) #include #endif /* defined(HAVE_LIBSECRET) */ #include "libbalsa.h" #include "libbalsa_private.h" #include "libbalsa-conf.h" #include "net-client-utils.h" #include #ifdef G_LOG_DOMAIN # undef G_LOG_DOMAIN #endif #define G_LOG_DOMAIN "libbalsa-server" #if defined(HAVE_LIBSECRET) static const SecretSchema server_schema = { "org.gnome.Balsa.NetworkPassword", SECRET_SCHEMA_NONE, { { "protocol", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "server", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "user", SECRET_SCHEMA_ATTRIBUTE_STRING }, { NULL, 0 } } }; static const SecretSchema cert_pass_schema = { "org.gnome.Balsa.CertificatePassword", SECRET_SCHEMA_NONE, { { "protocol", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "server", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "user", SECRET_SCHEMA_ATTRIBUTE_STRING }, { NULL, 0 } } }; #endif /* defined(HAVE_LIBSECRET) */ typedef struct _LibBalsaServerPrivate LibBalsaServerPrivate; struct _LibBalsaServerPrivate { const gchar *protocol; /**< type of the server: imap, pop3, or smtp. */ gchar *host; gchar *user; gchar *passwd; NetClientCryptMode security; gboolean client_cert; gchar *cert_file; gchar *cert_passphrase; gboolean remember_passwd; gboolean remember_cert_passphrase; NetClientAuthMode auth_mode; }; static void libbalsa_server_finalize(GObject * object); static void libbalsa_server_real_set_username(LibBalsaServer *server, const gchar *username); static void libbalsa_server_real_set_host(LibBalsaServer *server, const gchar *host, NetClientCryptMode security); static gchar *lbs_get_password(LibBalsaServer *server, gchar *cert_subject); static gchar *libbalsa_free_password(gchar *password); G_DEFINE_TYPE_WITH_PRIVATE(LibBalsaServer, libbalsa_server, G_TYPE_OBJECT) enum { SET_USERNAME, SET_HOST, CONFIG_CHANGED, GET_PASSWORD, LAST_SIGNAL }; static guint libbalsa_server_signals[LAST_SIGNAL]; static void libbalsa_server_class_init(LibBalsaServerClass * klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS(klass); object_class->finalize = libbalsa_server_finalize; libbalsa_server_signals[SET_USERNAME] = g_signal_new("set-username", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(LibBalsaServerClass, set_username), NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); libbalsa_server_signals[SET_HOST] = g_signal_new("set-host", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(LibBalsaServerClass, set_host), NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT ); libbalsa_server_signals[CONFIG_CHANGED] = g_signal_new("config-changed", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(LibBalsaServerClass, config_changed), NULL, NULL, NULL, G_TYPE_NONE, 0); libbalsa_server_signals[GET_PASSWORD] = g_signal_new("get-password", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_LAST, 0U, NULL, NULL, NULL, G_TYPE_STRING, 1, G_TYPE_BYTE_ARRAY); klass->set_username = libbalsa_server_real_set_username; klass->set_host = libbalsa_server_real_set_host; } static void libbalsa_server_init(LibBalsaServer * server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); priv->protocol = NULL; priv->host = NULL; priv->user = NULL; priv->passwd = NULL; priv->remember_passwd = TRUE; priv->security = NET_CLIENT_CRYPT_STARTTLS; } /* leave object in sane state (NULLified fields) */ static void libbalsa_server_finalize(GObject * object) { LibBalsaServer *server = LIBBALSA_SERVER(object); LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_free(priv->host); g_free(priv->user); g_free(priv->cert_file); priv->passwd = libbalsa_free_password(priv->passwd); priv->cert_passphrase = libbalsa_free_password(priv->cert_passphrase); G_OBJECT_CLASS(libbalsa_server_parent_class)->finalize(object); } LibBalsaServer * libbalsa_server_new(void) { LibBalsaServer *server; server = g_object_new(LIBBALSA_TYPE_SERVER, NULL); return server; } void libbalsa_server_set_username(LibBalsaServer * server, const gchar * username) { g_return_if_fail(server != NULL); g_return_if_fail(LIBBALSA_IS_SERVER(server)); g_signal_emit(server, libbalsa_server_signals[SET_USERNAME], 0, username); } void libbalsa_server_set_password(LibBalsaServer *server, const gchar *passwd, gboolean for_cert) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); gchar **target; g_return_if_fail(LIBBALSA_IS_SERVER(server)); if (for_cert) { target = &priv->cert_passphrase; } else { target = &priv->passwd; } *target = libbalsa_free_password(*target); if ((passwd != NULL) && (passwd[0] != '\0')) { *target = g_strdup(passwd); } } void libbalsa_server_set_host(LibBalsaServer * server, const gchar * host, NetClientCryptMode security) { g_return_if_fail(server != NULL); g_return_if_fail(LIBBALSA_IS_SERVER(server)); g_signal_emit(server, libbalsa_server_signals[SET_HOST], 0, host, security); } void libbalsa_server_config_changed(LibBalsaServer * server) { g_return_if_fail(server != NULL); g_return_if_fail(LIBBALSA_IS_SERVER(server)); g_signal_emit(server, libbalsa_server_signals[CONFIG_CHANGED], 0); } static gchar * lbs_get_password(LibBalsaServer *server, gchar *cert_subject) { gchar *retval = NULL; g_return_val_if_fail(server != NULL, NULL); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), NULL); g_signal_emit(server, libbalsa_server_signals[GET_PASSWORD], 0, cert_subject, &retval); return retval; } static void libbalsa_server_real_set_username(LibBalsaServer * server, const gchar * username) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_free(priv->user); priv->user = g_strdup(username); } static void libbalsa_server_real_set_host(LibBalsaServer * server, const gchar * host, NetClientCryptMode security) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_free(priv->host); priv->host = g_strdup(host); priv->security = security; } void libbalsa_server_load_security_config(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); gboolean not_found; priv->security = libbalsa_conf_get_int_with_default("Security", ¬_found); if (not_found) { gboolean want_ssl; g_debug("server %s@%s: no security config, try to read old settings", priv->protocol, priv->host); want_ssl = libbalsa_conf_get_bool_with_default("SSL", ¬_found); if (want_ssl && !not_found) { priv->security = NET_CLIENT_CRYPT_ENCRYPTED; libbalsa_conf_clean_key("SSL"); } else { int want_tls; want_tls = libbalsa_conf_get_int_with_default("TLSMode", ¬_found); if (not_found) { priv->security = NET_CLIENT_CRYPT_STARTTLS; } else { switch (want_tls) { case 0: priv->security = NET_CLIENT_CRYPT_NONE; break; case 1: priv->security = NET_CLIENT_CRYPT_STARTTLS_OPT; break; default: priv->security = NET_CLIENT_CRYPT_STARTTLS; } libbalsa_conf_clean_key("SSL"); } } } } #if defined(HAVE_LIBSECRET) static gchar * libbalsa_free_password(gchar *password) { secret_password_free(password); return NULL; } static void store_password_libsecret(LibBalsaServer *server, const gchar *password, const gchar *cfg_path, const SecretSchema *schema) { if (libbalsa_conf_use_libsecret()) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); GError *err = NULL; secret_password_store_sync(schema, NULL, _("Balsa passwords"), password, NULL, &err, "protocol", priv->protocol, "server", priv->host, "user", priv->user, NULL); if (err != NULL) { libbalsa_information(LIBBALSA_INFORMATION_ERROR, /* Translators: #1 user name; #2 protocol (imap, etc); #3 server name; #4 error message */ _("Error saving credentials for user “%s”, protocol “%s”, server “%s” in Secret Service: %s"), priv->user, priv->protocol, priv->host, err->message); g_error_free(err); } else { g_debug("stored password for %s@%s:%s in secret service", priv->user, priv->protocol, priv->host); libbalsa_conf_clean_key(cfg_path); } } else { libbalsa_conf_private_set_string(cfg_path, password, TRUE); } } static gchar * load_password_libsecret(LibBalsaServer *server, const gchar *cfg_path, const SecretSchema *schema) { gchar *password; if (libbalsa_conf_use_libsecret()) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); GError *err = NULL; password = secret_password_lookup_sync(schema, NULL, &err, "protocol", priv->protocol, "server", priv->host, "user", priv->user, NULL); if (err != NULL) { libbalsa_information(LIBBALSA_INFORMATION_ERROR, /* Translators: #1 user name; #2 protocol (imap, etc); #3 server name; #4 error message */ _("Error loading credentials for user %s, protocol “%s”, server “%s” from Secret Service: %s"), priv->user, priv->protocol, priv->host, err->message); g_error_free(err); } /* check the config file if the returned password is NULL, make sure to remove it from the config file otherwise */ if (password == NULL) { password = libbalsa_conf_private_get_string(cfg_path, TRUE); if (password != NULL) { store_password_libsecret(server, password, cfg_path, schema); } } else { g_debug("loaded password for %s@%s:%s from secret service", priv->user, priv->protocol, priv->host); libbalsa_conf_clean_key(cfg_path); } } else { password = libbalsa_conf_private_get_string(cfg_path, TRUE); } return password; } static void erase_password_libsecret(LibBalsaServer *server, const SecretSchema *schema) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); GError *err = NULL; gboolean removed; removed = secret_password_clear_sync(schema, NULL, &err, "protocol", priv->protocol, "server", priv->host, "user", priv->user, NULL); if (err != NULL) { g_info("error erasing password for %s@%s:%s from secret service: %s", priv->user, priv->protocol, priv->host, err->message); g_error_free(err); } else if (removed) { g_debug("erased password for %s@%s:%s from secret service", priv->user, priv->protocol, priv->host); } else { g_debug("no password erased for %s@%s:%s from secret service", priv->user, priv->protocol, priv->host); } } #else static gchar * libbalsa_free_password(gchar *password) { net_client_free_authstr(password); return NULL; } #endif /* libbalsa_server_load_config: load the server configuration using gnome-config. Try to use sensible defaults. FIXME: Port field is kept here only for compatibility, drop after 1.4.x release. */ void libbalsa_server_load_config(LibBalsaServer * server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); priv->host = libbalsa_conf_get_string("Server"); if ((priv->host != NULL) && (strrchr(priv->host, ':') == NULL)) { gint port; gboolean d; port = libbalsa_conf_get_int_with_default("Port", &d); if (!d) { gchar *newhost = g_strdup_printf("%s:%d", priv->host, port); g_free(priv->host); priv->host = newhost; } } libbalsa_server_load_security_config(server); priv->user = libbalsa_conf_private_get_string("Username", FALSE); if (priv->user == NULL) { priv->user = g_strdup(g_get_user_name()); } priv->auth_mode = libbalsa_conf_get_int("AuthMode=2"); /* default NET_CLIENT_AUTH_USER_PASS */ if (libbalsa_conf_has_key("Anonymous")) { if (libbalsa_conf_get_bool("Anonymous")) { priv->auth_mode = NET_CLIENT_AUTH_NONE_ANON; } libbalsa_conf_clean_key("Anonymous"); } priv->remember_passwd = libbalsa_conf_get_bool("RememberPasswd=false"); priv->passwd = libbalsa_free_password(priv->passwd); if (priv->remember_passwd) { #if defined(HAVE_LIBSECRET) priv->passwd = load_password_libsecret(server, "Password", &server_schema); #else priv->passwd = libbalsa_conf_private_get_string("Password", TRUE); #endif /* HAVE_LIBSECRET */ if ((priv->passwd != NULL) && (priv->passwd[0] == '\0')) { priv->passwd = libbalsa_free_password(priv->passwd); } } /* client certificate stuff */ priv->client_cert = libbalsa_conf_get_bool("NeedClientCert=false"); priv->cert_file = libbalsa_conf_get_string("UserCertificateFile"); priv->remember_cert_passphrase = libbalsa_conf_get_bool("RememberCertPasswd=false"); priv->cert_passphrase = libbalsa_free_password(priv->cert_passphrase); if (priv->client_cert && priv->remember_cert_passphrase) { #if defined(HAVE_LIBSECRET) priv->cert_passphrase = load_password_libsecret(server, "CertificatePassphrase", &cert_pass_schema); #else priv->cert_passphrase = libbalsa_conf_private_get_string("CertificatePassphrase", TRUE); #endif /* HAVE_LIBSECRET */ if ((priv->cert_passphrase != NULL) && (priv->cert_passphrase[0] == '\0')) { priv->cert_passphrase = libbalsa_free_password(priv->cert_passphrase); } } } /* libbalsa_server_save_config: save config. It is bit tricky to decide the value of the remember_passwd field. Should empty values be remembered? Even if they are, balsa will still ask for the password if it is empty. */ void libbalsa_server_save_config(LibBalsaServer * server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); libbalsa_conf_set_string("Server", priv->host); libbalsa_conf_private_set_string("Username", priv->user, FALSE); libbalsa_conf_set_int("AuthMode", priv->auth_mode); if (priv->remember_passwd && (priv->passwd != NULL)) { libbalsa_conf_set_bool("RememberPasswd", TRUE); #if defined(HAVE_LIBSECRET) store_password_libsecret(server, priv->passwd, "Password", &server_schema); #else libbalsa_conf_private_set_string("Password", priv->passwd, TRUE); #endif } else { libbalsa_conf_set_bool("RememberPasswd", FALSE); #if defined(HAVE_LIBSECRET) erase_password_libsecret(server, &server_schema); #endif /* HAVE_LIBSECRET */ libbalsa_conf_private_set_string("Password", NULL, TRUE); } libbalsa_conf_set_bool("NeedClientCert", priv->client_cert); if (priv->cert_file != NULL) { libbalsa_conf_set_string("UserCertificateFile", priv->cert_file); if (priv->remember_cert_passphrase && (priv->cert_passphrase != NULL)) { libbalsa_conf_set_bool("RememberCertPasswd", TRUE); #if defined(HAVE_LIBSECRET) store_password_libsecret(server, priv->cert_passphrase, "CertificatePassphrase", &cert_pass_schema); #else libbalsa_conf_private_set_string("CertificatePassphrase", priv->cert_passphrase, TRUE); #endif } else { libbalsa_conf_set_bool("RememberCertPasswd", FALSE); #if defined(HAVE_LIBSECRET) erase_password_libsecret(server, &cert_pass_schema); #endif /* HAVE_LIBSECRET */ libbalsa_conf_private_set_string("CertificatePassphrase", NULL, TRUE); } } libbalsa_conf_set_int("Security", priv->security); } /* Connect the server's "get-password" signal to the callback; if the * ask-password callback is connected more than once, the dialog is * popped up the corresponding number of times, so we'll ignore the * request if a callback is already connected. */ void libbalsa_server_connect_signals(LibBalsaServer * server, GCallback cb, gpointer cb_data) { if (!g_signal_has_handler_pending(server, libbalsa_server_signals [GET_PASSWORD], 0, TRUE)) g_signal_connect(server, "get-password", cb, cb_data); } gchar ** libbalsa_server_get_auth(NetClient *client, NetClientAuthMode mode, gpointer user_data) { LibBalsaServer *server = LIBBALSA_SERVER(user_data); LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); gchar **result = NULL; g_debug("%s: %p %d %p: encrypted = %d", __func__, client, mode, user_data, net_client_is_encrypted(client)); if (priv->auth_mode != NET_CLIENT_AUTH_NONE_ANON) { result = g_new0(gchar *, 3U); result[0] = g_strdup(priv->user); switch (mode) { case NET_CLIENT_AUTH_USER_PASS: if ((priv->passwd != NULL) && (priv->passwd[0] != '\0')) { result[1] = g_strdup(priv->passwd); } else { result[1] = lbs_get_password(server, NULL); } break; case NET_CLIENT_AUTH_KERBEROS: break; /* only user name required */ default: g_assert_not_reached(); } } return result; } gboolean libbalsa_server_check_cert(NetClient *client, GTlsCertificate *peer_cert, GTlsCertificateFlags errors, gpointer user_data) { return libbalsa_is_cert_known(peer_cert, errors); } gchar * libbalsa_server_get_cert_pass(NetClient *client, gchar *cert_subject, gpointer user_data) { LibBalsaServer *server = LIBBALSA_SERVER(user_data); LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); gchar *result; if ((priv->cert_passphrase != NULL) && (priv->cert_passphrase[0] != '\0')) { result = g_strdup(priv->cert_passphrase); } else { result = lbs_get_password(server, cert_subject); } return result; } /* Test whether a server is reachable */ typedef struct { LibBalsaCanReachCallback * cb; gpointer cb_data; GObject * source_object; } CanReachInfo; static void libbalsa_server_can_reach_cb(GObject * monitor, GAsyncResult * res, gpointer user_data) { CanReachInfo *info = user_data; gboolean can_reach; can_reach = g_network_monitor_can_reach_finish((GNetworkMonitor *) monitor, res, NULL); info->cb(info->source_object, can_reach, info->cb_data); g_object_unref(info->source_object); g_free(info); } void libbalsa_server_test_can_reach_full(LibBalsaServer * server, LibBalsaCanReachCallback * cb, gpointer cb_data, GObject * source_object) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); CanReachInfo *info; gchar *host; GNetworkMonitor *monitor; GSocketConnectable *address; info = g_new(CanReachInfo, 1); info->cb = cb; info->cb_data = cb_data; info->source_object = g_object_ref(source_object); monitor = g_network_monitor_get_default(); host = net_client_host_only(priv->host); address = g_network_address_new(host, 0); g_free(host); g_network_monitor_can_reach_async(monitor, address, NULL, libbalsa_server_can_reach_cb, info); g_object_unref(address); } void libbalsa_server_test_can_reach(LibBalsaServer * server, LibBalsaCanReachCallback * cb, gpointer cb_data) { libbalsa_server_test_can_reach_full(server, cb, cb_data, (GObject *) server); } /* * Getters */ const gchar * libbalsa_server_get_host(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), NULL); return priv->host; } const gchar * libbalsa_server_get_user(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), NULL); return priv->user; } const gchar * libbalsa_server_get_cert_file(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), NULL); return priv->cert_file; } const gchar * libbalsa_server_get_protocol(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), NULL); return priv->protocol; } const gchar * libbalsa_server_get_password(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), NULL); return priv->passwd; } const gchar * libbalsa_server_get_cert_passphrase(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), NULL); return priv->cert_passphrase; } NetClientCryptMode libbalsa_server_get_security(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), (NetClientCryptMode) 0); return priv->security; } NetClientAuthMode libbalsa_server_get_auth_mode(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), (NetClientAuthMode) 0); return priv->auth_mode; } gboolean libbalsa_server_get_client_cert(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), FALSE); return priv->client_cert; } gboolean libbalsa_server_get_remember_password(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), FALSE); return priv->remember_passwd; } gboolean libbalsa_server_get_remember_cert_passphrase(LibBalsaServer *server) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_val_if_fail(LIBBALSA_IS_SERVER(server), FALSE); return priv->remember_cert_passphrase; } /* * Setters */ void libbalsa_server_set_protocol(LibBalsaServer *server, const gchar *protocol) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_if_fail(LIBBALSA_IS_SERVER(server)); g_return_if_fail(priv->protocol == NULL); /* We do not allocate a string for the protocol: */ priv->protocol = protocol; } void libbalsa_server_set_cert_file(LibBalsaServer *server, const gchar *cert_file) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_if_fail(LIBBALSA_IS_SERVER(server)); g_free(priv->cert_file); priv->cert_file = g_strdup(cert_file); } void libbalsa_server_set_security(LibBalsaServer *server, NetClientCryptMode security) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_if_fail(LIBBALSA_IS_SERVER(server)); priv->security = security; } void libbalsa_server_set_auth_mode(LibBalsaServer *server, NetClientAuthMode auth_mode) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_if_fail(LIBBALSA_IS_SERVER(server)); priv->auth_mode = auth_mode; } void libbalsa_server_set_remember_password(LibBalsaServer *server, gboolean remember_password) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_if_fail(LIBBALSA_IS_SERVER(server)); priv->remember_passwd = remember_password; } void libbalsa_server_set_client_cert(LibBalsaServer *server, gboolean client_cert) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_if_fail(LIBBALSA_IS_SERVER(server)); priv->client_cert = client_cert; } void libbalsa_server_set_remember_cert_passphrase(LibBalsaServer *server, gboolean remember_cert_passphrase) { LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server); g_return_if_fail(LIBBALSA_IS_SERVER(server)); priv->remember_cert_passphrase = remember_cert_passphrase; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/server.h000066400000000000000000000116501477646064400236550ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __LIBBALSA_SERVER_H__ #define __LIBBALSA_SERVER_H__ #ifndef BALSA_VERSION # error "Include config.h before this file." #endif #include "imap/libimap.h" #include "libbalsa.h" #include "net-client.h" #define LIBBALSA_TYPE_SERVER (libbalsa_server_get_type()) G_DECLARE_DERIVABLE_TYPE(LibBalsaServer, libbalsa_server, LIBBALSA, SERVER, GObject) struct _LibBalsaServerClass { GObjectClass parent_class; void (*set_username) (LibBalsaServer * server, const gchar * name); void (*set_host) (LibBalsaServer * server, const gchar * host, NetClientCryptMode security); void (*config_changed) (LibBalsaServer * server); }; LibBalsaServer *libbalsa_server_new(void); void libbalsa_server_set_username(LibBalsaServer * server, const gchar * username); void libbalsa_server_set_password(LibBalsaServer *server, const gchar *passwd, gboolean for_cert); void libbalsa_server_set_host(LibBalsaServer *server, const gchar *host, NetClientCryptMode security); void libbalsa_server_config_changed(LibBalsaServer * server); void libbalsa_server_load_config(LibBalsaServer * server); void libbalsa_server_load_security_config(LibBalsaServer * server); void libbalsa_server_save_config(LibBalsaServer * server); /* NetClient related signal handlers */ gchar **libbalsa_server_get_auth(NetClient *client, NetClientAuthMode mode, gpointer user_data); gboolean libbalsa_server_check_cert(NetClient *client, GTlsCertificate *peer_cert, GTlsCertificateFlags errors, gpointer user_data); gchar *libbalsa_server_get_cert_pass(NetClient *client, gchar *cert_subject, gpointer user_data); void libbalsa_server_connect_signals(LibBalsaServer * server, GCallback cb, gpointer cb_data); /* Check whether a server can be reached */ void libbalsa_server_test_can_reach(LibBalsaServer * server, LibBalsaCanReachCallback * cb, gpointer cb_data); /* Private: used only by LibBalsaMailboxRemote */ void libbalsa_server_test_can_reach_full(LibBalsaServer * server, LibBalsaCanReachCallback * cb, gpointer cb_data, GObject * source_object); /* Getters */ const gchar * libbalsa_server_get_host(LibBalsaServer *server); const gchar * libbalsa_server_get_user(LibBalsaServer *server); const gchar * libbalsa_server_get_cert_file(LibBalsaServer *server); const gchar * libbalsa_server_get_protocol(LibBalsaServer *server); const gchar * libbalsa_server_get_password(LibBalsaServer *server); const gchar * libbalsa_server_get_cert_passphrase(LibBalsaServer *server); NetClientCryptMode libbalsa_server_get_security(LibBalsaServer *server); NetClientAuthMode libbalsa_server_get_auth_mode(LibBalsaServer *server); gboolean libbalsa_server_get_client_cert(LibBalsaServer *server); gboolean libbalsa_server_get_remember_password(LibBalsaServer *server); gboolean libbalsa_server_get_remember_cert_passphrase(LibBalsaServer *server); /* Setters */ void libbalsa_server_set_protocol(LibBalsaServer *server, const gchar *protocol); void libbalsa_server_set_cert_file(LibBalsaServer *server, const gchar *cert_file); void libbalsa_server_set_security(LibBalsaServer *server, NetClientCryptMode security); void libbalsa_server_set_auth_mode(LibBalsaServer *server, NetClientAuthMode auth_mode); void libbalsa_server_set_remember_password(LibBalsaServer *server, gboolean remember_password); void libbalsa_server_set_client_cert(LibBalsaServer *server, gboolean client_cert); void libbalsa_server_set_remember_cert_passphrase(LibBalsaServer *server, gboolean remember_cert_passphrase); #endif /* __LIBBALSA_SERVER_H__ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/smtp-server.c000066400000000000000000000274761477646064400246460ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ /* * LibBalsaSmtpServer is a subclass of LibBalsaServer. */ #include "smtp-server.h" #include #include "libbalsa-conf.h" #include "server-config.h" #ifdef G_LOG_DOMAIN # undef G_LOG_DOMAIN #endif #define G_LOG_DOMAIN "libbalsa-server" struct _LibBalsaSmtpServer { LibBalsaServer server; gchar *name; guint big_message; /* size of partial messages; in kB; 0 disables splitting */ gint lock_state; /* 0 means unlocked; access via atomic operations */ }; /* Class boilerplate */ G_DEFINE_TYPE(LibBalsaSmtpServer, libbalsa_smtp_server, LIBBALSA_TYPE_SERVER) /* Object class method */ static void libbalsa_smtp_server_finalize(GObject * object) { LibBalsaSmtpServer *smtp_server; g_return_if_fail(LIBBALSA_IS_SMTP_SERVER(object)); smtp_server = LIBBALSA_SMTP_SERVER(object); g_free(smtp_server->name); G_OBJECT_CLASS(libbalsa_smtp_server_parent_class)->finalize(object); } static void libbalsa_smtp_server_class_init(LibBalsaSmtpServerClass * klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS(klass); object_class->finalize = libbalsa_smtp_server_finalize; } static void libbalsa_smtp_server_init(LibBalsaSmtpServer * smtp_server) { libbalsa_server_set_protocol(LIBBALSA_SERVER(smtp_server), "smtp"); } /* Public methods */ /** * libbalsa_smtp_server_new: * @username: username to use to login * @host: hostname of server * * Creates or recycles a #LibBalsaSmtpServer matching the host+username pair. * * Return value: A #LibBalsaSmtpServer */ LibBalsaSmtpServer * libbalsa_smtp_server_new(void) { LibBalsaSmtpServer *smtp_server; smtp_server = g_object_new(LIBBALSA_TYPE_SMTP_SERVER, NULL); /* Change the default. */ libbalsa_server_set_remember_password(LIBBALSA_SERVER(smtp_server), TRUE); return smtp_server; } LibBalsaSmtpServer * libbalsa_smtp_server_new_from_config(const gchar * name) { LibBalsaSmtpServer *smtp_server; smtp_server = libbalsa_smtp_server_new(); smtp_server->name = g_strdup(name); libbalsa_server_load_config(LIBBALSA_SERVER(smtp_server)); smtp_server->big_message = libbalsa_conf_get_int("BigMessage=0"); return smtp_server; } void libbalsa_smtp_server_save_config(LibBalsaSmtpServer * smtp_server) { libbalsa_server_save_config(LIBBALSA_SERVER(smtp_server)); libbalsa_conf_set_int("BigMessage", smtp_server->big_message); } void libbalsa_smtp_server_set_name(LibBalsaSmtpServer * smtp_server, const gchar * name) { g_free(smtp_server->name); smtp_server->name = g_strdup(name); } const gchar * libbalsa_smtp_server_get_name(LibBalsaSmtpServer * smtp_server) { return smtp_server ? smtp_server->name : _("Default"); } guint libbalsa_smtp_server_get_big_message(LibBalsaSmtpServer * smtp_server) { /* big_message is stored in kB, but we want the value in bytes. */ return smtp_server->big_message * 1024; } static gint smtp_server_compare(gconstpointer a, gconstpointer b) { const LibBalsaSmtpServer *smtp_server_a = a; const LibBalsaSmtpServer *smtp_server_b = b; return g_strcmp0(smtp_server_a->name, smtp_server_b->name); } void libbalsa_smtp_server_add_to_list(LibBalsaSmtpServer * smtp_server, GSList ** server_list) { GSList *list; if ((list = g_slist_find_custom(*server_list, smtp_server, smtp_server_compare)) != NULL) { g_object_unref(list->data); *server_list = g_slist_delete_link(*server_list, list); } *server_list = g_slist_prepend(*server_list, smtp_server); } gboolean libbalsa_smtp_server_trylock(LibBalsaSmtpServer *smtp_server) { gint prev_state; gboolean result; prev_state = g_atomic_int_add(&smtp_server->lock_state, 1); if (prev_state == 0) { result = TRUE; } else { result = FALSE; (void) g_atomic_int_dec_and_test(&smtp_server->lock_state); } g_debug("%s: lock %s: %d", __func__, libbalsa_smtp_server_get_name(smtp_server), result); return result; } void libbalsa_smtp_server_unlock(LibBalsaSmtpServer *smtp_server) { (void) g_atomic_int_dec_and_test(&smtp_server->lock_state); g_debug("%s: unlock %s", __func__, libbalsa_smtp_server_get_name(smtp_server)); } /* SMTP server dialog */ #define LIBBALSA_SMTP_SERVER_DIALOG_KEY "libbalsa-smtp-server-dialog" struct smtp_server_dialog_info { LibBalsaSmtpServer *smtp_server; gchar *old_name; LibBalsaSmtpServerUpdate update; GtkWidget *dialog; LibBalsaServerCfg *notebook; GtkWidget *split_button; GtkWidget *big_message; }; /* GDestroyNotify for smtp_server_dialog_info. */ static void smtp_server_destroy_notify(struct smtp_server_dialog_info *sdi) { g_free(sdi->old_name); if (sdi->dialog) gtk_widget_destroy(sdi->dialog); g_free(sdi); } /* GWeakNotify for dialog. */ static void smtp_server_weak_notify(struct smtp_server_dialog_info *sdi, GObject *dialog) { sdi->dialog = NULL; g_object_set_data(G_OBJECT(sdi->smtp_server), LIBBALSA_SMTP_SERVER_DIALOG_KEY, NULL); } static void smtp_server_response(GtkDialog * dialog, gint response, struct smtp_server_dialog_info *sdi) { LibBalsaServer *server = LIBBALSA_SERVER(sdi->smtp_server); GError *error = NULL; switch (response) { case GTK_RESPONSE_HELP: gtk_show_uri_on_window(GTK_WINDOW(dialog), "help:balsa/preferences-mail-options#smtp-server-config", gtk_get_current_event_time(), &error); if (error) { libbalsa_information(LIBBALSA_INFORMATION_WARNING, _("Error displaying server help: %s\n"), error->message); g_error_free(error); } return; case GTK_RESPONSE_OK: libbalsa_smtp_server_set_name(sdi->smtp_server, libbalsa_server_cfg_get_name(sdi->notebook)); libbalsa_server_cfg_assign_server(sdi->notebook, server); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sdi->split_button))) { /* big_message is stored in kB, but the widget is in MB. */ sdi->smtp_server->big_message = gtk_spin_button_get_value(GTK_SPIN_BUTTON(sdi->big_message)) * 1024.0; } else { sdi->smtp_server->big_message = 0U; } break; default: break; } /* The update may unref the server, so we temporarily ref it; * we use server instead of sdi->smtp_server, as sdi is deallocated * when the object data is cleared. */ g_object_ref(server); sdi->update(sdi->smtp_server, response, sdi->old_name); g_object_unref(server); gtk_widget_destroy(GTK_WIDGET(dialog)); } static void smtp_server_changed(GtkWidget G_GNUC_UNUSED *widget, struct smtp_server_dialog_info *sdi) { gboolean sensitive; gboolean enable_ok = libbalsa_server_cfg_valid(sdi->notebook); /* split big messages */ if ((sdi->big_message != NULL) && (sdi->split_button != NULL)) { sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sdi->split_button)); gtk_widget_set_sensitive(sdi->big_message, sensitive); } gtk_dialog_set_response_sensitive(GTK_DIALOG(sdi->dialog), GTK_RESPONSE_OK, enable_ok); gtk_dialog_set_default_response(GTK_DIALOG(sdi->dialog), enable_ok ? GTK_RESPONSE_OK : GTK_RESPONSE_CANCEL); } void libbalsa_smtp_server_dialog(LibBalsaSmtpServer * smtp_server, GtkWindow * parent, LibBalsaSmtpServerUpdate update) { LibBalsaServer *server = LIBBALSA_SERVER(smtp_server); struct smtp_server_dialog_info *sdi; GtkWidget *dialog; GtkWidget *content_area; GtkWidget *label, *hbox; /* Show only one dialog at a time. */ sdi = g_object_get_data(G_OBJECT(smtp_server), LIBBALSA_SMTP_SERVER_DIALOG_KEY); if (sdi != NULL) { gtk_window_present_with_time(GTK_WINDOW(sdi->dialog), gtk_get_current_event_time()); return; } sdi = g_new0(struct smtp_server_dialog_info, 1U); g_object_set_data_full(G_OBJECT(smtp_server), LIBBALSA_SMTP_SERVER_DIALOG_KEY, sdi, (GDestroyNotify) smtp_server_destroy_notify); sdi->smtp_server = smtp_server; sdi->old_name = g_strdup(libbalsa_smtp_server_get_name(smtp_server)); sdi->update = update; sdi->dialog = dialog = gtk_dialog_new_with_buttons(_("SMTP Server"), parent, GTK_DIALOG_DESTROY_WITH_PARENT | libbalsa_dialog_flags(), _("_OK"), GTK_RESPONSE_OK, _("_Cancel"), GTK_RESPONSE_CANCEL, _("_Help"), GTK_RESPONSE_HELP, NULL); content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); g_object_weak_ref(G_OBJECT(dialog), (GWeakNotify) smtp_server_weak_notify, sdi); g_signal_connect(dialog, "response", G_CALLBACK(smtp_server_response), sdi); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL); gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, FALSE); sdi->notebook = libbalsa_server_cfg_new(server, smtp_server->name); gtk_container_add(GTK_CONTAINER(content_area), GTK_WIDGET(sdi->notebook)); /* split large messages */ sdi->split_button = gtk_check_button_new_with_mnemonic(_("Sp_lit message larger than")); hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); sdi->big_message = gtk_spin_button_new_with_range(0.1, 100, 0.1); gtk_widget_set_hexpand(sdi->big_message, TRUE); gtk_widget_set_halign(sdi->big_message, GTK_ALIGN_FILL); gtk_container_add(GTK_CONTAINER(hbox), sdi->big_message); label = gtk_label_new(_("MB")); gtk_container_add(GTK_CONTAINER(hbox), label); if (smtp_server->big_message > 0) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sdi->split_button), TRUE); /* The widget is in MB, but big_message is stored in kB. */ gtk_spin_button_set_value(GTK_SPIN_BUTTON(sdi->big_message), ((gdouble) smtp_server->big_message) / 1024.0); } else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sdi->split_button), FALSE); gtk_spin_button_set_value(GTK_SPIN_BUTTON(sdi->big_message), 1); } libbalsa_server_cfg_add_row(sdi->notebook, FALSE, sdi->split_button, hbox); g_signal_connect(sdi->notebook, "changed", G_CALLBACK(smtp_server_changed), sdi); g_signal_connect(sdi->split_button, "toggled", G_CALLBACK(smtp_server_changed), sdi); g_signal_connect(sdi->big_message, "changed", G_CALLBACK(smtp_server_changed), sdi); smtp_server_changed(NULL, sdi); gtk_widget_show_all(dialog); } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/smtp-server.h000066400000000000000000000047571477646064400246500ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __SMTP_SERVER_H__ #define __SMTP_SERVER_H__ #include #include "server.h" #define LIBBALSA_TYPE_SMTP_SERVER (libbalsa_smtp_server_get_type()) G_DECLARE_FINAL_TYPE(LibBalsaSmtpServer, libbalsa_smtp_server, LIBBALSA, SMTP_SERVER, LibBalsaServer) LibBalsaSmtpServer *libbalsa_smtp_server_new(void); LibBalsaSmtpServer *libbalsa_smtp_server_new_from_config(const gchar * name); void libbalsa_smtp_server_save_config(LibBalsaSmtpServer * server); void libbalsa_smtp_server_set_name(LibBalsaSmtpServer * smtp_server, const gchar * name); const gchar *libbalsa_smtp_server_get_name(LibBalsaSmtpServer * smtp_server); guint libbalsa_smtp_server_get_big_message(LibBalsaSmtpServer * smtp_server); void libbalsa_smtp_server_add_to_list(LibBalsaSmtpServer * smtp_server, GSList ** server_list); typedef void (*LibBalsaSmtpServerUpdate) (LibBalsaSmtpServer * smtp_server, GtkResponseType response, const gchar * old_name); void libbalsa_smtp_server_dialog(LibBalsaSmtpServer * smtp_server, GtkWindow * parent, LibBalsaSmtpServerUpdate update); gboolean libbalsa_smtp_server_trylock(LibBalsaSmtpServer *smtp_server); void libbalsa_smtp_server_unlock(LibBalsaSmtpServer *smtp_server); #endif /* __SMTP_SERVER_H__ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/source-viewer.c000066400000000000000000000205101477646064400251340ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1998-2016 Stuart Parmenter and others, see AUTHORS file. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ /* this is simple window that reads text from given file and shows in in a GtkText widget. */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include "application-helpers.h" #include "misc.h" #include "libbalsa.h" #include "libbalsa_private.h" #include "misc.h" #include "geometry-manager.h" #include typedef struct { LibBalsaMessage *msg; GtkWidget *text; GtkWidget *window; gboolean *escape_specials; } LibBalsaSourceViewerInfo; static void lsv_close_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data) { gtk_widget_destroy(GTK_WIDGET(user_data)); } static void lsv_copy_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data) { LibBalsaSourceViewerInfo *lsvi = g_object_get_data(G_OBJECT(user_data), "lsvi"); GtkTextView *text = GTK_TEXT_VIEW(lsvi->text); GtkTextBuffer *buffer = gtk_text_view_get_buffer(text); GdkDisplay *display; GtkClipboard *clipboard; display = gtk_widget_get_display(GTK_WIDGET(text)); clipboard = gtk_clipboard_get_for_display(display, GDK_NONE); gtk_text_buffer_copy_clipboard(buffer, clipboard); } static void lsv_select_activated(GSimpleAction * action, GVariant * parameter, gpointer user_data) { LibBalsaSourceViewerInfo *lsvi = g_object_get_data(G_OBJECT(user_data), "lsvi"); GtkTextView *text = GTK_TEXT_VIEW(lsvi->text); GtkTextBuffer *buffer = gtk_text_view_get_buffer(text); GtkTextIter start, end; gtk_text_buffer_get_bounds(buffer, &start, &end); gtk_text_buffer_move_mark_by_name(buffer, "insert", &start); gtk_text_buffer_move_mark_by_name(buffer, "selection_bound", &end); } static void lsv_show_message(const char *message, LibBalsaSourceViewerInfo * lsvi, gboolean escape) { GtkTextBuffer *buffer; GtkTextIter start; gchar *tmp; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(lsvi->text)); gtk_text_buffer_set_text(buffer, "", 0); if (escape) tmp = g_strescape(message, "\n“"); else { tmp = g_strdup(message); libbalsa_utf8_sanitize(&tmp, FALSE, NULL); } if (tmp) { gtk_text_buffer_insert_at_cursor(buffer, tmp, -1); g_free(tmp); } gtk_text_buffer_get_start_iter(buffer, &start); gtk_text_buffer_place_cursor(buffer, &start); } static void lsv_escape_change_state(GSimpleAction * action, GVariant * state, gpointer user_data) { LibBalsaSourceViewerInfo *lsvi = g_object_get_data(G_OBJECT(user_data), "lsvi"); LibBalsaMessage *msg = lsvi->msg; LibBalsaMailbox *mailbox; GMimeStream *msg_stream; GMimeStream *mem_stream; char *raw_message; mailbox = libbalsa_message_get_mailbox(msg); if (mailbox == NULL) { libbalsa_information(LIBBALSA_INFORMATION_WARNING, _("Mailbox closed")); return; } msg_stream = libbalsa_mailbox_get_message_stream(mailbox, libbalsa_message_get_msgno(msg), TRUE); if (msg_stream == NULL) return; mem_stream = g_mime_stream_mem_new(); libbalsa_mailbox_lock_store(mailbox); g_mime_stream_write_to_stream(msg_stream, mem_stream); libbalsa_mailbox_unlock_store(mailbox); g_mime_stream_write(mem_stream, "", 1); /* close string */ raw_message = (char *) GMIME_STREAM_MEM(mem_stream)->buffer->data; *(lsvi->escape_specials) = g_variant_get_boolean(state); lsv_show_message(raw_message, lsvi, *(lsvi->escape_specials)); g_object_unref(msg_stream); g_object_unref(mem_stream); g_simple_action_set_state(action, state); } static GActionEntry entries[] = { {"close", lsv_close_activated}, {"copy", lsv_copy_activated}, {"select", lsv_select_activated}, {"escape", NULL, NULL, "false", lsv_escape_change_state} }; static void lsv_window_destroy_notify(LibBalsaSourceViewerInfo * lsvi) { g_object_unref(lsvi->msg); g_free(lsvi); } /* libbalsa_show_message_source: pops up a window containing the source of the message msg. */ #define BALSA_SOURCE_VIEWER "balsa-source-viewer" void libbalsa_show_message_source(GtkApplication * application, LibBalsaMessage * msg, const gchar * font, gboolean * escape_specials) { GtkWidget *text; gchar *css; GtkCssProvider *css_provider; GtkWidget *vbox, *interior; GtkWidget *window; const gchar resource_path[] = "/org/desktop/Balsa/source-viewer.ui"; GtkWidget *menu_bar; GError *err = NULL; LibBalsaSourceViewerInfo *lsvi; GAction *escape_action; g_return_if_fail(msg != NULL); g_return_if_fail(MAILBOX_OPEN(libbalsa_message_get_mailbox(msg))); text = gtk_text_view_new(); gtk_widget_set_name(text, BALSA_SOURCE_VIEWER); css = libbalsa_font_string_to_css(font, BALSA_SOURCE_VIEWER); css_provider = gtk_css_provider_new(); gtk_css_provider_load_from_data(css_provider, css, -1, NULL); g_free(css); gtk_style_context_add_provider(gtk_widget_get_style_context(text) , GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); g_object_unref(css_provider); gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD_CHAR); interior = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(interior), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(interior), GTK_WIDGET(text)); window = gtk_application_window_new(application); gtk_window_set_title(GTK_WINDOW(window), _("Message Source")); gtk_window_set_role(GTK_WINDOW(window), "message-source"); geometry_manager_attach(GTK_WINDOW(window), "SourceView"); menu_bar = libbalsa_window_get_menu_bar(GTK_APPLICATION_WINDOW(window), entries, G_N_ELEMENTS(entries), resource_path, &err, window); if (!menu_bar) { libbalsa_information(LIBBALSA_INFORMATION_WARNING, _("Error adding from %s: %s\n"), resource_path, err->message); g_error_free(err); return; } vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1); libbalsa_set_vmargins(menu_bar, 1); gtk_container_add(GTK_CONTAINER(vbox), menu_bar); libbalsa_set_margins(interior, 2); gtk_widget_set_vexpand(interior, TRUE); gtk_container_add(GTK_CONTAINER(vbox), interior); gtk_container_add(GTK_CONTAINER(window), vbox); lsvi = g_new(LibBalsaSourceViewerInfo, 1); lsvi->msg = g_object_ref(msg); lsvi->text = text; lsvi->window = window; lsvi->escape_specials = escape_specials; g_object_set_data_full(G_OBJECT(window), "lsvi", lsvi, (GDestroyNotify) lsv_window_destroy_notify); gtk_widget_show_all(window); escape_action = g_action_map_lookup_action(G_ACTION_MAP(window), "escape"); lsv_escape_change_state(G_SIMPLE_ACTION(escape_action), g_variant_new_boolean(*escape_specials), window); } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/system-tray.c000066400000000000000000000071761477646064400246530ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2022 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #ifdef ENABLE_SYSTRAY #include #include #include "files.h" #include "system-tray.h" static XAppStatusIcon *status_icon; static gchar *icon_path[2] = {NULL, NULL}; static gboolean icon_attention; static GtkMenu *icon_menu; static libbalsa_systray_cb_t icon_activate_cb; static gpointer icon_activate_cb_data; static void systray_cb_internal(XAppStatusIcon *icon, guint button, guint time, gpointer user_data); void libbalsa_systray_icon_init(GtkMenu *menu, libbalsa_systray_cb_t activate_cb, gpointer activate_cb_data) { g_return_if_fail(icon_path[0] == NULL); icon_path[0] = libbalsa_pixmap_finder("balsa_icon.png"); icon_path[1] = libbalsa_pixmap_finder("balsa_attention.png"); icon_activate_cb = activate_cb; icon_activate_cb_data = activate_cb_data; if (menu != NULL) { icon_menu = g_object_ref(menu); } } void libbalsa_systray_icon_enable(gboolean enable) { g_return_if_fail(icon_path[0] != NULL); if (enable) { if (status_icon == NULL) { status_icon = xapp_status_icon_new(); if (icon_menu != NULL) { xapp_status_icon_set_secondary_menu(status_icon, icon_menu); } if (icon_activate_cb != NULL) { g_signal_connect(status_icon, "activate", G_CALLBACK(systray_cb_internal), icon_activate_cb_data); } xapp_status_icon_set_visible(status_icon, TRUE); icon_attention = TRUE; libbalsa_systray_icon_attention(FALSE); } } else { if (status_icon != NULL) { g_object_unref(status_icon); status_icon = NULL; } } } void libbalsa_systray_icon_attention(gboolean attention) { g_return_if_fail(icon_path[0] != NULL); if ((status_icon != NULL) && (attention != icon_attention)) { icon_attention = attention; if (attention) { xapp_status_icon_set_icon_name(status_icon, icon_path[1]); xapp_status_icon_set_tooltip_text(status_icon, _("Balsa: you have new mail")); } else { xapp_status_icon_set_icon_name(status_icon, icon_path[0]); xapp_status_icon_set_tooltip_text(status_icon, _("Balsa")); } } } void libbalsa_systray_icon_destroy(void) { size_t n; if (icon_path[0] != NULL) { icon_activate_cb = NULL; if (icon_menu != NULL) { g_object_unref(icon_menu); icon_menu = NULL; } for (n = 0; n < G_N_ELEMENTS(icon_path); n++) { g_free(icon_path[n]); icon_path[n] = NULL; } if (status_icon != NULL) { g_object_unref(status_icon); status_icon = NULL; } } } static void systray_cb_internal(XAppStatusIcon G_GNUC_UNUSED *icon, guint button, guint G_GNUC_UNUSED time, gpointer user_data) { g_return_if_fail(status_icon != NULL); if ((button == 1) && (icon_activate_cb != NULL)) { icon_activate_cb(user_data); } } #endif /* ENABLE_SYSTRAY */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/system-tray.h000066400000000000000000000026541477646064400246540ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * * Copyright (C) 1997-2022 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef _SYSTEM_TRAY_H_ #define _SYSTEM_TRAY_H_ #ifndef BALSA_VERSION # error "Include config.h before this file." #endif #ifdef ENABLE_SYSTRAY #include G_BEGIN_DECLS typedef void (*libbalsa_systray_cb_t)(gpointer); void libbalsa_systray_icon_init(GtkMenu *menu, libbalsa_systray_cb_t activate_cb, gpointer activate_cb_data); void libbalsa_systray_icon_enable(gboolean enable); void libbalsa_systray_icon_attention(gboolean attention); void libbalsa_systray_icon_destroy(void); G_END_DECLS #endif /* ENABLE_SYSTRAY */ #endif /* _SYSTEM_TRAY_H_ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/x509-cert-widget.c000066400000000000000000000405041477646064400252630ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* * Balsa E-Mail Client * * X509 certificate (TLS, S/MIME) widgets * Copyright (C) 2019 Albrecht Dreß * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifdef HAVE_CONFIG_H #include #endif #if HAVE_GCR #define GCR_API_SUBJECT_TO_CHANGE #include #else #include #include #include "libbalsa.h" #endif #include "misc.h" #include #include "libbalsa-gpgme.h" #include "libbalsa-gpgme-keys.h" #include "x509-cert-widget.h" /* stuff for displaying a certificate chain */ enum { CERT_NAME_COLUMN = 0, CERT_WIDGET_COLUMN, CERT_COLUMNS }; typedef struct { gchar *label; GtkWidget *widget; } cert_data_t; static GtkWidget *x509_cert_widget_from_buffer(const guchar *buffer, size_t buflen, gchar **subject); static cert_data_t *cert_data_tls(GTlsCertificate *cert); static cert_data_t *cert_data_smime(gpgme_ctx_t ctx, gchar **fingerprint); static void cert_data_free(cert_data_t *cert_data); static GtkWidget *create_chain_widget(GList *cert_list); static void cert_selected_cb(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, GtkStack *stack); /* documentation - see header file */ GtkWidget * x509_cert_chain_tls(GTlsCertificate *cert) { GList *chain; GTlsCertificate *issuer; GtkWidget *widget; g_return_val_if_fail(G_IS_TLS_CERTIFICATE(cert), NULL); chain = g_list_prepend(NULL, cert_data_tls(cert)); issuer = g_tls_certificate_get_issuer(cert); while (issuer != NULL) { GTlsCertificate *parent; chain = g_list_prepend(chain, cert_data_tls(issuer)); /* get parent - note: this is part of the source certificate, so *don't* unref it */ parent = g_tls_certificate_get_issuer(issuer); issuer = parent; } if (chain->next != NULL) { widget = create_chain_widget(chain); } else { widget = ((cert_data_t *) chain->data)->widget; } g_list_free_full(chain, (GDestroyNotify) cert_data_free); return widget; } /* documentation - see header file */ GtkWidget * x509_cert_chain_smime(const gchar *fingerprint) { gpgme_ctx_t ctx; GtkWidget *widget = NULL; if (fingerprint != NULL) { ctx = libbalsa_gpgme_new_with_proto(GPGME_PROTOCOL_CMS, NULL, NULL, NULL); if (ctx != NULL) { GList *chain = NULL; gchar *keyid; keyid = g_strdup(fingerprint); while (keyid != NULL) { chain = g_list_prepend(chain, cert_data_smime(ctx, &keyid)); } gpgme_release(ctx); if (chain != NULL) { if (chain->next != NULL) { widget = create_chain_widget(chain); } else { widget = ((cert_data_t *) chain->data)->widget; } g_list_free_full(chain, (GDestroyNotify) cert_data_free); } } } if (widget == NULL) { widget = gtk_label_new(_("Broken key, cannot identify certificate chain.")); } return widget; } /** \brief Create the certificate chain widget * * \param cert_list list of \ref cert_data_t items, starting with the root certificate * \return a newly created certificate chain widget * * The certificate chain widget is a VBox, containing the certificate chain tree view in the upper and a GtkStack in the lower part. * The latter displays the certificate selected in the tree view. */ static GtkWidget * create_chain_widget(GList *cert_list) { GtkWidget *vbox; GtkWidget *scrolledwin; GtkTreeStore *store; GtkTreeIter iter; GtkTreeIter parent; GtkWidget *tree_view; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreePath *path; GtkWidget *stack; GList *p; gboolean is_root; vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, HIG_PADDING); scrolledwin = gtk_scrolled_window_new(NULL, NULL); gtk_widget_set_vexpand(scrolledwin, TRUE); gtk_widget_set_valign(scrolledwin, GTK_ALIGN_FILL); libbalsa_set_vmargins(scrolledwin, HIG_PADDING); gtk_container_add(GTK_CONTAINER(vbox), scrolledwin); store = gtk_tree_store_new(CERT_COLUMNS, G_TYPE_STRING, GTK_TYPE_WIDGET); tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_container_add(GTK_CONTAINER(scrolledwin), tree_view); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes(NULL, renderer, "text", CERT_NAME_COLUMN, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(tree_view), FALSE); gtk_tree_view_set_level_indentation(GTK_TREE_VIEW(tree_view), 2 * HIG_PADDING); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE); gtk_tree_view_set_activate_on_single_click(GTK_TREE_VIEW(tree_view), TRUE); stack = gtk_stack_new(); gtk_widget_set_vexpand(stack, TRUE); gtk_widget_set_valign(stack, GTK_ALIGN_FILL); libbalsa_set_vmargins(stack, HIG_PADDING); gtk_container_add(GTK_CONTAINER(vbox), stack); g_signal_connect(tree_view, "row-activated", G_CALLBACK(cert_selected_cb), stack); is_root = TRUE; for (p = cert_list; p != NULL; p = p->next) { cert_data_t *cert = (cert_data_t *) p->data; gtk_widget_show(cert->widget); gtk_tree_store_append(store, &iter, is_root ? NULL : &parent); parent = iter; gtk_tree_store_set(store, &iter, CERT_NAME_COLUMN, cert->label, CERT_WIDGET_COLUMN, cert->widget, -1); gtk_stack_add_named(GTK_STACK(stack), cert->widget, cert->label); gtk_stack_set_visible_child(GTK_STACK(stack), cert->widget); is_root = FALSE; } gtk_tree_view_expand_all(GTK_TREE_VIEW(tree_view)); gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)), &iter); path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(tree_view), path, NULL, FALSE, 0.0, 0.0); gtk_tree_path_free(path); g_object_unref(store); return vbox; } /** \brief Certificate selection callback * * \param tree_view tree view * \param path selected tree view path * \param column selected tree view column, unused * \param stack target stack * * Switch the passed GtkStack to display the widget indicated by the \ref CERT_WIDGET_COLUMN of the selected tree view path. */ static void cert_selected_cb(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn G_GNUC_UNUSED *column, GtkStack *stack) { GtkTreeModel *model = gtk_tree_view_get_model(tree_view); GtkTreeIter iter; if (gtk_tree_model_get_iter(model, &iter, path)) { GtkWidget *widget; gtk_tree_model_get(model, &iter, CERT_WIDGET_COLUMN, &widget, -1); gtk_stack_set_visible_child(stack, widget); } } /** \brief Get subject and widget for a S/MIME certificate * * \param ctx properly initialised GpgME context * \param fingerprint fingerprint of the S/MIME certificate to be loaded, replaced by the parent certificate fingerprint * \return a newly allocated certificate data item, containing subject string and widget * * If the certificate can be loaded using the passed fingerprint, the widget in the returned struct is a display widget as created * by calling x509_cert_widget_from_buffer(), and the subject is the sanitised primary uid. The passed fingerprint is replaced by * the fingerprint of the issuer certificate. The caller shall free this value if necessary. * * Otherwise, the widget is just a GtkLabel saying that the certificate is not available, the label contains the fingerprint string, * and the passed fingerprint is freed and returned as NULL. */ static cert_data_t * cert_data_smime(gpgme_ctx_t ctx, gchar **fingerprint) { gpgme_key_t key; GError *error = NULL; cert_data_t *result; result = g_new0(cert_data_t, 1U); key = libbalsa_gpgme_load_key(ctx, *fingerprint, &error); if (key != NULL) { gpgme_data_t keybuf; gchar *key_data; size_t key_bytes; result->label = libbalsa_cert_subject_readable(key->uids->uid); gpgme_data_new(&keybuf); (void) gpgme_op_export(ctx, *fingerprint, 0, keybuf); key_data = gpgme_data_release_and_get_mem(keybuf, &key_bytes); result->widget = x509_cert_widget_from_buffer((const guchar *) key_data, key_bytes, NULL); gpgme_free(key_data); /* check if we reached the root */ if ((key->chain_id != NULL) && (g_ascii_strcasecmp(*fingerprint, key->chain_id) != 0)) { g_free(*fingerprint); *fingerprint = g_strdup(key->chain_id); } else { g_free(*fingerprint); *fingerprint = NULL; } gpgme_key_unref(key); } else { gchar *errbuf; result->label = g_strdup_printf(_("fingerprint %s"), *fingerprint); errbuf = g_strdup_printf(_("cannot load key with fingerprint %s: %s"), *fingerprint, error->message); g_error_free(error); result->widget = gtk_label_new(errbuf); g_free(errbuf); g_free(*fingerprint); *fingerprint = NULL; } return result; } /** \brief Free a certificate data item * * \param cert_data certificate data * * This function is used as callback for g_list_free_full() from x509_cert_chain_tls() and x509_cert_chain_smime() when cleaning up * the certificate chain data. It frees cert_data_t::label and the passed data item itself, but \em not cert_data::widget, as it * is consumed in the returned widget of the aforementioned functions. */ static void cert_data_free(cert_data_t *cert_data) { g_free(cert_data->label); g_free(cert_data); } #if HAVE_GCR /** \brief Get subject and widget for a TLS certificate * * \param cert TLS certificate * \return a newly allocated certificate data item, containing subject string and widget */ static cert_data_t * cert_data_tls(GTlsCertificate *cert) { GByteArray *der_data; GcrCertificate *gcr_cert; cert_data_t *result; result = g_new0(cert_data_t, 1U); g_object_get(cert, "certificate", &der_data, NULL); gcr_cert = gcr_simple_certificate_new(der_data->data, der_data->len); g_byte_array_unref(der_data); result->label = gcr_certificate_get_subject_name(gcr_cert); result->widget = GTK_WIDGET(gcr_certificate_widget_new(gcr_cert)); g_object_unref(gcr_cert); return result; } /** \brief Create a certificate widget from a DER buffer * * \param buffer DER data buffer * \param buflen number of bytes in the DER data buffer * \param subject unused, required for a unified API when GCR is not available * \return a new (GCR) certificate widget */ static GtkWidget * x509_cert_widget_from_buffer(const guchar *buffer, size_t buflen, gchar G_GNUC_UNUSED **subject) { GcrCertificate *gcr_cert; GtkWidget *widget; g_return_val_if_fail((buffer != NULL) && (buflen > 0U), NULL); gcr_cert = gcr_simple_certificate_new(buffer, buflen); widget = GTK_WIDGET(gcr_certificate_widget_new(gcr_cert)); g_object_unref(gcr_cert); return widget; } #else /** \brief Create a GnuTLS certificate item from DER data * * \param buffer DER data buffer * \param buflen number of bytes in the DER data buffer * \return a new GnuTLS certificate item */ static gnutls_x509_crt_t G_GNUC_WARN_UNUSED_RESULT get_gnutls_cert(const guchar *buffer, guint buflen) { gnutls_x509_crt_t res_crt; int gnutls_res; gnutls_res = gnutls_x509_crt_init(&res_crt); if (gnutls_res == GNUTLS_E_SUCCESS) { gnutls_datum_t data; data.data = (unsigned char *) buffer; data.size = buflen; gnutls_res = gnutls_x509_crt_import(res_crt, &data, GNUTLS_X509_FMT_DER); if (gnutls_res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(res_crt); res_crt = NULL; } } else { res_crt = NULL; } if (res_crt == NULL) { g_warning("GnuTLS: %d: %s", gnutls_res, gnutls_strerror(gnutls_res)); } return res_crt; } /** \brief Get a DN from a GnuTLS certificate * * \param cert GnuTLS certificate * \param load_fn function pointer for loading the DN * \return a newly allocated, utf8-clean string containing the loaded DN */ static gchar * G_GNUC_WARN_UNUSED_RESULT gnutls_get_dn(gnutls_x509_crt_t cert, int (*load_fn)(gnutls_x509_crt_t cert, char *buf, size_t *buf_size)) { size_t buf_size; gchar *str_buf; buf_size = 0U; (void) load_fn(cert, NULL, &buf_size); str_buf = g_malloc0(buf_size + 1U); if (load_fn(cert, str_buf, &buf_size) != GNUTLS_E_SUCCESS) { g_free(str_buf); str_buf = NULL; } else { libbalsa_utf8_sanitize(&str_buf, TRUE, NULL); } return str_buf; } /** \brief Get the certificate fingerprint * * \param cert GnuTLS certificate * \param algo fingerprint hash algorithm * \return a newly allocated string containing the fingerprint as a series of colon-separated hex bytes */ static gchar * G_GNUC_WARN_UNUSED_RESULT x509_fingerprint(gnutls_x509_crt_t cert, gnutls_digest_algorithm_t algo) { size_t buf_size; guint8 *sha_buf; gchar *str_buf; size_t n; buf_size = gnutls_hash_get_len(algo); sha_buf = g_malloc(buf_size); gnutls_x509_crt_get_fingerprint(cert, algo, sha_buf, &buf_size); str_buf = g_malloc0((3 * buf_size) + 1U); for (n = 0U; n < buf_size; n++) { sprintf(&str_buf[3U * n], "%02x:", sha_buf[n]); } g_free(sha_buf); str_buf[(3 * buf_size) - 1U] = '\0'; return str_buf; } /** \brief Create a certificate widget from a DER buffer * * \param buffer DER data buffer * \param buflen number of bytes in the DER data buffer * \param subject if not NULL, filled with a newly allocated string containing the certificate's subject * \return a new (GCR) certificate widget * * The Widget is basically a label, containing the certificate's dn, the issuer dn, the SHA1 and SHA256 fingerprints, and the * validity period. */ static GtkWidget * x509_cert_widget_from_buffer(const guchar *buffer, size_t buflen, gchar **subject) { gnutls_x509_crt_t cert; GtkWidget *widget; GString *str; gchar *name; gchar *valid_from; gchar *valid_until; gchar *sha256_fp; gchar *c; cert = get_gnutls_cert(buffer, buflen); if (cert == NULL) { g_warning("%s: unable to create gnutls cert", __func__); return NULL; } str = g_string_new("This certificate belongs to:\n"); name = gnutls_get_dn(cert, gnutls_x509_crt_get_dn); g_string_append(str, name); if (subject != NULL) { *subject = name; } else { g_free(name); } g_string_append(str, _("\nThis certificate was issued by:\n")); name = gnutls_get_dn(cert, gnutls_x509_crt_get_issuer_dn); g_string_append_printf(str, "%s\n", name); g_free(name); name = x509_fingerprint(cert, GNUTLS_DIG_SHA1); sha256_fp = x509_fingerprint(cert, GNUTLS_DIG_SHA256); valid_from = libbalsa_date_to_utf8(gnutls_x509_crt_get_activation_time(cert), "%x %X"); valid_until = libbalsa_date_to_utf8(gnutls_x509_crt_get_expiration_time(cert), "%x %X"); g_string_append_printf(str, _("This certificate is valid\n" "from %s\n" "to %s\n" "Fingerprint:\nSHA1: %s\nSHA256: %s"), valid_from, valid_until, name, sha256_fp); g_free(sha256_fp); g_free(name); g_free(valid_from); g_free(valid_until); gnutls_x509_crt_deinit(cert); /* This string uses markup, so we must replace "&" with "&" */ c = str->str; while ((c = strchr(c, '&'))) { gssize pos; pos = (c - str->str) + 1; g_string_insert(str, pos, "amp;"); c = str->str + pos; } widget = gtk_label_new(str->str); gtk_label_set_use_markup(GTK_LABEL(widget), TRUE); gtk_label_set_ellipsize(GTK_LABEL(widget), PANGO_ELLIPSIZE_END); g_string_free(str, TRUE); return widget; } /** \brief Get subject and widget for a TLS certificate * * \param cert TLS certificate * \return a newly allocated certificate data item, containing subject string and widget */ static cert_data_t * cert_data_tls(GTlsCertificate *cert) { GByteArray *der_data; cert_data_t *result; result = g_new0(cert_data_t, 1U); g_object_get(cert, "certificate", &der_data, NULL); result->widget = x509_cert_widget_from_buffer(der_data->data, der_data->len, &result->label); g_byte_array_unref(der_data); return result; } #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libbalsa/x509-cert-widget.h000066400000000000000000000042601477646064400252670ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* * Balsa E-Mail Client * * X509 certificate (TLS, S/MIME) widgets * Copyright (C) 2019 Albrecht Dreß * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef LIBBALSA_X509_CERT_WIDGET_H_ #define LIBBALSA_X509_CERT_WIDGET_H_ #include G_BEGIN_DECLS /** \brief Create a certificate chain widget for a TLS certificate * * \param cert TLS certificate * \return a new widget on success or NULL on error * * If the passed certificate is self-signed or if the issuer cannot be determined, the function returns a widget containing the * certificate information. Otherwise, the returned widget is a vertical GtkBox, containing the certificate chain tree view in the * upper and a GtkStack in the lower part. The latter displays the certificate selected in the tree view. */ GtkWidget *x509_cert_chain_tls(GTlsCertificate *cert); /** \brief Create a certificate chain widget for a S/MIME certificate * * \param fingerprint fingerprint of a S/MIME certificate * \return a new widget on success or NULL on error * * If S/MIME certificate identified by the fingerprint is self-signed or if the issuer cannot be determined, the function returns a * widget containing the certificate information. Otherwise, the returned widget is a vertical GtkBox, containing the certificate * chain tree view in the upper and a GtkStack in the lower part. The latter displays the certificate selected in the tree view. */ GtkWidget *x509_cert_chain_smime(const gchar *fingerprint); G_END_DECLS #endif /* LIBBALSA_X509_CERT_WIDGET_H_ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/000077500000000000000000000000001477646064400232165ustar00rootroot00000000000000balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/.cvsignore000066400000000000000000000000561477646064400252170ustar00rootroot00000000000000.deps Makefile.in Makefile balsa-*.c balsa-*.hbalsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/Makefile.am000066400000000000000000000012771477646064400252610ustar00rootroot00000000000000noinst_LIBRARIES = libinit_balsa.a libinit_balsa_a_SOURCES = \ assistant_page_defclient.c \ assistant_page_defclient.h \ assistant_page_directory.c \ assistant_page_directory.h \ assistant_page_finish.c \ assistant_page_finish.h \ assistant_page_server.c \ assistant_page_server.h \ assistant_page_user.c \ assistant_page_user.h \ assistant_page_welcome.c \ assistant_page_welcome.h \ assistant_init.c \ assistant_init.h \ assistant_helper.c \ assistant_helper.h AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) \ -I$(top_srcdir)/libbalsa \ -I${top_srcdir}/libnetclient \ -I$(top_srcdir)/src \ $(BALSA_CFLAGS) AM_CFLAGS = $(BALSA_DEFS) EXTRA_DIST = \ meson.build balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/README000066400000000000000000000167051477646064400241070ustar00rootroot00000000000000libinit_balsa Peter Williams 12/9/99 This document explains quickly how libinit_balsa works. 1. OVERVIEW libinit_balsa is a static library. It can thus access Balsa's library functions and modify Balsa's data without kludginess. It is separate from the rest of the code because of limitations of GOB (see below) and for the sake of modularity. The purpose of libinit_balsa is to help the user set up Balsa when they first use it. Because this code will usually only be executed once by any given user, the bloat it adds is an important consideration. However, I justify the size of libinit_balsa thusly: Linux (and AFAIK the other kernels it runs on) load code pages on demand: the executable starts, jumps to an unloaded address, generates a page fault that causes the necessary code to be loaded, continues until it generates another page fault, until all the code that will be used by the program is in RAM. Hopefully the libinit_balsa code will not be loaded unless the user runs it, which will only happen once, so bloat is not an issue. 2. IMPLEMENTATION libinit_balsa is based on GOB, the GTK+ Object Builder. It's like a lex for generating GTK+ objects instead of lexical scanners. It will automatically do the gtk_type_unique()'s, the gtk_signal_new()'s, and all those other chores. GOB is not very old but is pretty smart, and has not proven to limit the code I've written here. Almost all of libinit_balsa consists of GTK+ objects derived from the GnomeDruid objects. There are custom BalsaInitDruids and BalsaDruidPages. The same functionality could be (and has been) implemented as instances of GnomeDruid's and GnomeDruidPage's without the object code, but it had a few issues: o There were too many gtk_object_{g,s}et_data() calls o The code was crammed into one file and confusing o It was not extensible by any means I believe the current implementation addresses those problems 3. INTERFACE libinit_balsa provides one function to the outside word: balsa_init_begin(), which creates the druid and takes control of the interface. While the druid is active it will modify some of Balsa's structures and call some functions, but the UI is completely frozen. 4. BALSAINITDRUID The BalsaInitDruid object is essentially a GnomeDruid that knows exactly what pages it needs. On creation it populates itself with the custom init page. The only interesting data it maintains is a default icon for pages to use. This object is not designed to be extended. If the druid is cancelled, it will confirm whether the user wants to exit Balsa (not just the wizard) and conditionally exits. 5. BALSADRUIDPAGE The BalsaDruidPage extends the GnomeDruidPageStandard's capabilities somewhat. It provides next and prev fields, for navigating the sequence of pages, a druid field that is probably superfluous (it references the owning druid), and implements the 'construct' class function. Unfortunately, the implementation of GnomeDruidPageStandard contains a function, gnome_druid_page_standard_construct(), that is both necessary and only accessible to the immediate file: it is static and not a class function or signal. It creates the canvas items needed to draw the page. BalsaDruidPage implements this function by copying it straight out of gnome-libs/libgnomeui/gnome-druid-page-standard.c. BalsaDruidPage allows children to call this function, so that the functionality can be extended properly. BalsaDruidPage provides 'back' and 'next' functions that use the next and prev fields correctly. Someday the nomenclature (back vs. prev) should be standardized. All children of BalsaDruidPage are expected to behave a certain way: create their specific widgets on init / new; check for valid entries when next is clicked; go on to an error page (see below) if an entry is not valid; otherwise apply the changes and go on to another page. Note that all the messages and titles are preset, not up to the caller. BalsaDruidPage doesn't do much by itself, and should be subclassed. 6. BALSADRUIDPAGEWELCOME The first page seen by the user is of class BalsaDruidPageWelcome. IT IS NOT A CHILD OF BalsaDruidPage! IT IS A CHILD OF GnomeDruidPageStart! This is because GnomeDruidPageStart provides too many services to make it worthwhile to do them myself. Also, the welcome page will not need any special functionality; some code relies on pages being BalsaDruidPages, but since the welcome page does nothing interesting along these lines. The Welcome page again reimplements the construct code from the Gnome sources. It is not designed to be subclassed. 7. BALSADRUIDPAGEUSER The first real page the user sees is BalsaDruidPageUser. This collects user information in a table driven by the EntryData scheme (see below). When next is pressed, the data is validated, the local mail directory is created if necessary, and the user proceeds on to the mail files page. If an error occurs in creating the local mail directory the user goes on to an error page (see below). This page should not be subclassed. 8. BALSADRUIDPAGEDIRECTORY The BalsaDruidPageDirectory lets the user set up their default mail files. If not present, directories and files will be created. It should not be subclassed. 9. BALSADRUIDPAGEFINISH This page displays a message that Balsa is set up and closes the whole druid, which applies the changes made, saves the config, and returns control to the main program. It should not be subclassed. 10. BALSADRUIDPAGEERROR BalsaDruidPageError is an exception. It is a child of BalsaDruidPage, but it is a little bit configurable. At new()-time you specify a title and an error message. Otherwise, the page behaves the same all the time: it disables the forward button, and displays the error message and extra information (currently only errno). If the user goes back the page will remove itself from the list of pages and destroy itself. Well, that's not exactly how it works out, but you can pretend that's what happens. Although the error page is configurable it should not be subclassed. 11. ENTRYDATA Also in libinit_balsa is a little utility routine to create tables for entering data. These tables do nifty things like preventing the user from continuing until all the fields contain text. If a page wishes to use this it needs to provide: an EntryMaster structure for containing information about the state of all the fields, and EntryData struct for each individual field, and a GtkTable that will have the fields packed into it. This code is very inflexible; it makes a great many assumptions. The table is filled at the second row, because in the times it is used so far the first row is filled with an instructional label. The EntryMaster structure having been initialized, and the EntryData structures blank except for the reference to the EntryMaster, your code should call balsa_init_add_table_entry(). The arguments are: o The table to pack the widgets into o The serial number of this entry o The text to put in label describing this entry o The default text of this entry o The EntryData describing this entry o The page that owns this table o (out) The entry widget that was created The result can be seen in BalsaDruidPageUser. 12. OTHER HELPER FUNCTIONS balsa_init_get_png() -- Makes a GdkImlibImage out of a filename is it appears in balsa/pixmaps/*.png. Once we move to GdkPixbuf this'll have to be changed. balsa_init_create_to_directory() -- Given a directory pathname, creates directories (mode 700) up to and including that point. complaint is set to a nonnull string describing the error, and true is returned, when an error occursbalsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_helper.c000066400000000000000000000115021477646064400267310ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "assistant_helper.h" #include #include #include #include #include #include #include "libbalsa.h" /* * #ifdef BALSA_LOCAL_INSTALL * #define gnome_pixmap_file(s) g_strconcat(BALSA_RESOURCE_PREFIX, "/pixmaps/", s, NULL) * #define gnome_unconditional_pixmap_file(s) g_strconcat(BALSA_RESOURCE_PREFIX, "/pixmaps", s, NULL) * #endif */ /* ************************************************************************** */ static void entry_changed_cb(GtkEntry * entry, EntryData * ed); /* ************************************************************************** */ GtkWidget * balsa_init_add_grid_entry(GtkGrid * grid, gint num, const gchar * ltext, const gchar * etext, EntryData * ed, GtkAssistant * druid, GtkWidget *page, GtkWidget ** dest) { GtkWidget *l, *e; l = gtk_label_new_with_mnemonic(ltext); gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_RIGHT); gtk_widget_set_halign(l, GTK_ALIGN_END); gtk_grid_attach(grid, l, 0, num + 1, 1, 1); e = gtk_entry_new(); gtk_label_set_mnemonic_widget(GTK_LABEL(l), e); gtk_widget_set_hexpand(e, TRUE); gtk_grid_attach(grid, e, 1, num + 1, 1, 1); (*dest) = e; if(ed) { g_signal_connect(e, "changed", G_CALLBACK(entry_changed_cb), ed); ed->num = ed->controller->numentries++; ed->druid = druid; ed->page = page; if (etext && etext[0] != '\0') ed->controller->setbits |= (1 << num); ed->controller->donemask = (ed->controller->donemask << 1) | 1; } gtk_entry_set_text(GTK_ENTRY(e), etext); return e; } static void entry_changed_cb(GtkEntry * entry, EntryData * ed) { g_assert(ed != NULL); if (gtk_entry_get_text_length(entry)) { ed->controller->setbits |= (1 << ed->num); } else { ed->controller->setbits &= ~(1 << ed->num); } /* The stuff below is only when we are displayed... which is not * always the case. */ if (!gtk_widget_get_visible(GTK_WIDGET(entry))) return; if (GTK_IS_ASSISTANT(ed->druid)) { /* Don't let them continue unless all entries have something. */ if (ENTRY_CONTROLLER_DONE(ed->controller)) { gtk_assistant_set_page_complete(ed->druid, ed->page, TRUE); } else { gtk_assistant_set_page_complete(ed->druid, ed->page, FALSE); } } } void balsa_init_add_grid_option(GtkGrid *grid, gint num, const gchar *ltext, const gchar **optns, GtkAssistant *druid, GtkWidget **dest) { GtkWidget *l, *om; int i; l = gtk_label_new_with_mnemonic(ltext); gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_RIGHT); gtk_widget_set_halign(l, GTK_ALIGN_END); gtk_grid_attach(grid, l, 0, num + 1, 1, 1); *dest = om = gtk_combo_box_text_new(); for(i=0; optns[i]; i++) gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(om), _(optns[i])); gtk_label_set_mnemonic_widget(GTK_LABEL(l), om); gtk_combo_box_set_active(GTK_COMBO_BOX(om), 0); gtk_widget_set_hexpand(om, TRUE); gtk_grid_attach(grid, om, 1, num + 1, 1, 1); } gint balsa_option_get_active(GtkWidget *option_widget) { return gtk_combo_box_get_active(GTK_COMBO_BOX(option_widget)); } gboolean balsa_init_create_to_directory(const gchar * dir, gchar ** complaint) { if (!g_path_is_absolute(dir)) { (*complaint) = g_strdup_printf(_ ("The path %s must be relative to the filesystem root (start with /)."), dir); return TRUE; } if (g_mkdir_with_parents(dir, S_IRWXU) == -1) { (*complaint) = g_strdup_printf(_("Couldn’t create a directory “%s”: %s"), dir, g_strerror(errno)); return TRUE; } return FALSE; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_helper.h000066400000000000000000000041031477646064400267350ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef LIBINIT_BALSA_HELPER_H #define LIBINIT_BALSA_HELPER_H #include typedef struct EntryData_s EntryData; typedef struct EntryController_s EntryController; struct EntryData_s { GtkAssistant *druid; GtkWidget *page; guint num; EntryController *controller; }; #define ENTRY_DATA_INIT { NULL, 0 } struct EntryController_s { guint32 setbits; guint32 numentries; guint32 donemask; }; #define ENTRY_CONTROLLER_INIT { 0, 0, 0 } #define ENTRY_CONTROLLER_DONE( e ) ( ((e)->setbits & (e)->donemask) == (e)->donemask ) GtkWidget *balsa_init_add_grid_entry(GtkGrid * grid, gint num, const gchar * ltext, const gchar * etext, EntryData * ed, GtkAssistant * druid, GtkWidget * page, GtkWidget ** dest); void balsa_init_add_grid_option(GtkGrid *grid, gint num, const gchar *ltext, const gchar **optns, GtkAssistant *druid, GtkWidget **dest); gint balsa_option_get_active(GtkWidget *option_widget); gboolean balsa_init_create_to_directory(const gchar * dir, gchar ** complaint); #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_init.c000066400000000000000000000126151477646064400264230ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "assistant_init.h" #include #include #include "libbalsa-conf.h" #include "misc.h" #include "save-restore.h" #include "balsa-app.h" #include "assistant_page_welcome.h" #include "assistant_page_user.h" #include "assistant_page_server.h" #include "assistant_page_directory.h" #include "assistant_page_defclient.h" #include "assistant_page_finish.h" static void balsa_initdruid_cancel_response(GtkDialog *self, gint response_id, gpointer user_data); static void balsa_initdruid_cancel(GtkAssistant * druid, gpointer user_data) { GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_ancestor (GTK_WIDGET(druid), GTK_TYPE_WINDOW)), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("This will exit Balsa.\n" "Do you really want to do this?")); g_signal_connect(dialog, "response", G_CALLBACK(balsa_initdruid_cancel_response), NULL); gtk_widget_show_all(dialog); } static void balsa_initdruid_cancel_response(GtkDialog *self, gint response_id, gpointer user_data) { GtkResponseType reply = response_id; gtk_widget_destroy(GTK_WIDGET(self)); if (reply == GTK_RESPONSE_YES) { libbalsa_conf_drop_all(); exit(0); } } static void balsa_initdruid_apply(GtkAssistant * druid, gpointer user_data) { gchar *address_book; LibBalsaAddressBook *ab = NULL; address_book = g_build_filename(g_get_home_dir(), "GnomeCard.gcrd", NULL); if (g_file_test(address_book, G_FILE_TEST_EXISTS)) ab = libbalsa_address_book_vcard_new(_("GnomeCard Address Book"), address_book); g_free(address_book); if(!ab) { address_book = g_build_filename(g_get_home_dir(), ".addressbook.ldif", NULL); if (g_file_test(address_book, G_FILE_TEST_EXISTS)) ab = libbalsa_address_book_ldif_new(_("Address Book"), address_book); g_free(address_book); } if(!ab) { /* This will be the default address book and its location */ address_book = g_build_filename(g_get_user_config_dir(), "balsa", "addressbook.ldif", NULL); ab = libbalsa_address_book_ldif_new(_("Address Book"), address_book); g_free(address_book); } balsa_app.address_book_list = g_list_prepend(balsa_app.address_book_list, ab); balsa_app.default_address_book = ab; g_signal_handlers_disconnect_by_func(druid, G_CALLBACK(exit), NULL); libbalsa_conf_push_group("Notifications"); libbalsa_conf_set_bool("GtkUIManager", TRUE); libbalsa_conf_set_bool("LibBalsaAddressView", TRUE); libbalsa_conf_pop_group(); config_save(); gtk_main_quit(); } static void balsa_initdruid(GtkAssistant * assistant) { g_signal_connect(assistant, "cancel", G_CALLBACK(balsa_initdruid_cancel), NULL); g_signal_connect(assistant, "close", G_CALLBACK(balsa_initdruid_apply), NULL); balsa_druid_page_welcome(assistant); balsa_druid_page_user(assistant); balsa_druid_page_server(assistant); balsa_druid_page_directory(assistant); balsa_druid_page_defclient(assistant); balsa_druid_page_finish(assistant); } /* The external interface code */ static gboolean dismiss_the_wizard(GtkWidget *wizard) { gtk_widget_destroy(wizard); return FALSE; } void balsa_init_begin(void) { GtkWidget *assistant; assistant = gtk_assistant_new(); gtk_window_set_title(GTK_WINDOW(assistant), _("Configure Balsa")); gtk_window_set_default_size(GTK_WINDOW(assistant), 1, 1); balsa_initdruid(GTK_ASSISTANT(assistant)); gtk_widget_show_all(assistant); gtk_main(); /* we do not want to destroy wizard immediately to avoid confusing delay between the wizard that left and balsa that entered. */ g_idle_add((GSourceFunc)dismiss_the_wizard, assistant); } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_init.h000066400000000000000000000020261477646064400264230ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __BALSA_INITDRUID_H__ #define __BALSA_INITDRUID_H__ #include #include "assistant_helper.h" G_BEGIN_DECLS /* * Public methods */ void balsa_init_begin( void ); G_END_DECLS #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_defclient.c000066400000000000000000000102101477646064400303760ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "assistant_page_defclient.h" #include #include #include #include #include #include "balsa-app.h" /* here are local prototypes */ static void balsa_druid_page_defclient_init(BalsaDruidPageDefclient *defclient, GtkWidget *page, GtkAssistant *druid); static void balsa_druid_page_defclient_toggle(GtkWidget * page, BalsaDruidPageDefclient * defclient); static void balsa_druid_page_defclient_init(BalsaDruidPageDefclient * defclient, GtkWidget * page, GtkAssistant * druid) { GtkLabel *label; GtkWidget *yes, *no; GtkWidget *widget; defclient->default_client = 1; balsa_app.default_client = defclient->default_client; label = GTK_LABEL(gtk_label_new (_("Use Balsa as default email client?"))); gtk_label_set_justify(label, GTK_JUSTIFY_CENTER); gtk_label_set_line_wrap(label, TRUE); yes = gtk_radio_button_new_with_mnemonic(NULL, _("_Yes")); no = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(yes), _("_No")); g_signal_connect(yes, "toggled", G_CALLBACK(balsa_druid_page_defclient_toggle), defclient); widget = GTK_WIDGET(label); gtk_widget_set_vexpand(widget, FALSE); gtk_widget_set_valign(widget, GTK_ALIGN_FILL); libbalsa_set_vmargins(widget, HIG_PADDING + 2); gtk_container_add(GTK_CONTAINER(page), widget); widget = GTK_WIDGET(yes); gtk_widget_set_vexpand(widget, FALSE); gtk_widget_set_valign(widget, GTK_ALIGN_FILL); libbalsa_set_vmargins(widget, 2); gtk_container_add(GTK_CONTAINER(page), widget); widget = GTK_WIDGET(no); gtk_widget_set_vexpand(widget, FALSE); gtk_widget_set_valign(widget, GTK_ALIGN_FILL); libbalsa_set_vmargins(widget, 2); gtk_container_add(GTK_CONTAINER(page), widget); return; } void balsa_druid_page_defclient(GtkAssistant *druid) { GAppInfo *info; BalsaDruidPageDefclient *defclient; GtkWidget *page; info = g_app_info_get_default_for_uri_scheme("mailto"); if (info) { gboolean set_to_balsa_already; set_to_balsa_already = !strcmp(g_app_info_get_name(info), "Balsa"); g_object_unref(info); if(set_to_balsa_already) return; } defclient = g_new0(BalsaDruidPageDefclient, 1); page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_assistant_append_page(druid, page); gtk_assistant_set_page_title(druid, page, _("Default Client")); balsa_druid_page_defclient_init(defclient, page, druid); /* This one is ready to pass through. */ gtk_assistant_set_page_complete(druid, page, TRUE); g_object_weak_ref(G_OBJECT(druid), (GWeakNotify)g_free, defclient); } static void balsa_druid_page_defclient_toggle(GtkWidget * page, BalsaDruidPageDefclient * defclient) { defclient->default_client = ! (defclient->default_client); balsa_app.default_client = defclient->default_client; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_defclient.h000066400000000000000000000031321477646064400304100ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #include #ifndef __BALSA_DRUID_PAGE_DEFCLIENT_H__ #define __BALSA_DRUID_PAGE_DEFCLIENT_H__ #ifndef BALSA_VERSION # error "Include config.h before this file." #endif #include "assistant_helper.h" #include "assistant_init.h" G_BEGIN_DECLS /* * Main object structure */ #ifndef __TYPEDEF_BALSA_DRUID_PAGE_DEFCLIENT__ #define __TYPEDEF_BALSA_DRUID_PAGE_DEFCLIENT__ typedef struct _BalsaDruidPageDefclient BalsaDruidPageDefclient; #endif #define BALSA_DRUID_PAGE_DEFCLIENT(obj) ((BalsaDruidPageDefclient *) obj) struct _BalsaDruidPageDefclient { int default_client; }; /* * Public methods */ void balsa_druid_page_defclient(GtkAssistant * druid); void balsa_druid_page_defclient_save(BalsaDruidPageDefclient * defclient); G_END_DECLS #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_directory.c000066400000000000000000000245541477646064400304650ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "assistant_page_directory.h" #include #include #include #include #include #include #include #include #include "balsa-app.h" #include "save-restore.h" #include "misc.h" #include "server.h" #define INBOX_NAME "Inbox" #define OUTBOX_NAME "Outbox" #define SENTBOX_NAME "Sentbox" #define DRAFTBOX_NAME "Draftbox" #define TRASH_NAME "Trash" static const gchar * const init_mbnames[NUM_EDs] = { N_("_Inbox:"), N_("_Outbox:"), N_("_Sentbox:"), N_("_Draftbox:"), N_("_Trash:") }; static void balsa_druid_page_directory_prepare(GtkAssistant * druid, GtkWidget * page, BalsaDruidPageDirectory * dir); static void balsa_druid_page_directory_back(GtkAssistant * druid, GtkWidget * page, BalsaDruidPageDirectory * dir); static void balsa_druid_page_directory_next(GtkAssistant * druid, GtkWidget * page, BalsaDruidPageDirectory * dir); static void unconditional_mailbox(const gchar * path, const gchar * prettyname, LibBalsaMailbox ** box, gchar ** error); static void unconditional_mailbox(const gchar * path, const gchar * prettyname, LibBalsaMailbox ** box, gchar ** error) { gchar *folder; if ((*error) != NULL) return; folder = g_path_get_dirname(path); if (balsa_init_create_to_directory(folder, error)) { /*TRUE->error */ g_free(folder); return; } g_free(folder); *box = libbalsa_mailbox_local_new(path, TRUE); if (*box == NULL) { *error = g_strdup_printf(_("Could not create mailbox at path “%s”."), path); return; } libbalsa_mailbox_set_name(*box, gettext(prettyname)); config_mailbox_add(*box, (char *) prettyname); if (box == &balsa_app.outbox) libbalsa_mailbox_set_no_reassemble(*box, TRUE); } static void verify_mailbox_entry(GtkWidget * entry, const gchar * name, LibBalsaMailbox ** mailbox, gboolean * verify) { const gchar *text; gchar *error; if (!*verify) return; text = gtk_entry_get_text(GTK_ENTRY(entry)); error = NULL; unconditional_mailbox(text, name, mailbox, &error); if (error) { GtkWidget *dlg = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_ancestor (GTK_WIDGET(entry), GTK_TYPE_WINDOW)), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Problem verifying path “%s”:\n%s"), text, error); g_free(error); *verify = FALSE; g_signal_connect(dlg, "response", G_CALLBACK(gtk_widget_destroy), NULL); gtk_widget_show_all(dlg); } } static void verify_button_clicked_cb(GtkWidget * button, gpointer data) { BalsaDruidPageDirectory *dir = data; gboolean verify = TRUE; verify_mailbox_entry(dir->inbox, INBOX_NAME, &balsa_app.inbox, &verify); verify_mailbox_entry(dir->outbox, OUTBOX_NAME, &balsa_app.outbox, &verify); verify_mailbox_entry(dir->sentbox, SENTBOX_NAME, &balsa_app.sentbox, &verify); verify_mailbox_entry(dir->draftbox, DRAFTBOX_NAME, &balsa_app.draftbox, &verify); verify_mailbox_entry(dir->trash, TRASH_NAME, &balsa_app.trash, &verify); gtk_assistant_set_page_complete(dir->druid, dir->page, verify); } static GtkWidget * verify_button(BalsaDruidPageDirectory * dir) { GtkWidget *button; button = gtk_button_new_with_mnemonic(_("_Verify locations")); g_signal_connect(button, "clicked", G_CALLBACK(verify_button_clicked_cb), dir); gtk_widget_show(button); return button; } static void entry_changed_cb(GtkEditable * editable, gpointer data) { BalsaDruidPageDirectory *dir = data; gtk_assistant_set_page_complete(dir->druid, dir->page, FALSE); } static void balsa_druid_page_directory_init(BalsaDruidPageDirectory * dir, GtkWidget * page, GtkAssistant * druid) { GtkGrid *grid; GtkWidget *label_widget; int i; GtkWidget **init_widgets[NUM_EDs]; gchar *init_presets[NUM_EDs] = { NULL, NULL, NULL, NULL, NULL }; dir->druid = druid; dir->paths_locked = FALSE; grid = GTK_GRID(gtk_grid_new()); gtk_grid_set_column_spacing(grid, HIG_PADDING); label_widget = gtk_label_new(_("Please verify the locations " "of your default mail files. " "These will be created if necessary.")); gtk_label_set_line_wrap(GTK_LABEL(label_widget), TRUE); gtk_widget_set_hexpand(label_widget, TRUE); gtk_widget_set_vexpand(label_widget, FALSE); gtk_widget_set_margin_bottom(label_widget, 12); gtk_grid_attach(grid, label_widget, 0, 0, 2, 1); init_presets[INBOX] = libbalsa_guess_mail_spool(); init_widgets[INBOX] = &(dir->inbox); init_widgets[OUTBOX] = &(dir->outbox); init_widgets[SENTBOX] = &(dir->sentbox); init_widgets[DRAFTBOX] = &(dir->draftbox); init_widgets[TRASH] = &(dir->trash); for (i = 0; i < NUM_EDs; i++) { gchar *preset; GtkWidget *entry; if (init_presets[i]) preset = init_presets[i]; else preset = g_strdup("[Dummy value]"); entry = balsa_init_add_grid_entry(grid, i, _(init_mbnames[i]), preset, NULL, NULL, NULL, init_widgets[i]); g_signal_connect(entry, "changed", G_CALLBACK(entry_changed_cb), dir); g_free(preset); } gtk_widget_set_vexpand(GTK_WIDGET(grid), FALSE); gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_FILL); gtk_container_add(GTK_CONTAINER(page), GTK_WIDGET(grid)); gtk_widget_show_all(GTK_WIDGET(grid)); gtk_container_add(GTK_CONTAINER(page), verify_button(dir)); g_signal_connect(druid, "prepare", G_CALLBACK(balsa_druid_page_directory_prepare), dir); dir->my_num = 98765; dir->need_set = FALSE; } void balsa_druid_page_directory(GtkAssistant * druid) { BalsaDruidPageDirectory *dir; dir = g_new0(BalsaDruidPageDirectory, 1); dir->page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); gtk_assistant_append_page(druid, dir->page); gtk_assistant_set_page_title(druid, dir->page, _("Mail Files")); balsa_druid_page_directory_init(dir, dir->page, druid); g_object_weak_ref(G_OBJECT(druid), (GWeakNotify)g_free, dir); } static void balsa_druid_page_directory_prepare(GtkAssistant * druid, GtkWidget * page, BalsaDruidPageDirectory * dir) { gchar *buf; gint current_page_no = gtk_assistant_get_current_page(druid); if(page != dir->page) { /* This is not the page to be prepared. */ if(dir->need_set) { if(current_page_no > dir->my_num) balsa_druid_page_directory_next(druid, page, dir); else balsa_druid_page_directory_back(druid, page, dir); dir->need_set = FALSE; } return; } dir->my_num = current_page_no; /* We want a change in the local mailroot to be reflected in the * directories here, but we don't want to trash user's custom * settings if needed. Hence the paths_locked variable; it should * work pretty well, because only a movement backwards should * change the mailroot; going forward should not lock the paths: * envision an error occurring; upon return to the Dir page the * entries should be the same. */ if (!dir->paths_locked) { buf = g_build_filename(balsa_app.local_mail_directory, "outbox", NULL); gtk_entry_set_text(GTK_ENTRY(dir->outbox), buf); g_free(buf); buf = g_build_filename(balsa_app.local_mail_directory, "sentbox", NULL); gtk_entry_set_text(GTK_ENTRY(dir->sentbox), buf); g_free(buf); buf = g_build_filename(balsa_app.local_mail_directory, "draftbox", NULL); gtk_entry_set_text(GTK_ENTRY(dir->draftbox), buf); g_free(buf); buf = g_build_filename(balsa_app.local_mail_directory, "trash", NULL); gtk_entry_set_text(GTK_ENTRY(dir->trash), buf); g_free(buf); } /* Don't let them continue unless all entries have something. */ gtk_assistant_set_page_complete(druid, page, FALSE); dir->need_set = TRUE; } static void balsa_druid_page_directory_back(GtkAssistant *druid, GtkWidget *page, BalsaDruidPageDirectory * dir) { dir->paths_locked = FALSE; } static void balsa_druid_page_directory_next(GtkAssistant *druid, GtkWidget *page, BalsaDruidPageDirectory * dir) { dir->paths_locked = TRUE; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_directory.h000066400000000000000000000034451477646064400304660ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __BALSA_DRUID_PAGE_DIRECTORY_H__ #define __BALSA_DRUID_PAGE_DIRECTORY_H__ #include #include "assistant_helper.h" #include "assistant_init.h" G_BEGIN_DECLS /* * Main object structure */ #ifndef __TYPEDEF_BALSA_DRUID_PAGE_DIRECTORY__ #define __TYPEDEF_BALSA_DRUID_PAGE_DIRECTORY__ typedef struct _BalsaDruidPageDirectory BalsaDruidPageDirectory; #endif #define BALSA_DRUID_PAGE_DIRECTORY(obj) ((BalsaDruidPageDirectory *) obj) enum __ed_types { INBOX, OUTBOX, SENTBOX, DRAFTBOX, TRASH, NUM_EDs }; struct _BalsaDruidPageDirectory { GtkWidget *page; GtkWidget *inbox; GtkWidget *outbox; GtkWidget *sentbox; GtkWidget *draftbox; GtkWidget *trash; gint my_num; gboolean paths_locked, need_set; GtkAssistant *druid; }; /* * Public methods */ void balsa_druid_page_directory(GtkAssistant * druid); G_END_DECLS #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_finish.c000066400000000000000000000037551477646064400277410ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "assistant_page_finish.h" #include "assistant_page_directory.h" #include #include "save-restore.h" #if 0 /* here are local prototypes */ static void balsa_druid_page_finish_prepare(GtkWidget * page, GtkAssistant * druid); static void balsa_druid_page_finish_finish(GtkWidget * page, GtkAssistant * druid); #endif void balsa_druid_page_finish(GtkAssistant * druid) { static const gchar bye[] = N_("You’ve successfully set up Balsa. Have fun!\n" " -- The Balsa development team"); GtkWidget *page = gtk_label_new(_(bye)); gtk_assistant_append_page(druid, page); gtk_assistant_set_page_title(druid, page, _("All Done!")); gtk_assistant_set_page_type(druid, page, GTK_ASSISTANT_PAGE_SUMMARY); } #if 0 static void balsa_druid_page_finish_prepare(GnomeDruidPage * page, GnomeDruid * druid) { gnome_druid_set_buttons_sensitive(druid, TRUE, FALSE, TRUE, FALSE); gnome_druid_set_show_finish(druid, TRUE); } #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_finish.h000066400000000000000000000021321477646064400277320ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __BALSA_DRUID_PAGE_FINISH_H__ #define __BALSA_DRUID_PAGE_FINISH_H__ #include #include "assistant_helper.h" #include "assistant_init.h" G_BEGIN_DECLS /* * Public methods */ void balsa_druid_page_finish(GtkAssistant * druid); G_END_DECLS #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_server.c000066400000000000000000000435141477646064400277640ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2022 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "assistant_page_server.h" #include #include #include #include #include "imap/imap-handle.h" #include "imap-server.h" #include "smtp-server.h" #include "server.h" #include "balsa-app.h" #include "save-restore.h" #include "net-client-utils.h" #include "net-client-pop.h" #include "net-client-smtp.h" static void balsa_druid_page_server_init(BalsaDruidPageServer *server, GtkWidget *page, GtkAssistant *druid); static void balsa_druid_page_server_prepare(GtkAssistant *druid, GtkWidget *page, BalsaDruidPageServer *server); static void balsa_druid_page_server_next(GtkAssistant *druid, GtkWidget *page, BalsaDruidPageServer *server); static void on_server_type_changed(GtkComboBox *widget, gpointer user_data); static gchar **guess_servers(const gchar *mail_address) G_GNUC_WARN_UNUSED_RESULT; static gchar *server_from_srv(GResolver *resolver, const gchar * const *service, const gchar *domain) G_GNUC_WARN_UNUSED_RESULT; static gchar *server_by_name(GResolver *resolver, const gchar * const *prefix, const gchar *domain) G_GNUC_WARN_UNUSED_RESULT; static void balsa_druid_page_server_init(BalsaDruidPageServer *server, GtkWidget *page, GtkAssistant *druid) { static const char *header = N_("The pre-set server configuration is a best guess based " "upon your email address. Balsa will automatically choose " "optimum settings for encryption and user name, and select " "password based authentication. Please note that probing the " "server capabilities when you click “Next” will take a few seconds.\n" "Check the “Edit \342\217\265 Preferences \342\217\265 Settings " "\342\217\265 Mail options” menu item if you need to fine-tune them."); static const char* server_types[] = { "IMAP", "POP3", NULL }; static const char* remember_passwd[] = { N_("Yes, remember it"), N_("No, type it in every time"), NULL }; GtkGrid *grid; GtkLabel *label; gchar *preset; int row = 0; label = GTK_LABEL(gtk_label_new(_(header))); gtk_label_set_line_wrap(label, TRUE); gtk_widget_set_hexpand(GTK_WIDGET(label), TRUE); gtk_widget_set_margin_bottom(GTK_WIDGET(label), 12); gtk_container_add(GTK_CONTAINER(page), GTK_WIDGET(label)); grid = GTK_GRID(gtk_grid_new()); gtk_grid_set_row_spacing(grid, 2); gtk_grid_set_column_spacing(grid, 5); balsa_init_add_grid_option(grid, row++, _("_Type of mail server:"), server_types, druid, &(server->incoming_type)); g_signal_connect(server->incoming_type, "changed", G_CALLBACK(on_server_type_changed), server); balsa_init_add_grid_entry(grid, row++, _("Name of mail server for incoming _mail:"), "", /* no guessing here */ NULL, druid, page, &(server->incoming_srv)); balsa_init_add_grid_entry(grid, row++, _("Your email _login name:"), g_get_user_name(), NULL, druid, page, &(server->login)); balsa_init_add_grid_entry(grid, row++, _("Your _password:"), "", NULL, druid, page, &(server->passwd)); libbalsa_entry_config_passwd(GTK_ENTRY(server->passwd)); /* separator line here */ preset = "localhost:25"; balsa_init_add_grid_entry(grid, row++, _("_SMTP Server:"), preset, NULL, druid, page, &(server->smtp)); balsa_init_add_grid_option(grid, row++, _("_Remember your password:"), remember_passwd, druid, &(server->remember_passwd)); libbalsa_set_vmargins(GTK_WIDGET(grid), 3); gtk_container_add(GTK_CONTAINER(page), GTK_WIDGET(grid)); server->need_set = FALSE; } static void on_server_type_changed(GtkComboBox *widget, gpointer user_data) { BalsaDruidPageServer *server = (BalsaDruidPageServer *) user_data; const gchar **servers; int idx; servers = g_object_get_data(G_OBJECT(widget), "SERVERS"); idx = 1 + gtk_combo_box_get_active(widget); gtk_entry_set_text(GTK_ENTRY(server->incoming_srv), ((servers != NULL) && (servers[idx] != NULL)) ? servers[idx] : ""); } void balsa_druid_page_server(GtkAssistant * druid) { BalsaDruidPageServer *server; server = g_new0(BalsaDruidPageServer, 1); server->page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_assistant_append_page(druid, server->page); gtk_assistant_set_page_title(druid, server->page, _("Server Settings")); balsa_druid_page_server_init(server, server->page, druid); g_signal_connect(druid, "prepare", G_CALLBACK(balsa_druid_page_server_prepare), server); g_object_weak_ref(G_OBJECT(druid), (GWeakNotify) g_free, server); } static void balsa_druid_page_server_prepare(GtkAssistant *druid, GtkWidget *page, BalsaDruidPageServer *server) { if (page != server->page) { if (server->need_set) { balsa_druid_page_server_next(druid, page, server); server->need_set = FALSE; } return; } g_object_set_data(G_OBJECT(server->incoming_type), "SERVERS", NULL); if (balsa_app.current_ident != NULL) { InternetAddress *ia; const gchar *address; ia = libbalsa_identity_get_address(balsa_app.current_ident); /* should never be NULL */ address = internet_address_mailbox_get_addr(INTERNET_ADDRESS_MAILBOX(ia)); if (address != NULL) { const gchar *at_sign; at_sign = strchr(address, '@'); if (at_sign != NULL) { gchar *login; gchar **servers; /* wild guess: login is the part up to the '@' in the mail address */ login = g_strndup(address, at_sign - address); gtk_entry_set_text(GTK_ENTRY(server->login), login); g_free(login); /* try to guess proper servers */ servers = guess_servers(address); if (servers != NULL) { g_object_set_data_full(G_OBJECT(server->incoming_type), "SERVERS", servers, (GDestroyNotify) g_strfreev); if (servers[0] != NULL) { gtk_entry_set_text(GTK_ENTRY(server->smtp), servers[0]); } gtk_combo_box_set_active(GTK_COMBO_BOX(server->incoming_type), -1); /* force update */ gtk_combo_box_set_active(GTK_COMBO_BOX(server->incoming_type), (servers[1] != NULL) ? 0 : 1); } } } } gtk_assistant_set_page_complete(druid, page, TRUE); gtk_widget_grab_focus(server->incoming_srv); server->need_set = TRUE; } static void create_pop3_mbx(const gchar *host, const gchar *login, const gchar *passwd, gboolean save_pwd) { gchar *host_only; gchar *host_port; NetClientProbeResult probe_res; LibBalsaMailboxPOP3 *mailbox_pop3; LibBalsaMailbox *mailbox; LibBalsaServer *server; GError *error = NULL; host_only = net_client_host_only(host); if (net_client_pop_probe(host_only, 5, &probe_res, G_CALLBACK(libbalsa_server_check_cert), &error)) { host_port = g_strdup_printf("%s:%hu", host_only, probe_res.port); g_debug("probe result for server %s: port %hu, crypt mode %d", host, probe_res.port, probe_res.crypt_mode); } else { g_debug("failed to probe server %s, fall back to POP3S: %s", host, error->message); host_port = g_strdup_printf("%s:995", host_only); probe_res.crypt_mode = NET_CLIENT_CRYPT_ENCRYPTED; } g_clear_error(&error); mailbox_pop3 = libbalsa_mailbox_pop3_new(); mailbox = LIBBALSA_MAILBOX(mailbox_pop3); server = LIBBALSA_MAILBOX_REMOTE_GET_SERVER(mailbox); libbalsa_server_set_host(server, host_port, probe_res.crypt_mode); libbalsa_server_set_username(server, login); libbalsa_server_set_password(server, passwd, FALSE); libbalsa_server_set_auth_mode(server, NET_CLIENT_AUTH_USER_PASS); libbalsa_server_set_remember_password(server, save_pwd); libbalsa_mailbox_set_name(mailbox, host_only); libbalsa_mailbox_pop3_set_check(mailbox_pop3, TRUE); libbalsa_mailbox_pop3_set_disable_apop(mailbox_pop3, FALSE); libbalsa_mailbox_pop3_set_delete_from_server(mailbox_pop3, TRUE); libbalsa_mailbox_pop3_set_filter(mailbox_pop3, FALSE); libbalsa_mailbox_pop3_set_filter_cmd(mailbox_pop3, "procmail -f -"); config_mailbox_add(mailbox, NULL); g_free(host_only); g_free(host_port); } static void create_imap_mbx(const gchar *host, const gchar *login, const gchar *passwd, gboolean save_pwd) { gchar *host_only; gchar *host_port; NetClientProbeResult probe_res; BalsaMailboxNode *mbnode; LibBalsaServer *server; GError *error = NULL; host_only = net_client_host_only(host); server = LIBBALSA_SERVER(libbalsa_imap_server_new(login, host)); if (imap_server_probe(host_only, 5, &probe_res, G_CALLBACK(libbalsa_server_check_cert), &error)) { host_port = g_strdup_printf("%s:%hu", host_only, probe_res.port); g_debug("probe result for server %s: port %hu, crypt mode %d", host, probe_res.port, probe_res.crypt_mode); } else { g_debug("failed to probe server %s, fall back to IMAPS: %s", host, error->message); host_port = g_strdup_printf("%s:993", host_only); probe_res.crypt_mode = NET_CLIENT_CRYPT_ENCRYPTED; } g_clear_error(&error); libbalsa_server_set_host(server, host_port, probe_res.crypt_mode); libbalsa_server_set_username(server, login); libbalsa_server_set_password(server, passwd, FALSE); libbalsa_server_set_auth_mode(server, NET_CLIENT_AUTH_USER_PASS); libbalsa_server_set_remember_password(server, save_pwd); mbnode = balsa_mailbox_node_new_imap_folder(server, NULL); balsa_mailbox_node_set_name(mbnode, host_only); config_folder_add(mbnode, NULL); g_object_unref(mbnode); g_free(host_only); g_free(host_port); } static void config_smtp(const gchar *host, LibBalsaServer *smtpserver) { gchar *host_only; gchar *host_port; NetClientProbeResult probe_res; GError *error = NULL; host_only = net_client_host_only(host); if (net_client_smtp_probe(host_only, 5, &probe_res, G_CALLBACK(libbalsa_server_check_cert), &error)) { host_port = g_strdup_printf("%s:%hu", host_only, probe_res.port); g_debug("probe result for server %s: port %hu, crypt mode %d", host, probe_res.port, probe_res.crypt_mode); } else { /* Note: the better choice in this case would be SUBMISSIONS (RFC 8314), but in practice some ISP's do not support it. */ g_debug("failed to probe server %s, fall back to SUBMISSION w/ STARTTLS: %s", host, error->message); host_port = g_strdup_printf("%s:587", host_only); probe_res.crypt_mode = NET_CLIENT_CRYPT_STARTTLS; } libbalsa_server_set_host(smtpserver, host_port, probe_res.crypt_mode); g_clear_error(&error); g_free(host_only); g_free(host_port); } static void balsa_druid_page_server_next(GtkAssistant *druid, GtkWidget *page, BalsaDruidPageServer *server) { const gchar *login; const gchar *passwd; gboolean save_pwd; const gchar *host; LibBalsaServer *lbserver; LibBalsaSmtpServer *smtp_server; /* common stuff: user name, password, remember password */ login = gtk_entry_get_text(GTK_ENTRY(server->login)); passwd = gtk_entry_get_text(GTK_ENTRY(server->passwd)); save_pwd = balsa_option_get_active(server->remember_passwd) == 0; /* incoming mail - skip if nothing has been entered */ host = gtk_entry_get_text(GTK_ENTRY(server->incoming_srv)); if ((host != NULL) && (host[0] != '\0')) { switch (balsa_option_get_active(server->incoming_type)) { case 0: /* IMAP */ create_imap_mbx(host, login, passwd, save_pwd); break; case 1: /* POP */ create_pop3_mbx(host, login, passwd, save_pwd); break; default: g_assert_not_reached(); /* internal error */ } } /* outgoing mail */ if (balsa_app.smtp_servers == NULL) { smtp_server = libbalsa_smtp_server_new(); libbalsa_smtp_server_set_name(smtp_server, libbalsa_smtp_server_get_name(NULL)); balsa_app.smtp_servers = g_slist_prepend(NULL, smtp_server); } else { smtp_server = balsa_app.smtp_servers->data; } lbserver = LIBBALSA_SERVER(smtp_server); host = gtk_entry_get_text(GTK_ENTRY(server->smtp)); if ((host != NULL) && (host[0] != '\0') && (strncmp(host, "localhost", 9U) != 0)) { config_smtp(host, lbserver); libbalsa_server_set_username(lbserver, login); libbalsa_server_set_password(lbserver, passwd, FALSE); libbalsa_server_set_auth_mode(lbserver, NET_CLIENT_AUTH_USER_PASS); libbalsa_server_set_remember_password(lbserver, save_pwd); } else { /* localhost at port 25, without encryption and authentication */ libbalsa_server_set_host(lbserver, "localhost:25", NET_CLIENT_CRYPT_NONE); libbalsa_server_set_auth_mode(lbserver, NET_CLIENT_AUTH_NONE_ANON); } } /** @brief Guess the email servers for a given email address * * @param[in] mail_address email address * @return an NULL-terminated array containing the submission, imap and pop3 servers on success, @em must be freed by the caller * * Strategy for guessing the server names: * - some ISP's have "strange" server names (inter alia Microsoft for outlook.com, Yahoo for yahoo.*): return them from a * hard-wired lookup table; * - do a DNS lookup for SRV records (see https://www.rfc-editor.org/rfc/rfc6186.html, e.g. _imaps._tcp.); * - try to guess servers by name (e.g. imap.). */ static gchar ** guess_servers(const gchar *mail_address) { static const gchar * const srv_names[3][3] = { {"submissions", "submission", NULL}, {"imaps", "imap", NULL}, {"pop3s", "pop3", NULL} }; static const gchar * const dns_prefix[3][4] = { {"smtp", "mail", "submission", NULL}, {"imap", "imap4", "mail", NULL}, {"pop", "pop3", "mail", NULL} }; /* FIXME - this list of uncommon server names probably needs to be extended * format: mail domain (lower-case glob string); smtp; imap; pop3 servers */ static const gchar * const specials[][4] = { /* Microsoft: for outlook.com and apparently also for old hotmail.com and live.com addresses */ {"outlook.com", "outlook.office365.com", "outlook.office365.com", "outlook.office365.com"}, {"hotmail.com", "outlook.office365.com", "outlook.office365.com", "outlook.office365.com"}, {"live.com", "outlook.office365.com", "outlook.office365.com", "outlook.office365.com"}, /* Yahoo: same servers for yahoo.com, yahoo.de, yahoo.co.uk... */ {"yahoo.??*", "smtp.mail.yahoo.com", "imap.mail.yahoo.com", "pop.mail.yahoo.com"}, /* T-Online: magenta is their corporate colour... */ {"t-online.de", "securesmtp.t-online.de", "secureimap.t-online.de", "securepop.t-online.de"}, {"magenta.de", "securesmtp.t-online.de", "secureimap.t-online.de", "securepop.t-online.de"} }; GResolver *resolver; const gchar *at_sign; gchar *domain; gchar **result; size_t n; at_sign = strchr(mail_address, '@'); g_return_val_if_fail(at_sign != NULL, NULL); result = g_new0(gchar *, 4UL); /* a few (?) mail providers are known to be special... */ domain = g_ascii_strdown(&at_sign[1], -1); for (n = 0U; n < G_N_ELEMENTS(specials); n++) { if (g_pattern_match_simple(specials[n][0], domain)) { result[0] = g_strdup(specials[n][1]); result[1] = g_strdup(specials[n][2]); result[2] = g_strdup(specials[n][3]); g_free(domain); return result; } } /* try to resolve the proper servers */ resolver = g_resolver_get_default(); for (n = 0; n < 3; n++) { result[n] = server_from_srv(resolver, srv_names[n], domain); if (result[n] == NULL) { result[n] = server_by_name(resolver, dns_prefix[n], domain); } } g_object_unref(resolver); g_free(domain); return result; } /** @brief Try to look up a server by DNS SRV record * * @param[in] resolver resolver object * @param[in] service NULL-terminated array of services to look up * @param[in] domain email domain * @return the name of a suitable server on success, NULL if none could be found */ static gchar * server_from_srv(GResolver *resolver, const gchar * const *service, const gchar *domain) { int n; gchar *result = NULL; for (n = 0; (result == NULL) && (service[n] != NULL); n++) { GList *res; GError *error = NULL; res = g_resolver_lookup_service(resolver, service[n], "tcp", domain, NULL, &error); if (res != NULL) { GList *p; for (p = res; (result == NULL) && (p != NULL); p = p->next) { GSrvTarget *target = (GSrvTarget *) p->data; const gchar *host; guint16 port; host = g_srv_target_get_hostname(target); port = g_srv_target_get_port(target); if ((host != NULL) && (host[0] != '\0') && (port > 0U)) { result = g_strdup(host); g_debug("lookup for TCP service %s of domain %s: %s:%hu", service[n], domain, result, port); } } g_resolver_free_targets(res); } else if (error != NULL) { g_debug("lookup for TCP service %s of domain %s failed: %s", service[n], domain, error->message); } g_clear_error(&error); } return result; } /** @brief Try to look up a server by DNS name * * @param[in] resolver resolver object * @param[in] service NULL-terminated array of server names to look up * @param[in] domain email domain * @return the name of a suitable server on success, NULL if none could be found */ static gchar * server_by_name(GResolver *resolver, const gchar * const *prefix, const gchar *domain) { int n; gchar *fullname = NULL; for (n = 0; (fullname == NULL) && (prefix[n] != NULL); n++) { GList *res; GError *error = NULL; fullname = g_strconcat(prefix[n], ".", domain, NULL); res = g_resolver_lookup_by_name(resolver, fullname, NULL, &error); if (res == NULL) { g_debug("lookup of %s failed: %s", fullname, error->message); g_free(fullname); fullname = NULL; } else { g_debug("lookup of %s: success", fullname); g_resolver_free_addresses(res); } g_clear_error(&error); } return fullname; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_server.h000066400000000000000000000030461477646064400277650ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2022 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __BALSA_DRUID_PAGE_SERVER_H__ #define __BALSA_DRUID_PAGE_SERVER_H__ #include #include "assistant_helper.h" #include "assistant_init.h" G_BEGIN_DECLS /* * Main object structure */ #ifndef __TYPEDEF_BALSA_DRUID_PAGE_SERVER__ #define __TYPEDEF_BALSA_DRUID_PAGE_SERVER__ typedef struct _BalsaDruidPageServer BalsaDruidPageServer; #endif #define BALSA_DRUID_PAGE_SERVER(obj) ((BalsaDruidPageServer *) obj) struct _BalsaDruidPageServer { GtkWidget *page; GtkWidget *incoming_type; GtkWidget *incoming_srv; GtkWidget *login; GtkWidget *passwd; GtkWidget *smtp; GtkWidget *remember_passwd; gboolean need_set; }; /* * Public methods */ void balsa_druid_page_server(GtkAssistant * druid); G_END_DECLS #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_user.c000066400000000000000000000155251477646064400274350ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "assistant_page_user.h" #include #include #include #include #include "imap-server.h" #include "smtp-server.h" #include "server.h" #include "balsa-app.h" #include "save-restore.h" /* here are local prototypes */ static void balsa_druid_page_user_init(BalsaDruidPageUser * user, GtkWidget * page, GtkAssistant * druid); static void balsa_druid_page_user_prepare(GtkAssistant * druid, GtkWidget * page, BalsaDruidPageUser * user); static void balsa_druid_page_user_next(GtkAssistant * druid, GtkWidget * page, BalsaDruidPageUser * user); static void balsa_druid_page_user_init(BalsaDruidPageUser * user, GtkWidget * page, GtkAssistant * druid) { static const char *header2 = N_("The following settings are also needed " "(and you can find them later, if need be, in the Email " "application in the “Edit \342\217\265 Preferences \342\217\265 Identities…” " "menu item)"); GtkGrid *grid; GtkLabel *label; gchar *preset; int row = 0; user->econtroller.setbits = 0; user->econtroller.numentries = 0; user->econtroller.donemask = 0; user->ed0.controller = &(user->econtroller); user->ed1.controller = &(user->econtroller); user->ed2.controller = &(user->econtroller); label = GTK_LABEL(gtk_label_new(_(header2))); gtk_label_set_line_wrap(label, TRUE); gtk_widget_set_hexpand(GTK_WIDGET(label), TRUE); gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_START); gtk_widget_set_margin_bottom(GTK_WIDGET(label), 12); gtk_container_add(GTK_CONTAINER(page), GTK_WIDGET(label)); grid = GTK_GRID(gtk_grid_new()); gtk_grid_set_row_spacing(grid, 2); gtk_grid_set_column_spacing(grid, 5); gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_START); /* 2.1 */ balsa_init_add_grid_entry(grid, row++, _("Your real _name:"), g_get_real_name(), &(user->ed0), druid, page, &(user->name)); balsa_init_add_grid_entry (grid, row++, _("Your _email address for this email account:"), "", &(user->ed1), druid, page, &(user->email)); preset = g_build_filename(g_get_home_dir(), "mail", NULL); balsa_init_add_grid_entry(grid, row++, _("_Local mail directory:"), preset, &(user->ed2), druid, page, &(user->localmaildir)); g_free(preset); libbalsa_set_vmargins(GTK_WIDGET(grid), 3); gtk_container_add(GTK_CONTAINER(page), GTK_WIDGET(grid)); user->need_set = FALSE; } void balsa_druid_page_user(GtkAssistant * druid) { BalsaDruidPageUser *user; user = g_new0(BalsaDruidPageUser, 1); user->page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_assistant_append_page(druid, user->page); gtk_assistant_set_page_title(druid, user->page, _("User Settings")); balsa_druid_page_user_init(user, user->page, druid); g_signal_connect(druid, "prepare", G_CALLBACK(balsa_druid_page_user_prepare), user); g_object_weak_ref(G_OBJECT(druid), (GWeakNotify)g_free, user); } static void balsa_druid_page_user_prepare(GtkAssistant * druid, GtkWidget * page, BalsaDruidPageUser * user) { if(page != user->page) { if(user->need_set) { balsa_druid_page_user_next(druid, page, user); user->need_set = FALSE; } return; } /* Don't let them continue unless all entries have something. */ gtk_assistant_set_page_complete(druid, page, ENTRY_CONTROLLER_DONE(&user->econtroller)); gtk_widget_grab_focus(user->email); user->need_set = TRUE; } static void balsa_druid_page_user_next(GtkAssistant * druid, GtkWidget * page, BalsaDruidPageUser * user) { const gchar *mailbox; gchar *uhoh; LibBalsaIdentity *ident; InternetAddress *ia; /* identity */ mailbox = gtk_entry_get_text(GTK_ENTRY(user->name)); if (balsa_app.identities == NULL) { gchar *domain = strrchr(mailbox, '@'); ident = LIBBALSA_IDENTITY(libbalsa_identity_new_with_name (_("Default Identity"))); balsa_app.identities = g_list_append(NULL, ident); balsa_app.current_ident = ident; if(domain) libbalsa_identity_set_domain(ident, domain+1); } else { ident = balsa_app.current_ident; } ia = internet_address_mailbox_new (mailbox, gtk_entry_get_text(GTK_ENTRY(user->email))); libbalsa_identity_set_address (ident, ia); g_free(balsa_app.local_mail_directory); balsa_app.local_mail_directory = gtk_editable_get_chars(GTK_EDITABLE(user->localmaildir), 0, -1); if (balsa_init_create_to_directory (balsa_app.local_mail_directory, &uhoh)) { GtkWidget* err = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_ancestor (GTK_WIDGET(druid), GTK_TYPE_WINDOW)), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Local Mail Problem\n%s"), uhoh); g_free(uhoh); /* Do not go to the next page! * Go back to the previous page, so that we reappear on this one */ gtk_assistant_previous_page(druid); g_signal_connect(err, "response", G_CALLBACK(gtk_widget_destroy), NULL); gtk_widget_show_all(err); return; } balsa_app.current_ident = ident; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_user.h000066400000000000000000000031431477646064400274330ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __BALSA_DRUID_PAGE_USER_H__ #define __BALSA_DRUID_PAGE_USER_H__ #include #include "assistant_helper.h" #include "assistant_init.h" G_BEGIN_DECLS /* * Main object structure */ #ifndef __TYPEDEF_BALSA_DRUID_PAGE_USER__ #define __TYPEDEF_BALSA_DRUID_PAGE_USER__ typedef struct _BalsaDruidPageUser BalsaDruidPageUser; #endif #define BALSA_DRUID_PAGE_USER(obj) ((BalsaDruidPageUser *) obj) struct _BalsaDruidPageUser { GtkWidget *page; GtkWidget *name; GtkWidget *email; GtkWidget *localmaildir; EntryController econtroller; EntryData ed0; EntryData ed1; EntryData ed2; gboolean need_set; }; /* * Public methods */ void balsa_druid_page_user(GtkAssistant * druid); G_END_DECLS #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_welcome.c000066400000000000000000000035531477646064400301100ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #include "assistant_page_welcome.h" #include void balsa_druid_page_welcome(GtkAssistant * druid) { GtkWidget *page; static const gchar title[] = N_("Welcome to Balsa!"); static const gchar text[] = N_ ("Before you can send or receive email:\n\n" "• either you should already have Internet access and an " "email account, provided by an Internet Service Provider, " "and you should have made that Internet connection on your " "computer\n\n" "• or your network administrator at your place of " "work/study/similar may have set up your computer to " "connect to the network."); page = gtk_label_new(_(text)); gtk_label_set_line_wrap(GTK_LABEL(page), TRUE); gtk_widget_set_valign(page, GTK_ALIGN_START); gtk_assistant_append_page(druid, page); gtk_assistant_set_page_title(druid, page, _(title)); gtk_assistant_set_page_type(druid, page, GTK_ASSISTANT_PAGE_INTRO); gtk_assistant_set_page_complete(druid, page, TRUE); } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/assistant_page_welcome.h000066400000000000000000000021331477646064400301060ustar00rootroot00000000000000/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ /* Balsa E-Mail Client * Copyright (C) 1997-2016 Stuart Parmenter and others, * See the file AUTHORS for a list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 . */ #ifndef __BALSA_DRUID_PAGE_WELCOME_H__ #define __BALSA_DRUID_PAGE_WELCOME_H__ #include #include "assistant_helper.h" #include "assistant_init.h" G_BEGIN_DECLS /* * Public methods */ void balsa_druid_page_welcome(GtkAssistant * druid); G_END_DECLS #endif balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libinit_balsa/meson.build000066400000000000000000000017471477646064400253710ustar00rootroot00000000000000# libinit_balsa/meson.build libinit_balsa_sources = [ 'assistant_page_defclient.c', 'assistant_page_defclient.h', 'assistant_page_directory.c', 'assistant_page_directory.h', 'assistant_page_finish.c', 'assistant_page_finish.h', 'assistant_page_server.c', 'assistant_page_server.h', 'assistant_page_user.c', 'assistant_page_user.h', 'assistant_page_welcome.c', 'assistant_page_welcome.h', 'assistant_init.c', 'assistant_init.h', 'assistant_helper.c', 'assistant_helper.h' ] libinit_balsa_a = static_library('init_balsa', libinit_balsa_sources, dependencies : balsa_deps, include_directories : [top_include, libbalsa_include, libnetclient_include, src_include], install : false) balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/000077500000000000000000000000001477646064400230765ustar00rootroot00000000000000balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/Makefile.am000066400000000000000000000007551477646064400251410ustar00rootroot00000000000000# $Id$ noinst_LIBRARIES = libnetclient.a libnetclient_a_SOURCES = \ net-client.c \ net-client.h \ net-client-pop.c \ net-client-pop.h \ net-client-siobuf.c \ net-client-siobuf.h \ net-client-smtp.c \ net-client-smtp.h \ net-client-utils.c \ net-client-utils.h CLEANFILES = doxygen.log SUBDIRS = test AM_CFLAGS = $(LIBNETCLIENT_CFLAGS) AM_CPPFLAGS = -DG_LOG_DOMAIN=\"libnetclient\" EXTRA_DIST = \ meson.build clean-local: -rm -rf html doc: @DOXYGEN@ libnetclient.dox balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/README000066400000000000000000000077161477646064400237710ustar00rootroot00000000000000Written by Albrecht Dreß Copyright (C) Albrecht Dreß 2017 - 2020 This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 2 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this library. If not, see . Purpose ======= This library provides an implementation of CRLF-terminated line-based client protocols built on top of GIO. It provides a base module, containing the line-based IO methods, and on top of that POP3 (RFC1939) and SMTP (RFC5321) client classes. Coding Style ============ The implementation tries to follow the MISRA C:2012 (MISRA C3) and SEI CERT Secure Coding standards for safer code. For further details about these standards, see and . Requirements ============ Apart from GLib/GIO (at least version 2.40.0) it requires GnuTLS. For Kerberos V5 single sign-on (GSSAPI, RFC 4752) authentication, a Kerberos library (e.g. Heimdal) is required. API Documentation ================= Doxygen is required to create a HTML API documentation. Install doxygen from . Then run in this folder make doc and open html/index.html. Testing ======= In the folder test, a test application for running unit tests, a check for memory leaks and a coverage analysis is available. The following packages are required for running them: - the Sput Unit Testing Framework for C/C++, available from - python2 - screen, available from - sudo, available from - Valgrind, avilable from - LCOV and Genhtml, available from - gnutls-serv, which is a part of the GnuTLS package, available from - INetSim Internet Services Simulation Suite, available from Note that most of these requirements are typically available pre-packaged for your favorite distribution. Unfortunately, INetSim 1.3.2 has two bugs in POP3 handling and does not offer pipelining. The file test/inetsim-1.3.2.diff contains a patch which fixes these issues. Some gnutls-serv versions will replace received CRLF line endings by just LF, breaking several tests. A fixed version is available from the GnuTLS gitlab repository only (see https://gitlab.com/gnutls/gnutls/-/issues/1073 and https://gitlab.com/gnutls/gnutls/-/merge_requests/1314). For running the tests, open two terminal windows, and cd to the test folder of this package. In the first terminal, call ./start-test-env.sh which will launch several dummy servers and two INetSim instances required for testing. Note that INetSim requires root permissions and is thus called via sudo. Then, in the second terminal, call make tests to build the test application, and run it in Valgrind. The test produces the following output: - stdout/stderr: unit test results, which shall report zero failed - tests.vg: the output of the Valgrind memory check - gcov/index.html: results of the coverage analysis Finally, just terminate the test servers in the first window. Note that INetSim will dump further information in its output files in the test folder. You should verify that INetSim recorded the requested operations properly. Note that no unit tests are available for the GSSAPI authentication methods as they are not supported by INetSim. -oOo- balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/libnetclient.dox000066400000000000000000000135731477646064400262770ustar00rootroot00000000000000DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "libnetclient" PROJECT_NUMBER = "0.1.0" PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = . CREATE_SUBDIRS = NO ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" "The $name widget" "The $name file" is provides specifies contains represents a an the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 4 TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES AUTOLINK_SUPPORT = YES BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO GROUP_NESTED_COMPOUNDS = NO SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 EXTRACT_ALL = YES EXTRACT_PRIVATE = YES EXTRACT_PACKAGE = NO EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = NO HIDE_SCOPE_NAMES = NO HIDE_COMPOUND_REFERENCE = NO SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO STRICT_PROTO_MATCHING = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST = YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = CITE_BIB_FILES = QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_AS_ERROR = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = doxygen.log INPUT = ./ INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.h RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = YES USE_HTAGS = NO VERBATIM_HEADERS = YES CLANG_ASSISTED_PARSING = NO CLANG_OPTIONS = ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = NO HTML_DYNAMIC_SECTIONS = NO HTML_INDEX_NUM_ENTRIES = 100 GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO CHM_INDEX_ENCODING = BINARY_TOC = NO TOC_EXPAND = NO GENERATE_QHP = NO QCH_FILE = QHP_NAMESPACE = org.doxygen.Project QHP_VIRTUAL_FOLDER = doc QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = QHG_LOCATION = GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.doxygen.Project DISABLE_INDEX = NO GENERATE_TREEVIEW = YES ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES USE_MATHJAX = NO MATHJAX_FORMAT = HTML-CSS MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest MATHJAX_EXTENSIONS = MATHJAX_CODEFILE = SEARCHENGINE = YES SERVER_BASED_SEARCH = NO EXTERNAL_SEARCH = NO SEARCHENGINE_URL = SEARCHDATA_FILE = searchdata.xml EXTERNAL_SEARCH_ID = EXTRA_SEARCH_MAPPINGS = GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4 EXTRA_PACKAGES = LATEX_HEADER = LATEX_FOOTER = LATEX_EXTRA_STYLESHEET = LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain LATEX_TIMESTAMP = NO GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = RTF_SOURCE_CODE = NO GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_SUBDIR = MAN_LINKS = NO GENERATE_XML = NO XML_OUTPUT = xml XML_PROGRAMLISTING = YES GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook DOCBOOK_PROGRAMLISTING = NO GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = .. INCLUDE_FILE_PATTERNS = PREDEFINED = G_GNUC_MALLOC= G_GNUC_PRINTF(x,y)= EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = NO TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES PERL_PATH = /usr/bin/perl CLASS_DIAGRAMS = NO MSCGEN_PATH = DIA_PATH = HIDE_UNDOC_RELATIONS = NO HAVE_DOT = YES DOT_NUM_THREADS = 0 DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = YES UML_LIMIT_NUM_FIELDS = 10 TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = YES CALLER_GRAPH = YES GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png INTERACTIVE_SVG = NO DOT_PATH = DOTFILE_DIRS = MSCFILE_DIRS = DIAFILE_DIRS = PLANTUML_JAR_PATH = PLANTUML_INCLUDE_PATH = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/meson.build000066400000000000000000000015051477646064400252410ustar00rootroot00000000000000# libnetclient/test/meson.build libnetclient_a_sources = [ 'net-client.c', 'net-client.h', 'net-client-pop.c', 'net-client-pop.h', 'net-client-smtp.c', 'net-client-smtp.h', 'net-client-siobuf.c', 'net-client-siobuf.h', 'net-client-utils.c', 'net-client-utils.h' ] libnetclient_a = static_library('netclient', libnetclient_a_sources, c_args : '-DG_LOG_DOMAIN="libnetclient"', dependencies : libnetclient_deps, include_directories : top_include, install : false) if libnetclient_docs dox_path = join_paths(meson.source_root(), meson.current_source_dir(), 'libnetclient.dox') run_command(doxygen_program, dox_path, check : true) endif subdir('test') balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client-pop.c000066400000000000000000000766601477646064400261170ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2017 - 2020 * * 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 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, see * . */ #include #include #include #include "net-client-utils.h" #include "net-client-pop.h" /*lint -esym(754,_NetClientPop::parent) required field, not referenced directly */ struct _NetClientPop { NetClient parent; NetClientCryptMode crypt_mode; gchar *apop_banner; guint auth_enabled; gboolean can_pipelining; gboolean can_uidl; gboolean use_pipelining; }; /** @name POP authentication methods * * Note that the availability of these authentication methods depends upon the result of the CAPABILITY list. According to RFC * 1939, Section 4, at least either APOP or USER/PASS @em must be supported. * @{ */ /** RFC 1939 "USER" and "PASS" authentication method. */ #define NET_CLIENT_POP_AUTH_USER_PASS 0x001U /** RFC 1939 "APOP" authentication method. */ #define NET_CLIENT_POP_AUTH_APOP 0x002U /** RFC 5034 SASL "LOGIN" authentication method. */ #define NET_CLIENT_POP_AUTH_LOGIN 0x004U /** RFC 5034 SASL "PLAIN" authentication method. */ #define NET_CLIENT_POP_AUTH_PLAIN 0x008U /** RFC 5034 SASL "CRAM-MD5" authentication method. */ #define NET_CLIENT_POP_AUTH_CRAM_MD5 0x010U /** RFC 5034 SASL "CRAM-SHA1" authentication method. */ #define NET_CLIENT_POP_AUTH_CRAM_SHA1 0x020U /** RFC 4752 "GSSAPI" authentication method. */ #define NET_CLIENT_POP_AUTH_GSSAPI 0x040U /** RFC 4505 "ANONYMOUS" authentication method. */ #define NET_CLIENT_POP_AUTH_ANONYMOUS 0x200U /** Mask of all authentication methods requiring user name and password. */ #define NET_CLIENT_POP_AUTH_PASSWORD \ (NET_CLIENT_POP_AUTH_USER_PASS | NET_CLIENT_POP_AUTH_APOP | NET_CLIENT_POP_AUTH_LOGIN | NET_CLIENT_POP_AUTH_PLAIN | \ NET_CLIENT_POP_AUTH_CRAM_MD5 | NET_CLIENT_POP_AUTH_CRAM_SHA1) /** Mask of all authentication methods. */ #define NET_CLIENT_POP_AUTH_ALL \ (NET_CLIENT_POP_AUTH_PASSWORD + NET_CLIENT_POP_AUTH_GSSAPI + NET_CLIENT_POP_AUTH_ANONYMOUS) /** @} */ /* Note: the maximum line length of a message body downloaded from the POP3 server may be up to 998 chars, excluding the terminating * CRLF, see RFC 5322, Sect. 2.1.1. However, it also states that "Receiving implementations would do well to handle an arbitrarily * large number of characters in a line for robustness sake", so we actually accept lines from POP3 of unlimited length. */ #define MAX_POP_LINE_LEN 0U #define POP_DATA_BUF_SIZE 4096U /*lint -save -e9026 allow function-like macros, see MISRA C:2012, Directive 4.9 */ #define IS_ML_TERM(str) ((str[0] == '.') && (str[1] == '\0')) /*lint -emacro(9079,POP_MSG_INFO) -emacro(9087,POP_MSG_INFO) * allow conversion of GList data pointer, MISRA C:2012, Rules 11.3, 11.5 */ #define POP_MSG_INFO(list) ((NetClientPopMessageInfo *) ((list)->data)) /*lint -restore */ /*lint -esym(528,net_client_pop_get_instance_private) auto-generated function, not referenced */ G_DEFINE_TYPE(NetClientPop, net_client_pop, NET_CLIENT_TYPE) static void net_client_pop_finalise(GObject *object); static void net_client_pop_get_capa(NetClientPop *client, guint *auth_supported); static gboolean net_client_pop_read_reply(NetClientPop *client, gchar **reply, GError **error); static gboolean net_client_pop_uidl(NetClientPop *client, GList * const *msg_list, GError **error); static gboolean net_client_pop_starttls(NetClientPop *client, GError **error); static gboolean net_client_pop_execute(NetClientPop *client, const gchar *request_fmt, gchar **last_reply, GError **error, ...) G_GNUC_PRINTF(2, 5); static gboolean net_client_pop_execute_sasl(NetClientPop *client, const gchar *request_fmt, gchar **challenge, GError **error, ...); static gboolean net_client_pop_auth(NetClientPop *client, guint auth_supported, GError **error); static gboolean net_client_pop_auth_plain(NetClientPop *client, const gchar* user, const gchar* passwd, GError** error); static gboolean net_client_pop_auth_login(NetClientPop *client, const gchar *user, const gchar *passwd, GError **error); static gboolean net_client_pop_auth_anonymous(NetClientPop *client, GError **error); static gboolean net_client_pop_auth_user_pass(NetClientPop *client, const gchar* user, const gchar* passwd, GError** error); static gboolean net_client_pop_auth_apop(NetClientPop *client, const gchar* user, const gchar* passwd, GError** error); static gboolean net_client_pop_auth_cram(NetClientPop *client, GChecksumType chksum_type, const gchar *user, const gchar *passwd, GError **error); static gboolean net_client_pop_auth_gssapi(NetClientPop *client, const gchar *user, GError **error); static gboolean net_client_pop_retr_msg(NetClientPop *client, const NetClientPopMessageInfo *info, NetClientPopMsgCb callback, gpointer user_data, GError **error); NetClientPop * net_client_pop_new(const gchar *host, guint16 port, NetClientCryptMode crypt_mode, gboolean use_pipelining) { NetClientPop *client; g_return_val_if_fail((host != NULL) && (crypt_mode >= NET_CLIENT_CRYPT_ENCRYPTED) && (crypt_mode <= NET_CLIENT_CRYPT_NONE), NULL); client = NET_CLIENT_POP(g_object_new(NET_CLIENT_POP_TYPE, NULL)); if (!net_client_configure(NET_CLIENT(client), host, port, MAX_POP_LINE_LEN, NULL)) { g_assert_not_reached(); } client->crypt_mode = crypt_mode; client->use_pipelining = use_pipelining; return client; } gboolean net_client_pop_probe(const gchar *host, guint timeout_secs, NetClientProbeResult *result, GCallback cert_cb, GError **error) { guint16 probe_ports[] = {995U, 110U, 0U}; /* pop3s, pop3 */ gchar *host_only; gboolean retval = FALSE; gint check_id; /* paranoia check */ g_return_val_if_fail((host != NULL) && (result != NULL), FALSE); host_only = net_client_host_only(host); if (!net_client_host_reachable(host_only, error)) { g_free(host_only); return FALSE; } for (check_id = 0; !retval && (probe_ports[check_id] > 0U); check_id++) { NetClientPop *client; g_debug("%s: probing %s:%u…", __func__, host_only, probe_ports[check_id]); client = net_client_pop_new(host_only, probe_ports[check_id], NET_CLIENT_CRYPT_NONE, FALSE); net_client_set_timeout(NET_CLIENT(client), timeout_secs); if (net_client_connect(NET_CLIENT(client), NULL)) { gboolean this_success; guint auth_supported = 0U; gboolean can_starttls = FALSE; if (cert_cb != NULL) { g_signal_connect(client, "cert-check", cert_cb, client); } if (check_id == 0) { /* pop3s */ this_success = net_client_start_tls(NET_CLIENT(client), NULL); } else { this_success = TRUE; } /* get the greeting */ if (this_success) { this_success = net_client_pop_read_reply(client, NULL, error); } /* send CAPA and read the capabilities of the server */ if (this_success) { net_client_pop_get_capa(client, &auth_supported); } /* try to perform STARTTLS unless we are already encrypted, and send CAPA again */ if (this_success && (check_id != 0)) { can_starttls = net_client_pop_starttls(client, NULL); if (can_starttls) { net_client_pop_get_capa(client, &auth_supported); } } /* evaluate on success */ if (this_success) { result->port = probe_ports[check_id]; if (check_id == 0) { result->crypt_mode = NET_CLIENT_CRYPT_ENCRYPTED; } else if (can_starttls) { result->crypt_mode = NET_CLIENT_CRYPT_STARTTLS; } else { result->crypt_mode = NET_CLIENT_CRYPT_NONE; } /* RFC 1939, Section 4, require at least either APOP or USER/PASS */ result->auth_mode = NET_CLIENT_AUTH_USER_PASS; if ((auth_supported & NET_CLIENT_POP_AUTH_GSSAPI) != 0U) { result->auth_mode |= NET_CLIENT_AUTH_KERBEROS; } retval = TRUE; } } g_object_unref(client); } if (!retval) { g_set_error(error, NET_CLIENT_ERROR_QUARK, NET_CLIENT_PROBE_FAILED, _("the server %s does not offer the POP3 service at port 995 or 110"), host_only); } g_free(host_only); return retval; } gboolean net_client_pop_set_auth_mode(NetClientPop *client, NetClientAuthMode auth_mode, gboolean disable_apop) { g_return_val_if_fail(NET_IS_CLIENT_POP(client), FALSE); client->auth_enabled = 0U; if ((auth_mode & NET_CLIENT_AUTH_NONE_ANON) != 0U) { client->auth_enabled |= NET_CLIENT_POP_AUTH_ANONYMOUS; } if ((auth_mode & NET_CLIENT_AUTH_USER_PASS) != 0U) { client->auth_enabled |= NET_CLIENT_POP_AUTH_PASSWORD; if (disable_apop) { client->auth_enabled &= ~NET_CLIENT_POP_AUTH_APOP; } } #if defined(HAVE_GSSAPI) if ((auth_mode & NET_CLIENT_AUTH_KERBEROS) != 0U) { client->auth_enabled |= NET_CLIENT_POP_AUTH_GSSAPI; } #endif return (client->auth_enabled != 0U); } gboolean net_client_pop_connect(NetClientPop *client, gchar **greeting, GError **error) { gchar *server_msg = NULL; guint auth_supported = 0U; gboolean result; /* paranoia checks */ g_return_val_if_fail(NET_IS_CLIENT_POP(client), FALSE); /* establish connection, and immediately switch to TLS if required */ result = net_client_connect(NET_CLIENT(client), error); if (result && (client->crypt_mode == NET_CLIENT_CRYPT_ENCRYPTED)) { result = net_client_start_tls(NET_CLIENT(client), error); } /* get the greeting */ if (result) { result = net_client_pop_read_reply(client, &server_msg, error); } /* extract the APOP banner */ if (result) { const gchar *ang_open; /*lint -e{668,9034} server_msg cannot be NULL; accept char literal as int (MISRA C:2012 Rule 10.3) */ ang_open = strchr(server_msg, '<'); if (ang_open != NULL) { const gchar *ang_close; ang_close = strchr(ang_open, '>'); /*lint !e9034 accept char literal as int (MISRA C:2012 Rule 10.3) */ if (ang_close != NULL) { /*lint -e{737,946,947,9029} allowed exception according to MISRA Rules 18.2 and 18.3 */ client->apop_banner = g_strndup(ang_open, (ang_close - ang_open) + 1U); auth_supported = NET_CLIENT_POP_AUTH_APOP; } } if (greeting != NULL) { *greeting = g_strdup(server_msg); } g_free(server_msg); } /* perform STLS if required- note that some servers support STLS, but do not announce it. So just try... */ if (result && ((client->crypt_mode == NET_CLIENT_CRYPT_STARTTLS) || (client->crypt_mode == NET_CLIENT_CRYPT_STARTTLS_OPT))) { result = net_client_pop_starttls(client, error); if (!result) { if (client->crypt_mode == NET_CLIENT_CRYPT_STARTTLS_OPT) { result = TRUE; g_clear_error(error); } } } /* read the capabilities (which may be unsupported, so ignore any negative result) */ if (result) { net_client_pop_get_capa(client, &auth_supported); } /* authenticate if we were successful so far */ if (result) { result = net_client_pop_auth(client, auth_supported, error); } return result; } gboolean net_client_pop_stat(NetClientPop *client, gsize *msg_count, gsize *mbox_size, GError **error) { gboolean result; gchar *stat_buf; /* paranoia checks */ g_return_val_if_fail(NET_IS_CLIENT_POP(client), FALSE); /* run the STAT command */ result = net_client_pop_execute(client, "STAT", &stat_buf, error); if (result) { unsigned long count; unsigned long total_size; if (sscanf(stat_buf, "%lu %lu", &count, &total_size) == 2) { if (msg_count != NULL) { *msg_count = count; } if (mbox_size != NULL) { *mbox_size = total_size; } } else { result = FALSE; g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_PROTOCOL, _("bad server reply: %s"), stat_buf); } g_free(stat_buf); } return result; } gboolean net_client_pop_list(NetClientPop *client, GList **msg_list, gboolean with_uid, GError **error) { gboolean result; gboolean done; /* paranoia checks */ g_return_val_if_fail(NET_IS_CLIENT_POP(client) && (msg_list != NULL), FALSE); *msg_list = NULL; /* run the LIST command */ result = net_client_pop_execute(client, "LIST", NULL, error); done = FALSE; while (result && !done) { gchar *reply; result = net_client_read_line(NET_CLIENT(client), &reply, error); if (result) { if (IS_ML_TERM(reply)) { done = TRUE; } else { NetClientPopMessageInfo *info; info = g_new0(NetClientPopMessageInfo, 1U); *msg_list = g_list_prepend(*msg_list, info); if (sscanf(reply, "%u %" G_GSIZE_FORMAT, &info->id, &info->size) != 2) { result = FALSE; g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_PROTOCOL, _("bad server reply")); } } g_free(reply); } } /* on success, turn the list into the order reported by the remote server */ if (result) { *msg_list = g_list_reverse(*msg_list); } /* get all uid's if requested */ if (result && with_uid && client->can_uidl && (*msg_list != NULL)) { result = net_client_pop_uidl(client, msg_list, error); } if (!result) { /*lint -e{9074,9087} accept sane pointer conversion (MISRA C:2012 Rules 11.1, 11.3) */ g_list_free_full(*msg_list, (GDestroyNotify) net_client_pop_msg_info_free); } return result; } gboolean net_client_pop_retr(NetClientPop *client, GList *msg_list, NetClientPopMsgCb callback, gpointer user_data, GError **error) { gboolean result; gboolean pipelining; const GList *p; /* paranoia checks */ g_return_val_if_fail(NET_IS_CLIENT_POP(client) && (msg_list != NULL) && (callback != NULL), FALSE); /* pipelining: send all RETR commands */ pipelining = client->can_pipelining && client->use_pipelining; if (pipelining) { GString *retr_buf; retr_buf = g_string_sized_new(10U * g_list_length(msg_list)); for (p = msg_list; p != NULL; p = p->next) { g_string_append_printf(retr_buf, "RETR %u\r\n", POP_MSG_INFO(p)->id); } result = net_client_write_buffer(NET_CLIENT(client), retr_buf->str, retr_buf->len, error); (void) g_string_free(retr_buf, TRUE); } else { result = TRUE; } for (p = msg_list; result && (p != NULL); p = p->next) { const NetClientPopMessageInfo *info = POP_MSG_INFO(p); if (pipelining) { result = net_client_pop_read_reply(client, NULL, error); } else { result = net_client_pop_execute(client, "RETR %u", NULL, error, info->id); } if (result) { result = net_client_pop_retr_msg(client, info, callback, user_data, error); } } return result; } gboolean net_client_pop_dele(NetClientPop *client, GList *msg_list, GError **error) { gboolean result; gboolean pipelining; const GList *p; /* paranoia checks */ g_return_val_if_fail(NET_IS_CLIENT_POP(client) && (msg_list != NULL), FALSE); /* pipelining: send all DELE commands */ pipelining = client->can_pipelining && client->use_pipelining; if (pipelining) { GString *dele_buf; dele_buf = g_string_sized_new(10U * g_list_length(msg_list)); for (p = msg_list; p != NULL; p = p->next) { g_string_append_printf(dele_buf, "DELE %u\r\n", POP_MSG_INFO(p)->id); } result = net_client_write_buffer(NET_CLIENT(client), dele_buf->str, dele_buf->len, error); (void) g_string_free(dele_buf, TRUE); } else { result = TRUE; } for (p = msg_list; result && (p != NULL); p = p->next) { const NetClientPopMessageInfo *info = POP_MSG_INFO(p); if (pipelining) { result = net_client_pop_read_reply(client, NULL, error); } else { result = net_client_pop_execute(client, "DELE %u", NULL, error, info->id); } } return result; } void net_client_pop_msg_info_free(NetClientPopMessageInfo *info) { if (info != NULL) { g_free(info->uid); g_free(info); } } /* == local functions =========================================================================================================== */ static void net_client_pop_class_init(NetClientPopClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->finalize = net_client_pop_finalise; } static void net_client_pop_init(NetClientPop *self) { self->auth_enabled = NET_CLIENT_POP_AUTH_ALL; } static void net_client_pop_finalise(GObject *object) { NetClientPop *client = NET_CLIENT_POP(object); const GObjectClass *parent_class = G_OBJECT_CLASS(net_client_pop_parent_class); /* send the 'QUIT' command - no need to evaluate the reply or check for errors */ if (net_client_is_connected(NET_CLIENT(client))) { (void) net_client_execute(NET_CLIENT(client), NULL, "QUIT", NULL); } g_free(client->apop_banner); (*parent_class->finalize)(object); } /* Note: if supplied, reply is never NULL on success */ static gboolean net_client_pop_read_reply(NetClientPop *client, gchar **reply, GError **error) { gboolean result; gchar *reply_buf; result = net_client_read_line(NET_CLIENT(client), &reply_buf, error); if (result) { if (strncmp(reply_buf, "+OK", 3U) == 0) { if (reply != NULL) { if (strlen(reply_buf) > 3U) { *reply = g_strdup(&reply_buf[4]); } else { *reply = g_strdup(""); } } } else if (strncmp(reply_buf, "-ERR", 4U) == 0) { if (strlen(reply_buf) > 4U) { g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_SERVER_ERR, _("error: %s"), &reply_buf[5]); } else { g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_SERVER_ERR, _("error")); } result = FALSE; } else { /* unexpected server reply */ g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_PROTOCOL, _("bad server reply: %s"), reply_buf); result = FALSE; } g_free(reply_buf); } return result; } /* note: if supplied, last_reply is never NULL on success */ static gboolean net_client_pop_execute(NetClientPop *client, const gchar *request_fmt, gchar **last_reply, GError **error, ...) { va_list args; gboolean result; va_start(args, error); result = net_client_vwrite_line(NET_CLIENT(client), request_fmt, args, error); va_end(args); if (result) { result = net_client_pop_read_reply(client, last_reply, error); } return result; } static gboolean net_client_pop_starttls(NetClientPop *client, GError **error) { gboolean result; result = net_client_pop_execute(client, "STLS", NULL, error); if (result) { result = net_client_start_tls(NET_CLIENT(client), error); } return result; } static gboolean net_client_pop_auth(NetClientPop *client, guint auth_supported, GError **error) { gboolean result = FALSE; guint auth_mask; gchar **auth_data = NULL; /* calculate the possible authentication methods */ auth_mask = client->auth_enabled & auth_supported; /* try, in this order, enabled modes: anonymous; GSSAPI/Kerberos; user name and password */ if (auth_mask == 0U) { g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH, _("no suitable authentication mechanism")); } else if ((auth_mask & NET_CLIENT_POP_AUTH_ANONYMOUS) != 0U) { /* Anonymous authentication - nothing required */ result = net_client_pop_auth_anonymous(client, error); } else if ((auth_mask & NET_CLIENT_POP_AUTH_GSSAPI) != 0U) { /* GSSAPI aka Kerberos authentication - user name required */ g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_KERBEROS, &auth_data); if ((auth_data == NULL) || (auth_data[0] == NULL)) { g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH, _("user name required")); } else { result = net_client_pop_auth_gssapi(client, auth_data[0], error); } } else { /* user name and password authentication methods */ g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_USER_PASS, &auth_data); if ((auth_data == NULL) || (auth_data[0] == NULL) || (auth_data[1] == NULL)) { g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH, _("user name and password required")); } else { /* first check for safe (hashed) authentication methods, used plain-text ones if they are not supported */ if ((auth_mask & NET_CLIENT_POP_AUTH_CRAM_SHA1) != 0U) { result = net_client_pop_auth_cram(client, G_CHECKSUM_SHA1, auth_data[0], auth_data[1], error); } else if ((auth_mask & NET_CLIENT_POP_AUTH_CRAM_MD5) != 0U) { result = net_client_pop_auth_cram(client, G_CHECKSUM_MD5, auth_data[0], auth_data[1], error); } else if ((auth_mask & NET_CLIENT_POP_AUTH_APOP) != 0U) { result = net_client_pop_auth_apop(client, auth_data[0], auth_data[1], error); } else if ((auth_mask & NET_CLIENT_POP_AUTH_PLAIN) != 0U) { result = net_client_pop_auth_plain(client, auth_data[0], auth_data[1], error); } else if ((auth_mask & NET_CLIENT_POP_AUTH_LOGIN) != 0U) { result = net_client_pop_auth_login(client, auth_data[0], auth_data[1], error); } else if ((auth_mask & NET_CLIENT_POP_AUTH_USER_PASS) != 0U) { result = net_client_pop_auth_user_pass(client, auth_data[0], auth_data[1], error); } else { g_assert_not_reached(); } } } /* POP3 does not define a mechanism to indicate that the authentication failed due to a too weak mechanism or wrong * credentials, so we treat all server -ERR responses as authentication failures */ if (!result && (error != NULL) && (*error != NULL) && ((*error)->code == (gint) NET_CLIENT_ERROR_POP_SERVER_ERR)) { (*error)->code = (gint) NET_CLIENT_ERROR_POP_AUTHFAIL; } /* clean up any auth data */ if (auth_data != NULL) { if (auth_data[0] != NULL) { net_client_free_authstr(auth_data[0]); net_client_free_authstr(auth_data[1]); } free(auth_data); } return result; } static gboolean net_client_pop_auth_plain(NetClientPop *client, const gchar *user, const gchar *passwd, GError **error) { gboolean result ; gchar *base64_buf; base64_buf = net_client_auth_plain_calc(user, passwd); if (base64_buf != NULL) { result = net_client_pop_execute_sasl(client, "AUTH PLAIN", NULL, error); if (result) { result = net_client_pop_execute(client, "%s", NULL, error, base64_buf); } net_client_free_authstr(base64_buf); } else { result = FALSE; } return result; } static gboolean net_client_pop_auth_login(NetClientPop *client, const gchar *user, const gchar *passwd, GError **error) { gboolean result; result = net_client_pop_execute_sasl(client, "AUTH LOGIN", NULL, error); if (result) { gchar *base64_buf; base64_buf = g_base64_encode((const guchar *) user, strlen(user)); result = net_client_pop_execute_sasl(client, "%s", NULL, error, base64_buf); net_client_free_authstr(base64_buf); if (result) { base64_buf = g_base64_encode((const guchar *) passwd, strlen(passwd)); result = net_client_pop_execute(client, "%s", NULL, error, base64_buf); net_client_free_authstr(base64_buf); } } return result; } static gboolean net_client_pop_auth_anonymous(NetClientPop *client, GError **error) { gboolean result; result = net_client_pop_execute_sasl(client, "AUTH ANONYMOUS", NULL, error); if (result) { gchar *base64_buf; base64_buf = net_client_auth_anonymous_token(); result = net_client_pop_execute(client, "%s", NULL, error, base64_buf); net_client_free_authstr(base64_buf); } return result; } static gboolean net_client_pop_auth_user_pass(NetClientPop *client, const gchar *user, const gchar *passwd, GError **error) { gboolean result; result = net_client_pop_execute(client, "USER %s", NULL, error, user); if (result) { result = net_client_pop_execute(client, "PASS %s", NULL, error, passwd); } return result; } static gboolean net_client_pop_auth_apop(NetClientPop *client, const gchar *user, const gchar *passwd, GError **error) { gboolean result; gchar *auth_buf; gchar *md5_buf; auth_buf = g_strconcat(client->apop_banner, passwd, NULL); md5_buf = g_compute_checksum_for_string(G_CHECKSUM_MD5, auth_buf, -1); net_client_free_authstr(auth_buf); result = net_client_pop_execute(client, "APOP %s %s", NULL, error, user, md5_buf); net_client_free_authstr(md5_buf); return result; } static gboolean net_client_pop_auth_cram(NetClientPop *client, GChecksumType chksum_type, const gchar *user, const gchar *passwd, GError **error) { gboolean result; gchar *challenge = NULL; result = net_client_pop_execute_sasl(client, "AUTH CRAM-%s", &challenge, error, net_client_chksum_to_str(chksum_type)); if (result) { gchar *auth_buf; auth_buf = net_client_cram_calc(challenge, chksum_type, user, passwd); if (auth_buf != NULL) { result = net_client_pop_execute(client, "%s", NULL, error, auth_buf); net_client_free_authstr(auth_buf); } else { result = FALSE; } } g_free(challenge); return result; } #if defined(HAVE_GSSAPI) static gboolean net_client_pop_auth_gssapi(NetClientPop *client, const gchar *user, GError **error) { NetClientGssCtx *gss_ctx; gboolean result = FALSE; gss_ctx = net_client_gss_ctx_new("pop", net_client_get_host(NET_CLIENT(client)), user, error); if (gss_ctx != NULL) { gint state; gboolean initial = TRUE; gchar *input_token = NULL; gchar *output_token = NULL; do { state = net_client_gss_auth_step(gss_ctx, input_token, &output_token, error); g_free(input_token); input_token = NULL; if (state >= 0) { if (initial) { /* split the initial auth command as the initial-response argument will typically exceed the 255-octet limit on * the length of a single command, see RFC 5034, Sect. 4 */ initial = FALSE; result = net_client_pop_execute_sasl(client, "AUTH GSSAPI =", NULL, error); } if (result) { result = net_client_pop_execute_sasl(client, "%s", &input_token, error, output_token); } } g_free(output_token); } while (result && (state == 0)); if (state == 1) { output_token = net_client_gss_auth_finish(gss_ctx, input_token, error); if (output_token != NULL) { result = net_client_pop_execute(client, "%s", NULL, error, output_token); g_free(output_token); } } g_free(input_token); net_client_gss_ctx_free(gss_ctx); } return result; } #else /*lint -e{715,818} */ static gboolean net_client_pop_auth_gssapi(NetClientPop G_GNUC_UNUSED *client, const gchar G_GNUC_UNUSED *user, GError G_GNUC_UNUSED **error) { g_assert_not_reached(); /* this should never happen! */ return FALSE; /* never reached, make gcc happy */ } #endif /* HAVE_GSSAPI */ /* Note: if supplied, challenge is never NULL on success */ static gboolean net_client_pop_execute_sasl(NetClientPop *client, const gchar *request_fmt, gchar **challenge, GError **error, ...) { va_list args; gboolean result; va_start(args, error); result = net_client_vwrite_line(NET_CLIENT(client), request_fmt, args, error); va_end(args); if (result) { gchar *reply_buf; result = net_client_read_line(NET_CLIENT(client), &reply_buf, error); if (result) { if (strncmp(reply_buf, "+ ", 2U) == 0) { if (challenge != NULL) { *challenge = g_strdup(&reply_buf[2]); } } else { result = FALSE; g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_SERVER_ERR, _("error: %s"), reply_buf); } g_free(reply_buf); } } return result; } static void net_client_pop_get_capa(NetClientPop *client, guint *auth_supported) { gboolean result; gboolean done; /* clear all capability flags except APOP and send the CAPA command */ *auth_supported = *auth_supported & NET_CLIENT_POP_AUTH_APOP; client->can_pipelining = FALSE; result = net_client_pop_execute(client, "CAPA", NULL, NULL); /* evaluate the response */ done = FALSE; while (result && !done) { gchar *reply; result = net_client_read_line(NET_CLIENT(client), &reply, NULL); if (result) { if (IS_ML_TERM(reply)) { done = TRUE; } else if (strcmp(reply, "USER") == 0) { *auth_supported |= NET_CLIENT_POP_AUTH_USER_PASS; } else if (strncmp(reply, "SASL ", 5U) == 0) { gchar **auth; guint n; auth = g_strsplit(&reply[5], " ", -1); for (n = 0U; auth[n] != NULL; n++) { if (strcmp(auth[n], "PLAIN") == 0) { *auth_supported |= NET_CLIENT_POP_AUTH_PLAIN; } else if (strcmp(auth[n], "LOGIN") == 0) { *auth_supported |= NET_CLIENT_POP_AUTH_LOGIN; } else if (strcmp(auth[n], "CRAM-MD5") == 0) { *auth_supported |= NET_CLIENT_POP_AUTH_CRAM_MD5; } else if (strcmp(auth[n], "CRAM-SHA1") == 0) { *auth_supported |= NET_CLIENT_POP_AUTH_CRAM_SHA1; } else if (strcmp(auth[n], "ANONYMOUS") == 0) { *auth_supported |= NET_CLIENT_POP_AUTH_ANONYMOUS; #if defined(HAVE_GSSAPI) } else if (strcmp(auth[n], "GSSAPI") == 0) { *auth_supported |= NET_CLIENT_POP_AUTH_GSSAPI; #endif } else { /* other auth methods are ignored for the time being (see MISRA C:2012, Rule 15.7) */ } } g_strfreev(auth); } else if (strcmp(reply, "PIPELINING") == 0) { client->can_pipelining = TRUE; } else if (strcmp(reply, "UIDL") == 0) { client->can_uidl = TRUE; } else { /* ignore this capability (see MISRA C:2012, Rule 15.7) */ } g_free(reply); } } /* see RFC 1939, Sect. 4: if no other authentication method is supported explicitly (in particular no APOP), the server *must* * at least support USER/PASS... */ if (*auth_supported == 0U) { *auth_supported = NET_CLIENT_POP_AUTH_USER_PASS; } } static gboolean net_client_pop_uidl(NetClientPop *client, GList * const *msg_list, GError **error) { gboolean result; gboolean done; const GList *p; result = net_client_pop_execute(client, "UIDL", NULL, error); done = FALSE; p = *msg_list; while (result && !done) { gchar *reply; result = net_client_read_line(NET_CLIENT(client), &reply, error); if (result) { if (IS_ML_TERM(reply)) { done = TRUE; } else { guint msg_id; gchar *endptr; msg_id = strtoul(reply, &endptr, 10); if (endptr[0] != ' ') { result = FALSE; } else { /* we assume the passed list is already in the proper order, re-scan it if not */ if ((p == NULL) || (POP_MSG_INFO(p)->id != msg_id)) { for (p = *msg_list; (p != NULL) && (POP_MSG_INFO(p)->id != msg_id); p = p->next) { /* nothing to do (see MISRA C:2012, Rule 15.7) */ } } /* FIXME - error if we get a UID for a message which is not in the list? */ if (p != NULL) { NetClientPopMessageInfo* info = POP_MSG_INFO(p); g_free(info->uid); info->uid = g_strdup(&endptr[1]); p = p->next; } } } g_free(reply); } } return result; } static gboolean net_client_pop_retr_msg(NetClientPop *client, const NetClientPopMessageInfo *info, NetClientPopMsgCb callback, gpointer user_data, GError **error) { gboolean result; gboolean done; GString *msg_buf; gsize lines; result = TRUE; done = FALSE; msg_buf = g_string_sized_new(POP_DATA_BUF_SIZE); lines = 0U; while (!done && result) { gchar *linebuf; result = net_client_read_line(NET_CLIENT(client), &linebuf, error); if (result) { if (IS_ML_TERM(linebuf)) { done = TRUE; } else { if (linebuf[0] == '.') { msg_buf = g_string_append(msg_buf, &linebuf[1]); } else { msg_buf = g_string_append(msg_buf, linebuf); } msg_buf = g_string_append_c(msg_buf, '\n'); lines++; /* pass an almost full buffer to the callback */ if (msg_buf->len > (POP_DATA_BUF_SIZE - 100U)) { result = callback(msg_buf->str, (gssize) msg_buf->len, lines, info, user_data, error); msg_buf = g_string_truncate(msg_buf, 0U); lines = 0U; } } g_free(linebuf); } } if (result) { if (msg_buf->len > 0U) { result = callback(msg_buf->str, (gssize) msg_buf->len, lines, info, user_data, error); } if (result) { result = callback(NULL, 0, 0U, info, user_data, error); } } if (!result) { (void) callback(NULL, -1, 0U, info, user_data, NULL); } (void) g_string_free(msg_buf, TRUE); return result; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client-pop.h000066400000000000000000000267161477646064400261210ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2017 - 2020 * * 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 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, see * . */ #ifndef NET_CLIENT_POP_H_ #define NET_CLIENT_POP_H_ #include "net-client.h" #include "net-client-utils.h" G_BEGIN_DECLS #define NET_CLIENT_POP_TYPE (net_client_pop_get_type()) G_DECLARE_FINAL_TYPE(NetClientPop, net_client_pop, NET, CLIENT_POP, NetClient) #define NET_CLIENT_POP_ERROR_QUARK (g_quark_from_static_string("net-client-pop")) typedef struct _NetClientPopMessage NetClientPopMessage; typedef struct _NetClientPopMessageInfo NetClientPopMessageInfo; /** @brief POP-specific error codes */ enum _NetClientPopError { NET_CLIENT_ERROR_POP_PROTOCOL = 1, /**< A bad server reply has been received. */ NET_CLIENT_ERROR_POP_SERVER_ERR, /**< The server replied with an error. */ NET_CLIENT_ERROR_POP_NO_AUTH, /**< The server offers no suitable authentication mechanism. */ NET_CLIENT_ERROR_POP_NO_STARTTLS, /**< The server does not support STARTTLS. */ NET_CLIENT_ERROR_POP_AUTHFAIL /**< Authentication failure. */ }; /** @brief Message information * * This structure is returned in a GList by net_client_pop_list() and contains information about on message in the remote mailbox. */ struct _NetClientPopMessageInfo { guint id; /**< Message ID in the remote mailbox. */ gsize size; /**< Size of the message in bytes. */ gchar *uid; /**< Message UID, or NULL if it was not requested or the remote server does not support the UIDL * command. */ }; /** @brief POP3 Message Read Callback Function * * The user-provided callback function to receive a message from the remote POP3 server: * - @em buffer - the next NUL-terminated chunk of data, always guaranteed to consist of complete, LF terminated lines, or NULL * when the @em count is <= 0 (see below) * - @em count - indicates the number of bytes in the buffer (> 0), the end of the message (== 0), or that the download is * terminated due to an error condition (-1) * - @em lines - number of lines in the buffer, valid only if @em count > 0 * - @em info - information for the current message * - @em user_data - user data pointer * - @em error - shall be filled with error information if an error occurs in the callback; this location is actually the @em error * parameter passed to net_client_pop_retr() with the exception of a call when the @em count is -1 when this parameter is always * NULL * - return value: TRUE if the message download shall proceed, or FALSE to terminate it because an error occurred in the callback. * In the latter case, the callback function should set @em error appropriately. * * The message retrieved from the remote POP3 server is passed as "raw" data. The line endings are always LF (i.e. @em not CRLF), * and byte-stuffed termination '.' characters have been unstuffed. If the data passed to the callback function shall be fed into *
GMime, it is thus @em not necessary to run it through a GMimeFilterCRLF * filter. * * The download of every message is terminated by calling the callback with a @em count of 0. If the callback returns FALSE for a * count >= 0, it is called again for the same message with count == -1 before the download is terminated. The return value of the * callback called with count == -1 is ignored. */ typedef gboolean (*NetClientPopMsgCb)(const gchar *buffer, gssize count, gsize lines, const NetClientPopMessageInfo *info, gpointer user_data, GError **error); /** @brief Probe a POP3 server * * @param host host name or IP address of the server to probe * @param timeout_secs time-out in seconds * @param result filled with the probe results * @param cert_cb optional server certificate acceptance callback * @param error filled with error information if probing fails * @return TRUE if probing the passed server was successful, FALSE if not * * Probe the passed server by trying to connect to the standard ports (in this order) 995 and 110. */ gboolean net_client_pop_probe(const gchar *host, guint timeout_secs, NetClientProbeResult *result, GCallback cert_cb, GError **error); /** @brief Create a new POP network client * * @param host host name or IP address to connect * @param port port number to connect * @param crypt_mode encryption mode * @param use_pipelining whether POP3 PIPELINING shall be used if supported by the remote server * @return the POP network client object */ NetClientPop *net_client_pop_new(const gchar *host, guint16 port, NetClientCryptMode crypt_mode, gboolean use_pipelining); /** @brief Set allowed POP AUTH methods * * @param client POP network client object * @param auth_mode mask of allowed authentication methods * @param disable_apop TRUE to disable APOP authentication which is not supported by some broken servers * @return TRUE on success or FALSE on error or if no authentication method is allowed * * Set the allowed authentication methods for the passed connection. The default is to enable all authentication methods. * * @note Call this function @em before calling net_client_pop_connect().\n * POP3 does not allow anonymous access without authentication, i.e. the flag @ref NET_CLIENT_AUTH_ANONYMOUS in the argument * is ignored. */ gboolean net_client_pop_set_auth_mode(NetClientPop *client, NetClientAuthMode auth_mode, gboolean disable_apop); /** @brief Connect a POP network client * * @param client POP network client object * @param greeting filled with the greeting of the POP server on success, may be NULL to ignore * @param error filled with error information if the connection fails * @return TRUE on success or FALSE if the connection failed * * Connect the remote POP server, initialise the encryption if requested, and emit the @ref auth signal to request authentication * information. Simply ignore the signal for an unauthenticated connection. * * The function will try only @em one authentication method which is both supported by the server and enabled by calling * net_client_pop_set_auth_mode(). The precedence is: ANONYMOUS, GSSAPI (Kerberos), user name and password. For the latter, the * order is CRAM-SHA1, CRAM-MD5, APOP, PLAIN, LOGIN or USER/PASS. It is up to the caller to ensure encryption or a connection to * @c localhost if one of the plain text methods shall be used. * * In order to shut down a successfully established connection, just call g_object_unref() on the POP network client * object. * * @note The caller must free the returned greeting when it is not needed any more. */ gboolean net_client_pop_connect(NetClientPop *client, gchar **greeting, GError **error); /** @brief Get the status of a POP3 mailbox * * @param client POP network client object * @param msg_count filled with the number of messages available in the mailbox, may be NULL to ignore the value * @param mbox_size filled with the total mailbox size in bytes, may be NULL to ignore the value * @param error filled with error information if the connection fails * @return TRUE on success or FALSE if the command failed * * Run the POP3 STAT command to retrieve the mailbox status. */ gboolean net_client_pop_stat(NetClientPop *client, gsize *msg_count, gsize *mbox_size, GError **error); /** @brief List the messages in the POP3 mailbox * * @param client POP network client object * @param msg_list filled with a list of @ref NetClientPopMessageInfo items * @param with_uid TRUE to include the UID's of the messages in the returned list * @param error filled with error information if the connection fails * @return TRUE on success or FALSE if the command failed * * Run the LIST command and fill the passed list with the message identifier and message size for all messages available in the * mailbox. If the parameter @em with_uid is TRUE, also run the UIDL command and include the UID's reported by the remote server in * the returned list. * * The caller shall free the items in the returned list by calling net_client_pop_msg_info_free() on them. * * @note The UID's can be added only if the remote server reports in its @em CAPABILITY list that the @em UIDL command is supported. */ gboolean net_client_pop_list(NetClientPop *client, GList **msg_list, gboolean with_uid, GError **error); /** @brief Load messages from the POP3 mailbox * * @param client POP network client object * @param msg_list list of @ref NetClientPopMessageInfo items which shall be read from the server * @param callback callback function which shall be called to process the downloaded message data * @param user_data user data pointer passed to the callback function * @param error filled with error information if the connection fails * @return TRUE on success or FALSE if the command failed * * Load all messages in the passed list from the remote server, passing them through the specified callback function. The function * takes advantage of the RFC 2449 @em PIPELINING capability if supported by the remote server. */ gboolean net_client_pop_retr(NetClientPop *client, GList *msg_list, NetClientPopMsgCb callback, gpointer user_data, GError **error); /** @brief Delete messages from the POP3 mailbox * * @param client POP network client object * @param msg_list list of @ref NetClientPopMessageInfo items which shall be deleted from the server * @param error filled with error information if the connection fails * @return TRUE on success or FALSE if the command failed * * Delete all messages in the passed list from the remote server. The function takes advantage of the RFC 2449 @em PIPELINING * capability if supported by the remote server. */ gboolean net_client_pop_dele(NetClientPop *client, GList *msg_list, GError **error); /** @brief Free POP3 message item information * * @param info POP3 message item information as returned by net_client_pop_list() * * Free the data of a POP3 message item information. */ void net_client_pop_msg_info_free(NetClientPopMessageInfo *info); /** @file * * This module implements a POP3 client class conforming with RFC 1939. * * The following features are supported: * - the STAT, LIST, RETR and DELE commands as defined in RFC 1939; * - support for PIPELINING and UIDL as defined by RFC 2449; * - STLS encryption as defined by RFC 2595; * - authentication using APOP, USER/PASS (both RFC 1939) or the SASL methods ANONYMOUS, PLAIN, * LOGIN, CRAM-MD5, CRAM-SHA1 and GSSAPI (see RFC * 4752 depending upon the capabilities reported by the server. Note that GSSAPI is available only if * configured with the respective support. */ G_END_DECLS #endif /* NET_CLIENT_POP_H_ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client-siobuf.c000066400000000000000000000167361477646064400266060ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2018 - 2020 * * 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 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, see * . */ #include #include #include #include "net-client-utils.h" #include "net-client-siobuf.h" /*lint -esym(754,_NetClientSioBuf::parent) required field, not referenced directly */ struct _NetClientSioBuf { NetClient parent; GString *buffer; /**< hold a line read from the remote server, including the terminating CRLF */ gchar *read_ptr; /**< point to the next char which shall be read in buffer's GString::str. */ GString *writebuf; /**< buffer for buffered write functions */ }; /*lint -esym(528,net_client_siobuf_get_instance_private) auto-generated function, not referenced */ G_DEFINE_TYPE(NetClientSioBuf, net_client_siobuf, NET_CLIENT_TYPE) static void net_client_siobuf_finalise(GObject *object); static gboolean net_client_siobuf_fill(NetClientSioBuf *client, GError **error); NetClientSioBuf * net_client_siobuf_new(const gchar *host, guint16 port) { NetClientSioBuf *client; g_return_val_if_fail(host != NULL, NULL); client = NET_CLIENT_SIOBUF(g_object_new(NET_CLIENT_SIOBUF_TYPE, NULL)); if (!net_client_configure(NET_CLIENT(client), host, port, 0, NULL)) { g_assert_not_reached(); } client->buffer = g_string_sized_new(1024U); client->read_ptr = NULL; client->writebuf = g_string_sized_new(1024U); return client; } gint net_client_siobuf_read(NetClientSioBuf *client, void *buffer, gsize count, GError **error) { gboolean fill_res; gchar *dest; gsize left; g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client) && (buffer != NULL) && (count > 0U), -1); dest = (gchar *) buffer; /*lint !e9079 sane pointer conversion (MISRA C:2012 Rule 11.5) */ left = count; fill_res = net_client_siobuf_fill(client, error); while (fill_res && (left > 0U)) { gsize avail; gsize chunk; /*lint -e{737,946,947,9029} allowed exception according to MISRA C:2012 Rules 18.2, 18.3 */ avail = client->buffer->len - (client->read_ptr - client->buffer->str); if (avail > left) { chunk = left; } else { chunk = avail; } memcpy(dest, client->read_ptr, chunk); dest += chunk; client->read_ptr += chunk; left -= chunk; if (left > 0U) { fill_res = net_client_siobuf_fill(client, error); } } return (left < count) ? ((gint) count - (gint) left) : -1; } gint net_client_siobuf_getc(NetClientSioBuf *client, GError **error) { gint retval; g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), -1); if (net_client_siobuf_fill(client, error)) { retval = (gint) *client->read_ptr++; } else { retval = -1; } return retval; } gint net_client_siobuf_ungetc(NetClientSioBuf *client) { gint retval; g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), -1); /*lint -e{946} allowed exception according to MISRA C:2012 Rules 18.2 and 18.3 */ if ((client->buffer->len != 0U) && (client->read_ptr > client->buffer->str)) { client->read_ptr--; retval = 0; } else { retval = -1; } return retval; } gchar * net_client_siobuf_gets(NetClientSioBuf *client, gchar *buffer, gsize buflen, GError **error) { gchar *result; g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client) && (buffer != NULL) && (buflen > 0U), NULL); if (net_client_siobuf_fill(client, error)) { gsize avail; gsize chunk; /*lint -e{737,946,947,9029} allowed exception according to MISRA C:2012 Rules 18.2 and 18.3 */ avail = client->buffer->len - (client->read_ptr - client->buffer->str); if (avail > (buflen - 1U)) { chunk = buflen - 1U; } else { chunk = avail; } memcpy(buffer, client->read_ptr, chunk); client->read_ptr += chunk; buffer[chunk] = '\0'; result = buffer; } else { result = NULL; } return result; } gchar * net_client_siobuf_get_line(NetClientSioBuf *client, GError **error) { gchar *result; g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), NULL); if (net_client_siobuf_fill(client, error)) { gsize avail; /*lint -e{737,946,947,9029} allowed exception according to MISRA C:2012 Rules 18.2 and 18.3 */ avail = client->buffer->len - (client->read_ptr - client->buffer->str); if (avail > 2U) { result = g_strndup(client->read_ptr, avail - 2U); } else { result = g_strdup(""); } client->buffer->len = 0U; } else { result = NULL; } return result; } gint net_client_siobuf_discard_line(NetClientSioBuf *client, GError **error) { gint result; g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), -1); if (net_client_siobuf_fill(client, error)) { client->buffer->len = 0U; result = (gint) '\n'; } else { result = -1; } return result; } void net_client_siobuf_write(NetClientSioBuf *client, const void *buffer, gsize count) { g_return_if_fail(NET_IS_CLIENT_SIOBUF(client) && (buffer != NULL) && (count > 0U)); /*lint -e{9079} sane pointer conversion (MISRA C:2012 Rule 11.5) */ (void) g_string_append_len(client->writebuf, (const gchar *) buffer, (gssize) count); } void net_client_siobuf_printf(NetClientSioBuf *client, const gchar *format, ...) { va_list args; g_return_if_fail(NET_IS_CLIENT_SIOBUF(client) && (format != NULL)); va_start(args, format); g_string_append_vprintf(client->writebuf, format, args); va_end(args); } gboolean net_client_siobuf_flush(NetClientSioBuf *client, GError **error) { gboolean result; g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), FALSE); if (client->writebuf->len > 0U) { (void) g_string_append(client->writebuf, "\r\n"); result = net_client_write_buffer(NET_CLIENT(client), client->writebuf->str, client->writebuf->len, error); (void) g_string_truncate(client->writebuf, 0U); } else { result = FALSE; } return result; } /* == local functions =========================================================================================================== */ static void net_client_siobuf_class_init(NetClientSioBufClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->finalize = net_client_siobuf_finalise; } /*lint -e{715,818} */ static void net_client_siobuf_init(G_GNUC_UNUSED NetClientSioBuf *self) { } static gboolean net_client_siobuf_fill(NetClientSioBuf *client, GError **error) { gboolean result; if ((client->buffer->len == 0U) || (client->read_ptr == NULL) || (*client->read_ptr == '\0')) { gchar *read_buf; result = net_client_read_line(NET_CLIENT(client), &read_buf, error); if (result) { (void) g_string_assign(client->buffer, read_buf); (void) g_string_append(client->buffer, "\r\n"); client->read_ptr = client->buffer->str; g_free(read_buf); } } else { result = TRUE; } return result; } static void net_client_siobuf_finalise(GObject *object) { const NetClientSioBuf *client = NET_CLIENT_SIOBUF(object); const GObjectClass *parent_class = G_OBJECT_CLASS(net_client_siobuf_parent_class); (void) g_string_free(client->buffer, TRUE); (void) g_string_free(client->writebuf, TRUE); (*parent_class->finalize)(object); } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client-siobuf.h000066400000000000000000000145441477646064400266060ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2018 - 2020 * * 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 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, see * . */ #ifndef NET_CLIENT_SIOBUF_H_ #define NET_CLIENT_SIOBUF_H_ #include "net-client.h" G_BEGIN_DECLS #define NET_CLIENT_SIOBUF_TYPE (net_client_siobuf_get_type()) G_DECLARE_FINAL_TYPE(NetClientSioBuf, net_client_siobuf, NET, CLIENT_SIOBUF, NetClient) #define NET_CLIENT_SIOBUF_ERROR_QUARK (g_quark_from_static_string("net-client-siobuf")) /** @brief Create a new SIOBUF network client * * @param host host name or IP address to connect * @param port port number to connect * @return the SIOBUF network client object */ NetClientSioBuf *net_client_siobuf_new(const gchar *host, guint16 port); /** @brief Read a number of bytes from a SIOBUF network client object * * @param client SIOBUF network client object * @param buffer destination buffer * @param count number of bytes which shall be read * @param error filled with error information on error * @return the number of bytes actually read, or -1 if nothing could be read * * Read a number of bytes, including the CRLF line terminations if applicable, from the remote server. Note that the error location * may be filled on a short read (i. e. when the number of bytes read is smaller than the requested count). */ gint net_client_siobuf_read(NetClientSioBuf *client, void *buffer, gsize count, GError **error); /** @brief Read a character from a SIOBUF network client object * * @param client SIOBUF network client object * @param error filled with error information on error * @return the next character, or -1 if reading more data from the remote server failed * * Read the next character from the remote server. This includes the terminating CR and LF characters of each line. */ gint net_client_siobuf_getc(NetClientSioBuf *client, GError **error); /** @brief Read a character from a SIOBUF network client object * * @param client SIOBUF network client object * @return 0 on success, or ä1 on error * * Put back the last character read from the remote server. The function fails if no data is available or if the start of the * internal buffer has been reached. */ gint net_client_siobuf_ungetc(NetClientSioBuf *client); /** @brief Read a buffer from a SIOBUF network client object * * @param client SIOBUF network client object * @param buffer destination buffer * @param buflen number of characters which shall be read * @param error filled with error information on error * @return the passed buffer on success, or NULL on error * * Fill the passed buffer with data from the remote server until either the end of the line is reached, or the buffer is full. The * CRLF termination sequence is included in the buffer. The buffer is always NUL-terminated. */ gchar *net_client_siobuf_gets(NetClientSioBuf *client, gchar *buffer, gsize buflen, GError **error); /** @brief Read a line from a SIOBUF network client object * * @param client SIOBUF network client object * @param error filled with error information on error * @return a line of data, excluding the terminating CRLF on success, or NULL on error * * Return a newly allocated buffer, containing data from the remote server, but excluding the terminating CRLF sequence. If the * read buffer contains only 1 or 2 characters (i. e. the terminating CRLF or only LF), the function returns an empty string. The * internal read buffer is empty after calling this function. * * @note The caller must free the returned buffer when it is not needed any more. */ gchar *net_client_siobuf_get_line(NetClientSioBuf *client, GError **error) G_GNUC_WARN_UNUSED_RESULT; /** @brief Empty the SIOBUF network client object read buffer * * @param client SIOBUF network client object * @param error filled with error information on error * @return '\n' on success, or -1 on error * * Discard all pending data in the read buffer. If the read buffer is empty, the function reads the next line and discards it. */ gint net_client_siobuf_discard_line(NetClientSioBuf *client, GError **error); /** @brief Write data to the SIOBUF output buffer * * @param client SIOBUF network client object * @param buffer data buffer which shall be written * @param count number of bytes which shall be written * * Append the the passed data to the client's internal write buffer. Call net_client_siobuf_flush() to actually send the data to * the remote server. */ void net_client_siobuf_write(NetClientSioBuf *client, const void *buffer, gsize count); /** @brief Print to the SIOBUF output buffer * * @param client SIOBUF network client object * @param format printf-like format string * @param ... additional arguments according to the format string * * Format a string according to the passed arguments, and append the the passed data to the client's internal write buffer. Call * net_client_siobuf_flush() to actually send the data to the remote server. */ void net_client_siobuf_printf(NetClientSioBuf *client, const gchar *format, ...) G_GNUC_PRINTF(2, 3); /** @brief Send buffered SIOBUF output data * * @param client SIOBUF network client object * @param error filled with error information on error * @return TRUE is the send operation was successful, FALSE on error * * Transmit the client's internal write buffer, followed by a CRLF sequence, to the remote server and clear it. */ gboolean net_client_siobuf_flush(NetClientSioBuf *client, GError **error); /** @file * * This module implements a glue layer client class for Balsa's imap implementation. In addition to the base class, it implements * an internal input line buffer which provides reading single characters and lines, reading an exact amount of bytes, and buffered * write operations. */ #endif /* NET_CLIENT_SIOBUF_H_ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client-smtp.c000066400000000000000000000674471477646064400263070ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2017 - 2020 * * 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 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, see * . */ #include #include #include "net-client-utils.h" #include "net-client-smtp.h" /*lint -esym(754,_NetClientSmtp::parent) required field, not referenced directly */ struct _NetClientSmtp { NetClient parent; NetClientCryptMode crypt_mode; guint auth_enabled; /* Note: 0 = anonymous connection w/o authentication */ gboolean can_dsn; gboolean data_state; }; struct _NetClientSmtpMessage { gchar *sender; GList *recipients; gchar *dsn_envid; gboolean dsn_ret_full; gboolean have_dsn_rcpt; NetClientSmtpSendCb data_callback; gpointer user_data; }; typedef struct { gchar *rfc5321_addr; NetClientSmtpDsnMode dsn_mode; } smtp_rcpt_t; /** @name SMTP authentication methods * @{ */ /** Anonymous access (no authentication) */ #define NET_CLIENT_SMTP_AUTH_NONE 0x01U /** RFC 4616 "PLAIN" authentication method. */ #define NET_CLIENT_SMTP_AUTH_PLAIN 0x02U /** "LOGIN" authentication method. */ #define NET_CLIENT_SMTP_AUTH_LOGIN 0x04U /** RFC 2195 "CRAM-MD5" authentication method. */ #define NET_CLIENT_SMTP_AUTH_CRAM_MD5 0x08U /** RFC xxxx "CRAM-SHA1" authentication method. */ #define NET_CLIENT_SMTP_AUTH_CRAM_SHA1 0x10U /** RFC 4752 "GSSAPI" authentication method. */ #define NET_CLIENT_SMTP_AUTH_GSSAPI 0x20U /** Mask of all authentication methods requiring user name and password. */ #define NET_CLIENT_SMTP_AUTH_PASSWORD \ (NET_CLIENT_SMTP_AUTH_PLAIN | NET_CLIENT_SMTP_AUTH_LOGIN | NET_CLIENT_SMTP_AUTH_CRAM_MD5 | NET_CLIENT_SMTP_AUTH_CRAM_SHA1) /** Mask of all authentication methods. */ #define NET_CLIENT_SMTP_AUTH_ALL \ (NET_CLIENT_SMTP_AUTH_NONE | NET_CLIENT_SMTP_AUTH_PASSWORD | NET_CLIENT_SMTP_AUTH_GSSAPI) /** @} */ /* Note: RFC 5321 defines a maximum line length of 512 octets, including the terminating CRLF. However, RFC 4954, Sect. 4. defines * 12288 octets as safe maximum length for SASL authentication. */ #define MAX_SMTP_LINE_LEN 12288U #define SMTP_DATA_BUF_SIZE 8192U /*lint -esym(528,net_client_smtp_get_instance_private) auto-generated function, not referenced */ G_DEFINE_TYPE(NetClientSmtp, net_client_smtp, NET_CLIENT_TYPE) static void net_client_smtp_finalise(GObject *object); static gboolean net_client_smtp_ehlo(NetClientSmtp *client, guint *auth_supported, gboolean *can_starttls, GError **error); static gboolean net_client_smtp_starttls(NetClientSmtp *client, GError **error); static gboolean net_client_smtp_execute(NetClientSmtp *client, const gchar *request_fmt, gint expect_code, gchar **last_reply, GError **error, ...) G_GNUC_PRINTF(2, 6); static gboolean net_client_smtp_auth(NetClientSmtp *client, guint auth_supported, GError **error); static gboolean net_client_smtp_auth_plain(NetClientSmtp *client, const gchar *user, const gchar *passwd, GError **error); static gboolean net_client_smtp_auth_login(NetClientSmtp *client, const gchar *user, const gchar *passwd, GError **error); static gboolean net_client_smtp_auth_cram(NetClientSmtp *client, GChecksumType chksum_type, const gchar *user, const gchar *passwd, GError **error); static gboolean net_client_smtp_auth_gssapi(NetClientSmtp *client, const gchar *user, GError **error); static gboolean net_client_smtp_read_reply(NetClientSmtp *client, gint expect_code, gchar **last_reply, GError **error); static gboolean net_client_smtp_eval_rescode(gint res_code, gint expect_code, const gchar *reply, GError **error); static gchar *net_client_smtp_dsn_to_string(const NetClientSmtp *client, NetClientSmtpDsnMode dsn_mode); static void smtp_rcpt_free(smtp_rcpt_t *rcpt); NetClientSmtp * net_client_smtp_new(const gchar *host, guint16 port, NetClientCryptMode crypt_mode) { NetClientSmtp *client; g_return_val_if_fail((host != NULL) && (crypt_mode >= NET_CLIENT_CRYPT_ENCRYPTED) && (crypt_mode <= NET_CLIENT_CRYPT_NONE), NULL); client = NET_CLIENT_SMTP(g_object_new(NET_CLIENT_SMTP_TYPE, NULL)); if (!net_client_configure(NET_CLIENT(client), host, port, MAX_SMTP_LINE_LEN, NULL)) { g_assert_not_reached(); } client->crypt_mode = crypt_mode; return client; } gboolean net_client_smtp_set_auth_mode(NetClientSmtp *client, NetClientAuthMode auth_mode) { g_return_val_if_fail(NET_IS_CLIENT_SMTP(client), FALSE); client->auth_enabled = 0U; if ((auth_mode & NET_CLIENT_AUTH_NONE_ANON) != 0U) { client->auth_enabled |= NET_CLIENT_SMTP_AUTH_NONE; } if ((auth_mode & NET_CLIENT_AUTH_USER_PASS) != 0U) { client->auth_enabled |= NET_CLIENT_SMTP_AUTH_PASSWORD; } #if defined(HAVE_GSSAPI) if ((auth_mode & NET_CLIENT_AUTH_KERBEROS) != 0U) { client->auth_enabled |= NET_CLIENT_SMTP_AUTH_GSSAPI; } #endif return (client->auth_enabled != 0U); } gboolean net_client_smtp_probe(const gchar *host, guint timeout_secs, NetClientProbeResult *result, GCallback cert_cb, GError **error) { guint16 probe_ports[] = {465U, 587U, 25U, 0U}; /* submissions, submission, smtp */ gchar *host_only; gboolean retval = FALSE; gint check_id; /* paranoia check */ g_return_val_if_fail((host != NULL) && (result != NULL), FALSE); host_only = net_client_host_only(host); if (!net_client_host_reachable(host_only, error)) { g_free(host_only); return FALSE; } for (check_id = 0; !retval && (probe_ports[check_id] > 0U); check_id++) { NetClientSmtp *client; g_debug("%s: probing %s:%u…", __func__, host_only, probe_ports[check_id]); client = net_client_smtp_new(host_only, probe_ports[check_id], NET_CLIENT_CRYPT_NONE); net_client_set_timeout(NET_CLIENT(client), timeout_secs); if (net_client_connect(NET_CLIENT(client), NULL)) { gboolean this_success; guint auth_supported; gboolean can_starttls; if (cert_cb != NULL) { g_signal_connect(client, "cert-check", cert_cb, client); } if (check_id == 0) { /* submissions */ this_success = net_client_start_tls(NET_CLIENT(client), NULL); } else { this_success = TRUE; } /* get the greeting */ if (this_success) { this_success = net_client_smtp_read_reply(client, 220, NULL, NULL); } /* send EHLO and read the capabilities of the server */ if (this_success) { this_success = net_client_smtp_ehlo(client, &auth_supported, &can_starttls, NULL); } /* try to perform STARTTLS if supported, and send EHLO again */ if (this_success && can_starttls) { can_starttls = net_client_smtp_starttls(client, NULL); if (can_starttls) { gboolean dummy; can_starttls = net_client_smtp_ehlo(client, &auth_supported, &dummy, NULL); } } /* evaluate on success */ if (this_success) { result->port = probe_ports[check_id]; if (check_id == 0) { result->crypt_mode = NET_CLIENT_CRYPT_ENCRYPTED; } else if (can_starttls) { result->crypt_mode = NET_CLIENT_CRYPT_STARTTLS; } else { result->crypt_mode = NET_CLIENT_CRYPT_NONE; } result->auth_mode = 0U; if ((auth_supported & NET_CLIENT_SMTP_AUTH_PASSWORD) != 0U) { result->auth_mode |= NET_CLIENT_AUTH_USER_PASS; } if ((auth_supported & NET_CLIENT_SMTP_AUTH_GSSAPI) != 0U) { result->auth_mode |= NET_CLIENT_AUTH_KERBEROS; } retval = TRUE; } } g_object_unref(client); } if (!retval) { g_set_error(error, NET_CLIENT_ERROR_QUARK, NET_CLIENT_PROBE_FAILED, _("the server %s does not offer the SMTP service at port 465, 587 or 25"), host_only); } g_free(host_only); return retval; } gboolean net_client_smtp_connect(NetClientSmtp *client, gchar **greeting, GError **error) { gboolean result; gboolean can_starttls = FALSE; guint auth_supported = 0U; /* paranoia checks */ g_return_val_if_fail(NET_IS_CLIENT_SMTP(client), FALSE); /* establish connection, and immediately switch to TLS if required */ result = net_client_connect(NET_CLIENT(client), error); if (result && (client->crypt_mode == NET_CLIENT_CRYPT_ENCRYPTED)) { result = net_client_start_tls(NET_CLIENT(client), error); } /* get the greeting, RFC 5321 requires status 220 */ if (result) { (void) net_client_set_timeout(NET_CLIENT(client), 5U * 60U); /* RFC 5321, Sect. 4.5.3.2.1.: 5 minutes timeout */ result = net_client_smtp_read_reply(client, 220, greeting, error); } /* send EHLO and read the capabilities of the server */ if (result) { result = net_client_smtp_ehlo(client, &auth_supported, &can_starttls, error); } /* perform STARTTLS if required, and send EHLO again */ if (result && ((client->crypt_mode == NET_CLIENT_CRYPT_STARTTLS) || (client->crypt_mode == NET_CLIENT_CRYPT_STARTTLS_OPT))) { if (!can_starttls) { if (client->crypt_mode == NET_CLIENT_CRYPT_STARTTLS) { g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_STARTTLS, _("remote server does not support STARTTLS")); result = FALSE; } } else { result = net_client_smtp_starttls(client, error); if (result) { result = net_client_smtp_ehlo(client, &auth_supported, &can_starttls, error); } } } /* authenticate if we were successful so far, unless anonymous access is configured */ if (result && ((client->auth_enabled & NET_CLIENT_SMTP_AUTH_NONE) == 0U)) { result = net_client_smtp_auth(client, auth_supported, error); } return result; } gboolean net_client_smtp_can_dsn(NetClientSmtp *client) { return NET_IS_CLIENT_SMTP(client) ? client->can_dsn : FALSE; } gboolean net_client_smtp_send_msg(NetClientSmtp *client, const NetClientSmtpMessage *message, gchar **server_stat, GError **error) { NetClient *netclient; gboolean result; const GList *rcpt; /* paranoia checks */ g_return_val_if_fail(NET_IS_CLIENT_SMTP(client) && (message != NULL) && (message->sender != NULL) && (message->recipients != NULL) && (message->data_callback != NULL), FALSE); /* set the RFC 5321 sender and recipient(s); Sect. 3.3 requires status 250 */ netclient = NET_CLIENT(client); /* convenience pointer */ (void) net_client_set_timeout(netclient, 5U * 60U); /* RFC 5321, Sect. 4.5.3.2.2., 4.5.3.2.3.: 5 minutes timeout */ if (client->can_dsn && message->have_dsn_rcpt) { if (message->dsn_envid != NULL) { result = net_client_smtp_execute(client, "MAIL FROM:<%s> RET=%s ENVID=%s", 250, NULL, error, message->sender, (message->dsn_ret_full) ? "FULL" : "HDRS", message->dsn_envid); } else { result = net_client_smtp_execute(client, "MAIL FROM:<%s> RET=%s", 250, NULL, error, message->sender, (message->dsn_ret_full) ? "FULL" : "HDRS"); } } else { result = net_client_smtp_execute(client, "MAIL FROM:<%s>", 250, NULL, error, message->sender); } rcpt = message->recipients; while (result && (rcpt != NULL)) { const smtp_rcpt_t *this_rcpt = (const smtp_rcpt_t *) rcpt->data; /*lint !e9079 !e9087 (MISRA C:2012 Rules 11.3, 11.5) */ gchar *dsn_opts; /* create the RFC 3461 DSN string */ dsn_opts = net_client_smtp_dsn_to_string(client, this_rcpt->dsn_mode); result = net_client_smtp_execute(client, "RCPT TO:<%s>%s", 250, NULL, error, this_rcpt->rfc5321_addr, dsn_opts); g_free(dsn_opts); rcpt = rcpt->next; } /* initialise sending the message data; Sect. 3.3 requires status 354 */ if (result) { (void) net_client_set_timeout(netclient, 2U * 60U); /* RFC 5321, Sect. 4.5.3.2.4.: 2 minutes timeout */ result = net_client_smtp_execute(client, "DATA", 354, NULL, error); } /* call the data callback until all data has been transmitted or an error occurs */ if (result) { gchar buffer[SMTP_DATA_BUF_SIZE]; gssize count; gchar last_char = '\0'; (void) net_client_set_timeout(netclient, 3U * 60U); /* RFC 5321, Sect. 4.5.3.2.5.: 3 minutes timeout */ client->data_state = TRUE; do { count = message->data_callback(buffer, SMTP_DATA_BUF_SIZE, message->user_data, error); if (count < 0) { result = FALSE; } else if (count > 0) { result = net_client_write_buffer(netclient, buffer, (gsize) count, error); last_char = buffer[count - 1]; } else { /* write termination */ if (last_char == '\n') { result = net_client_write_buffer(netclient, ".\r\n", 3U, error); } else { result = net_client_write_buffer(netclient, "\r\n.\r\n", 5U, error); } } } while (result && (count > 0)); } if (result) { (void) net_client_set_timeout(netclient, 10U * 60U); /* RFC 5321, Sect 4.5.3.2.6.: 10 minutes timeout */ result = net_client_smtp_read_reply(client, -1, server_stat, error); client->data_state = FALSE; } return result; } NetClientSmtpMessage * net_client_smtp_msg_new(NetClientSmtpSendCb data_callback, gpointer user_data) { NetClientSmtpMessage *smtp_msg; g_return_val_if_fail(data_callback != NULL, NULL); smtp_msg = g_new0(NetClientSmtpMessage, 1U); smtp_msg->data_callback = data_callback; smtp_msg->user_data = user_data; return smtp_msg; } gboolean net_client_smtp_msg_set_dsn_opts(NetClientSmtpMessage *smtp_msg, const gchar *envid, gboolean ret_full) { g_return_val_if_fail(smtp_msg != NULL, FALSE); g_free(smtp_msg->dsn_envid); if (envid != NULL) { smtp_msg->dsn_envid = g_strdup(envid); } else { smtp_msg->dsn_envid = NULL; } smtp_msg->dsn_ret_full = ret_full; return TRUE; } gboolean net_client_smtp_msg_set_sender(NetClientSmtpMessage *smtp_msg, const gchar *rfc5321_sender) { g_return_val_if_fail((smtp_msg != NULL) && (rfc5321_sender != NULL), FALSE); g_free(smtp_msg->sender); smtp_msg->sender = g_strdup(rfc5321_sender); return TRUE; } gboolean net_client_smtp_msg_add_recipient(NetClientSmtpMessage *smtp_msg, const gchar *rfc5321_rcpt, NetClientSmtpDsnMode dsn_mode) { smtp_rcpt_t *new_rcpt; g_return_val_if_fail((smtp_msg != NULL) && (rfc5321_rcpt != NULL), FALSE); new_rcpt = g_new0(smtp_rcpt_t, 1U); new_rcpt->rfc5321_addr = g_strdup(rfc5321_rcpt); new_rcpt->dsn_mode = dsn_mode; smtp_msg->recipients = g_list_append(smtp_msg->recipients, new_rcpt); if (dsn_mode != NET_CLIENT_SMTP_DSN_NEVER) { smtp_msg->have_dsn_rcpt = TRUE; } return TRUE; } void net_client_smtp_msg_free(NetClientSmtpMessage *smtp_msg) { if (smtp_msg != NULL) { g_free(smtp_msg->sender); g_free(smtp_msg->dsn_envid); /*lint -e{9074} -e{9087} accept safe (and required) pointer conversion (MISRA C:2012 Rules 11.1, 11.3) */ g_list_free_full(smtp_msg->recipients, (GDestroyNotify) smtp_rcpt_free); g_free(smtp_msg); } } /* == local functions =========================================================================================================== */ static void net_client_smtp_class_init(NetClientSmtpClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->finalize = net_client_smtp_finalise; } static void net_client_smtp_init(NetClientSmtp *self) { self->auth_enabled = NET_CLIENT_SMTP_AUTH_ALL; } static void net_client_smtp_finalise(GObject *object) { NetClientSmtp *client = NET_CLIENT_SMTP(object); const GObjectClass *parent_class = G_OBJECT_CLASS(net_client_smtp_parent_class); /* send the 'QUIT' command unless we are in 'DATA' state where the server will probably fail to reply - no need to evaluate the * reply or check for errors */ if (net_client_is_connected(NET_CLIENT(client)) && !client->data_state) { (void) net_client_execute(NET_CLIENT(client), NULL, "QUIT", NULL); } (*parent_class->finalize)(object); } static gboolean net_client_smtp_starttls(NetClientSmtp *client, GError **error) { gboolean result; /* RFC 3207, Sect. 4 requires status 220 */ result = net_client_smtp_execute(client, "STARTTLS", 220, NULL, error); if (result) { result = net_client_start_tls(NET_CLIENT(client), error); } return result; } static gboolean net_client_smtp_auth(NetClientSmtp *client, guint auth_supported, GError **error) { gboolean result = FALSE; guint auth_mask; gchar **auth_data = NULL; /* calculate the possible authentication methods */ auth_mask = client->auth_enabled & auth_supported; /* try, in this order, enabled modes: GSSAPI/Kerberos; user name and password */ if (auth_mask == 0U) { g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_AUTH, _("no suitable authentication mechanism")); } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_GSSAPI) != 0U) { /* GSSAPI aka Kerberos authentication - user name required */ g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_KERBEROS, &auth_data); if ((auth_data == NULL) || (auth_data[0] == NULL)) { g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_AUTH, _("user name required")); } else { result = net_client_smtp_auth_gssapi(client, auth_data[0], error); } } else { /* user name and password authentication methods */ g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_USER_PASS, &auth_data); if ((auth_data == NULL) || (auth_data[0] == NULL) || (auth_data[1] == NULL)) { g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_AUTH, _("user name and password required")); } else { /* first check for safe (hashed) authentication methods, used plain-text ones if they are not supported */ if ((auth_mask & NET_CLIENT_SMTP_AUTH_CRAM_SHA1) != 0U) { result = net_client_smtp_auth_cram(client, G_CHECKSUM_SHA1, auth_data[0], auth_data[1], error); } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_CRAM_MD5) != 0U) { result = net_client_smtp_auth_cram(client, G_CHECKSUM_MD5, auth_data[0], auth_data[1], error); } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_PLAIN) != 0U) { result = net_client_smtp_auth_plain(client, auth_data[0], auth_data[1], error); } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_LOGIN) != 0U) { result = net_client_smtp_auth_login(client, auth_data[0], auth_data[1], error); } else { g_assert_not_reached(); } } } /* clean up any auth data */ if (auth_data != NULL) { if (auth_data[0] != NULL) { net_client_free_authstr(auth_data[0]); net_client_free_authstr(auth_data[1]); } free(auth_data); } return result; } static gboolean net_client_smtp_auth_plain(NetClientSmtp *client, const gchar *user, const gchar *passwd, GError **error) { gboolean result; gchar *base64_buf; base64_buf = net_client_auth_plain_calc(user, passwd); if (base64_buf != NULL) { /* RFC 4954, Sect. 6 requires status 235 */ result = net_client_smtp_execute(client, "AUTH PLAIN %s", 235, NULL, error, base64_buf); net_client_free_authstr(base64_buf); } else { result = FALSE; } return result; } static gboolean net_client_smtp_auth_login(NetClientSmtp *client, const gchar *user, const gchar *passwd, GError **error) { gboolean result; gchar *base64_buf; /* RFC 4954, Sect. 4 requires status 334 for the challenge; Sect. 6 requires status 235 */ base64_buf = g_base64_encode((const guchar *) user, strlen(user)); result = net_client_smtp_execute(client, "AUTH LOGIN %s", 334, NULL, error, base64_buf); net_client_free_authstr(base64_buf); if (result) { base64_buf = g_base64_encode((const guchar *) passwd, strlen(passwd)); result = net_client_smtp_execute(client, "%s", 235, NULL, error, base64_buf); net_client_free_authstr(base64_buf); } return result; } static gboolean net_client_smtp_auth_cram(NetClientSmtp *client, GChecksumType chksum_type, const gchar *user, const gchar *passwd, GError **error) { gboolean result; gchar *challenge = NULL; /* RFC 4954, Sect. 4 requires status 334 for the challenge; Sect. 6 requires status 235 */ result = net_client_smtp_execute(client, "AUTH CRAM-%s", 334, &challenge, error, net_client_chksum_to_str(chksum_type)); if (result) { gchar *auth_buf; auth_buf = net_client_cram_calc(challenge, chksum_type, user, passwd); if (auth_buf != NULL) { result = net_client_smtp_execute(client, "%s", 235, NULL, error, auth_buf); net_client_free_authstr(auth_buf); } else { result = FALSE; } } g_free(challenge); return result; } #if defined(HAVE_GSSAPI) static gboolean net_client_smtp_auth_gssapi(NetClientSmtp *client, const gchar *user, GError **error) { NetClientGssCtx *gss_ctx; gboolean result = FALSE; /* RFC 4954, Sect. 4 requires status 334 for the challenges; Sect. 6 requires status 235 */ gss_ctx = net_client_gss_ctx_new("smtp", net_client_get_host(NET_CLIENT(client)), user, error); if (gss_ctx != NULL) { gint state; gboolean initial = TRUE; gchar *input_token = NULL; gchar *output_token = NULL; do { state = net_client_gss_auth_step(gss_ctx, input_token, &output_token, error); g_free(input_token); input_token = NULL; if (state >= 0) { if (initial) { result = net_client_smtp_execute(client, "AUTH GSSAPI %s", 334, &input_token, error, output_token); initial = FALSE; } else { result = net_client_smtp_execute(client, "%s", 334, &input_token, error, output_token); } } g_free(output_token); } while (result && (state == 0)); if (state == 1) { output_token = net_client_gss_auth_finish(gss_ctx, input_token, error); if (output_token != NULL) { result = net_client_smtp_execute(client, "%s", 235, NULL, error, output_token); g_free(output_token); } } g_free(input_token); net_client_gss_ctx_free(gss_ctx); } return result; } #else /*lint -e{715,818} */ static gboolean net_client_smtp_auth_gssapi(NetClientSmtp G_GNUC_UNUSED *client, const gchar G_GNUC_UNUSED *user, GError G_GNUC_UNUSED **error) { g_assert_not_reached(); /* this should never happen! */ return FALSE; /* never reached, make gcc happy */ } #endif /* HAVE_GSSAPI */ /* note: if supplied, last_reply is never NULL on success */ static gboolean net_client_smtp_execute(NetClientSmtp *client, const gchar *request_fmt, gint expect_code, gchar **last_reply, GError **error, ...) { va_list args; gboolean result; va_start(args, error); result = net_client_vwrite_line(NET_CLIENT(client), request_fmt, args, error); va_end(args); if (result) { result = net_client_smtp_read_reply(client, expect_code, last_reply, error); } return result; } static gboolean net_client_smtp_ehlo(NetClientSmtp *client, guint *auth_supported, gboolean *can_starttls, GError **error) { gboolean result; gboolean done; result = net_client_write_line(NET_CLIENT(client), "EHLO %s", error, g_get_host_name()); /* clear all capability flags */ *auth_supported = 0U; client->can_dsn = FALSE; *can_starttls = FALSE; /* evaluate the response */ done = FALSE; while (result && !done) { gchar *reply; result = net_client_read_line(NET_CLIENT(client), &reply, error); if (result) { gint reply_code; gchar *endptr; reply_code = strtol(reply, &endptr, 10); if (reply_code != 250) { g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_PROTOCOL, _("bad server reply: %s"), reply); result = FALSE; } else { if (strcmp(&endptr[1], "DSN") == 0) { client->can_dsn = TRUE; } else if (strcmp(&endptr[1], "STARTTLS") == 0) { *can_starttls = TRUE; } else if ((strncmp(&endptr[1], "AUTH ", 5U) == 0) || (strncmp(&endptr[1], "AUTH=", 5U) == 0)) { gchar **auth; guint n; auth = g_strsplit(&endptr[6], " ", -1); for (n = 0U; auth[n] != NULL; n++) { if (strcmp(auth[n], "PLAIN") == 0) { *auth_supported |= NET_CLIENT_SMTP_AUTH_PLAIN; } else if (strcmp(auth[n], "LOGIN") == 0) { *auth_supported |= NET_CLIENT_SMTP_AUTH_LOGIN; } else if (strcmp(auth[n], "CRAM-MD5") == 0) { *auth_supported |= NET_CLIENT_SMTP_AUTH_CRAM_MD5; } else if (strcmp(auth[n], "CRAM-SHA1") == 0) { *auth_supported |= NET_CLIENT_SMTP_AUTH_CRAM_SHA1; #if defined(HAVE_GSSAPI) } else if (strcmp(auth[n], "GSSAPI") == 0) { *auth_supported |= NET_CLIENT_SMTP_AUTH_GSSAPI; #endif } else { /* other auth methods are ignored for the time being */ } } g_strfreev(auth); } else { /* ignored (see MISRA C:2012, Rule 15.7) */ } if (*endptr == ' ') { done = TRUE; } } g_free(reply); } } return result; } /* Note: according to RFC 5321, sect. 4.2, \em any reply may be multiline. If supplied, last_reply is never NULL on success */ static gboolean net_client_smtp_read_reply(NetClientSmtp *client, gint expect_code, gchar **last_reply, GError **error) { gboolean done; gboolean result; done = FALSE; do { gchar *reply; GError *this_error = NULL; result = net_client_read_line(NET_CLIENT(client), &reply, &this_error); if (result) { gint this_rescode; this_rescode = strtol(reply, NULL, 10); result = net_client_smtp_eval_rescode(this_rescode, expect_code, reply, &this_error); if (!result) { if ((error != NULL) && (*error != NULL)) { g_prefix_error(&this_error, "%s ", (*error)->message); g_clear_error(error); } g_propagate_error(error, this_error); } if (expect_code == -1) { expect_code = this_rescode; } if ((strlen(reply) > 3UL) && (reply[3] == ' ')) { done = TRUE; if (last_reply != NULL) { *last_reply = g_strdup(&reply[4]); } } g_free(reply); } else { g_clear_error(error); g_propagate_error(error, this_error); done = TRUE; } } while (!done); return result; } static gboolean net_client_smtp_eval_rescode(gint res_code, gint expect_code, const gchar *reply, GError **error) { gboolean result; switch (res_code / 100) { case 2: case 3: if ((expect_code == -1) || (res_code == expect_code)) { result = TRUE; } else { g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_TRANSIENT, _("unexpected reply: %s"), reply); result = FALSE; } break; case 4: g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_TRANSIENT, /* Translators: #1 SMTP (RFC 5321) error code; #2 error message */ _("transient error %d: %s"), res_code, reply); result = FALSE; break; case 5: if ((res_code == 534) || (res_code == 535)) { g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_AUTHFAIL, /* Translators: #1 SMTP (RFC 5321) error code; #2 error message */ _("authentication failure %d: %s"), res_code, reply); } else { g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_PERMANENT, /* Translators: #1 SMTP (RFC 5321) error code; #2 error message */ _("permanent error %d: %s"), res_code, reply); } result = FALSE; break; default: g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_PROTOCOL, _("bad server reply: %s"), reply); result = FALSE; break; } return result; } static gchar * net_client_smtp_dsn_to_string(const NetClientSmtp *client, NetClientSmtpDsnMode dsn_mode) { gchar *result; /* create the RFC 3461 DSN string */ if (client->can_dsn && (dsn_mode != NET_CLIENT_SMTP_DSN_NEVER)) { GString *dsn_buf; gsize start_len; dsn_buf = g_string_new(" NOTIFY="); start_len = dsn_buf->len; /*lint -save -e655 -e9027 -e9029 accept logical AND for enum, MISRA C:2012 Rules 10.1, 10.4 */ if ((dsn_mode & NET_CLIENT_SMTP_DSN_DELAY) == NET_CLIENT_SMTP_DSN_DELAY) { dsn_buf = g_string_append(dsn_buf, "DELAY"); } if ((dsn_mode & NET_CLIENT_SMTP_DSN_FAILURE) == NET_CLIENT_SMTP_DSN_FAILURE) { if (start_len != dsn_buf->len) { dsn_buf = g_string_append_c(dsn_buf, ','); } dsn_buf = g_string_append(dsn_buf, "FAILURE"); } if ((dsn_mode & NET_CLIENT_SMTP_DSN_SUCCESS) == NET_CLIENT_SMTP_DSN_SUCCESS) { if (start_len != dsn_buf->len) { dsn_buf = g_string_append_c(dsn_buf, ','); } dsn_buf = g_string_append(dsn_buf, "SUCCESS"); } /*lint -restore */ result = g_string_free(dsn_buf, FALSE); } else { result = g_strdup(""); } return result; } static void smtp_rcpt_free(smtp_rcpt_t *rcpt) { g_free(rcpt->rfc5321_addr); g_free(rcpt); } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client-smtp.h000066400000000000000000000255611477646064400263030ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2017 - 2020 * * 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 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, see * . */ #ifndef NET_CLIENT_SMTP_H_ #define NET_CLIENT_SMTP_H_ #include "net-client.h" #include "net-client-utils.h" G_BEGIN_DECLS #define NET_CLIENT_SMTP_TYPE (net_client_smtp_get_type()) G_DECLARE_FINAL_TYPE(NetClientSmtp, net_client_smtp, NET, CLIENT_SMTP, NetClient) #define NET_CLIENT_SMTP_ERROR_QUARK (g_quark_from_static_string("net-client-smtp")) typedef struct _NetClientSmtpMessage NetClientSmtpMessage; typedef enum _NetClientSmtpDsnMode NetClientSmtpDsnMode; /** @brief SMTP-specific error codes */ enum _NetClientSmtpError { NET_CLIENT_ERROR_SMTP_PROTOCOL = 1, /**< A bad server reply has been received. */ NET_CLIENT_ERROR_SMTP_TRANSIENT, /**< The server replied with a transient error code (code 4yz). */ NET_CLIENT_ERROR_SMTP_PERMANENT, /**< The server replied with a permanent error code (code 5yz, except 534 or 535). */ NET_CLIENT_ERROR_SMTP_NO_AUTH, /**< The server offers no suitable authentication mechanism. */ NET_CLIENT_ERROR_SMTP_NO_STARTTLS, /**< The server does not support STARTTLS. */ NET_CLIENT_ERROR_SMTP_AUTHFAIL /**< Authentication failure (see RFC 4954, section 6): mechanism is too weak (534) or * credentials invalid (535). */ }; /** @brief Delivery Status Notification mode * * See RFC 3461 for a description of Delivery Status Notifications (DSNs). The * DSN mode is the logical OR of these options. */ enum _NetClientSmtpDsnMode { NET_CLIENT_SMTP_DSN_NEVER = 0, /**< Never request a DSN (do not combine with other options). */ NET_CLIENT_SMTP_DSN_SUCCESS = 1, /**< Request a DSN on successful delivery. */ NET_CLIENT_SMTP_DSN_FAILURE = 2, /**< Request a DSN on delivery failure. */ NET_CLIENT_SMTP_DSN_DELAY = 4 /**< Request a DSN if delivery of a message has been delayed. */ }; /** @brief SMTP Message Transmission Callback Function * * The user-provided callback function to send a message to the remote SMTP server: * - @em buffer - shall be filled with the next chunk of data * - @em count - maximum number of bytes which may be written to @em buffer * - @em user_data - user data pointer (_NetClientSmtpMessage::user_data) * - @em error - shall be filled with error information if an error occurs in the callback * - return value: a value > 0 indicating the number of bytes written to @em buffer, or 0 to indicate that all data has been * transferred, or a value < 0 to indicate an error in the callback function. * * @note The callback function is responsible for properly formatting the message body according to * RFC 5321, RFC 5322 and * further relevant standards, e.g. by using GMime. */ typedef gssize (*NetClientSmtpSendCb)(gchar *buffer, gsize count, gpointer user_data, GError **error); /** @brief Probe a SMTP server * * @param host host name or IP address of the server to probe * @param timeout_secs time-out in seconds * @param result filled with the probe results * @param cert_cb optional server certificate acceptance callback * @param error filled with error information if probing fails * @return TRUE if probing the passed server was successful, FALSE if not * * Probe the passed server by trying to connect to the standard ports (in this order) 465, 587 and 25. * * \sa https://www.rfc-editor.org/rfc/rfc8314.html#section-3.3 */ gboolean net_client_smtp_probe(const gchar *host, guint timeout_secs, NetClientProbeResult *result, GCallback cert_cb, GError **error); /** @brief Create a new SMTP network client * * @param host host name or IP address to connect * @param port port number to connect * @param crypt_mode encryption mode * @return the SMTP network client object */ NetClientSmtp *net_client_smtp_new(const gchar *host, guint16 port, NetClientCryptMode crypt_mode); /** @brief Set allowed SMTP AUTH methods * * @param client SMTP network client object * @param auth_mode mask of allowed authentication methods * @return TRUE on success or FALSE on error * * Set the allowed authentication methods for the passed connection. The default is to enable all authentication methods. * * @note Call this function @em before calling net_client_smtp_connect(). */ gboolean net_client_smtp_set_auth_mode(NetClientSmtp *client, NetClientAuthMode auth_mode); /** @brief Connect a SMTP network client * * @param client SMTP network client object * @param greeting filled with the greeting of the SMTP server on success, may be NULL to ignore * @param error filled with error information if the connection fails * @return TRUE on success or FALSE if the connection failed * * Connect the remote SMTP server, initialise the encryption if requested, and emit the @ref auth signal to request authentication * information unless anonymous access has been configured by calling net_client_smtp_set_auth_mode(). * * The function will try only @em one authentication method which is both supported by the server and enabled by calling * net_client_smtp_set_auth_mode(). The precedence is: no authentication, GSSAPI (Kerberos), user name and password. For the * latter, the order is CRAM-SHA1, CRAM-MD5, PLAIN, or LOGIN. It is up to the caller to ensure encryption or a connection to * @c localhost if one of the plain text methods shall be used. * * In order to shut down a successfully established connection, just call g_object_unref() on the SMTP network client * object. * * @note The caller must free the returned greeting when it is not needed any more. */ gboolean net_client_smtp_connect(NetClientSmtp *client, gchar **greeting, GError **error); /** @brief Check if the SMTP network client supports Delivery Status Notifications * * @param client connected SMTP network client object * @return TRUE is DSN's are supported, FALSE if not * * Return if the connected SMTP server announced support for Delivery Status Notifications (DSNs) according to * RFC 3461. */ gboolean net_client_smtp_can_dsn(NetClientSmtp *client); /** @brief Send a message to a SMTP network client * * @param client connected SMTP network client object * @param message message data * @param server_stat filled with the final server response on success, may be NULL * @param error filled with error information if the connection fails * @return TRUE on success or FALSE if sending the message failed * * Send the passed SMTP message to the connected SMTP server. */ gboolean net_client_smtp_send_msg(NetClientSmtp *client, const NetClientSmtpMessage *message, gchar **server_stat, GError **error); /** @brief Create a SMTP message * * @param data_callback callback function called to send the message data * @param user_data additional user data passed to the callback function * @return a newly create SMTP message * * Create a message suitable for transmission by calling net_client_smtp_send_msg(). At least one sender and at least one recipient * must be added by calling net_client_smtp_msg_set_sender() and net_client_smtp_msg_add_recipient(), respectively. When the SMTP * message is not needed any more, call net_client_smtp_msg_free() to free it. */ NetClientSmtpMessage *net_client_smtp_msg_new(NetClientSmtpSendCb data_callback, gpointer user_data) G_GNUC_MALLOC; /** @brief Set the sender of a SMTP message * * @param smtp_msg SMTP message returned by net_client_smtp_msg_new() * @param rfc5321_sender RFC 5321-compliant sender address * @return TRUE on success or FALSE on error * * Set the sender address ("MAIL FROM" reverse-path, see RFC 5321) of the SMTP * message. */ gboolean net_client_smtp_msg_set_sender(NetClientSmtpMessage *smtp_msg, const gchar *rfc5321_sender); /** @brief Set options for Delivery Status Notifications * * @param smtp_msg SMTP message returned by net_client_smtp_msg_new() * @param envid ENVID parameter to the ESMTP MAIL command, may be NULL * @param ret_full return the full message on failure instead of the headers only * @return TRUE on success or FALSE on error * * Set the @em ENVID and @em RET parameters for Delivery Status Notifications (DSN's). The default is to omit the ENVID and to * request headers only. */ gboolean net_client_smtp_msg_set_dsn_opts(NetClientSmtpMessage *smtp_msg, const gchar *envid, gboolean ret_full); /** @brief Add a recipient to a SMTP message * * @param smtp_msg SMTP message returned by net_client_smtp_msg_new() * @param rfc5321_rcpt RFC 5321-compliant recipient address * @param dsn_mode Delivery Status Notification mode for the recipient * @return TRUE on success or FALSE on error * * Add a recipient address ("RCPT TO" forward-path, see RFC 5321) to the SMTP * message. */ gboolean net_client_smtp_msg_add_recipient(NetClientSmtpMessage *smtp_msg, const gchar *rfc5321_rcpt, NetClientSmtpDsnMode dsn_mode); /** @brief Free a SMTP message * * @param smtp_msg SMTP message returned by net_client_smtp_msg_new() * * Free all resources of the passed SMTP message. */ void net_client_smtp_msg_free(NetClientSmtpMessage *smtp_msg); /** @file * * This module implements a SMTP client class conforming with RFC 5321. * * The following additional features are supported: * - Authentication according to RFC 4954, using the methods * - CRAM-MD5 according to RFC 2195 * - CRAM-SHA1 according to TBD * - PLAIN according to RFC 4616 * - LOGIN * - GSSAPI according to RFC 4752 (if configured with gssapi support) * - STARTTLS encryption according to RFC 3207 * - Delivery Status Notifications (DSNs) according to RFC 3461 */ G_END_DECLS #endif /* NET_CLIENT_SMTP_H_ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client-utils.c000066400000000000000000000270131477646064400264450ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2017 - 2020 * * 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 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, see * . */ #include #include #include "net-client.h" #include "net-client-utils.h" #if defined(HAVE_GSSAPI) # if defined(HAVE_HEIMDAL) # include # else # include # endif #endif /* HAVE_GSSAPI */ gboolean net_client_host_reachable(const gchar *host, GError **error) { GSocketConnectable *remote_address; GNetworkMonitor *monitor; gboolean success; g_return_val_if_fail(host != NULL, FALSE); remote_address = g_network_address_new(host, 1024U); monitor = g_network_monitor_get_default(); success = g_network_monitor_can_reach(monitor, remote_address, NULL, error); g_object_unref(remote_address); return success; } #if defined(HAVE_GSSAPI) struct _NetClientGssCtx { gchar *user; gss_ctx_id_t context; gss_name_t target_name; OM_uint32 req_flags; }; static gchar *gss_error_string(OM_uint32 err_maj, OM_uint32 err_min) G_GNUC_WARN_UNUSED_RESULT; #endif /* HAVE_GSSAPI */ gchar * net_client_cram_calc(const gchar *base64_challenge, GChecksumType chksum_type, const gchar *user, const gchar *passwd) { guchar *chal_plain; gsize plain_len; gchar *digest; gchar *auth_buf; gchar *base64_buf; g_return_val_if_fail((base64_challenge != NULL) && (user != NULL) && (passwd != NULL), NULL); chal_plain = g_base64_decode(base64_challenge, &plain_len); digest = g_compute_hmac_for_data(chksum_type, (const guchar *) passwd, strlen(passwd), chal_plain, plain_len); net_client_free_authstr((gchar *) chal_plain); auth_buf = g_strdup_printf("%s %s", user, digest); net_client_free_authstr(digest); base64_buf = g_base64_encode((const guchar *) auth_buf, strlen(auth_buf)); net_client_free_authstr(auth_buf); return base64_buf; } const gchar * net_client_chksum_to_str(GChecksumType chksum_type) { /*lint -e{904} -e{9077} -e{9090} -e{788} (MISRA C:2012 Rules 15.5, 16.1, 16.3) */ switch (chksum_type) { case G_CHECKSUM_MD5: return "MD5"; case G_CHECKSUM_SHA1: return "SHA1"; case G_CHECKSUM_SHA256: return "SHA256"; case G_CHECKSUM_SHA512: return "SHA512"; default: return "_UNKNOWN_"; } } gchar * net_client_auth_plain_calc(const gchar *user, const gchar *passwd) { gchar *base64_buf; gchar *plain_buf; size_t user_len; size_t passwd_len; g_return_val_if_fail((user != NULL) && (passwd != NULL), NULL); user_len = strlen(user); passwd_len = strlen(passwd); plain_buf = g_malloc0((2U * user_len) + passwd_len + 3U); /*lint !e9079 (MISRA C:2012 Rule 11.5) */ strcpy(plain_buf, user); strcpy(&plain_buf[user_len + 1U], user); strcpy(&plain_buf[(2U * user_len) + 2U], passwd); base64_buf = g_base64_encode((const guchar *) plain_buf, (2U * user_len) + passwd_len + 2U); /* contains \0 chars, cannot use net_client_free_authstr */ memset(plain_buf, 0, (2U * user_len) + passwd_len + 2U); g_free(plain_buf); return base64_buf; } gchar * net_client_auth_anonymous_token(void) { gchar *buffer; GChecksum *hash; const gchar *hash_str; buffer = g_strdup_printf("%s@%s:%ld", g_get_user_name(), g_get_host_name(), (long) time(NULL)); hash = g_checksum_new(G_CHECKSUM_SHA256); g_checksum_update(hash, (const guchar *) buffer, strlen(buffer)); g_free(buffer); hash_str = g_checksum_get_string(hash); buffer = g_base64_encode((const guchar *) hash_str, strlen(hash_str)); g_checksum_free(hash); return buffer; } gchar * net_client_host_only(const gchar *host_and_port) { gchar *result; gchar *colon; g_return_val_if_fail(host_and_port != NULL, NULL); result = g_strdup(host_and_port); colon = strchr(result, ':'); if (colon != NULL) { colon[0] = '\0'; } return result; } void net_client_free_authstr(gchar *str) { if (str != NULL) { guint n; for (n = 0; str[n] != '\0'; n++) { str[n] = (gchar) g_random_int_range(32, 128); } g_free(str); } } #if defined(HAVE_GSSAPI) NetClientGssCtx * net_client_gss_ctx_new(const gchar *service, const gchar *host, const gchar *user, GError **error) { NetClientGssCtx *gss_ctx; gchar *service_str; gchar *colon; gss_buffer_desc request; OM_uint32 maj_stat; OM_uint32 min_stat; g_return_val_if_fail((service != NULL) && (host != NULL) && (user != NULL), NULL); gss_ctx = g_new0(NetClientGssCtx, 1U); service_str = g_strconcat(service, "@", host, NULL); colon = strchr(service_str, ':'); /*lint !e9034 accept char literal as int */ if (colon != NULL) { colon[0] = '\0'; /* strip off any port specification */ } request.value = service_str; request.length = strlen(service_str) + 1U; maj_stat = gss_import_name(&min_stat, &request, GSS_C_NT_HOSTBASED_SERVICE, &gss_ctx->target_name); if (GSS_ERROR(maj_stat) != 0U) { gchar *gss_err = gss_error_string(maj_stat, min_stat); g_debug("gss_import_name: %x:%x: %s", maj_stat, min_stat, gss_err); g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GSSAPI, _("importing GSS service name %s failed: %s"), service_str, gss_err); g_free(gss_err); g_free(gss_ctx); gss_ctx = NULL; } else { /* configure the context according to RFC 4752, Sect. 3.1 */ gss_ctx->req_flags = GSS_C_INTEG_FLAG + GSS_C_MUTUAL_FLAG + GSS_C_SEQUENCE_FLAG + GSS_C_CONF_FLAG; gss_ctx->user = g_strdup(user); } g_free(service_str); return gss_ctx; } gint net_client_gss_auth_step(NetClientGssCtx *gss_ctx, const gchar *in_token, gchar **out_token, GError **error) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_buffer_desc input_token; gss_buffer_desc output_token; gint result; g_return_val_if_fail((gss_ctx != NULL) && (out_token != NULL), -1); if (in_token != NULL) { gsize out_len; input_token.value = g_base64_decode(in_token, &out_len); input_token.length = out_len; } else { input_token.value = NULL; input_token.length = 0U; } maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &gss_ctx->context, gss_ctx->target_name, GSS_C_NO_OID, gss_ctx->req_flags, 0U, GSS_C_NO_CHANNEL_BINDINGS, &input_token, NULL, &output_token, NULL, NULL); if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) { gchar *gss_err = gss_error_string(maj_stat, min_stat); g_debug("gss_init_sec_context: %x:%x: %s", maj_stat, min_stat, gss_err); g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GSSAPI, _("cannot initialize GSS security context: %s"), gss_err); g_free(gss_err); result = -1; } else { if (output_token.length > 0U) { *out_token = g_base64_encode(output_token.value, output_token.length); /*lint !e9079 (MISRA C:2012 Rule 11.5) */ } else { *out_token = g_strdup(""); } (void) gss_release_buffer(&min_stat, &output_token); if (maj_stat == GSS_S_COMPLETE) { result = 1; } else { result = 0; } } (void) gss_release_buffer(&min_stat, &input_token); return result; } gchar * net_client_gss_auth_finish(const NetClientGssCtx *gss_ctx, const gchar *in_token, GError **error) { OM_uint32 maj_stat; OM_uint32 min_stat; gsize out_len; gss_buffer_desc input_token; gss_buffer_desc output_token; gchar *result = NULL; input_token.value = g_base64_decode(in_token, &out_len); input_token.length = out_len; maj_stat = gss_unwrap(&min_stat, gss_ctx->context, &input_token, &output_token, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { gchar *gss_err = gss_error_string(maj_stat, min_stat); g_debug("gss_unwrap: %x:%x: %s", maj_stat, min_stat, gss_err); g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GSSAPI, _("malformed GSS security token: %s"), gss_err); g_free(gss_err); } else { const guchar *src; /* RFC 4752 requires a token length of 4, and a first octet == 0x01 */ src = (unsigned char *) output_token.value; /*lint !e9079 (MISRA C:2012 Rule 11.5) */ if ((output_token.length != 4U) || (src[0] != 0x01U)) { (void) gss_release_buffer(&min_stat, &output_token); g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GSSAPI, _("malformed GSS security token")); } else { guchar *dst; (void) gss_release_buffer(&min_stat, &input_token); input_token.length = strlen(gss_ctx->user) + 4U; input_token.value = g_malloc(input_token.length); dst = input_token.value; /*lint !e9079 (MISRA C:2012 Rule 11.5) */ memcpy(input_token.value, output_token.value, 4U); (void) gss_release_buffer(&min_stat, &output_token); memcpy(&dst[4], gss_ctx->user, input_token.length - 4U); maj_stat = gss_wrap(&min_stat, gss_ctx->context, 0, GSS_C_QOP_DEFAULT, &input_token, NULL, &output_token); if (maj_stat != GSS_S_COMPLETE) { gchar *gss_err = gss_error_string(maj_stat, min_stat); g_debug("gss_wrap: %x:%x: %s", maj_stat, min_stat, gss_err); g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GSSAPI, _("cannot create GSS login request: %s"), gss_err); g_free(gss_err); } else { result = g_base64_encode(output_token.value, output_token.length); /*lint !e9079 (MISRA C:2012 Rule 11.5) */ (void) gss_release_buffer(&min_stat, &output_token); } } } (void) gss_release_buffer(&min_stat, &input_token); return result; } void net_client_gss_ctx_free(NetClientGssCtx *gss_ctx) { if (gss_ctx != NULL) { OM_uint32 min_stat; if (gss_ctx->context != NULL) { (void) gss_delete_sec_context(&min_stat, &gss_ctx->context, GSS_C_NO_BUFFER); } if (gss_ctx->target_name != NULL) { (void) gss_release_name(&min_stat, &gss_ctx->target_name); } g_free(gss_ctx->user); g_free(gss_ctx); } } static gchar * gss_error_string(OM_uint32 err_maj, OM_uint32 err_min) { OM_uint32 maj_stat; OM_uint32 min_stat; OM_uint32 msg_ctx; gss_buffer_desc status_string; GString *message = g_string_new(NULL); gchar *result; do { maj_stat = gss_display_status(&min_stat, err_maj, GSS_C_GSS_CODE, GSS_C_NO_OID, &msg_ctx, &status_string); if (GSS_ERROR(maj_stat) == 0U) { if (message->len > 0U) { message = g_string_append(message, "; "); } message = g_string_append(message, (const gchar *) status_string.value); /*lint !e9079 (MISRA C:2012 Rule 11.5) */ (void) gss_release_buffer(&min_stat, &status_string); maj_stat = gss_display_status(&min_stat, err_min, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); if (GSS_ERROR(maj_stat) == 0U) { message = g_string_append(message, ": "); message = g_string_append(message, (const gchar *) status_string.value); /*lint !e9079 (MISRA C:2012 Rule 11.5) */ (void) gss_release_buffer(&min_stat, &status_string); } } } while ((GSS_ERROR(maj_stat) == 0U) && (msg_ctx != 0U)); if (message->len > 0U) { result = g_string_free(message, FALSE); } else { (void) g_string_free(message, TRUE); result = g_strdup_printf(_("unknown error code %u:%u"), (unsigned) err_maj, (unsigned) err_min); } return result; } #endif /* HAVE_GSSAPI */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client-utils.h000066400000000000000000000177201477646064400264560ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2017 - 2020 * * 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 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, see * . */ #ifndef NET_CLIENT_UTILS_H_ #define NET_CLIENT_UTILS_H_ #include "config.h" #include #include "net-client.h" G_BEGIN_DECLS #if defined(HAVE_GSSAPI) typedef struct _NetClientGssCtx NetClientGssCtx; #endif /* HAVE_GSSAPI */ typedef struct _NetClientProbeResult NetClientProbeResult; /** @brief Server probe results */ struct _NetClientProbeResult { guint16 port; /**< The port where the server listens. */ NetClientCryptMode crypt_mode; /**< The encryption mode the server supports for the returned port. */ NetClientAuthMode auth_mode; /**< The authentication modes the server supports for the port and encryption mode. */ }; /** @brief Check is a host is resolvable and reachable * * @param host host name or IP address * @param error filled with error information on error * @return TRUE if the passed host name is resolvable and reachable */ gboolean net_client_host_reachable(const gchar *host, GError **error); /** @brief Calculate a CRAM authentication string * * @param base64_challenge base64-encoded challenge sent by the server * @param chksum_type checksum type * @param user user name * @param passwd password * @return a newly allocated string containing the base64-encoded authentication * * This helper function calculates the the base64-encoded authentication string from the server challenge, the user name and the * password according to the standards RFC 2104 (MD5, SHA1) and * RFC 4868 (SHA256, SHA512). The caller shall free the returned string when it * is not needed any more. * * \sa RFC 2195. */ gchar *net_client_cram_calc(const gchar *base64_challenge, GChecksumType chksum_type, const gchar *user, const gchar *passwd) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** @brief Get the checksum type as string * * @param chksum_type checksum type * @return a string representation of the checksum type */ const gchar *net_client_chksum_to_str(GChecksumType chksum_type); /** @brief Calculate a SASL AUTH PLAIN authentication string * * @param user user name * @param passwd password * @return a newly allocated string containing the base64-encoded authentication * * This helper function calculates the base64-encoded SASL AUTH PLAIN authentication string from the user name and the password * according to RFC 4616. The caller shall free the returned string when it is * not needed any more. */ gchar *net_client_auth_plain_calc(const gchar *user, const gchar *passwd) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** @brief Safely free an authentication string * * @param str string * * This function can be used to safely free an authentication string. It overwrites the passed string with random characters, and * then frees it. */ void net_client_free_authstr(gchar *str); /** @brief Create a token for anonymous authentication * * @return a newly allocated string containing the base64-encoded authentication * * This helper function calculates a base64-encoded SASL AUTH ANONYMOUS authentication token which is used as trace information by * the server. As recommended by RFC 4505, the token does not contain personal data. The returned value is the encoded SHA256 hex * hash of the string user-name@host-name:time (time is the creation time stamp as returned by time()). This token will be * unique, but makes it impossible for the server to extract user and host. However, the client @em may store to token if linking * server to client operations is required, e.g. for debugging purposes. * * The caller shall free the returned string when it is not needed any more. */ gchar *net_client_auth_anonymous_token(void) G_GNUC_WARN_UNUSED_RESULT; /** \brief Return the host part of a host:port string * * @param[in] host_and_port a string containing a host name, optionally followed by a colon and a port number * @return a newly allocated string containing the host part only */ gchar *net_client_host_only(const gchar *host_and_port) G_GNUC_WARN_UNUSED_RESULT; #if defined(HAVE_GSSAPI) /** @brief Create a GSSAPI authentication context * * @param service service name (smtp, imap or pop) * @param host full-qualified host name of the machine providing the service * @param user user name * @param error filled with error information on error * @return a newly allocated and initialised GSSAPI context on success, or NULL on error * * Create a new authentication context for Kerberos v5 SASL AUTH GSSAPI based authentication for the passed service and host * according to RFC 4752. The returned context shall be used for the * authentication process and must be freed by calling net_client_gss_ctx_free(). * * @note The host may optionally contain a port definition (e.g. smtp.mydom.org:25) which will be omitted. * @sa net_client_gss_auth_step(), net_client_gss_auth_finish() */ NetClientGssCtx *net_client_gss_ctx_new(const gchar *service, const gchar *host, const gchar *user, GError **error) G_GNUC_WARN_UNUSED_RESULT; /** @brief Perform a GSSAPI authentication step * * @param gss_ctx GSSAPI authentication context * @param in_token base64-encoded input token, or NULL for the initial authentication step * @param out_token filled with the base64-encoded output token on success * @param error filled with error information on error * @return 0 if an additional step has to be performed, 1 if net_client_gss_auth_finish() shall be called, or -1 on error * * Initially, the function shall be called with a NULL input token. The resulting output token shall be sent to the remote server * to obtain a new input token until the function returns 1. Then, net_client_gss_auth_finish() shall be called to finish the * authentication process. */ gint net_client_gss_auth_step(NetClientGssCtx *gss_ctx, const gchar *in_token, gchar **out_token, GError **error) G_GNUC_WARN_UNUSED_RESULT; /** @brief Finish the GSSAPI authentication * * @param gss_ctx GSSAPI authentication context * @param in_token base64-encoded input token, received in the final net_client_gss_auth_step() * @param error filled with error information on error * @return the base64-encoded final authentication token on success, or NULL on error * * Create the final token which has to be sent to the remote server to finalise the GSSAPI authentication process. */ /*lint -ecall(9076,net_client_gss_auth_finish) suppress false-positive re. [const] NetClientGssCtx* (FlexeLint 9.00L bug) */ gchar *net_client_gss_auth_finish(const NetClientGssCtx *gss_ctx, const gchar *in_token, GError **error) G_GNUC_WARN_UNUSED_RESULT; /** @brief Free a GSSAPI authentication context * * @param gss_ctx GSSAPI authentication context * * Free all resources in the passed GSSAPI authentication context by net_client_gss_ctx_new() and the context itself. */ void net_client_gss_ctx_free(NetClientGssCtx *gss_ctx); #endif /* HAVE_GSSAPI */ /** @file * * This module implements probing and authentication-related helper functions for the network client library. */ G_END_DECLS #endif /* NET_CLIENT_UTILS_H_ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client.c000066400000000000000000000541011477646064400253050ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2017 - 2020 * * 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 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, see * . */ #include #include #include #include #include "net-client-utils.h" #include "net-client.h" /* * Stacking of the streams: * Input channel: * GSocketClient *sock * GSocketConnection *plain_conn * GIOStream *tls_conn -- optional * GInputStream *comp_istream -- optional * GDataInputStream *istream * * Output channel: * GSocketClient *sock * GSocketConnection *plain_conn * GIOStream *tls_conn -- optional * GOutputStream *ostream -- optionally compressed */ typedef struct _NetClientPrivate NetClientPrivate; struct _NetClientPrivate { gchar *host_and_port; guint16 default_port; gsize max_line_len; GSocketClient *sock; GSocketConnectable *remote_address; GSocketConnection *plain_conn; GIOStream *tls_conn; GDataInputStream *istream; GOutputStream *ostream; GTlsCertificate *certificate; GZlibCompressor *comp; GZlibDecompressor *decomp; GInputStream *comp_istream; }; static guint signals[3]; G_DEFINE_TYPE_WITH_PRIVATE(NetClient, net_client, G_TYPE_OBJECT) static void net_client_finalise(GObject *object); static gboolean cert_accept_cb(GTlsConnection *conn, GTlsCertificate *peer_cert, GTlsCertificateFlags errors, gpointer user_data); NetClient * net_client_new(const gchar *host_and_port, guint16 default_port, gsize max_line_len) { NetClient *client; NetClientPrivate *priv; g_return_val_if_fail(host_and_port != NULL, NULL); client = NET_CLIENT(g_object_new(NET_CLIENT_TYPE, NULL)); /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ priv = net_client_get_instance_private(client); if (priv->sock == NULL) { g_object_unref(client); client = NULL; } else { priv->host_and_port = g_strdup(host_and_port); priv->default_port = default_port; priv->max_line_len = max_line_len; } return client; } gboolean net_client_configure(NetClient *client, const gchar *host_and_port, guint16 default_port, gsize max_line_len, GError **error) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ NetClientPrivate *priv = net_client_get_instance_private(client); gboolean result; g_return_val_if_fail(NET_IS_CLIENT(client) && (host_and_port != NULL), FALSE); if (priv->plain_conn != NULL) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_CONNECTED, _("network client is already connected")); result = FALSE; } else { g_free(priv->host_and_port); priv->host_and_port = g_strdup(host_and_port); priv->default_port = default_port; priv->max_line_len = max_line_len; result = TRUE; } return result; } const gchar * net_client_get_host(NetClient *client) { const gchar *result; if (NET_IS_CLIENT(client)) { const NetClientPrivate *priv; /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ priv = net_client_get_instance_private(client); result = priv->host_and_port; } else { result = NULL; } return result; } gboolean net_client_connect(NetClient *client, GError **error) { gboolean result = FALSE; /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ NetClientPrivate *priv = net_client_get_instance_private(client); g_return_val_if_fail(NET_IS_CLIENT(client), FALSE); if (priv->plain_conn != NULL) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_CONNECTED, _("network client is already connected")); } else { priv->remote_address = g_network_address_parse(priv->host_and_port, priv->default_port, error); if (priv->remote_address != NULL) { priv->plain_conn = g_socket_client_connect(priv->sock, priv->remote_address, NULL, error); if (priv->plain_conn != NULL) { g_debug("connected to %s", priv->host_and_port); priv->istream = g_data_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(priv->plain_conn))); g_data_input_stream_set_newline_type(priv->istream, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); priv->ostream = g_io_stream_get_output_stream(G_IO_STREAM(priv->plain_conn)); result = TRUE; } else { g_object_unref(priv->remote_address); priv->remote_address = NULL; } } } return result; } void net_client_shutdown(NetClient *client) { if (NET_IS_CLIENT(client)) { NetClientPrivate *priv; /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ priv = net_client_get_instance_private(client); /* Note: we must unref the GDataInputStream, but the GOutputStream only if compression is active! */ if (priv->comp != NULL) { /* Note: for some strange reason, GIO decides to send a 0x03 0x00 sequence when closing a compressed connection, before * sending the usual FIN, ACK TCP reply packet. As the remote server does not expect the former (the connection has * already been closed on its side), it replies with with a RST TCP packet. Unref'ing client->priv->ostream and * client->priv->comp /after/ all other components of the connection fixes the issue for unencrypted connections, but * throws a critical error for TLS. Observed with gio 2.48.2 and 2.50.3, no idea how it can be fixed. * See also https://bugzilla.gnome.org/show_bug.cgi?id=795985. */ if (priv->ostream != NULL) { g_object_unref(priv->ostream); } g_object_unref(priv->comp); } if (priv->decomp != NULL) { g_object_unref(priv->decomp); priv->decomp = NULL; } if (priv->comp_istream!= NULL) { g_object_unref(priv->comp_istream); priv->comp_istream = NULL; } if (priv->istream != NULL) { g_object_unref(priv->istream); priv->istream = NULL; } if (priv->tls_conn != NULL) { g_object_unref(priv->tls_conn); priv->tls_conn = NULL; } if (priv->plain_conn != NULL) { g_object_unref(priv->plain_conn); priv->plain_conn = NULL; } if (priv->remote_address != NULL) { g_object_unref(priv->remote_address); priv->remote_address = NULL; } } } gboolean net_client_is_connected(NetClient *client) { gboolean result; if (NET_IS_CLIENT(client)) { const NetClientPrivate *priv; /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ priv = net_client_get_instance_private(client); result = (priv->plain_conn != NULL); } else { result = FALSE; } return result; } gboolean net_client_is_encrypted(NetClient *client) { gboolean result; if (net_client_is_connected(client)) { const NetClientPrivate *priv; /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ priv = net_client_get_instance_private(client); result = (priv->tls_conn != NULL); } else { result = FALSE; } return result; } gboolean net_client_read_line(NetClient *client, gchar **recv_line, GError **error) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ const NetClientPrivate *priv = net_client_get_instance_private(client); gboolean result = FALSE; g_return_val_if_fail(NET_IS_CLIENT(client), FALSE); if (priv->istream == NULL) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_NOT_CONNECTED, _("network client is not connected")); } else { gchar *line_buf; gsize length; GError *read_err = NULL; line_buf = g_data_input_stream_read_line(priv->istream, &length, NULL, &read_err); if (line_buf != NULL) { /* check that the protocol-specific maximum line length is not exceeded */ if ((priv->max_line_len > 0U) && (length > priv->max_line_len)) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_LINE_TOO_LONG, _("reply length %lu exceeds the maximum allowed length %lu"), (unsigned long) length, (unsigned long) priv->max_line_len); g_free(line_buf); } else { g_debug("R '%s'", line_buf); result = TRUE; if (recv_line != NULL) { *recv_line = line_buf; } else { g_free(line_buf); } } } else { if (read_err != NULL) { g_propagate_error(error, read_err); } else { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_CONNECTION_LOST, _("connection lost")); } } } return result; } gboolean net_client_write_buffer(NetClient *client, const gchar *buffer, gsize count, GError **error) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ const NetClientPrivate *priv = net_client_get_instance_private(client); gboolean result; g_return_val_if_fail(NET_IS_CLIENT(client) && (buffer != NULL) && (count > 0UL), FALSE); if (priv->ostream == NULL) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_NOT_CONNECTED, _("network client is not connected")); result = FALSE; } else { gsize bytes_written; if ((count >= 2U) && (buffer[count - 1U] == '\n')) { g_debug("W '%.*s'", (int) count - 2, buffer); } else { g_debug("W '%.*s'", (int) count, buffer); } result = g_output_stream_write_all(priv->ostream, buffer, count, &bytes_written, NULL, error); if (result) { result = g_output_stream_flush(priv->ostream, NULL, error); } } return result; } gboolean net_client_vwrite_line(NetClient *client, const gchar *format, va_list args, GError **error) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ const NetClientPrivate *priv = net_client_get_instance_private(client); gboolean result; GString *buffer; g_return_val_if_fail(NET_IS_CLIENT(client) && (format != NULL), FALSE); buffer = g_string_new(NULL); g_string_vprintf(buffer, format, args); if ((priv->max_line_len > 0U) && (buffer->len > priv->max_line_len)) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_LINE_TOO_LONG, _("line too long")); result = FALSE; } else { buffer = g_string_append(buffer, "\r\n"); result = net_client_write_buffer(client, buffer->str, buffer->len, error); } (void) g_string_free(buffer, TRUE); return result; } gboolean net_client_write_line(NetClient *client, const gchar *format, GError **error, ...) { va_list args; gboolean result; va_start(args, error); result = net_client_vwrite_line(client, format, args, error); va_end(args); return result; } gboolean net_client_execute(NetClient *client, gchar **response, const gchar *request_fmt, GError **error, ...) { va_list args; gboolean result; va_start(args, error); result = net_client_vwrite_line(client, request_fmt, args, error); va_end(args); if (result) { result = net_client_read_line(client, response, error); } return result; } /* Note: I have no idea how I can load a PEM with an encrypted key into a GTlsCertificate using g_tls_certificate_new_from_file() * or g_tls_certificate_new_from_pem(), as this will always fail with a GnuTLS error "ASN1 parser: Error in DER parsing". There * /might/ be a solution with GTlsInteraction and GTlsPassword, though. Please enlighten me if you know more... * * This function uses "raw" GnuTLS calls and will emit the cert-pass signal if necessary. * * See also . */ gboolean net_client_set_cert_from_pem(NetClient *client, const gchar *pem_data, GError **error) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ NetClientPrivate *priv = net_client_get_instance_private(client); gboolean result = FALSE; gnutls_x509_crt_t cert; int res; g_return_val_if_fail(NET_IS_CLIENT(client) && (pem_data != NULL), FALSE); /* always free any existing certificate */ if (priv->certificate != NULL) { g_object_unref(priv->certificate); priv->certificate = NULL; } /* load the certificate */ res = gnutls_x509_crt_init(&cert); if (res != GNUTLS_E_SUCCESS) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GNUTLS, _("error initializing certificate: %s"), gnutls_strerror(res)); } else { gnutls_datum_t data; /*lint -e9005 cast'ing away the const is safe as gnutls treats data as const */ data.data = (unsigned char *) pem_data; data.size = strlen(pem_data); res = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_PEM); if (res != GNUTLS_E_SUCCESS) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GNUTLS, _("error loading certificate: %s"), gnutls_strerror(res)); } else { gnutls_x509_privkey_t key; /* try to load the key, emit cert-pass signal if gnutls says the key is encrypted */ res = gnutls_x509_privkey_init(&key); if (res != GNUTLS_E_SUCCESS) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GNUTLS, _("error initializing key: %s"), gnutls_strerror(res)); } else { res = gnutls_x509_privkey_import2(key, &data, GNUTLS_X509_FMT_PEM, NULL, 0); if (res == GNUTLS_E_DECRYPTION_FAILED) { size_t dn_size; gchar *dn_str; /* determine dn string buffer size requirements */ dn_size = 0U; (void) gnutls_x509_crt_get_dn(cert, NULL, &dn_size); dn_str = g_malloc0(dn_size + 1U); /*lint !e9079 (MISRA C:2012 Rule 11.5) */ res = gnutls_x509_crt_get_dn(cert, dn_str, &dn_size); if (res == GNUTLS_E_SUCCESS) { gchar *key_pass = NULL; if (!g_utf8_validate(dn_str, -1, NULL)) { gchar *buf; buf = g_locale_to_utf8(dn_str, -1, NULL, NULL, NULL); g_free(dn_str); dn_str = buf; } g_debug("emit 'cert-pass' signal for client %p", client); g_signal_emit(client, signals[2], 0, dn_str, &key_pass); if (key_pass != NULL) { res = gnutls_x509_privkey_import2(key, &data, GNUTLS_X509_FMT_PEM, key_pass, 0); net_client_free_authstr(key_pass); } } g_free(dn_str); } /* on success, set the certificate using the unencrypted key */ if (res == GNUTLS_E_SUCCESS) { gchar *pem_buf; size_t key_buf_size = 0; size_t crt_buf_size = 0; /* determine buffer size requirements */ (void) gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, NULL, &key_buf_size); (void) gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, NULL, &crt_buf_size); pem_buf = g_malloc(key_buf_size + crt_buf_size); /*lint !e9079 (MISRA C:2012 Rule 11.5) */ res = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, pem_buf, &key_buf_size); if (res == GNUTLS_E_SUCCESS) { res = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, &pem_buf[key_buf_size], &crt_buf_size); } if (res == GNUTLS_E_SUCCESS) { priv->certificate = g_tls_certificate_new_from_pem(pem_buf, -1, error); if (priv->certificate != NULL) { result = TRUE; } } g_free(pem_buf); } gnutls_x509_privkey_deinit(key); if (res != GNUTLS_E_SUCCESS) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_CERT_KEY_PASS, _("error loading key: %s"), gnutls_strerror(res)); } } } gnutls_x509_crt_deinit(cert); } return result; } gboolean net_client_set_cert_from_file(NetClient *client, const gchar *pem_path, GError **error) { gboolean result; GFile *pem_file; gchar *pem_buf; g_return_val_if_fail(pem_path != NULL, FALSE); pem_file = g_file_new_for_path(pem_path); result = g_file_load_contents(pem_file, NULL, &pem_buf, NULL, NULL, error); if (result) { result = net_client_set_cert_from_pem(client, pem_buf, error); g_free(pem_buf); } g_object_unref(pem_file); return result; } gboolean net_client_start_tls(NetClient *client, GError **error) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ NetClientPrivate *priv = net_client_get_instance_private(client); gboolean result = FALSE; g_return_val_if_fail(NET_IS_CLIENT(client), FALSE); if (priv->plain_conn == NULL) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_NOT_CONNECTED, _("not connected")); } else if (priv->tls_conn != NULL) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_TLS_ACTIVE, _("connection is already encrypted")); } else { priv->tls_conn = g_tls_client_connection_new(G_IO_STREAM(priv->plain_conn), priv->remote_address, error); if (priv->tls_conn != NULL) { if (priv->certificate != NULL) { g_tls_connection_set_certificate(G_TLS_CONNECTION(priv->tls_conn), priv->certificate); } (void) g_signal_connect(priv->tls_conn, "accept-certificate", G_CALLBACK(cert_accept_cb), client); result = g_tls_connection_handshake(G_TLS_CONNECTION(priv->tls_conn), NULL, error); if (result) { g_filter_input_stream_set_close_base_stream(G_FILTER_INPUT_STREAM(priv->istream), FALSE); g_object_unref(priv->istream); /* unref the plain connection's stream */ priv->istream = g_data_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(priv->tls_conn))); g_data_input_stream_set_newline_type(priv->istream, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); priv->ostream = g_io_stream_get_output_stream(G_IO_STREAM(priv->tls_conn)); g_debug("connection is encrypted"); } else { g_object_unref(priv->tls_conn); priv->tls_conn = NULL; } } } return result; } gboolean net_client_start_compression(NetClient *client, GError **error) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ NetClientPrivate *priv = net_client_get_instance_private(client); gboolean result = FALSE; g_return_val_if_fail(NET_IS_CLIENT(client), FALSE); if (priv->plain_conn == NULL) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_NOT_CONNECTED, _("not connected")); } else if (priv->comp != NULL) { g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_COMP_ACTIVE, _("connection is already compressed")); } else { priv->comp = g_zlib_compressor_new(G_ZLIB_COMPRESSOR_FORMAT_RAW, -1); priv->decomp = g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_RAW); g_filter_input_stream_set_close_base_stream(G_FILTER_INPUT_STREAM(priv->istream), FALSE); g_object_unref(priv->istream); if (priv->tls_conn != NULL) { priv->comp_istream = g_converter_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(priv->tls_conn)), G_CONVERTER(priv->decomp)); } else { priv->comp_istream = g_converter_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(priv->plain_conn)), G_CONVERTER(priv->decomp)); } priv->istream = g_data_input_stream_new(priv->comp_istream); g_data_input_stream_set_newline_type(priv->istream, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); priv->ostream = g_converter_output_stream_new(priv->ostream, G_CONVERTER(priv->comp)); result = TRUE; g_debug("connection is compressed"); } return result; } gboolean net_client_set_timeout(NetClient *client, guint timeout_secs) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ const NetClientPrivate *priv = net_client_get_instance_private(client); g_return_val_if_fail(NET_IS_CLIENT(client), FALSE); g_socket_client_set_timeout(priv->sock, timeout_secs); return TRUE; } GSocket * net_client_get_socket(NetClient *client) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ const NetClientPrivate *priv = net_client_get_instance_private(client); g_return_val_if_fail(NET_IS_CLIENT(client) && (priv->plain_conn != NULL), NULL); return g_socket_connection_get_socket(priv->plain_conn); } gboolean net_client_can_read(NetClient *client) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ const NetClientPrivate *priv = net_client_get_instance_private(client); g_return_val_if_fail(NET_IS_CLIENT(client) && (priv->plain_conn != NULL) && (priv->istream != NULL), FALSE); return (g_socket_condition_check(g_socket_connection_get_socket(priv->plain_conn), G_IO_IN) != 0) || (g_buffered_input_stream_get_available(G_BUFFERED_INPUT_STREAM(priv->istream)) > 0U); } /* == local functions =========================================================================================================== */ static void net_client_class_init(NetClientClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->finalize = net_client_finalise; signals[0] = g_signal_new("cert-check", NET_CLIENT_TYPE, G_SIGNAL_RUN_LAST, 0U, NULL, NULL, NULL, G_TYPE_BOOLEAN, 2U, G_TYPE_TLS_CERTIFICATE, G_TYPE_TLS_CERTIFICATE_FLAGS); signals[1] = g_signal_new("auth", NET_CLIENT_TYPE, G_SIGNAL_RUN_LAST, 0U, NULL, NULL, NULL, G_TYPE_STRV, 1U, G_TYPE_INT); signals[2] = g_signal_new("cert-pass", NET_CLIENT_TYPE, G_SIGNAL_RUN_LAST, 0U, NULL, NULL, NULL, G_TYPE_STRING, 1U, G_TYPE_STRING); } static void net_client_init(NetClient *self) { /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ NetClientPrivate *priv = net_client_get_instance_private(self); priv->sock = g_socket_client_new(); if (priv->sock != NULL) { g_socket_client_set_timeout(priv->sock, 180U); } } static void net_client_finalise(GObject *object) { NetClient *client = NET_CLIENT(object); /*lint -e{9079} (MISRA C:2012 Rule 11.5) intended use of this function */ NetClientPrivate *priv = net_client_get_instance_private(client); const GObjectClass *parent_class = G_OBJECT_CLASS(net_client_parent_class); net_client_shutdown(client); if (priv->sock != NULL) { g_object_unref(priv->sock); priv->sock = NULL; } if (priv->certificate != NULL) { g_object_unref(priv->certificate); priv->certificate = NULL; } g_debug("finalised connection to %s", priv->host_and_port); g_free(priv->host_and_port); (*parent_class->finalize)(object); } /*lint -e{715,818} */ static gboolean cert_accept_cb(G_GNUC_UNUSED GTlsConnection *conn, GTlsCertificate *peer_cert, GTlsCertificateFlags errors, gpointer user_data) { NetClient *client = NET_CLIENT(user_data); gboolean result; g_debug("emit 'cert-check' signal for client %p", client); g_signal_emit(client, signals[0], 0, peer_cert, errors, &result); return result; } balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/net-client.h000066400000000000000000000353621477646064400253220ustar00rootroot00000000000000/* NetClient - simple line-based network client library * * Copyright (C) Albrecht Dreß 2017 - 2020 * * 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 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, see * . */ #ifndef NET_CLIENT_H_ #define NET_CLIENT_H_ #include #include #include G_BEGIN_DECLS #define NET_CLIENT_TYPE (net_client_get_type()) G_DECLARE_DERIVABLE_TYPE(NetClient, net_client, NET, CLIENT, GObject) #define NET_CLIENT_ERROR_QUARK (g_quark_from_static_string("net-client")) struct _NetClientClass { GObjectClass parent; }; typedef enum _NetClientError NetClientError; typedef enum _NetClientCryptMode NetClientCryptMode; typedef enum _NetClientAuthMode NetClientAuthMode; /** @brief Encryption mode */ enum _NetClientCryptMode { NET_CLIENT_CRYPT_ENCRYPTED = 1, /**< TLS encryption @em before starting the protocol required (e.g. SMTPS). */ NET_CLIENT_CRYPT_STARTTLS, /**< Protocol-specific STARTTLS encryption required. */ NET_CLIENT_CRYPT_STARTTLS_OPT, /**< Optional protocol-specific STARTTLS encryption, proceed unencrypted on fail. */ NET_CLIENT_CRYPT_NONE /**< Unencrypted connection. */ }; /** @brief Authentication mode */ enum _NetClientAuthMode { NET_CLIENT_AUTH_NONE_ANON = 1, /**< No authentication (SMTP); anonymous authentication (RFC 4505 for POP3, IMAP). */ NET_CLIENT_AUTH_USER_PASS = 2, /**< Authenticate with user name and password. */ NET_CLIENT_AUTH_KERBEROS = 4 /**< Authenticate with user name and Kerberos ticket. */ }; /** @brief Error codes */ enum _NetClientError { NET_CLIENT_ERROR_CONNECTED = 1, /**< The client is already connected. */ NET_CLIENT_ERROR_NOT_CONNECTED, /**< The client is not connected. */ NET_CLIENT_ERROR_CONNECTION_LOST, /**< The connection is lost. */ NET_CLIENT_ERROR_TLS_ACTIVE, /**< TLS is already active for the connection. */ NET_CLIENT_ERROR_COMP_ACTIVE, /**< Compression is already active for the connection. */ NET_CLIENT_ERROR_LINE_TOO_LONG, /**< The line is too long. */ NET_CLIENT_ERROR_GNUTLS, /**< A GnuTLS error occurred (bad certificate or key data, or internal error). */ NET_CLIENT_ERROR_CERT_KEY_PASS, /**< GnuTLS could not decrypt the user certificate's private key. */ NET_CLIENT_ERROR_GSSAPI, /**< A GSSAPI error occurred. */ NET_CLIENT_PROBE_FAILED /**< Probing a server failed. */ }; /** @brief Create a new network client * * @param host_and_port remote host and port or service, separated by a colon, which shall be connected * @param default_port default remote port if host_and_port does not contain a port * @param max_line_len maximum line length supported by the underlying protocol, 0 for no limit * @return the net network client object * * Create a new network client object with the passed parameters. Call g_object_unref() on it to shut down the connection * and to free all resources of it. */ NetClient *net_client_new(const gchar *host_and_port, guint16 default_port, gsize max_line_len); /** @brief Configure a network client * * @param client network client * @param host_and_port remote host and port or service, separated by a colon, which shall be connected * @param default_port default remote port if host_and_port does not contain a port * @param max_line_len maximum line length supported by the underlying protocol, 0 for no limit * @param error filled with error information on error * @return TRUE is the connection was successful, FALSE on error * * Set the remote host and port and the maximum line length to the passed parameters, replacing the previous values set by calling * net_client_new(). */ gboolean net_client_configure(NetClient *client, const gchar *host_and_port, guint16 default_port, gsize max_line_len, GError **error); /** @brief Get the target host of a network client * * @param client network client * @return the currently set host on success, or NULL on error * * @note The function returns the value of @em host_and_port set by net_client_new() or net_client_configure(). */ const gchar *net_client_get_host(NetClient *client); /** @brief Connect a network client * * @param client network client * @param error filled with error information on error * @return TRUE is the connection was successful, FALSE on error * * Try to connect the remote host and TCP port. */ gboolean net_client_connect(NetClient *client, GError **error); /** @brief Shut down the connection to a network client * * @param client network client * * Shut down the connection. Note that it is usually not necessary to call this function, as the connection will be shut down when * the client is destroyed by calling g_object_unref(). */ void net_client_shutdown(NetClient *client); /** @brief Check if a network client is connected * * @param client network client * @return TRUE if the passed network client is connected, FALSE if not */ gboolean net_client_is_connected(NetClient *client); /** @brief Check if a network client is encrypted * * @param client network client * @return TRUE if the passed network client is encrypted, FALSE if not */ gboolean net_client_is_encrypted(NetClient *client); /** @brief Load a certificate and private key from PEM data * * @param client network client * @param pem_data NUL-terminated PEM data buffer * @param error filled with error information on error * @return TRUE is the certificate and private key were loaded, FALSE on error * * Load a client certificate and private key form the passed PEM data. If the private key is encrypted, the signal @ref cert-pass * is emitted. * * Use this function (or net_client_set_cert_from_file()) if the remote server requires a client certificate. */ gboolean net_client_set_cert_from_pem(NetClient *client, const gchar *pem_data, GError **error); /** @brief Load a certificate and private key from a PEM file * * @param client network client * @param pem_path path name of the file containing the PEM certificate and private key * @param error filled with error information on error * @return TRUE is the certificate and private key were loaded, FALSE on error * * Load a client certificate and private key form the passed PEM file. If the private key is encrypted, the signal @ref cert-pass * is emitted. * * Use this function (or net_client_set_cert_from_pem()) if the remote server requires a client certificate. */ gboolean net_client_set_cert_from_file(NetClient *client, const gchar *pem_path, GError **error); /** @brief Start encryption * * @param client network client * @param error filled with error information on error * @return TRUE if the connection is now TLS encrypted, FALSE on error * * Try to negotiate TLS encryption. If the remote server presents an untrusted certificate, the signal @ref cert-check is emitted. */ gboolean net_client_start_tls(NetClient *client, GError **error); /** @brief Start compression * * @param client network client * @param error filled with error information on error * @return TRUE if the connection is now compressed, FALSE on error * * Enable deflate compression of the connection, as defined by e. g. RFC 4978 The IMAP COMPRESS Extension. */ gboolean net_client_start_compression(NetClient *client, GError **error); /** @brief Read a CRLF-terminated line from a network client * * @param client network client * @param recv_line filled with the response buffer on success, may be NULL to discard the line read * @param error filled with error information on error * @return TRUE is the read operation was successful, FALSE on error * * Read a CRLF-terminated line from the remote server and return it in the passed buffer. The terminating CRLF is always stripped. * * @note If supplied, the response buffer is never NULL on success. The caller must free the returned buffer when it is not needed * any more. */ gboolean net_client_read_line(NetClient *client, gchar **recv_line, GError **error); /** @brief Write data to a network client * * @param client network client * @param buffer data buffer * @param count number of bytes in the data buffer * @param error filled with error information on error * @return TRUE is the send operation was successful, FALSE on error * * Send the complete data buffer to the remote server. The caller must ensure that the allowed line length is not exceeded, and * that the lines are CRLF-terminated. */ gboolean net_client_write_buffer(NetClient *client, const gchar *buffer, gsize count, GError **error); /** @brief Write a line to a network client * * @param client network client * @param format printf-like format string * @param args argument list for the format * @param error filled with error information on error * @return TRUE is the send operation was successful, FALSE on error * * Format a line according to the passed arguments, append CRLF, and send it to the remote server. */ gboolean net_client_vwrite_line(NetClient *client, const gchar *format, va_list args, GError **error); /** @brief Write a line with a variable argument list to a network client * * @param client network client * @param format printf-like format string * @param error filled with error information on error * @param ... additional arguments according to the format string * @return TRUE is the send operation was successful, FALSE on error * * Format a line according to the passed arguments, append CRLF, and send it to the remote server. */ gboolean net_client_write_line(NetClient *client, const gchar *format, GError **error, ...) G_GNUC_PRINTF(2, 4); /** @brief Execute a command-response sequence with a network client * * @param client network client * @param response filled with the response buffer on success, may be NULL to discard the response * @param request_fmt printf-like request format string * @param error filled with error information on error * @param ... additional arguments according to the format string * @return TRUE is the operation was successful, FALSE on error * * This convenience function calls net_client_vwrite_line() to write a one-line command to the remote server, and then * net_client_read_line() to read the response. The terminating CRLF of the response is always stripped. * * @note The caller must free the returned buffer when it is not needed any more. */ gboolean net_client_execute(NetClient *client, gchar **response, const gchar *request_fmt, GError **error, ...) G_GNUC_PRINTF(3, 5); /** @brief Set the connection time-out * * @param client network client * @param timeout_secs time-out in seconds * @return TRUE on success, FALSE on error * * @note The default timeout is 180 seconds (3 minutes). */ gboolean net_client_set_timeout(NetClient *client, guint timeout_secs); /** @brief Get the socket * * @param client network client * @return the network client's socket on success, or NULL on error * * Gets the underlying GSocket object of the network client connection, e. g. for monitoring it via a GSource. */ GSocket *net_client_get_socket(NetClient *client); /** @brief Check for pending input data * * @param client network client * @return TRUE if data is available for reading * * Returns if data is ready for reading, because either the socket is ready, or there is still data in the buffering input stream. */ gboolean net_client_can_read(NetClient *client); /** * @mainpage * * This library provides an implementation of CRLF-terminated line-based client protocols built on top of GIO. It provides a base * module (see file net-client.h), containing the line-based IO methods, and on top of that SMTP (RFC 5321) and POP3 (RFC 1939) * client classes (see files net-client-smtp.h and net-client-pop.h, respectively). The file net-client-utils.h contains some * helper functions for authentication. * * The module net-client-siobuf.h implements some functions for replacing the @em siobuf in Balsa's libbalsa/imap module. * * \author Written by Albrecht Dreß mailto:albrecht.dress@arcor.de * \copyright Copyright © Albrecht Dreß 2017 - 2020
* This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as * published bythe Free Software Foundation, either version 2 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 General Public License for more details.
* You should have received a copy of the GNU General Public License along with this library. If not, see * https://www.gnu.org/licenses/. * * @file * * This module implements the base class for a simple network client communication on the basis of CRLF-terminated lines. * * @section signals Signals * * The following signals are implemented: * * - @anchor cert-pass cert-pass * @code gchar *cert_pass(NetClient *client, char *cert_subject, gpointer user_data) @endcode The client certificate used * for the connection has a password-protected key. The certificate subject is passed to the signal handler, which shall * return a newly allocated string containing the password. The string is wiped and freed when it is not needed any more. * - @anchor cert-check cert-check * @code gboolean check_cert(NetClient *client, GTlsCertificate *peer_cert, GTlsCertificateFlags errors, gpointer user_data) * @endcode The server certificate is not trusted. The received certificate and the errors which occurred during the check are * passed to the signal handler. The handler shall return TRUE to accept the certificate, or FALSE to reject it. * - @anchor auth auth * @code gchar **get_auth(NetClient *client, NetClientAuthMode mode, gpointer user_data) @endcode Authentication is required by * the remote server. The signal handler shall return a NULL-terminated array of strings, containing the user name in the first * and the password (mode @ref NET_CLIENT_AUTH_USER_PASS) in the second element. For @ref NET_CLIENT_AUTH_KERBEROS, no password * is required. In this case, the second element must be present in the reply, but it is ignored and should be NULL. The * strings are wiped and freed when they are not needed any more. */ G_END_DECLS #endif /* NET_CLIENT_H_ */ balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/test/000077500000000000000000000000001477646064400240555ustar00rootroot00000000000000balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/test/Makefile.am000066400000000000000000000022601477646064400261110ustar00rootroot00000000000000# $Id$ # Note: the following hack is needed so lcov recognises the paths of the sources... libsrcdir = $(shell echo $(abs_srcdir) | sed -e 's;/test$$;;') test_src = $(libsrcdir)/net-client.c $(libsrcdir)/net-client-pop.c $(libsrcdir)/net-client-siobuf.c \ $(libsrcdir)/net-client-smtp.c $(libsrcdir)/net-client-utils.c EXTRA_DIST = \ tests.c \ inetsim.conf \ ca_cert.pem \ cert.pem \ cert_u.pem \ meson.build \ valgrind.supp TESTFLAGS = -fprofile-arcs -ftest-coverage -g -Wno-error LCOVFLGS = --rc lcov_branch_coverage=1 GENHTMLFLGS = --function-coverage --branch-coverage --num-spaces 4 VALGRFLAGS = --tool=memcheck --log-file=$@.vg --suppressions=valgrind.supp --leak-check=full --track-fds=yes \ --child-silent-after-fork=yes CLEANFILES = *.gcda *.gcno *.covi *.vg tests clean-local: -rm -rf gcov tests: tests.c $(CC) $(LIBNETCLIENT_CFLAGS) $(CPPFLAGS) $(TESTFLAGS) -DG_LOG_DOMAIN=\"libnetclient\" -I. -I.. -I../.. $< $(test_src) -o $@ $(LIBNETCLIENT_LIBS) $(VALGRIND) $(VALGRFLAGS) ./$@ $(LCOV) $(LCOVFLGS) -c -b $(libsrcdir) -d $(abs_srcdir) --no-external -o $@.covi $(LCOV) $(LCOVFLGS) -r $@.covi '*/'$< -o $@.covi $(GENHTML) $(GENHTMLFLGS) -o gcov $@.covi balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/test/ca_cert.pem000066400000000000000000000101301477646064400261530ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIF1jCCA76gAwIBAgIRAPERRXhxJuhkl6ZG1ErW9YcwDQYJKoZIhvcNAQENBQAw dDETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixkARkWBnNpbXBsZTET MBEGA1UECgwKU2ltcGxlIEluYzEXMBUGA1UECwwOU2ltcGxlIFJvb3QgQ0ExFzAV BgNVBAMMDlNpbXBsZSBSb290IENBMB4XDTIwMDQxODE0Mzg1OFoXDTMwMDQxODE0 Mzg1OFowdDETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixkARkWBnNp bXBsZTETMBEGA1UECgwKU2ltcGxlIEluYzEXMBUGA1UECwwOU2ltcGxlIFJvb3Qg Q0ExFzAVBgNVBAMMDlNpbXBsZSBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOC Ag8AMIICCgKCAgEAriMQ2A1KWGJ4uIIgbuEAL0HccY26LmpRmmN/y2HZXks2i5ZC b50gPJyd71ueQdHwsjooFnEl+ZHoazsn6CEByUcTfGokekw59xveNZ8l5whdFuED Ww5dI9pXSNU0R1iUVDtEiuCXkauQ21cEDBlSaf09wMXHnpsApB9s1SVuzvWchYxm 0vYuUnPaY0CgdWYiF7g37lboNRIMF/OXhVbaZFMPCCpbHW9b5MnjTegtQDMEVip7 KYeR2KCQ2Di5tha+2H5j9+o0UAxRL9ZnUAl8Ek41gO6Xof3+aNHpOBTEoaKAKKAP tut9LCjfD46pYOWyADpImi26iFAtoFHrHSu2r5Qnmm+hb35ujLuDtCSDPosQ1FFT KtONIl2PpruL0qIhMJIe8sMu0mLTHVY4qPAchpA1JTokqyUlqMAJLsOdFFKmufRg 1I5NdDUZH5cafrl3PpwqHqw0AfC+ai6cAdGd4fkU0ImTSIhssCnecw7MGzbWK4Oo HEvJrXVvZZsNEf94RwvIl5r/86CQeDr/9s32U2tnWZNHVRfFSH98Vp5KD/ViKOu4 UBl/gfn3zAhLtUu3IW6s7fcVmd+SWfJ21MdAZwu8X/6WIQwbA2Djaaf0xlFVdLbE 4+TuV6Ug2HU/QHruipH5J7wGjFLDw5LxFI4D0tKNLifIJZMTGGqDntXPP+8CAwEA AaNjMGEwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FAFyfXr2c9uIJ0G3bklmVILWdxKoMB8GA1UdIwQYMBaAFAFyfXr2c9uIJ0G3bklm VILWdxKoMA0GCSqGSIb3DQEBDQUAA4ICAQCh+0aeLQZUJos86k00AdiQCr9y0NGX cDRbjt91mcYqbpL3FinpUqUzPU6fqdReOHcwRCMOoYu5Gwovx5l1UX/LjoZfz6Zv U99H6g9fad/JzYh1V5EHd5WE0xfD0YrA5ZDZhym3MXF2wPkM1Ga2Q2rY2yA92TKi l10X4O6VwU97yLA4Yb2hod406LuZl/JnnEf3hNSzD3z6PIcwU9CmOQjHQp5YcoIl Mlpp0IQkWMqslD+AIQL7kpFRZ6imEojN+CEeo5lhVOfkIQxH2YJuhHmbqgQTGknk NI2NX6un1ZSrNbD+uTgeQYJnDwb1GOO/oXn3D7lz5jh33qe6kFg6IbWv3hO+NHOJ YzfgONfF/AqG+jcwY+0UbsYtDRRbw0m6bVuHnwIbQJUfXbOIjdrADvDO/C078D20 7aMeRqNcas/uKe6hV0lSNpxuqXBxgqNxgpVeKHYV6uFimRqBCueNeklyntB4vG4F l41P+iTvhiSuzAMQ7u/BabHyMc/LIU41tR6I4Vn8JNYsSOhPx9iyX+YcOV/eXi0N L7LG8BN7+9vZfmBgkCtw7ksngrg4rexYe879WxamIsaTgioZY+Tao9GkNDCWcg5b se5I+FuJvauD8MNTIH6zvLMJH/5LDpkJ58pzjoWjauaftO+z8Zn2x56sb1oYnXKg RczkgYKIzmZd7Q== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF3zCCA8egAwIBAgIRAPERRXhxJuhkl6ZG1ErW9YgwDQYJKoZIhvcNAQENBQAw dDETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixkARkWBnNpbXBsZTET MBEGA1UECgwKU2ltcGxlIEluYzEXMBUGA1UECwwOU2ltcGxlIFJvb3QgQ0ExFzAV BgNVBAMMDlNpbXBsZSBSb290IENBMB4XDTIwMDQxODE0Mzg1OVoXDTMwMDQxODE0 Mzg1OVowejETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixkARkWBnNp bXBsZTETMBEGA1UECgwKU2ltcGxlIEluYzEaMBgGA1UECwwRU2ltcGxlIFNpZ25p bmcgQ0ExGjAYBgNVBAMMEVNpbXBsZSBTaWduaW5nIENBMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAx9Ml4WPP5OvG0slRXubd8MFMxqiIwcC1BTvjp0ab iAid5jSeVBj3BdF0s9RwnE4fUgQe6OKFSRhCn6Wrm+oSiGJutfmK9nVv1rCQ+oXl K4oEYVXvIiT4BfS1g29OAc3hHmP9XbePuKdFPpDrGgMHFqZ6bbCsGWdRNPnhfi7F DLSER64FmC8VrQ9Gm9w5Gem6JHS+xE/mJjGgQ1QyRbGph7ow/NeDFKxvMMr6l1vU UtpViKto4z3uO8ayJBDNgm3uTMkjB8VUF7fFCv6GswMHz3NbpvU5LinUs0f/oyRL 7yBfpUrDAwNYHjwlU+0YoRAVJ2XcuwmkNCSQqThOa7hkS0sCtDpHrUFnwvKl5QrY Sc/Asq4Zxoww7aq0PvDmVfCmQJKUKnPmbAgK1pt85XKFadk/GMxIiy6in4mdo1Eu kKd7AFfBZHDtlFKQkBTmtbEN/erAQhhikYccIjNxKMDbjuusaulaYwR+hN/wfpGa wEQiA18jGW/DTKPJdsfIReEq5xkKYJKJbTIAinB8MXb6m6Bc3CaExPqEkp2xfVVA Ek0YgasbGNB+x+MM6vLPG90L9rGmZOzWpzMcgUrUsEl/55X/fH9E2Y82H1k6bzxU 6KrADtU2yUfq7TRqJ6C4r+bY1JQ4hwr9PRgkm/Bw+abQbwRUnilR6o90Yazoy352 afsCAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAw HQYDVR0OBBYEFKvMpDnWZBecYHz+zSdMrbG5DxpzMB8GA1UdIwQYMBaAFAFyfXr2 c9uIJ0G3bklmVILWdxKoMA0GCSqGSIb3DQEBDQUAA4ICAQBttUtYlW3beg2nHnQl J+rjlNCfE33Un4aB94FvkymfDrymlYRbNn7MFpJGI8+y5r3ChY0ILUicBfK4WO9b QweOetRDAwMoVF+fWYXQlQ0AC+btgOl18Xw5xbUsBsE0xY4nL2uJYnVw09Rxk+NB HP3KbXhTz7WAZYBu7ziSapG+t4aSYT96uD9iS1bELaUUnhtDr2wAdSs+RCOrtU9B TrIue6wQOdEZkasRjFtIg608u6fJ+0ZiZyox098xOFtXrPyNYMj9L2sGpAgAvs6P uziykvp36t2uF5RyuFRnf8RUYZcAXHwyTfAhdEUDby52JvWb/V6RJskvCx8hgLbb yB5OtgkK17LHsKC0ehyFlQzgKk10J2EWAUDrp55xcyqQ7izf7GaJFqoPFuOoiwRk W5VwZm/XVPVpnHHUzZbhMddCVS+dWr43g6L9YVb9jXmh+jC7vnmeQdk9tCAVyhPl E/SACjcW8N1CpHolWZ/G486F0CP9zQ91XpSmt5gC4BrqJoNxbvDJ32cJ8mrEKcjr PK2yCVsvzBlm5j6UEMsHirS5Uj0o3v/th8kOawytNCICX0UFrs6pIb4/P7JhOFi1 +WeLKTlauQaJDhMWT0JSPVt38TybhFjfkZKh7wEDqEdQNlccaWKnml0bvNff6hPL wduu/4nH3sMBsLVBa9a0a0bGdw== -----END CERTIFICATE----- balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/test/cert.pem000066400000000000000000000126751477646064400255300ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIGAjCCA+qgAwIBAgIRAJ63DEJlfGhbawjxo9814DAwDQYJKoZIhvcNAQENBQAw ejETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixkARkWBnNpbXBsZTET MBEGA1UECgwKU2ltcGxlIEluYzEaMBgGA1UECwwRU2ltcGxlIFNpZ25pbmcgQ0Ex GjAYBgNVBAMMEVNpbXBsZSBTaWduaW5nIENBMB4XDTIwMDQxODE0MzkwMFoXDTMw MDQxODE0MzkwMFowaTETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixk ARkWBnNpbXBsZTETMBEGA1UECgwKU2ltcGxlIEluYzERMA8GA1UECwwITWFjaGlu ZXMxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAMRZZbveF7gYMYXHoJw2LIHS1oFaUyJDCjk6N2s5PhSd/Q4p5oPj28Ub JAFmI7lDU1qmkPnBXFEk7NRzxv+cnTry2QUdvRY5wHWGU4J2Wyh6EsbmAelEkNWM C9MWb7uUIiVFCaTgRktuhcqL6Z/BSCafnT2ZhKI8r/xZ5p8OeNhW+tEfa+0xreil 9om5cORpe9r1WNffyewEdzoDAuxw+ooeMrKfzJygVbkaOTc70162zuEigo+ymmOP aFAN6cxMY3jsQlFOvJP6H6AJ2dGFC0dMdPZFx4C9Zjz8dUX57KyZNNb9vp6lQqSc KxHSDX3S2Hm7JGj3iu2t/ti15GbSXsr20Btu09+UtLzWC7Rrlnf/IOEHEyG9LbHm KUGoyPyVGF91O/U0NlSuoHCkMpKzKbKf0BsPcAjyV0NF0R3K1Cmndx+zRxVF+C95 jLxqeCMaIjgja6YMC7Cm/z5S5cKixiohz61C0YrbFbTchUiYPWULKsgWB3h2avar AQn22uq09yj5qKpLoqfSsIkzp/P6d5AlcTB6o+xwejEkqm/Zz4X3+iwmAOan+OjS awUee01w+kwEVv2niYJLI/lFHZXxZoWpzKU67GockCj8jLfIq8f1iXu78xoKLsYI hCbQx7UwIpxbXd308if1oSKpuiU+1/B9XMVwtsyPpyyxoFofw3nJAgMBAAGjgZMw gZAwDgYDVR0PAQH/BAQDAgWgMAkGA1UdEwQCMAAwHQYDVR0lBBYwFAYIKwYBBQUH AwEGCCsGAQUFBwMCMB0GA1UdDgQWBBQee/Yt/UxFVtCWazKdKWkvLpYr6zAfBgNV HSMEGDAWgBSrzKQ51mQXnGB8/s0nTK2xuQ8aczAUBgNVHREEDTALgglsb2NhbGhv c3QwDQYJKoZIhvcNAQENBQADggIBADexvHAZWppOTnG9wbnJ9DmcHtbNOBGmxeKi EJAYtXsvOOkvLAQl/5Q6nVCeinUpGoK1uLFfu9o/gubfRZUV3ytEzoXwggOhGqRM Se/LjjbYqTAr/G73yCtDU+jSuNkqTOYjV0NWN53F5YBJDDAORCNS5Uw1flL9v5kz G2a1HPavz0L+vAcF9vpzES4Em2LgnU5eN4nvazmGwFlAhxb5uvPInyCdP0sSNJ/f 9bXxajO+jNpd7ngpNIY3yYSe8fgVcQFw/G22V5it7U/N42jQ9Y5nVITlU1RrDS/R 4FLSH+Fvz6BTtTlCL2bgwKJAuTkwy48J8voNAeYytXWED75p47n9BULSF+tDvEdN FQnH72Ibbsh+p0Pz8gS4bMmrvXzp4+11SuZCvh6u+vuxc3YPAbHCeJ+z823MFz9r wpKascnjr6NeUGFlDbfvzqDpWHg8tfPz4KAC5tWlrMOs+1KbVMv+vc+wd4In+Eyj MbxLNqX5WxP7d0ltuKbs68YDMRcIale62/Z0J3Muwc1k+WaW2f4eMDOZFDkMg8mB 3wJo59gBpBmMzeVa4gwrllZglPwaC4H/UMw2ZZwcnHh+bYWpXHI6e5v9btnWEhdG Ea515g73j1bBMJYlpDurWumSb2B8lgCn1CYOYmLyQEr8TfK/R0RfOHsPEXLdwnLu Ync/p4RR -----END CERTIFICATE----- -----BEGIN ENCRYPTED PRIVATE KEY----- MIIJpDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI4nD0jntIbK4CAggA MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECKKIAsxfJvwKBIIJUHLYr0rKK3JL YcWLo7d8MXzF6HiIewpS9KgwYBsOeGH4McEHBR0VcCc4fi2RQ5zMM6RkCyEZ2UCR GK6XG2+mGAxlyV/slx9mX7Z2ey/xXhIIiFTXmwCQOB+BU6HiPT4adEPmLPns4Eym z5oXA/1zw/qlRWxfoflmmX3m+5U+q4Id3MJFIg9saNvmnLHUp6Ur15yYjh8cqLdo zdFGJdbPWAcI+xSOP0nIKo4V/V6ek2Rcw+HYTCFBkcM/dQPlxUdJLgyoYd/DmEVc pycCdnwF004K10pGmRUqFVYuwX4HF28+iwW4s8toS5Iy6TZQZW2m999PEIu91sSr im5VStVZ6SoaRDMRuXwp3/6r0AywU/4y0ckk9bq4wcg24dfqGB7EyIUGwj5m5rN6 jDpEzfTzI3ZV/r5nAG/uZPdtlbPwTZo+keoNiy4lR8pCwm9E8yMuDuSM0+lNgj9O TvMQy56Qg4bfw/fI7JEFu7/LwQC5bkPzf7OayLbRN0DLXmc0qtOs64NqTMOZ33w6 6OJN/n7kZ5tJotKxPKWfsz+DAtDtjsvyEhZnOyOVJW+TQxbsUFB3bodeurooOItr AE1kJjiXicffgM2iPOfS6oRQ9yclqNs7/QP2eZ171oVvSCL+Ta4dRgRDcaHUUg78 BU9t92vOy3KdNMvuuWfOhzL0mn8cQNjouJ2kJ0d2Wpayw5UwY/kN5xQnrmDgpjoV xNZZebyjf3Oc4sYs9gJ3hW0Utc0ODxFZOFXI1xczFW6psjfxeAlUF7xpoUxbDp5Q erdlowJBjrto4v44pBsRfJjGY0TdX1t6fLhEXsCE7qQCr838+81kNfmA6r/ckoqw 5mszT3WjLbFU2tczEjKZt+BsZSf7XZSj4ODxe/J/H26cOevhD9e9vOhGxGWiZYgG rGYEMErI196yAZQ4Xsmi8iT10Uc9RQFXUvknV3aAZx7k5EQT/n5rnqXgNYuU3ZRn ulIaQxhqo4D5aQ++XSupYLeO6+HC/5dWAEp8RsrBqXl++usHznxTjWJPaqxJCJ4+ XTrimvZlF4Z9yb1NREUS+IOweLCaQKdGNpvV0YYsBtS26bMMKuroizxMSccOfgOK c8HhzZsQKQcB4R0Y4GTbyjzxKcjlFSm2gRkqLj8uTnxGSh8KnndseQMCxpI2c62Q rF9EUkt1E7Z+v33cCcTfOegz5Te6kAnL5n7wr7CGGAFn5rR5JZm9KY1aLCcIWFNE 3X18B5UrGJO8D8udydtJtraJlM7elOhTkpgbA7O/OgRn/jshPBwZAFkfNwURJ0BV YXgxcT0gQqPTLU6X/DP8yw/4buu5FSQK2WYCZ5jgx8gOiUwn/0QWJCFQsaK5VkdB wKeZKWrqL1mVsoomD0Ixp6SYqOqem8RUBWwFHOggkcLNiAlSLS/KajuVapNgF4DZ HW5UlKgM26Cy6hVVU3xsKmIEEQ1zhcRepZSHQJ+P1nHZqK0WVVxBAgnKi6UsJYdz utXGpSFVTMLCuhtRYFaPobXJrnY4FnDzYzeFYZQItav4ED+/lZ4ZI+91rL5BhR/O PrP6NcjP6nKFfo4aIsYvZhLrWo6r8YKpjAdeev8ufVjYs4IGp1SdFe8AKtD/0c3e LiqYRAqRDUQpTdkfHFyKFLOwUp8CfE8E1Fm/lztGVOBAbzH35eOvf7/V3vD1W34h 9xzowBlCeTv5/jdoWKc9TBuqOS5R/4qD42C0p6Q/oefvyXYCq6iPR9svLljt2sTc z5ui0igOGNxq6j8Mkp5fdWND2wi1YqcqXQEyObQ3v8vweQO4EKPPqAuMnardSpx1 kxOyfc+zk0CBevWmesWixoSFmw/aIE+qdFX6JqIMNCa95Lq3Ywg77rqn9bbCrZMH pdCM62ybZ850nSxOSCULguKQmSE6HR/+dQG0Hi6dk2ZRxCaYjcCxnJVUeugkGIIj L55W1YndWcjrNuALxURoJNzK7kFBQb/BwpfZ8xR/TXLPDgW3gLIO9nbLjkrwnrNc LOMLMvVgqo/U7Nyn9vV/xE6d27lBEJ43ieIywApVcyhUIzVagN2xVdJ8cNWwSbOM vyspSuYtUmptuoti5IOBUd5nmGurLIIzVBTZS6jCUvlQhg76NCE38YQ7Vu43k85X 82yezYZWrbwQVvEjOjr8Hka+QUVfvHQTSKXsq4rtensn31RbXaI4Fqe/GzQC4aoH ZYGF/VV+TfRASOp5rEgPkHznFzrqaRbxkLWRfEDpQJzH6hs3nYUUx95WbjvlTWJC 7M6lIBVLyZDyX53dcjA8MmrkZKpt9tiYOZ5pKgVXklKc78pfVnsXQc+ZeJVx/owg Kf26vfyl0T6xLgyR9dEhKSwUwBpVHi/K2XE10+ueuaCfcFqEB4GnXd3Iccvps//m 3zYN+GkFYz01G/EOaKb/Ajz45lWDR2YDesmpxqpJUqAaTmtzfF9VAFZT0AshYpI2 Uksoj7hCVzLesj8lUsq4OSjtPeDs3TkLw1R4ZJAHs6S1VQHF8mY7Po7Al4bz3yhM TXPhPR/okI4lzsakdc36WWkMRhjB8jyoTHLoEokWMrypMBAGcyOJg9awsV+uiHqe Zo18Qo6P1yLHXdS9GMsfyvedKJmIu2kbPUIgBpElVGJyUrNl4Hotth44WYNGPP3P H8LqrxUqrHh9XQMYllB58aCW859tVmH95vdqZV39ENE2tYm6Bsh3A3CIPYB7MnB/ ssS6gjMRrpH2p4GHYLxcyVFq9HvA891GPBo3g1l6DlRxVa14zOO0WUZ7pqklbxt3 pmj4f+v0y0LL46kV5yd0skmX+xsXt2ypm7dI+l7m9cKafAAk95ZPpr3LeCUFrpxv SqjrXN6puHtozImuDjp8XE7jS8u6lBQ34wYZM2RwhoLkpKV21tL9K2Ycd+Or4sHU 3VtHaYM4Vz94MsfOnb5EPasgOtj/MmhZetaHQ2yPlf869HxoE/ekssRSxrK0vJ8v F9kBpMGO/ZMWr2Nj3BtyPR8q0nbKY7lsGB+ktzLFk73BIQ994bH4iRLzC9pP6myL 5RQqkzn6/2oYB7SLt94dO3ulih4ml0q5thG8ZRdRzKYYxfDEwLun60eq4keiHpsc CWh1rELVshn3QmkmfFZojlINgUOQ8gDAACCQCOYDegYViWaiqzuFc73s2yNxYaoP xAhfPXm/AR++DSgVFD4Vum7LGB1UT/AT -----END ENCRYPTED PRIVATE KEY----- balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/test/cert_u.pem000066400000000000000000000124471477646064400260510ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIGAjCCA+qgAwIBAgIRAJ63DEJlfGhbawjxo9814DEwDQYJKoZIhvcNAQENBQAw ejETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixkARkWBnNpbXBsZTET MBEGA1UECgwKU2ltcGxlIEluYzEaMBgGA1UECwwRU2ltcGxlIFNpZ25pbmcgQ0Ex GjAYBgNVBAMMEVNpbXBsZSBTaWduaW5nIENBMB4XDTIwMDQxODE0MzkwMFoXDTMw MDQxODE0MzkwMFowaTETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixk ARkWBnNpbXBsZTETMBEGA1UECgwKU2ltcGxlIEluYzERMA8GA1UECwwITWFjaGlu ZXMxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAOFx11lLH3LfT7k5ePy1e9nKVGmZyguGJogXtU4fxBTFM4BOOHXTSYXl ZHGUIuWYwnKbUbzQ5IYpEhpnihxgC3JoU5ettmtt3qsM20dL7V4tB/8x7e868FOC 1iGX9aP+uEN4GSP1B9q9oiO/XCakkk2mb8esxpAXm0lGi8i4ezxFIrA7lAg8oXKn dmofqvfnDLB2iHEbgQfsZFZrwIu3Owvr4vw5hHQZ4ldpKec/ZQ+duCEHldr7I8qT v/FHicQATeXbSQGWYUQz+zj5/ngABDOtuABQnsaCa0h+gwJcNicTAyX06ZmF+X9Y 4C7SfbSK7MXgtmhaKWhZ9S7Frn2Kb2gGrlB9TuTef+yCa3bfsTqWUTOUt34Ey5Mk O5CX/M2aYGEQYlfRJm4/Bb400hA8xLYGQnzoCh5GAyCe40MC6P1U1wJsvKgogE6q EeKoBKCUAZVVT6Ka/6wcB4w6FGJdIwBEx7CRGEATTrzPW46Ij98onkSNUwpiWhyy w/ZUPYyTZTIFlwTX0IiGlk4u6avBesL3zB6n0BkD5pZIIinqHIpNTSc1lTb8OtX0 4/htWwIHPQnCa2zsPaBzxdD/6D3dhF+D6lN6f04o8rinr6UQv5VAc6XtSiCPUvvB saybngAgkIe4Y2eI2NZkRoMCdPGTmAgo3WGJoKmsD93UCrr3DQ9xAgMBAAGjgZMw gZAwDgYDVR0PAQH/BAQDAgWgMAkGA1UdEwQCMAAwHQYDVR0lBBYwFAYIKwYBBQUH AwEGCCsGAQUFBwMCMB0GA1UdDgQWBBSRHd2RP8lMJZRdqY7fS4UymGSVZjAfBgNV HSMEGDAWgBSrzKQ51mQXnGB8/s0nTK2xuQ8aczAUBgNVHREEDTALgglsb2NhbGhv c3QwDQYJKoZIhvcNAQENBQADggIBABrh0+fYx9hNavwyI0kVePK+PelzxXuZoU/R KGxBcrFa4tlnNQD9sLcsFnX6ylBgylOWNOD0JU99mxwB6xy7hiAYf3qQn4eauTFP 0IiwopRAw5VculUjWNH84uYG7RpFPBy1NtbHz4jT4Ug+vVoPdG71/CMCs+YQqjlS IEaoJuqS3Rg9ClXP1KjYHHS70+VDAD7LuVRZTwrp39Ilg9HVqVN/pz3/r8u0E/XS EWJNL+7DjQmussBobKuOUebtuxACYpPYHFjOYQy3eX6BBi+P7frGHrxt2OLpTlO9 aVfBFfsfNcOWP/ssDakREhrj5EmfQejm3HZABxjiQiEUgIekpzzgUf/zzD0Tas3Y inzvKFlKivne5H3CDwHtpZSH2yXRooX7uFJbxgctcISVJxp624nuKudzlYXqffPG U/uGY9DCPjSIjRHUgOA6nEr2Ysp6J2lziuUpj1GI00G4bPB1wzg2LEy8g8JNaCsw xzbkK43avMcUnr5VZ3lSGPXoIdJwEnKsl6sicBXoWQY2LFnaw0aSTRJDKimJcafR n+MKzq8Cl4wKIZ3jF6vlSqisALjMIHQHQud3fQMo0dU3omf/zf2h7fDmPZn+pz98 YwCor7+3PnG12W8qLEPM5npRhyL9m+xptuK7hW8TCrSxHGVRf0YsxF2jsJBL70Md LvplZxn5 -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDhcddZSx9y30+5 OXj8tXvZylRpmcoLhiaIF7VOH8QUxTOATjh100mF5WRxlCLlmMJym1G80OSGKRIa Z4ocYAtyaFOXrbZrbd6rDNtHS+1eLQf/Me3vOvBTgtYhl/Wj/rhDeBkj9QfavaIj v1wmpJJNpm/HrMaQF5tJRovIuHs8RSKwO5QIPKFyp3ZqH6r35wywdohxG4EH7GRW a8CLtzsL6+L8OYR0GeJXaSnnP2UPnbghB5Xa+yPKk7/xR4nEAE3l20kBlmFEM/s4 +f54AAQzrbgAUJ7GgmtIfoMCXDYnEwMl9OmZhfl/WOAu0n20iuzF4LZoWiloWfUu xa59im9oBq5QfU7k3n/sgmt237E6llEzlLd+BMuTJDuQl/zNmmBhEGJX0SZuPwW+ NNIQPMS2BkJ86AoeRgMgnuNDAuj9VNcCbLyoKIBOqhHiqASglAGVVU+imv+sHAeM OhRiXSMARMewkRhAE068z1uOiI/fKJ5EjVMKYlocssP2VD2Mk2UyBZcE19CIhpZO LumrwXrC98wep9AZA+aWSCIp6hyKTU0nNZU2/DrV9OP4bVsCBz0Jwmts7D2gc8XQ /+g93YRfg+pTen9OKPK4p6+lEL+VQHOl7Uogj1L7wbGsm54AIJCHuGNniNjWZEaD AnTxk5gIKN1hiaCprA/d1Aq69w0PcQIDAQABAoICAQDeuwYzZhDQAOhW6v0pTnPq HAeBvTrsX8E5u5KYeLHUg2/6V01Yu0JsUtIFlIFVrLKPX/xFO2xLT9Be3eSJXCpz Abd0p18OjCHthGov6ke9P2gjLEUSkXxWRXEhB2zcdQ+/OKw95hu4dJn4D1sPopAY v1K4R251dZ0pq9T2nazDQtqemn4KFTy8dc570oWrHk5fGPx8Itw748TNzO8SGhjw EkDTSFAgFGKWUYPgv7Us1HnRyBi5nF0kCw0bZ74oMtTDPv7F3riCFYkiJXrPO9Tq 6bpcNUpofPlZSgRNFKU7vYDiwzD3SHHS6w+xsqwW7xo19WjBeDJosleVuiBGT7r3 hMqOh3azQmfSo6ugl9z4tBI6zSsr1kNPlrGjimdYjhPBQMuj1laroFPw3RFkq9dQ dpIh1VzJ5fARGQj1tI8Hw28q+Jx+C9jV0IuBCqXC/+4mpxTlM5NdNf9MiUOLqkQd b/OAxJMvEELeFFMtg66iGyC4wQocm46CWxpNWziKRJ6H6zYNt2p2hXl4o7smsJ4E QxlMrXwOZbK29z9hDOV3p+3bK1Utau16ghIRbJWpZqeuz+xd1lS0iow63hM7Ed5c VxkNxuGELU+Boqi+EcRPfzfXookSRvYnCqt9rrdBgt76nV+PzL6mZJ4g2lrtFS2j nnu6UZI0u59M9+lAgosTQQKCAQEA8nu6t5iKG37SM0Dp44/wV/nESPbl51ccomQj dqzlAEKXNcl5GVIRnJPTGxsc954HO6CYn4fZxw1CbGondfdXYAkq6PJeMOVT1uLa L26irwtibnXYKDBhpzCtAUJD5y2IhVFdS46k0XKkDCdC2HUOvtuEynvf9u3DqnE8 a96YessUB0nrItb8r94W/nWILLbqGb6ElipMsYngWmkIXvkJjAJbUzo+e3g3AkWG xSx0y7A5AxUbvqqfT8rlpFgKD2TyHyacKAKJxhZL5zpmmh+AdPTnpSR6HKZUV/aI 34KymNPGYv0JnD8AaJ0Y0oE/eg8TjbXYkidpz9+vlokQOUYrtQKCAQEA7gL34a86 GVvUiOX9r4v+Hvv66h4W5kd6Lyet7LcfWTWwFr0Zmx13ssCL78ec0c+qo/hJ0Y17 wldPGOROySIvCEbZlmQUs03bxjnUHUYeY0nl9MUWcD7VAfS8nbyrgk+10nfjXP3Z bclgzcOKx3KElpnySJgCXnlfNbnSy3QLh5LnQA2FEfuoZrNqTJLn3S4K3tqBAbgI kg+sIZp65ehiOeya2j2lfSCKnHix93uQTKxwn9o5cdKJ1XyI6j1HaV/hlPKi35vd C/ExvKMa5qaHYKqSVoEjPsh/HNv8fRhoZEsqM9jpVWoDpPH4DCGoIsKhVrmNoIUR 8QRCdITH58CCTQKCAQEA6ESMfgCnid7ZCi9L2qat2hdtZVbasdZHn2W8cpj6Yl1m 6iaq0Q5DwG/47yXxgV7mHr+ecnF2sayJy7+DPQRHtb4SVECU6NFClbuGs5iOTI3j I1vOSfDOGZAOp/4JfQ+ojct6Sj3Asr/VU67n4N9/2GH9uNcfmS/3FPSSo+D8veJ4 tOKhUSYNtYhPDj8WyX4Mj8xmxFCQVh9zwCaL1i1Gb85yHC7WWv6z8oEWrxf+aH3M np9BjElzgMMhZWLPgB95rU0Wl1yXDB+fZUYTsd4q9d0BZraiIX9Rm1CTm0VePfXd OkSXSAsxIQQaGsmjPA/k8wEVCiqmuG/TiaaQ28vTYQKCAQAuuNRyMBSmn7kz+nn3 OPL0oCBcTvXN1KAum4pv2m7D818Sx6I8KeeyZkvSEQw+v5ZOw9Gx2iU+PCdhyoeQ wi4bYNUbyZ+qpxEKc5Wo/Xe/o+UJTJsgA6WK0cEo8b11QjJ+E1zFh2tkOtDO86DN kDRo3+WIzJZCd27yO/0eRTRyM6tDjqPdqNog9v1Z9MihSYWGw7vpW3gLPBpdKlcP xLNrjX/Eca+HxZiQKL0+yLnF41/kcVEvf9Xg26aA3PCkxdahh5Pjc1RMINfToO0J 9AzFNBav9n+1tmQFhUWmROFRNtQdA2qigsIeYgWAVCcOU8iaHqinpxejiWOGPf6E Bu1NAoIBABTv/aN5PCq6wo+qvCo3Uue/aDQzvBAFPWrOvFB/QWD7xilNC1IEz9XI xjCo1fqWkgQI705QZdHBfQjMaI0pfUccG9oylJUgCz7RyQzDpeXHnYSocABM1ml+ xzaCFIr2yrZekriMp2WvK4q+bbF2gF6zD1p0IEexrOi0b2gRDh7wXRaTM0/JEYwG teMN05O0kwyOphLpQqUoJAwlxiNWuwvlTl6FYYNBMS5jlEz5y5hB86uuffUe1Y4H tnRWi8Q2dHD8zNDsTsy4+BYxRA3IE6997hofdPGVZ2UHdaIIPa3ckNpKXVmh5lSB BrXwsXY2ZPcP/iq/zC2yMQqnTkK748U= -----END PRIVATE KEY----- balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/test/echoserver.py000077500000000000000000000043161477646064400266030ustar00rootroot00000000000000#!/usr/bin/env python2 # -*- coding: utf-8 -*- # $Id$ # # Echo server listening at port 65000, with the following non-standard # features: # - any 'x' in the received string is replaced by 'ThisIsLong' # - 'COMPRESS' in the received string causes the connection to be switched # to deflate compression # - 'DISCONNECT' in the received string causes the connection to be closed # # Copyright (C) Albrecht Dreß 2017 - 2020 # # This script 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 of the License, or (at your option) # any later version. # # This script is distributed in the hope that 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 script. If not, see . import sys import socket import zlib sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = ('localhost', 65000) sock.bind(server_address) sock.listen(1) while True: connection, client_address = sock.accept() try: comp = False comp_ctx = zlib.compressobj(-1, zlib.DEFLATED, -15) decomp_ctx = zlib.decompressobj(-15) while True: if comp: data = decomp_ctx.decompress(connection.recv(2048)) else: data = connection.recv(2048) if data: print "received: {}".format(data.strip()) if 'DISCONNECT' in data: break data = data.replace('x', 'ThisIsLong') if comp: connection.sendall(comp_ctx.compress(data) + comp_ctx.flush(zlib.Z_FULL_FLUSH)) else: connection.sendall(data) if data.startswith('COMPRESS'): print "compression enabled" comp = True else: break finally: connection.close() balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/test/inetsim-1.2.6-POP3.diff000066400000000000000000000032751477646064400275470ustar00rootroot00000000000000--- inetsim-1.2.6-orig/lib/INetSim/POP3.pm 2016-08-29 09:43:28.000000000 +0200 +++ inetsim-1.2.6/lib/INetSim/POP3.pm 2017-03-20 18:47:24.082678213 +0100 @@ -32,7 +32,7 @@ "SASL" => 2, # RFC 2449, 1734, 5034, 2195 ... (http://www.iana.org/assignments/sasl-mechanisms) "RESP-CODES" => 1, # RFC 2449 "LOGIN-DELAY" => 2, # RFC 2449 - "PIPELINING" => 0, # RFC 2449 + "PIPELINING" => 1, # RFC 2449 "EXPIRE" => 2, # RFC 2449 "UIDL" => 1, # RFC 1939, 2449 "IMPLEMENTATION" => 2, # RFC 2449 @@ -292,6 +292,11 @@ $line =~ s/[\r\n\s\t]+$//g; alarm($self->{timeout}); $self->slog_("recv: $line"); + ### flush input buffer if pipelining is disabled + if (!defined $POP3_CAPA{PIPELINING}) { + + ### FIXME - flush any pending input here + } ### Auth via USER/PASS if ($line =~ /^USER(|([\s]+)(.*))$/i && defined $POP3_CAPA{USER}) { $self->USER($3); @@ -1038,9 +1043,11 @@ my ($flag, $hash, $uid, $size, $header, $body) = $self->read_mail($args); if (defined $flag && $flag) { $self->send_("+OK", "Message follows ($size octets)"); + # quote termination octet (RFC 1939, Sect. 3) + $body =~ s/\r\n\./\r\n../g; print $client "$header\r\n$body"; $self->slog_("send: <(MESSAGE)>"); - print $client "\r\n.\r\n"; + print $client ".\r\n"; $self->slog_("send: ."); $status{retrieved}++; } @@ -1300,8 +1307,6 @@ # convert LF to CR/LF $msg =~ s/\r\n/\n/g; $msg =~ s/\n/\r\n/g; - # quote 'CR+LF+.+CR+LF' - $msg =~ s/\r\n\.\r\n/\r\n\.\.\r\n/g; # split header & body $msg =~ s/(\r\n){2,}/\|/; ($header, $body) = split(/\|/, $msg, 2); balsa-2.6.5-a9ac73e6ca01c0eb97d22912eb8f026cb6f71f47/libnetclient/test/inetsim.conf000066400000000000000000001172501477646064400264020ustar00rootroot00000000000000############################################################# # # INetSim configuration file # ############################################################# ############################################################# # Main configuration ############################################################# ######################################### # start_service # # The services to start # # Syntax: start_service # # Default: none # # Available service names are: # dns, http, smtp, pop3, tftp, ftp, ntp, time_tcp, # time_udp, daytime_tcp, daytime_udp, echo_tcp, # echo_udp, discard_tcp, discard_udp, quotd_tcp, # quotd_udp, chargen_tcp, chargen_udp, finger, # ident, syslog, dummy_tcp, dummy_udp, smtps, pop3s, # ftps, irc, https # # start_service dns # start_service http # start_service https start_service smtp start_service smtps start_service pop3 start_service pop3s # start_service ftp # start_service ftps # start_service tftp # start_service irc # start_service ntp # start_service finger # start_service ident # start_service syslog # start_service time_tcp # start_service time_udp # start_service daytime_tcp # start_service daytime_udp # start_service echo_tcp # start_service echo_udp # start_service discard_tcp # start_service discard_udp # start_service quotd_tcp # start_service quotd_udp # start_service chargen_tcp # start_service chargen_udp # start_service dummy_tcp # start_service dummy_udp ######################################### # service_bind_address # # IP address to bind services to # # Syntax: service_bind_address # # Default: 127.0.0.1 # #service_bind_address 10.10.10.1 ######################################### # service_run_as_user # # User to run services # # Syntax: service_run_as_user # # Default: inetsim # #service_run_as_user nobody ######################################### # service_max_childs # # Maximum number of child processes (parallel connections) # for each service # # Syntax: service_max_childs [1..30] # # Default: 10 # #service_max_childs 15 ######################################### # service_timeout # # If a client does not send any data for the number of seconds # given here, the corresponding connection will be closed. # # Syntax: service_timeout [1..600] # # Default: 120 # #service_timeout 60 ######################################### # create_reports # # Create report with a summary of connections # for the session on shutdown # # Syntax: create_reports [yes|no] # # Default: yes # #create_reports no ######################################### # report_language # # Set language for reports # Note: Currently only languages 'en' and 'de' are supported # # Syntax: report_language # # Default: en # #report_language de ############################################################# # Faketime ############################################################# ######################################### # faketime_init_delta # # Initial number of seconds (positive or negative) # relative to current date/time for fake time used by all services # # Syntax: faketime_init_delta # # Default: 0 (use current date/time) # #faketime_init_delta 1000 ######################################### # faketime_auto_delay # # Number of seconds to wait before incrementing fake time # by value specified with 'faketime_auto_increment'. # Setting to '0' disables this option. # # Syntax: faketime_auto_delay [0..86400] # # Default: 0 (disabled) # #faketime_auto_delay 1000 ######################################### # faketime_auto_increment # # Number of seconds by which fake time is incremented at # regular intervals specified by 'faketime_auto_delay'. # This option only takes effect if 'faketime_auto_delay' # is enabled (not set to '0'). # # Syntax: faketime_auto_increment [-31536000..31536000] # # Default: 3600 # #faketime_auto_increment 86400 ############################################################# # Service DNS ############################################################# ######################################### # dns_bind_port # # Port number to bind DNS service to # # Syntax: dns_bind_port # # Default: 53 # #dns_bind_port 53 ######################################### # dns_default_ip # # Default IP address to return with DNS replies # # Syntax: dns_default_ip # # Default: 127.0.0.1 # #dns_default_ip 10.10.10.1 ######################################### # dns_default_hostname # # Default hostname to return with DNS replies # # Syntax: dns_default_hostname # # Default: www # #dns_default_hostname somehost ######################################### # dns_default_domainname # # Default domain name to return with DNS replies # # Syntax: dns_default_domainname # # Default: inetsim.org # #dns_default_domainname some.domain ######################################### # dns_static # # Static mappings for DNS # # Syntax: dns_static # # Default: none # #dns_static www.foo.com 10.10.10.10 #dns_static ns1.foo.com 10.70.50.30 #dns_static ftp.bar.net 10.10.20.30 ######################################### # dns_version # # DNS version # # Syntax: dns_version # # Default: "INetSim DNS Server" # #dns_version "9.2.4" ############################################################# # Service HTTP ############################################################# ######################################### # http_bind_port # # Port number to bind HTTP service to # # Syntax: http_bind_port # # Default: 80 # #http_bind_port 80 ######################################### # http_version # # Version string to return in HTTP replies # # Syntax: http_version # # Default: "INetSim HTTP server" # #http_version "Microsoft-IIS/4.0" ######################################### # http_fakemode # # Turn HTTP fake mode on or off # # Syntax: http_fakemode [yes|no] # # Default: yes # #http_fakemode no ######################################### # http_fakefile # # Fake files returned in fake mode based on the file extension # in the HTTP request. # The fake files must be placed in /http/fakefiles # # Syntax: http_fakefile # # Default: none # http_fakefile txt sample.txt text/plain http_fakefile htm sample.html text/html http_fakefile html sample.html text/html http_fakefile php sample.html text/html http_fakefile gif sample.gif image/gif http_fakefile jpg sample.jpg image/jpeg http_fakefile jpeg sample.jpg image/jpeg http_fakefile png sample.png image/png http_fakefile bmp sample.bmp image/x-ms-bmp http_fakefile ico favicon.ico image/x-icon http_fakefile exe sample_gui.exe x-msdos-program http_fakefile com sample_gui.exe x-msdos-program ######################################### # http_default_fakefile # # The default fake file returned in fake mode if the file extension # in the HTTP request does not match any of the extensions # defined above. # # The default fake file must be placed in /http/fakefiles # # Syntax: http_default_fakefile # # Default: none # http_default_fakefile sample.html text/html ######################################### # http_static_fakefile # # Fake files returned in fake mode based on static path. # The fake files must be placed in /http/fakefiles # # Syntax: http_static_fakefile # # Default: none # #http_static_fakefile /path/ sample_gui.exe x-msdos-program #http_static_fakefile /path/to/file.exe sample_gui.exe x-msdos-program ############################################################# # Service HTTPS ############################################################# ######################################### # https_bind_port # # Port number to bind HTTPS service to # # Syntax: https_bind_port # # Default: 443 # #https_bind_port 443 ######################################### # https_version # # Version string to return in HTTPS replies # # Syntax: https_version # # Default: "INetSim HTTPs server" # #https_version "Microsoft-IIS/4.0" ######################################### # https_fakemode # # Turn HTTPS fake mode on or off # # Syntax: https_fakemode [yes|no] # # Default: yes # #https_fakemode no ######################################### # https_fakefile # # Fake files returned in fake mode based on the file extension # in the HTTPS request. # The fake files must be placed in /http/fakefiles # # Syntax: https_fakefile # # Default: none # https_fakefile txt sample.txt text/plain https_fakefile htm sample.html text/html https_fakefile html sample.html text/html https_fakefile php sample.html text/html https_fakefile gif sample.gif image/gif https_fakefile jpg sample.jpg image/jpeg https_fakefile jpeg sample.jpg image/jpeg https_fakefile png sample.png image/png https_fakefile bmp sample.bmp image/x-ms-bmp https_fakefile ico favicon.ico image/x-icon https_fakefile exe sample_gui.exe x-msdos-program https_fakefile com sample_gui.exe x-msdos-program ######################################### # https_default_fakefile # # The default fake file returned in fake mode if the file extension # in the HTTPS request does not match any of the extensions # defined above. # # The default fake file must be placed in /http/fakefiles # # Syntax: https_default_fakefile # # Default: none # https_default_fakefile sample.html text/html ######################################### # https_static_fakefile # # Fake files returned in fake mode based on static path. # The fake files must be placed in /http/fakefiles # # Syntax: https_static_fakefile # # Default: none # #https_static_fakefile /path/ sample_gui.exe x-msdos-program #https_static_fakefile /path/to/file.exe sample_gui.exe x-msdos-program ######################################### # https_ssl_keyfile # # Name of the SSL private key PEM file. # The key MUST NOT be encrypted! # # The file must be placed in /certs/ # # Syntax: https_ssl_keyfile # # Default: default_key.pem # #https_ssl_keyfile https_key.pem ######################################### # https_ssl_certfile # # Name of the SSL certificate file. # # The file must be placed in /certs/ # # Syntax: https_ssl_certfile # # Default: default_cert.pem # #https_ssl_certfile https_cert.pem ######################################### # https_ssl_dhfile # # Name of the Diffie-Hellman parameter PEM file. # # The file must be placed in /certs/ # # Syntax: https_ssl_dhfile # # Default: none # #https_ssl_dhfile https_dh1024.pem ############################################################# # Service SMTP ############################################################# ######################################### # smtp_bind_port # # Port number to bind SMTP service to # # Syntax: smtp_bind_port # # Default: 25 # smtp_bind_port 65025 ######################################### # smtp_fqdn_hostname # # The FQDN hostname used for SMTP # # Syntax: smtp_fqdn_hostname # # Default: mail.inetsim.org # #smtp_fqdn_hostname foo.bar.org ######################################### # smtp_banner # # The banner string used in SMTP greeting message # # Syntax: smtp_banner # # Default: "INetSim Mail Service ready." # #smtp_banner "SMTP Mailer ready." ######################################### # smtp_helo_required # # Client has to send HELO/EHLO before any other command # # Syntax: smtp_helo_required [yes|no] # # Default: no # smtp_helo_required yes ######################################### # smtp_extended_smtp # # Turn support for extended smtp (ESMTP) on or off # # Syntax: smtp_extended_smtp [yes|no] # # Default: yes # #smtp_extended_smtp no ######################################### # smtp_service_extension # # SMTP service extensions offered to client. # For more information, see # # # Syntax: smtp_service_extension # # Supported extensions and parameters: # VRFY # EXPN # HELP # 8BITMIME # SIZE # one optional parameter # ENHANCEDSTATUSCODES # AUTH # one or more of [PLAIN LOGIN ANONYMOUS CRAM-MD5 CRAM-SHA1] # DSN # SEND # SAML # SOML # TURN # ETRN # ATRN # VERP # MTRK # CHUNKING # STARTTLS # DELIVERBY # one optional parameter # SUBMITTER # CHECKPOINT # BINARYMIME # NO-SOLICITING # one optional parameter # FUTURERELEASE # two required parameters # # Default: none # smtp_service_extension VRFY smtp_service_extension EXPN smtp_service_extension HELP smtp_service_extension 8BITMIME smtp_service_extension SIZE 102400000 smtp_service_extension ENHANCEDSTATUSCODES smtp_service_extension AUTH PLAIN LOGIN CRAM-MD5 CRAM-SHA1 smtp_service_extension DSN smtp_service_extension ETRN smtp_service_extension STARTTLS # ######################################### # smtp_auth_reversibleonly # # Only offer authentication mechanisms which allow reversing # the authentication information sent by a client # to clear text username/password. # This option only takes effect if 'smtp_extended_smtp' is # enabled and 'smtp_service_extension AUTH' is configured. # # Syntax: smtp_auth_reversibleonly [yes|no] # # Default: no # #smtp_auth_reversibleonly yes ######################################### # smtp_auth_required # # Force the client to authenticate. # This option only takes effect if 'smtp_extended_smtp' is # enabled and 'smtp_service_extension AUTH' is configured. # # Syntax: smtp_auth_required [yes|no] # # Default: no # smtp_auth_required yes ######################################### # smtp_ssl_keyfile # # Name of the SSL private key PEM file. # The key MUST NOT be encrypted! # # This option only takes effect if 'smtp_extended_smtp' is # enabled and 'smtp_service_extension STARTTLS' is configured. # # The file must be placed in /certs/ # # Note: If no key file is specified, the extension STARTTLS # will be disabled. # # Syntax: smtp_ssl_keyfile # # Default: default_key.pem # #smtp_ssl_keyfile default_key.pem ######################################### # smtp_ssl_certfile # # Name of the SSL certificate PEM file. # # This option only takes effect if 'smtp_extended_smtp' is # enabled and 'smtp_service_extension STARTTLS' is configured. # # The file must be placed in /certs/ # # Note: If no cert file is specified, the extension STARTTLS # will be disabled. # # Syntax: smtp_ssl_certfile # # Default: default_cert.pem # #smtp_ssl_certfile default_cert.pem ######################################### # smtp_ssl_dhfile # # Name of the Diffie-Hellman parameter PEM file. # # The file must be placed in /certs/ # # Syntax: smtp_ssl_dhfile # # Default: none # #smtp_ssl_dhfile smtp_dh1024.pem ############################################################# # Service SMTPS ############################################################# ######################################### # smtps_bind_port # # Port number to bind SMTPS service to # # Syntax: smtps_bind_port # # Default: 465 # smtps_bind_port 65465 ######################################### # smtps_fqdn_hostname # # The FQDN hostname used for SMTPS # # Syntax: smtps_fqdn_hostname # # Default: mail.inetsim.org # #smtps_fqdn_hostname foo.bar.org ######################################### # smtps_banner # # The banner string used in SMTPS greeting message # # Syntax: smtps_banner # # Default: "INetSim Mail Service ready." # #smtps_banner "SMTPS Mailer ready." ######################################### # smtps_helo_required # # Client has to send HELO/EHLO before any other command # # Syntax: smtps_helo_required [yes|no] # # Default: no # smtps_helo_required yes ######################################### # smtps_extended_smtp # # Turn support for extended smtp (ESMTP) on or off # # Syntax: smtps_extended_smtp [yes|no] # # Default: yes # #smtps_extended_smtp no ######################################### # smtps_service_extension # # SMTP service extensions offered to client. # For more information, see # # # Syntax: smtp_service_extension # # Supported extensions and parameters: # VRFY # EXPN # HELP # 8BITMIME # SIZE # one optional parameter # ENHANCEDSTATUSCODES # AUTH # one or more of [PLAIN LOGIN ANONYMOUS CRAM-MD5 CRAM-SHA1] # DSN # SEND # SAML # SOML # TURN # ETRN # ATRN # VERP # MTRK # CHUNKING # DELIVERBY # one optional parameter # SUBMITTER # CHECKPOINT # BINARYMIME # NO-SOLICITING # one optional parameter # FUTURERELEASE # two required parameters # # Default: none # smtps_service_extension VRFY smtps_service_extension EXPN smtps_service_extension HELP smtps_service_extension 8BITMIME smtps_service_extension SIZE 102400000 smtps_service_extension ENHANCEDSTATUSCODES smtps_service_extension AUTH PLAIN LOGIN CRAM-MD5 CRAM-SHA1 #smtps_service_extension DSN smtps_service_extension ETRN # ######################################### # smtps_auth_reversibleonly # # Only offer authentication mechanisms which allow reversing # the authentication information sent by a client # to clear text username/password. # This option only takes effect if 'smtps_extended_smtp' is # enabled and 'smtps_service_extension AUTH' is configured. # # Syntax: smtps_auth_reversibleonly [yes|no] # # Default: no # #smtps_auth_reversibleonly yes ######################################### # smtps_auth_required # # Force the client to authenticate. # This option only takes effect if 'smtps_extended_smtp' is # enabled and 'smtp_service_extension AUTH' is configured. # # Syntax: smtps_auth_required [yes|no] # # Default: no # smtps_auth_required yes ######################################### # smtps_ssl_keyfile # # Name of the SSL private key PEM file. # The key MUST NOT be encrypted! # # The file must be placed in /certs/ # # Syntax: smtps_ssl_keyfile # # Default: default_key.pem # #smtps_ssl_keyfile default_key.pem ######################################### # smtps_ssl_certfile # # Name of the SSL certificate PEM file. # # The file must be placed in /certs/ # # Syntax: smtps_ssl_certfile # # Default: default_cert.pem # #smtps_ssl_certfile default_cert.pem ######################################### # smtps_ssl_dhfile # # Name of the Diffie-Hellman parameter PEM file. # # The file must be placed in /certs/ # # Syntax: smtps_ssl_dhfile # # Default: none # #smtps_ssl_dhfile smtps_dh1024.pem ############################################################# # Service POP3 ############################################################# ######################################### # pop3_bind_port # # Port number to bind POP3 service to # # Syntax: pop3_bind_port # # Default: 110 # pop3_bind_port 64110 ######################################### # pop3_banner # # The banner string used in POP3 greeting message # # Syntax: pop3_banner # # Default: "INetSim POP3 Server ready" # #pop3_banner "POP3 Server ready" ######################################### # pop3_hostname # # The hostname used in POP3 greeting message # # Syntax: pop3_hostname # # Default: pop3host # #pop3_hostname pop3server ######################################### # pop3_mbox_maxmails # # Maximum number of e-mails to select from supplied mbox files # for creation of random POP3 mailbox # # Syntax: pop3_mbox_maxmails # # Default: 10 # #pop3_mbox_maxmails 20 ######################################### # pop3_mbox_reread # # Re-read supplied mbox files if POP3 service was inactive # for seconds # # Syntax: pop3_mbox_reread # # Default: 180 # #pop3_mbox_reread 300 ######################################### # pop3_mbox_rebuild # # Rebuild random POP3 mailbox if POP3 service was inactive # for seconds # # Syntax: pop3_mbox_rebuild # # Default: 60 # #pop3_mbox_rebuild 120 ######################################### # pop3_enable_apop # # Turn APOP on or off # # Syntax: pop3_enable_apop [yes|no] # # Default: yes # #pop3_enable_apop no ######################################### # pop3_auth_reversibleonly # # Only offer authentication mechanisms which allow reversing # the authentication information sent by a client # to clear text username/password # # Syntax: pop3_auth_reversibleonly [yes|no] # # Default: no # #pop3_auth_reversibleonly yes ######################################### # pop3_enable_capabilities # # Turn support for pop3 capabilities on or off # # Syntax: pop3_enable_capabilities [yes|no] # # Default: yes # #pop3_enable_capabilities no ######################################### # pop3_capability # # POP3 capabilities offered to client. # For more information, see # # # Syntax: pop3_capability # # Supported capabilities and parameters: # TOP # USER # UIDL # SASL # one or more of [PLAIN LOGIN ANONYMOUS CRAM-MD5 CRAM-SHA1] # RESP-CODES # EXPIRE # one required parameter and one optional parameter # LOGIN-DELAY # one required parameter and one optional parameter # IMPLEMENTATION # one required parameter # AUTH-RESP-CODE # STLS # # Default: none # pop3_capability TOP pop3_capability USER pop3_capability SASL PLAIN LOGIN ANONYMOUS CRAM-MD5 CRAM-SHA1 pop3_capability UIDL pop3_capability IMPLEMENTATION "INetSim POP3 server" pop3_capability STLS pop3_capability PIPELINING # ######################################### # pop3_ssl_keyfile # # Name of the SSL private key PEM file. # The key MUST NOT be encrypted! # # This option only takes effect if 'pop3_enable_capabilities' is # true and 'pop3_capability STLS' is configured. # # The file must be placed in /certs/ # # Note: If no key file is specified, capability STLS will be disabled. # # Syntax: pop3_ssl_keyfile # # Default: default_key.pem # #pop3_ssl_keyfile pop3_key.pem ######################################### # pop3_ssl_certfile # # Name of the SSL certificate PEM file. # # This option only takes effect if 'pop3_enable_capabilities' is # true and 'pop3_capability STLS' is configured. # # The file must be placed in /certs/ # # Note: If no cert file is specified, capability STLS will be disabled. # # Syntax: pop3_ssl_certfile # # Default: default_cert.pem # #pop3_ssl_certfile pop3_cert.pem ######################################### # pop3_ssl_dhfile # # Name of the Diffie-Hellman parameter PEM file. # # The file must be placed in /certs/ # # Syntax: pop3_ssl_dhfile # # Default: none # #pop3_ssl_dhfile pop3_dh1024.pem ############################################################# # Service POP3S ############################################################# ######################################### # pop3s_bind_port # # Port number to bind POP3S service to # # Syntax: pop3s_bind_port # # Default: 995 # pop3s_bind_port 64995 ######################################### # pop3s_banner # # The banner string used in POP3 greeting message # # Syntax: pop3s_banner # # Default: "INetSim POP3 Server ready" # #pop3s_banner "POP3 Server ready" ######################################### # pop3s_hostname # # The hostname used in POP3 greeting message # # Syntax: pop3s_hostname # # Default: pop3host # #pop3s_hostname pop3server ######################################### # pop3s_mbox_maxmails # # Maximum number of e-mails to select from supplied mbox files # for creation of random POP3 mailbox # # Syntax: pop3s_mbox_maxmails # # Default: 10 # #pop3s_mbox_maxmails 20 ######################################### # pop3s_mbox_reread # # Re-read supplied mbox files if POP3S service was inactive # for seconds # # Syntax: pop3s_mbox_reread # # Default: 180 # #pop3s_mbox_reread 300 ######################################### # pop3s_mbox_rebuild # # Rebuild random POP3 mailbox if POP3S service was inactive # for seconds # # Syntax: pop3s_mbox_rebuild # # Default: 60 # #pop3s_mbox_rebuild 120 ######################################### # pop3s_enable_apop # # Turn APOP on or off # # Syntax: pop3s_enable_apop [yes|no] # # Default: yes # pop3s_enable_apop no ######################################### # pop3s_auth_reversibleonly # # Only offer authentication mechanisms which allow reversing # the authentication information sent by a client # to clear text username/password # # Syntax: pop3s_auth_reversibleonly [yes|no] # # Default: no # #pop3s_auth_reversibleonly yes ######################################### # pop3s_enable_capabilities # # Turn support for pop3 capabilities on or off # # Syntax: pop3s_enable_capabilities [yes|no] # # Default: yes # #pop3s_enable_capabilities no ######################################### # pop3s_capability # # POP3 capabilities offered to client. # For more information, see # # # Syntax: pop3s_capability # # Supported capabilities and parameters: # TOP # USER # UIDL # SASL # one or more of [PLAIN LOGIN ANONYMOUS CRAM-MD5 CRAM-SHA1] # RESP-CODES # EXPIRE # one required parameter and one optional parameter # LOGIN-DELAY # one required parameter and one optional parameter # IMPLEMENTATION # one required parameter # AUTH-RESP-CODE # # Default: none # pop3s_capability TOP pop3s_capability USER pop3s_capability SASL PLAIN LOGIN ANONYMOUS CRAM-MD5 CRAM-SHA1 pop3s_capability UIDL pop3s_capability IMPLEMENTATION "INetSim POP3s server" # ######################################### # pop3s_ssl_keyfile # # Name of the SSL private key PEM file. # The key MUST NOT be encrypted! # # The file must be placed in /certs/ # # Syntax: pop3s_ssl_keyfile # # Default: default_key.pem # #pop3s_ssl_keyfile pop3s_key.pem ######################################### # pop3s_ssl_certfile # # Name of the SSL certificate PEM file. # # The file must be placed in /certs/ # # Syntax: pop3s_ssl_certfile # # Default: default_cert.pem # #pop3s_ssl_certfile pop3s_cert.pem ######################################### # pop3s_ssl_dhfile # # Name of the Diffie-Hellman parameter PEM file. # # The file must be placed in /certs/ # # Syntax: pop3s_ssl_dhfile # # Default: none # #pop3s_ssl_dhfile pop3s_dh1024.pem ############################################################# # Service TFTP ############################################################# ######################################### # tftp_bind_port # # Port number to bind TFTP service to # # Syntax: tftp_bind_port # # Default: 69 # #tftp_bind_port 69 ######################################### # tftp_allow_overwrite # # Allow overwriting of existing files # # Syntax: tftp_allow_overwrite [yes|no] # # Default: no # #tftp_allow_overwrite yes ######################################### # tftp_enable_options # # Turn support for tftp options on or off # # Syntax: tftp_enable_options [yes|no] # # Default: yes # #tftp_enable_options no ######################################### # tftp_option # # TFTP extensions offered to client. # For more information, see RFC 2347 # # Syntax: tftp_option