2013-02-17 [colin] 3.9.0cvs75
* src/plugins/Makefile.am * src/plugins/archive/Makefile.am * src/plugins/clamd/Makefile.am * src/plugins/clamd/clamav_plugin.c * src/plugins/clamd/clamav_plugin.h * src/plugins/clamd/clamav_plugin_gtk.c * src/plugins/clamd/placeholder.txt * src/plugins/clamd/libclamd/Makefile.am * src/plugins/clamd/libclamd/clamd-plugin.c * src/plugins/clamd/libclamd/clamd-plugin.h * src/plugins/fetchinfo/Makefile.am * src/plugins/fetchinfo/fetchinfo_plugin.c * src/plugins/fetchinfo/fetchinfo_plugin.h * src/plugins/fetchinfo/fetchinfo_plugin_gtk.c * src/plugins/fetchinfo/placeholder.txt * src/plugins/gdata/Makefile.am * src/plugins/gdata/cm_gdata_contacts.c * src/plugins/gdata/cm_gdata_contacts.h * src/plugins/gdata/cm_gdata_prefs.c * src/plugins/gdata/cm_gdata_prefs.h * src/plugins/gdata/gdata_plugin.c * src/plugins/gdata/gdata_plugin.h * src/plugins/gdata/placeholder.txt * src/plugins/geolocation/placeholder.txt * src/plugins/gtkhtml2_viewer/placeholder.txt * src/plugins/mailmbox/Makefile.am * src/plugins/mailmbox/carray.c * src/plugins/mailmbox/carray.h * src/plugins/mailmbox/chash.c * src/plugins/mailmbox/chash.h * src/plugins/mailmbox/clist.c * src/plugins/mailmbox/clist.h * src/plugins/mailmbox/mailimf.c * src/plugins/mailmbox/mailimf.h * src/plugins/mailmbox/mailimf_types.c * src/plugins/mailmbox/mailimf_types.h * src/plugins/mailmbox/mailimf_types_helper.c * src/plugins/mailmbox/mailimf_types_helper.h * src/plugins/mailmbox/mailimf_write.c * src/plugins/mailmbox/mailimf_write.h * src/plugins/mailmbox/maillock.c * src/plugins/mailmbox/maillock.h * src/plugins/mailmbox/mailmbox.c * src/plugins/mailmbox/mailmbox.h * src/plugins/mailmbox/mailmbox_folder.c * src/plugins/mailmbox/mailmbox_folder.h * src/plugins/mailmbox/mailmbox_gtk.deps * src/plugins/mailmbox/mailmbox_parse.c * src/plugins/mailmbox/mailmbox_parse.h * src/plugins/mailmbox/mailmbox_types.c * src/plugins/mailmbox/mailmbox_types.h * src/plugins/mailmbox/mmapstring.c * src/plugins/mailmbox/mmapstring.h * src/plugins/mailmbox/placeholder.txt * src/plugins/mailmbox/plugin.c * src/plugins/mailmbox/plugin_gtk.c * src/plugins/mailmbox/plugin_gtk.h * src/plugins/newmail/Makefile.am * src/plugins/newmail/newmail.c * src/plugins/newmail/placeholder.txt * src/plugins/notification/Makefile.am * src/plugins/notification/claws.def * src/plugins/notification/notification_banner.c * src/plugins/notification/notification_banner.h * src/plugins/notification/notification_command.c * src/plugins/notification/notification_command.h * src/plugins/notification/notification_core.c * src/plugins/notification/notification_core.h * src/plugins/notification/notification_foldercheck.c * src/plugins/notification/notification_foldercheck.h * src/plugins/notification/notification_hotkeys.c * src/plugins/notification/notification_hotkeys.h * src/plugins/notification/notification_indicator.c * src/plugins/notification/notification_indicator.h * src/plugins/notification/notification_lcdproc.c * src/plugins/notification/notification_lcdproc.h * src/plugins/notification/notification_pixbuf.c * src/plugins/notification/notification_pixbuf.h * src/plugins/notification/notification_plugin.c * src/plugins/notification/notification_plugin.h * src/plugins/notification/notification_popup.c * src/plugins/notification/notification_popup.h * src/plugins/notification/notification_prefs.c * src/plugins/notification/notification_prefs.h * src/plugins/notification/notification_trayicon.c * src/plugins/notification/notification_trayicon.h * src/plugins/notification/placeholder.txt * src/plugins/notification/plugin.def * src/plugins/notification/raw_claws_mail_logo_64x64.h * src/plugins/notification/version.rc * src/plugins/pdf_viewer/Makefile.am * src/plugins/pdf_viewer/doc_index.xpm * src/plugins/pdf_viewer/doc_index_close.xpm * src/plugins/pdf_viewer/doc_info.xpm * src/plugins/pdf_viewer/first_arrow.xpm * src/plugins/pdf_viewer/last_arrow.xpm * src/plugins/pdf_viewer/left_arrow.xpm * src/plugins/pdf_viewer/placeholder.txt * src/plugins/pdf_viewer/poppler_viewer.c * src/plugins/pdf_viewer/poppler_viewer.h * src/plugins/pdf_viewer/right_arrow.xpm * src/plugins/pdf_viewer/rotate_left.xpm * src/plugins/pdf_viewer/rotate_right.xpm * src/plugins/pdf_viewer/zoom_fit.xpm * src/plugins/pdf_viewer/zoom_in.xpm * src/plugins/pdf_viewer/zoom_out.xpm * src/plugins/pdf_viewer/zoom_width.xpm * src/plugins/perl/Makefile.am * src/plugins/perl/perl_gtk.c * src/plugins/perl/perl_gtk.h * src/plugins/perl/perl_plugin.c * src/plugins/perl/perl_plugin.h * src/plugins/perl/placeholder.txt * src/plugins/python/Makefile.am * src/plugins/python/clawsmailmodule.c * src/plugins/python/clawsmailmodule.h * src/plugins/python/composewindowtype.c * src/plugins/python/composewindowtype.h * src/plugins/python/foldertype.c * src/plugins/python/foldertype.h * src/plugins/python/messageinfotype.c * src/plugins/python/messageinfotype.h * src/plugins/python/nodetype.c * src/plugins/python/nodetype.h * src/plugins/python/placeholder.txt * src/plugins/python/python-hooks.c * src/plugins/python/python-hooks.h * src/plugins/python/python-shell.c * src/plugins/python/python-shell.h * src/plugins/python/python_plugin.c * src/plugins/vcalendar/Makefile.in Add some plugins (clamd, fetchinfo, gdata, mailmbox, newmail, notification, pdf_viewer, perl, python). Notification not yet enabled because it has too much autoconf switches for my taste.
This commit is contained in:
parent
2c79a205e4
commit
abf3a16d40
134 changed files with 42232 additions and 15 deletions
138
ChangeLog
138
ChangeLog
|
@ -1,3 +1,141 @@
|
|||
2013-02-17 [colin] 3.9.0cvs75
|
||||
|
||||
* src/plugins/Makefile.am
|
||||
* src/plugins/archive/Makefile.am
|
||||
* src/plugins/clamd/Makefile.am
|
||||
* src/plugins/clamd/clamav_plugin.c
|
||||
* src/plugins/clamd/clamav_plugin.h
|
||||
* src/plugins/clamd/clamav_plugin_gtk.c
|
||||
* src/plugins/clamd/placeholder.txt
|
||||
* src/plugins/clamd/libclamd/Makefile.am
|
||||
* src/plugins/clamd/libclamd/clamd-plugin.c
|
||||
* src/plugins/clamd/libclamd/clamd-plugin.h
|
||||
* src/plugins/fetchinfo/Makefile.am
|
||||
* src/plugins/fetchinfo/fetchinfo_plugin.c
|
||||
* src/plugins/fetchinfo/fetchinfo_plugin.h
|
||||
* src/plugins/fetchinfo/fetchinfo_plugin_gtk.c
|
||||
* src/plugins/fetchinfo/placeholder.txt
|
||||
* src/plugins/gdata/Makefile.am
|
||||
* src/plugins/gdata/cm_gdata_contacts.c
|
||||
* src/plugins/gdata/cm_gdata_contacts.h
|
||||
* src/plugins/gdata/cm_gdata_prefs.c
|
||||
* src/plugins/gdata/cm_gdata_prefs.h
|
||||
* src/plugins/gdata/gdata_plugin.c
|
||||
* src/plugins/gdata/gdata_plugin.h
|
||||
* src/plugins/gdata/placeholder.txt
|
||||
* src/plugins/geolocation/placeholder.txt
|
||||
* src/plugins/gtkhtml2_viewer/placeholder.txt
|
||||
* src/plugins/mailmbox/Makefile.am
|
||||
* src/plugins/mailmbox/carray.c
|
||||
* src/plugins/mailmbox/carray.h
|
||||
* src/plugins/mailmbox/chash.c
|
||||
* src/plugins/mailmbox/chash.h
|
||||
* src/plugins/mailmbox/clist.c
|
||||
* src/plugins/mailmbox/clist.h
|
||||
* src/plugins/mailmbox/mailimf.c
|
||||
* src/plugins/mailmbox/mailimf.h
|
||||
* src/plugins/mailmbox/mailimf_types.c
|
||||
* src/plugins/mailmbox/mailimf_types.h
|
||||
* src/plugins/mailmbox/mailimf_types_helper.c
|
||||
* src/plugins/mailmbox/mailimf_types_helper.h
|
||||
* src/plugins/mailmbox/mailimf_write.c
|
||||
* src/plugins/mailmbox/mailimf_write.h
|
||||
* src/plugins/mailmbox/maillock.c
|
||||
* src/plugins/mailmbox/maillock.h
|
||||
* src/plugins/mailmbox/mailmbox.c
|
||||
* src/plugins/mailmbox/mailmbox.h
|
||||
* src/plugins/mailmbox/mailmbox_folder.c
|
||||
* src/plugins/mailmbox/mailmbox_folder.h
|
||||
* src/plugins/mailmbox/mailmbox_gtk.deps
|
||||
* src/plugins/mailmbox/mailmbox_parse.c
|
||||
* src/plugins/mailmbox/mailmbox_parse.h
|
||||
* src/plugins/mailmbox/mailmbox_types.c
|
||||
* src/plugins/mailmbox/mailmbox_types.h
|
||||
* src/plugins/mailmbox/mmapstring.c
|
||||
* src/plugins/mailmbox/mmapstring.h
|
||||
* src/plugins/mailmbox/placeholder.txt
|
||||
* src/plugins/mailmbox/plugin.c
|
||||
* src/plugins/mailmbox/plugin_gtk.c
|
||||
* src/plugins/mailmbox/plugin_gtk.h
|
||||
* src/plugins/newmail/Makefile.am
|
||||
* src/plugins/newmail/newmail.c
|
||||
* src/plugins/newmail/placeholder.txt
|
||||
* src/plugins/notification/Makefile.am
|
||||
* src/plugins/notification/claws.def
|
||||
* src/plugins/notification/notification_banner.c
|
||||
* src/plugins/notification/notification_banner.h
|
||||
* src/plugins/notification/notification_command.c
|
||||
* src/plugins/notification/notification_command.h
|
||||
* src/plugins/notification/notification_core.c
|
||||
* src/plugins/notification/notification_core.h
|
||||
* src/plugins/notification/notification_foldercheck.c
|
||||
* src/plugins/notification/notification_foldercheck.h
|
||||
* src/plugins/notification/notification_hotkeys.c
|
||||
* src/plugins/notification/notification_hotkeys.h
|
||||
* src/plugins/notification/notification_indicator.c
|
||||
* src/plugins/notification/notification_indicator.h
|
||||
* src/plugins/notification/notification_lcdproc.c
|
||||
* src/plugins/notification/notification_lcdproc.h
|
||||
* src/plugins/notification/notification_pixbuf.c
|
||||
* src/plugins/notification/notification_pixbuf.h
|
||||
* src/plugins/notification/notification_plugin.c
|
||||
* src/plugins/notification/notification_plugin.h
|
||||
* src/plugins/notification/notification_popup.c
|
||||
* src/plugins/notification/notification_popup.h
|
||||
* src/plugins/notification/notification_prefs.c
|
||||
* src/plugins/notification/notification_prefs.h
|
||||
* src/plugins/notification/notification_trayicon.c
|
||||
* src/plugins/notification/notification_trayicon.h
|
||||
* src/plugins/notification/placeholder.txt
|
||||
* src/plugins/notification/plugin.def
|
||||
* src/plugins/notification/raw_claws_mail_logo_64x64.h
|
||||
* src/plugins/notification/version.rc
|
||||
* src/plugins/pdf_viewer/Makefile.am
|
||||
* src/plugins/pdf_viewer/doc_index.xpm
|
||||
* src/plugins/pdf_viewer/doc_index_close.xpm
|
||||
* src/plugins/pdf_viewer/doc_info.xpm
|
||||
* src/plugins/pdf_viewer/first_arrow.xpm
|
||||
* src/plugins/pdf_viewer/last_arrow.xpm
|
||||
* src/plugins/pdf_viewer/left_arrow.xpm
|
||||
* src/plugins/pdf_viewer/placeholder.txt
|
||||
* src/plugins/pdf_viewer/poppler_viewer.c
|
||||
* src/plugins/pdf_viewer/poppler_viewer.h
|
||||
* src/plugins/pdf_viewer/right_arrow.xpm
|
||||
* src/plugins/pdf_viewer/rotate_left.xpm
|
||||
* src/plugins/pdf_viewer/rotate_right.xpm
|
||||
* src/plugins/pdf_viewer/zoom_fit.xpm
|
||||
* src/plugins/pdf_viewer/zoom_in.xpm
|
||||
* src/plugins/pdf_viewer/zoom_out.xpm
|
||||
* src/plugins/pdf_viewer/zoom_width.xpm
|
||||
* src/plugins/perl/Makefile.am
|
||||
* src/plugins/perl/perl_gtk.c
|
||||
* src/plugins/perl/perl_gtk.h
|
||||
* src/plugins/perl/perl_plugin.c
|
||||
* src/plugins/perl/perl_plugin.h
|
||||
* src/plugins/perl/placeholder.txt
|
||||
* src/plugins/python/Makefile.am
|
||||
* src/plugins/python/clawsmailmodule.c
|
||||
* src/plugins/python/clawsmailmodule.h
|
||||
* src/plugins/python/composewindowtype.c
|
||||
* src/plugins/python/composewindowtype.h
|
||||
* src/plugins/python/foldertype.c
|
||||
* src/plugins/python/foldertype.h
|
||||
* src/plugins/python/messageinfotype.c
|
||||
* src/plugins/python/messageinfotype.h
|
||||
* src/plugins/python/nodetype.c
|
||||
* src/plugins/python/nodetype.h
|
||||
* src/plugins/python/placeholder.txt
|
||||
* src/plugins/python/python-hooks.c
|
||||
* src/plugins/python/python-hooks.h
|
||||
* src/plugins/python/python-shell.c
|
||||
* src/plugins/python/python-shell.h
|
||||
* src/plugins/python/python_plugin.c
|
||||
* src/plugins/vcalendar/Makefile.in
|
||||
Add some plugins (clamd, fetchinfo, gdata, mailmbox, newmail,
|
||||
notification, pdf_viewer, perl, python). Notification not yet
|
||||
enabled because it has too much autoconf switches for my taste.
|
||||
|
||||
|
||||
2013-02-16 [colin] 3.9.0cvs74
|
||||
|
||||
* po/POTFILES.in
|
||||
|
|
File diff suppressed because one or more lines are too long
248
configure.ac
248
configure.ac
|
@ -12,7 +12,7 @@ MINOR_VERSION=9
|
|||
MICRO_VERSION=0
|
||||
INTERFACE_AGE=0
|
||||
BINARY_AGE=0
|
||||
EXTRA_VERSION=74
|
||||
EXTRA_VERSION=75
|
||||
EXTRA_RELEASE=
|
||||
EXTRA_GTK2_VERSION=
|
||||
|
||||
|
@ -863,6 +863,9 @@ AC_ARG_ENABLE(acpi_notifier-plugin,
|
|||
[ac_cv_enable_acpi_notifier_plugin=$enableval], [ac_cv_enable_acpi_notifier_plugin=yes])
|
||||
if test x"$ac_cv_enable_acpi_notifier_plugin" = xyes; then
|
||||
PLUGINS="acpi_notifier $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_ACPI_NOTIFIER_PLUGIN, test x"$ac_cv_enable_acpi_notifier_plugin" = xyes)
|
||||
|
||||
|
@ -872,6 +875,9 @@ AC_ARG_ENABLE(address_keeper-plugin,
|
|||
[ac_cv_enable_address_keeper_plugin=$enableval], [ac_cv_enable_address_keeper_plugin=yes])
|
||||
if test x"$ac_cv_enable_address_keeper_plugin" = xyes; then
|
||||
PLUGINS="address_keeper $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_ADDRESS_KEEPER_PLUGIN, test x"$ac_cv_enable_address_keeper_plugin" = xyes)
|
||||
|
||||
|
@ -887,6 +893,9 @@ if test x"$ac_cv_enable_archive_plugin" = xyes; then
|
|||
exit 1
|
||||
)
|
||||
PLUGINS="archive $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_ARCHIVE_PLUGIN, test x"$ac_cv_enable_archive_plugin" = xyes)
|
||||
|
||||
|
@ -896,6 +905,9 @@ AC_ARG_ENABLE(att_remover-plugin,
|
|||
[ac_cv_enable_att_remover_plugin=$enableval], [ac_cv_enable_att_remover_plugin=yes])
|
||||
if test x"$ac_cv_enable_att_remover_plugin" = xyes; then
|
||||
PLUGINS="att_remover $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_ATT_REMOVER_PLUGIN, test x"$ac_cv_enable_att_remover_plugin" = xyes)
|
||||
|
||||
|
@ -905,6 +917,9 @@ AC_ARG_ENABLE(attachwarner-plugin,
|
|||
[ac_cv_enable_attachwarner_plugin=$enableval], [ac_cv_enable_attachwarner_plugin=yes])
|
||||
if test x"$ac_cv_enable_attachwarner_plugin" = xyes; then
|
||||
PLUGINS="attachwarner $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_ATTACHWARNER_PLUGIN, test x"$ac_cv_enable_attachwarner_plugin" = xyes)
|
||||
|
||||
|
@ -929,15 +944,34 @@ AC_ARG_ENABLE(bsfilter-plugin,
|
|||
[ac_cv_enable_bsfilter_plugin=$enableval], [ac_cv_enable_bsfilter_plugin=yes])
|
||||
if test x"$ac_cv_enable_bsfilter_plugin" = xyes; then
|
||||
PLUGINS="bsfilter $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_BSFILTER_PLUGIN, test x"$ac_cv_enable_bsfilter_plugin" = xyes)
|
||||
|
||||
dnl --- clamd ---
|
||||
AC_MSG_CHECKING([whether to build clamd plugin])
|
||||
AC_ARG_ENABLE(clamd-plugin,
|
||||
[ --disable-clamd-plugin do not build clamd plugin],
|
||||
[ac_cv_enable_clamd_plugin=$enableval], [ac_cv_enable_clamd_plugin=yes])
|
||||
if test x"$ac_cv_enable_clamd_plugin" = xyes; then
|
||||
PLUGINS="clamd $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_CLAMD_PLUGIN, test x"$ac_cv_enable_clamd_plugin" = xyes)
|
||||
|
||||
dnl --- Demo ---
|
||||
AC_ARG_ENABLE(demo-plugin,
|
||||
[ --enable-demo-plugin build demo plugin],
|
||||
[ac_cv_enable_demo_plugin=$enableval], [ac_cv_enable_demo_plugin=no])
|
||||
if test x"$ac_cv_enable_demo_plugin" = xyes; then
|
||||
PLUGINS="demo $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_DEMO_PLUGIN, test x"$ac_cv_enable_demo_plugin" = xyes)
|
||||
|
||||
|
@ -993,6 +1027,209 @@ if test x"$ac_cv_enable_fancy_plugin" = xyes; then
|
|||
fi
|
||||
AM_CONDITIONAL(BUILD_FANCY_PLUGIN, test x"$ac_cv_enable_fancy_plugin" = xyes)
|
||||
|
||||
dnl --- fetchinfo ---
|
||||
AC_MSG_CHECKING([whether to build fetchinfo plugin])
|
||||
AC_ARG_ENABLE(fetchinfo-plugin,
|
||||
[ --disable-fetchinfo-plugin do not build fetchinfo plugin],
|
||||
[ac_cv_enable_fetchinfo_plugin=$enableval], [ac_cv_enable_fetchinfo_plugin=yes])
|
||||
if test x"$ac_cv_enable_fetchinfo_plugin" = xyes; then
|
||||
PLUGINS="fetchinfo $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_FETCHINFO_PLUGIN, test x"$ac_cv_enable_fetchinfo_plugin" = xyes)
|
||||
|
||||
dnl --- gdata ---
|
||||
AC_MSG_CHECKING([whether to build gdata plugin])
|
||||
AC_ARG_ENABLE(gdata-plugin,
|
||||
[ --disable-gdata-plugin do not build gdata plugin],
|
||||
[ac_cv_enable_gdata_plugin=$enableval], [ac_cv_enable_gdata_plugin=yes])
|
||||
if test x"$ac_cv_enable_gdata_plugin" = xyes; then
|
||||
PKG_CHECK_MODULES(GDATA, libgdata >= 0.9.1, [ac_cv_enable_gdata_plugin=yes], [ac_cv_enable_gdata_plugin=no])
|
||||
if test x"$ac_cv_enable_gdata_plugin" = xyes; then
|
||||
AC_DEFINE(HAVE_GDATA_VERSION_0_9_1, 1, [at least version 0.9.1 of libgdata is available])
|
||||
AC_DEFINE(HAVE_GDATA_VERSION_0_9, 1, [at least version 0.9.0 of libgdata is available])
|
||||
else
|
||||
PKG_CHECK_MODULES(GDATA, libgdata >= 0.6.4, [ac_cv_enable_gdata_plugin=yes], [ac_cv_enable_gdata_plugin=no])
|
||||
fi
|
||||
if test x"$ac_cv_enable_gdata_plugin" = xyes; then
|
||||
AC_SUBST(GDATA_CFLAGS)
|
||||
AC_SUBST(GDATA_LIBS)
|
||||
AC_DEFINE(CM_GDATA_CLIENT_ID, ["Claws Mail GData plugin"], [client id])
|
||||
|
||||
PLUGINS="gdata $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_ERROR(libgdata is not available)
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_GDATA_PLUGIN, test x"$ac_cv_enable_gdata_plugin" = xyes)
|
||||
|
||||
dnl --- mailmbox ---
|
||||
AC_MSG_CHECKING([whether to build mailmbox plugin])
|
||||
AC_ARG_ENABLE(mailmbox-plugin,
|
||||
[ --disable-mailmbox-plugin do not build mailmbox plugin],
|
||||
[ac_cv_enable_mailmbox_plugin=$enableval], [ac_cv_enable_mailmbox_plugin=yes])
|
||||
if test x"$ac_cv_enable_mailmbox_plugin" = xyes; then
|
||||
PLUGINS="mailmbox $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_MAILMBOX_PLUGIN, test x"$ac_cv_enable_mailmbox_plugin" = xyes)
|
||||
|
||||
dnl --- newmail ---
|
||||
AC_MSG_CHECKING([whether to build newmail plugin])
|
||||
AC_ARG_ENABLE(newmail-plugin,
|
||||
[ --disable-newmail-plugin do not build newmail plugin],
|
||||
[ac_cv_enable_newmail_plugin=$enableval], [ac_cv_enable_newmail_plugin=yes])
|
||||
if test x"$ac_cv_enable_newmail_plugin" = xyes; then
|
||||
PLUGINS="newmail $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_NEWMAIL_PLUGIN, test x"$ac_cv_enable_newmail_plugin" = xyes)
|
||||
|
||||
dnl --- notification - disabled - too many autofoo annoyances for today ---
|
||||
AC_MSG_CHECKING([whether to build notification plugin])
|
||||
AC_ARG_ENABLE(notification-plugin,
|
||||
[ --disable-notification-plugin do not build notification plugin],
|
||||
[ac_cv_enable_notification_plugin=$enableval], [ac_cv_enable_notification_plugin=no])
|
||||
if test x"$ac_cv_enable_notification_plugin" = xyes; then
|
||||
PLUGINS="notification $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_NOTIFICATION_PLUGIN, test x"$ac_cv_enable_notification_plugin" = xyes)
|
||||
|
||||
dnl --- pdf_viewer ---
|
||||
AC_MSG_CHECKING([whether to build pdf_viewer plugin])
|
||||
AC_ARG_ENABLE(pdf_viewer-plugin,
|
||||
[ --disable-pdf_viewer-plugin do not build pdf_viewer plugin],
|
||||
[ac_cv_enable_pdf_viewer_plugin=$enableval], [ac_cv_enable_pdf_viewer_plugin=yes])
|
||||
if test x"$ac_cv_enable_pdf_viewer_plugin" = xyes; then
|
||||
PKG_CHECK_MODULES(POPPLER, poppler-glib >= 0.4.2, ,
|
||||
AC_MSG_ERROR([Can't find Poppler >= 0.4.2 Glib wrapper]))
|
||||
AC_SUBST(POPPLER_LIBS)
|
||||
AC_SUBST(POPPLER_CFLAGS)
|
||||
|
||||
OLD_CFLAGS=$CFLAGS
|
||||
CFLAGS="$POPPLER_CFLAGS $GTK_CFLAGS $GLIB_CFLAGS"
|
||||
AC_CHECK_DECL(POPPLER_DEST_NAMED,
|
||||
[AC_DEFINE([HAVE_POPPLER_DEST_NAMED], [], [Description])],
|
||||
,[#include <poppler-action.h>])
|
||||
AC_CHECK_DECL(POPPLER_DEST_XYZ,
|
||||
[AC_DEFINE([HAVE_POPPLER_DEST_XYZ], [], [Description])],
|
||||
,[#include <poppler-action.h>])
|
||||
CFLAGS=$OLD_CFLAGS
|
||||
PLUGINS="pdf_viewer $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_PDF_VIEWER_PLUGIN, test x"$ac_cv_enable_pdf_viewer_plugin" = xyes)
|
||||
|
||||
dnl --- perl ---
|
||||
AC_MSG_CHECKING([whether to build perl plugin])
|
||||
AC_ARG_ENABLE(perl-plugin,
|
||||
[ --disable-perl-plugin do not build perl plugin],
|
||||
[ac_cv_enable_perl_plugin=$enableval], [ac_cv_enable_perl_plugin=yes])
|
||||
if test x"$ac_cv_enable_perl_plugin" = xyes; then
|
||||
AC_PATH_PROG(sedpath, sed, no)
|
||||
if test x$sedpath = xno ; then
|
||||
AC_MSG_ERROR(Test for sed failed.)
|
||||
fi
|
||||
|
||||
dnl Perl
|
||||
AC_PATH_PROG(PERL_PATH, perl, no)
|
||||
if test x$PERL_PATH = xno ; then
|
||||
AC_MSG_ERROR(Test for Perl failed)
|
||||
fi
|
||||
AC_MSG_CHECKING(for perl >= 5.8.0)
|
||||
PERL_VER=`$PERL_PATH -e 'print $] > 5.0079999?"yes":"no"'`
|
||||
if test "$PERL_VER" = "yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR(Your Perl version is too old.)
|
||||
fi
|
||||
AC_MSG_CHECKING(for Perl compile flags)
|
||||
PERL_CFLAGS=`$PERL_PATH -MExtUtils::Embed -e ccopts`
|
||||
PERL_CFLAGS=`echo $PERL_CFLAGS | $sedpath 's/-D_FILE_OFFSET_BITS=[[0-9]]*//'`
|
||||
PERL_LDFLAGS=`$PERL_PATH -MExtUtils::Embed -e ldopts |$sedpath 's/-lgdbm//'`
|
||||
PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-ldb//'`
|
||||
PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lndbm//'`
|
||||
PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lc//'`
|
||||
AC_MSG_RESULT(ok)
|
||||
AC_SUBST(PERL_CFLAGS)
|
||||
AC_SUBST(PERL_LDFLAGS)
|
||||
PLUGINS="perl $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_PERL_PLUGIN, test x"$ac_cv_enable_perl_plugin" = xyes)
|
||||
|
||||
dnl --- python ---
|
||||
AC_MSG_CHECKING([whether to build python plugin])
|
||||
AC_ARG_ENABLE(python-plugin,
|
||||
[ --disable-python-plugin do not build python plugin],
|
||||
[ac_cv_enable_python_plugin=$enableval], [ac_cv_enable_python_plugin=yes])
|
||||
if test x"$ac_cv_enable_python_plugin" = xyes; then
|
||||
AM_PATH_PYTHON([2.5], [
|
||||
AC_PATH_PROG(PYTHON_CONFIG, python$PYTHON_VERSION-config)
|
||||
if test x"$PYTHON_CONFIG" = x"" ; then
|
||||
AC_PATH_PROG(PYTHON_CONFIG, python-config)
|
||||
fi
|
||||
if test x"$PYTHON_CONFIG" != x""; then
|
||||
PYTHON_CFLAGS=`$PYTHON_CONFIG --includes`
|
||||
PYTHON_LIBS=`$PYTHON_CONFIG --libs`
|
||||
PYTHON_PREFIX=`$PYTHON_CONFIG --prefix`
|
||||
else
|
||||
AC_MSG_ERROR(python-config not found. Maybe you need to install development packages for Python.)
|
||||
fi
|
||||
|
||||
# libpython.so
|
||||
PYTHON_SO_FILE="libpython${PYTHON_VERSION}.so"
|
||||
found_libpython_so="no"
|
||||
if test -f "$PYTHON_PREFIX/lib/$PYTHON_SO_FILE"; then
|
||||
found_libpython_so="yes"
|
||||
PYTHON_SHARED_LIB=`python -c "import os,sys; print os.path.basename(os.path.realpath(\"$PYTHON_PREFIX/lib/$PYTHON_SO_FILE\"))"`
|
||||
fi
|
||||
if test -f "$PYTHON_PREFIX/lib64/$PYTHON_SO_FILE"; then
|
||||
found_libpython_so="yes"
|
||||
PYTHON_SHARED_LIB=`python -c "import os,sys; print os.path.basename(os.path.realpath(\"$PYTHON_PREFIX/lib64/$PYTHON_SO_FILE\"))"`
|
||||
fi
|
||||
if test x"$found_libpython_so" != x"yes"; then
|
||||
AC_MSG_ERROR(Could not find Python shared libary: $PYTHON_SO_FILE does not exist. Maybe you need to install development packages for Python.)
|
||||
fi
|
||||
|
||||
# PyGTK
|
||||
PKG_CHECK_MODULES(PYGTK,
|
||||
[pygtk-2.0 >= 2.10.3],
|
||||
[
|
||||
AC_DEFINE(ENABLE_PYTHON, [1], [Enable Python support])
|
||||
])
|
||||
])
|
||||
|
||||
AC_SUBST(PYTHON_SHARED_LIB)
|
||||
AC_SUBST(PYTHON_CFLAGS)
|
||||
AC_SUBST(PYTHON_LIBS)
|
||||
AC_SUBST(PYGTK_CFLAGS)
|
||||
AC_SUBST(PYGTK_LIBS)
|
||||
|
||||
PLUGINS="python $PLUGINS"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_PYTHON_PLUGIN, test x"$ac_cv_enable_python_plugin" = xyes)
|
||||
|
||||
dnl --- PGP/CORE ---
|
||||
AC_MSG_CHECKING([whether to build PGP/CORE plugin])
|
||||
AC_ARG_ENABLE(pgpcore-plugin,
|
||||
|
@ -1214,9 +1451,18 @@ src/plugins/att_remover/Makefile
|
|||
src/plugins/attachwarner/Makefile
|
||||
src/plugins/bogofilter/Makefile
|
||||
src/plugins/bsfilter/Makefile
|
||||
src/plugins/clamd/Makefile
|
||||
src/plugins/clamd/libclamd/Makefile
|
||||
src/plugins/demo/Makefile
|
||||
src/plugins/dillo_viewer/Makefile
|
||||
src/plugins/fancy/Makefile
|
||||
src/plugins/fetchinfo/Makefile
|
||||
src/plugins/gdata/Makefile
|
||||
src/plugins/mailmbox/Makefile
|
||||
src/plugins/newmail/Makefile
|
||||
src/plugins/pdf_viewer/Makefile
|
||||
src/plugins/perl/Makefile
|
||||
src/plugins/python/Makefile
|
||||
src/plugins/pgpcore/Makefile
|
||||
src/plugins/pgpmime/Makefile
|
||||
src/plugins/pgpinline/Makefile
|
||||
|
|
|
@ -26,6 +26,10 @@ if BUILD_BSFILTER_PLUGIN
|
|||
bsfilter_dir = bsfilter
|
||||
endif
|
||||
|
||||
if BUILD_CLAMD_PLUGIN
|
||||
clamd_dir = clamd
|
||||
endif
|
||||
|
||||
if BUILD_DEMO_PLUGIN
|
||||
demo_dir = demo
|
||||
endif
|
||||
|
@ -38,6 +42,38 @@ if BUILD_FANCY_PLUGIN
|
|||
fancy_dir = fancy
|
||||
endif
|
||||
|
||||
if BUILD_FETCHINFO_PLUGIN
|
||||
fetchinfo_dir = fetchinfo
|
||||
endif
|
||||
|
||||
if BUILD_GDATA_PLUGIN
|
||||
gdata_dir = gdata
|
||||
endif
|
||||
|
||||
if BUILD_MAILMBOX_PLUGIN
|
||||
mailmbox_dir = mailmbox
|
||||
endif
|
||||
|
||||
if BUILD_NEWMAIL_PLUGIN
|
||||
newmail_dir = newmail
|
||||
endif
|
||||
|
||||
if BUILD_NOTIFICATION_PLUGIN
|
||||
notification_dir = notification
|
||||
endif
|
||||
|
||||
if BUILD_PDF_VIEWER_PLUGIN
|
||||
pdf_viewer_dir = pdf_viewer
|
||||
endif
|
||||
|
||||
if BUILD_PERL_PLUGIN
|
||||
perl_dir = perl
|
||||
endif
|
||||
|
||||
if BUILD_PYTHON_PLUGIN
|
||||
python_dir = python
|
||||
endif
|
||||
|
||||
if BUILD_PGPCORE_PLUGIN
|
||||
pgpcore_dir = pgpcore
|
||||
if BUILD_PGPMIME_PLUGIN
|
||||
|
@ -75,9 +111,18 @@ SUBDIRS = \
|
|||
$(attachwarner_dir) \
|
||||
$(bogofilter_dir) \
|
||||
$(bsfilter_dir) \
|
||||
$(clamd_dir) \
|
||||
$(demo_dir) \
|
||||
$(dillo_viewer_dir) \
|
||||
$(fancy_dir) \
|
||||
$(fetchinfo_dir) \
|
||||
$(gdata_dir) \
|
||||
$(mailmbox_dir) \
|
||||
$(newmail_dir) \
|
||||
$(notification_dir) \
|
||||
$(pdf_viewer_dir) \
|
||||
$(perl_dir) \
|
||||
$(python_dir) \
|
||||
$(pgpcore_dir) \
|
||||
$(pgpmime_dir) \
|
||||
$(pgpinline_dir) \
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
plugindir = $(pkglibdir)/plugins
|
||||
|
||||
INCLUDES = @GLIB_CFLAGS@ \
|
||||
-I$(top_srcdir) -I$(top_builddir)
|
||||
|
||||
plugin_LTLIBRARIES = archive.la
|
||||
|
||||
archive_la_SOURCES = \
|
||||
|
|
30
src/plugins/clamd/Makefile.am
Normal file
30
src/plugins/clamd/Makefile.am
Normal file
|
@ -0,0 +1,30 @@
|
|||
SUBDIRS = libclamd
|
||||
plugindir = $(pkglibdir)/plugins
|
||||
|
||||
plugin_LTLIBRARIES = clamd.la
|
||||
|
||||
clamd_la_SOURCES = \
|
||||
clamav_plugin.c \
|
||||
clamav_plugin_gtk.c \
|
||||
clamav_plugin.h
|
||||
|
||||
clamd_la_LDFLAGS = \
|
||||
-avoid-version -module \
|
||||
$(GTK_LIBS) \
|
||||
-L$(top_builddir)/src/plugins/clamd/libclamd
|
||||
|
||||
clamd_la_LIBADD = \
|
||||
-lclamd-plugin
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src/plugins/clamd/libclamd \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/common \
|
||||
-I$(top_srcdir)/src/gtk
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-Wall \
|
||||
$(CLAWS_MAIL_CFLAGS) \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(GTK_CFLAGS) \
|
||||
-DLOCALEDIR=\""$(localedir)"\"
|
344
src/plugins/clamd/clamav_plugin.c
Normal file
344
src/plugins/clamd/clamav_plugin.c
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 2003-2010 Michael Rasmussen and the Claws Mail Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# include "claws-features.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include "common/claws.h"
|
||||
#include "common/version.h"
|
||||
#include "plugin.h"
|
||||
#include "utils.h"
|
||||
#include "hooks.h"
|
||||
#include "inc.h"
|
||||
#include "mimeview.h"
|
||||
#include "folder.h"
|
||||
#include "prefs.h"
|
||||
#include "prefs_gtk.h"
|
||||
#include "alertpanel.h"
|
||||
|
||||
#include "clamav_plugin.h"
|
||||
#include "clamd-plugin.h"
|
||||
|
||||
#define PLUGIN_NAME (_("Clam AntiVirus"))
|
||||
|
||||
static guint hook_id;
|
||||
static MessageCallback message_callback;
|
||||
|
||||
static ClamAvConfig config;
|
||||
|
||||
static PrefParam param[] = {
|
||||
{"clamav_enable", "FALSE", &config.clamav_enable, P_BOOL,
|
||||
NULL, NULL, NULL},
|
||||
/* {"clamav_enable_arc", "FALSE", &config.clamav_enable_arc, P_BOOL,
|
||||
NULL, NULL, NULL},*/
|
||||
{"clamav_max_size", "1", &config.clamav_max_size, P_USHORT,
|
||||
NULL, NULL, NULL},
|
||||
{"clamav_recv_infected", "TRUE", &config.clamav_recv_infected, P_BOOL,
|
||||
NULL, NULL, NULL},
|
||||
{"clamav_save_folder", NULL, &config.clamav_save_folder, P_STRING,
|
||||
NULL, NULL, NULL},
|
||||
{"clamad_config_type", "TRUE", &config.clamd_config_type, P_BOOL,
|
||||
NULL, NULL, NULL},
|
||||
{"clamd_config_folder", NULL, &config.clamd_config_folder, P_STRING,
|
||||
NULL, NULL, NULL},
|
||||
{"clamd_host", NULL, &config.clamd_host, P_STRING,
|
||||
NULL, NULL, NULL},
|
||||
{"clamd_port", NULL, &config.clamd_port, P_INT,
|
||||
NULL, NULL, NULL},
|
||||
|
||||
{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
struct clamd_result {
|
||||
Clamd_Stat status;
|
||||
};
|
||||
|
||||
static gboolean scan_func(GNode *node, gpointer data)
|
||||
{
|
||||
struct clamd_result *result = (struct clamd_result *) data;
|
||||
MimeInfo *mimeinfo = (MimeInfo *) node->data;
|
||||
gchar *outfile;
|
||||
response buf;
|
||||
int max;
|
||||
struct stat info;
|
||||
|
||||
outfile = procmime_get_tmp_file_name(mimeinfo);
|
||||
if (procmime_get_part(outfile, mimeinfo) < 0)
|
||||
g_warning("Can't get the part of multipart message.");
|
||||
else {
|
||||
max = config.clamav_max_size * 1048576; /* maximum file size */
|
||||
if (stat(outfile, &info) == -1)
|
||||
g_warning("Can't determine file size");
|
||||
else {
|
||||
if (info.st_size <= max) {
|
||||
debug_print("Scanning %s\n", outfile);
|
||||
result->status = clamd_verify_email(outfile, &buf);
|
||||
debug_print("status: %d\n", result->status);
|
||||
switch (result->status) {
|
||||
case NO_SOCKET:
|
||||
g_warning("[scanning] No socket information");
|
||||
alertpanel_error(_("Scanning\nNo socket information.\nAntivirus disabled."));
|
||||
break;
|
||||
case NO_CONNECTION:
|
||||
g_warning("[scanning] Clamd does not respond to ping");
|
||||
alertpanel_warning(_("Scanning\nClamd does not respond to ping.\nIs clamd running?"));
|
||||
break;
|
||||
case VIRUS:
|
||||
g_warning("Detected %s virus.\n", clamd_get_virus_name(buf.msg));
|
||||
alertpanel_warning(_("Detected %s virus."), clamd_get_virus_name(buf.msg));
|
||||
break;
|
||||
case SCAN_ERROR:
|
||||
debug_print("Error: %s\n", buf.msg);
|
||||
alertpanel_error(_("Scanning error:\n%s"), buf.msg);
|
||||
break;
|
||||
case OK:
|
||||
debug_print("No virus detected.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug_print("File: %s. Size (%d) greater than limit (%d)\n",
|
||||
outfile, (int) info.st_size, max);
|
||||
}
|
||||
}
|
||||
g_unlink(outfile);
|
||||
}
|
||||
|
||||
return (result->status == OK) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
static gboolean mail_filtering_hook(gpointer source, gpointer data)
|
||||
{
|
||||
MailFilteringData *mail_filtering_data = (MailFilteringData *) source;
|
||||
MsgInfo *msginfo = mail_filtering_data->msginfo;
|
||||
MimeInfo *mimeinfo;
|
||||
|
||||
struct clamd_result result;
|
||||
|
||||
if (!config.clamav_enable)
|
||||
return FALSE;
|
||||
|
||||
mimeinfo = procmime_scan_message(msginfo);
|
||||
if (!mimeinfo) return FALSE;
|
||||
|
||||
debug_print("Scanning message %d for viruses\n", msginfo->msgnum);
|
||||
if (message_callback != NULL)
|
||||
message_callback(_("ClamAV: scanning message..."));
|
||||
|
||||
debug_print("status: %d\n", result.status);
|
||||
g_node_traverse(mimeinfo->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, scan_func, &result);
|
||||
|
||||
if (result.status == VIRUS) {
|
||||
if (config.clamav_recv_infected) {
|
||||
FolderItem *clamav_save_folder;
|
||||
|
||||
if ((!config.clamav_save_folder) ||
|
||||
(config.clamav_save_folder[0] == '\0') ||
|
||||
((clamav_save_folder = folder_find_item_from_identifier(config.clamav_save_folder)) == NULL))
|
||||
clamav_save_folder = folder_get_default_trash();
|
||||
|
||||
procmsg_msginfo_unset_flags(msginfo, ~0, 0);
|
||||
msginfo->filter_op = IS_MOVE;
|
||||
msginfo->to_filter_folder = clamav_save_folder;
|
||||
} else {
|
||||
folder_item_remove_msg(msginfo->folder, msginfo->msgnum);
|
||||
}
|
||||
}
|
||||
|
||||
procmime_mimeinfo_free_all(mimeinfo);
|
||||
|
||||
return (result.status == OK) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
Clamd_Stat clamd_prepare(void) {
|
||||
debug_print("Creating socket\n");
|
||||
if (!config.clamd_config_type || (config.clamd_host != NULL && config.clamd_port > 0)) {
|
||||
if (config.clamd_host == NULL || config.clamd_port < 1) {
|
||||
/* error */
|
||||
return NO_SOCKET;
|
||||
}
|
||||
/* Manual configuration has highest priority */
|
||||
debug_print("Using user input: %s:%d\n",
|
||||
config.clamd_host, config.clamd_port);
|
||||
clamd_create_config_manual(config.clamd_host, config.clamd_port);
|
||||
}
|
||||
else if (config.clamd_config_type || config.clamd_config_folder != NULL) {
|
||||
if (config.clamd_config_folder == NULL) {
|
||||
/* error */
|
||||
return NO_SOCKET;
|
||||
}
|
||||
debug_print("Using clamd.conf: %s\n", config.clamd_config_folder);
|
||||
clamd_create_config_automatic(config.clamd_config_folder);
|
||||
}
|
||||
else {
|
||||
/* Fall back. Try enable anyway */
|
||||
if (! clamd_find_socket())
|
||||
return NO_SOCKET;
|
||||
}
|
||||
|
||||
return clamd_init(NULL);
|
||||
}
|
||||
|
||||
ClamAvConfig *clamav_get_config(void)
|
||||
{
|
||||
return &config;
|
||||
}
|
||||
|
||||
void clamav_save_config(void)
|
||||
{
|
||||
PrefFile *pfile;
|
||||
gchar *rcpath;
|
||||
|
||||
debug_print("Saving Clamd Page\n");
|
||||
|
||||
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
|
||||
pfile = prefs_write_open(rcpath);
|
||||
g_free(rcpath);
|
||||
if (!pfile || (prefs_set_block_label(pfile, "ClamAV") < 0))
|
||||
return;
|
||||
|
||||
if (prefs_write_param(param, pfile->fp) < 0) {
|
||||
g_warning("failed to write Clamd configuration to file\n");
|
||||
prefs_file_close_revert(pfile);
|
||||
return;
|
||||
}
|
||||
if (fprintf(pfile->fp, "\n") < 0) {
|
||||
FILE_OP_ERROR(rcpath, "fprintf");
|
||||
prefs_file_close_revert(pfile);
|
||||
} else
|
||||
prefs_file_close(pfile);
|
||||
}
|
||||
|
||||
void clamav_set_message_callback(MessageCallback callback)
|
||||
{
|
||||
message_callback = callback;
|
||||
}
|
||||
|
||||
gint plugin_init(gchar **error)
|
||||
{
|
||||
gchar *rcpath;
|
||||
|
||||
if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
|
||||
VERSION_NUMERIC, PLUGIN_NAME, error))
|
||||
return -1;
|
||||
|
||||
hook_id = hooks_register_hook(MAIL_FILTERING_HOOKLIST, mail_filtering_hook, NULL);
|
||||
if (hook_id == -1) {
|
||||
*error = g_strdup(_("Failed to register mail filtering hook"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
prefs_set_default(param);
|
||||
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
|
||||
prefs_read_config(param, "ClamAV", rcpath, NULL);
|
||||
g_free(rcpath);
|
||||
|
||||
clamav_gtk_init();
|
||||
|
||||
if (config.clamav_enable) {
|
||||
debug_print("Creating socket\n");
|
||||
Clamd_Stat status = clamd_prepare();
|
||||
switch (status) {
|
||||
case NO_SOCKET:
|
||||
g_warning("[init] No socket information");
|
||||
alertpanel_error(_("Init\nNo socket information.\nAntivirus disabled."));
|
||||
break;
|
||||
case NO_CONNECTION:
|
||||
g_warning("[init] Clamd does not respond to ping");
|
||||
alertpanel_warning(_("Init\nClamd does not respond to ping.\nIs clamd running?"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
debug_print("Clamd plugin loaded\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
gboolean plugin_done(void)
|
||||
{
|
||||
hooks_unregister_hook(MAIL_FILTERING_HOOKLIST, hook_id);
|
||||
g_free(config.clamav_save_folder);
|
||||
clamav_gtk_done();
|
||||
clamd_free();
|
||||
|
||||
debug_print("Clamd plugin unloaded\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const gchar *plugin_name(void)
|
||||
{
|
||||
return PLUGIN_NAME;
|
||||
}
|
||||
|
||||
const gchar *plugin_desc(void)
|
||||
{
|
||||
return _("This plugin uses Clam AntiVirus to scan all messages that are "
|
||||
"received from an IMAP, LOCAL or POP account.\n"
|
||||
"\n"
|
||||
"When a message attachment is found to contain a virus it can be "
|
||||
"deleted or saved in a specially designated folder.\n"
|
||||
"\n"
|
||||
"Because this plugin communicates with clamd via a\n"
|
||||
"socket then there are some minimum requirements to\n"
|
||||
"the permissions for your home folder and the\n"
|
||||
".claws-mail folder provided the clamav-daemon is\n"
|
||||
"configured to communicate via a unix socket. All\n"
|
||||
"users at least need to be given execute permissions\n"
|
||||
"on these folders.\n"
|
||||
"\n"
|
||||
"To avoid changing permissions you could configure\n"
|
||||
"the clamav-daemon to communicate via a TCP socket\n"
|
||||
"and choose manual configuration for clamd.\n"
|
||||
"\n"
|
||||
"Options can be found in /Configuration/Preferences/Plugins/Clam AntiVirus");
|
||||
}
|
||||
|
||||
const gchar *plugin_type(void)
|
||||
{
|
||||
return "GTK2";
|
||||
}
|
||||
|
||||
const gchar *plugin_licence(void)
|
||||
{
|
||||
return "GPL3+";
|
||||
}
|
||||
|
||||
const gchar *plugin_version(void)
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
struct PluginFeature *plugin_provides(void)
|
||||
{
|
||||
static struct PluginFeature features[] =
|
||||
{ {PLUGIN_FILTERING, N_("Virus detection")},
|
||||
{PLUGIN_NOTHING, NULL}};
|
||||
return features;
|
||||
}
|
50
src/plugins/clamd/clamav_plugin.h
Normal file
50
src/plugins/clamd/clamav_plugin.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 2003-2010 Michael Rasmussen and the Claws Mail Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CLAMAV_PLUGIN_H
|
||||
#define CLAMAV_PLUGIN_H 1
|
||||
|
||||
#include <glib.h>
|
||||
#include "clamd-plugin.h"
|
||||
|
||||
typedef struct _ClamAvConfig ClamAvConfig;
|
||||
|
||||
typedef void (*MessageCallback) (gchar *);
|
||||
|
||||
struct _ClamAvConfig
|
||||
{
|
||||
gboolean clamav_enable;
|
||||
/* gboolean clamav_enable_arc;*/
|
||||
guint clamav_max_size;
|
||||
gboolean clamav_recv_infected;
|
||||
gchar *clamav_save_folder;
|
||||
gboolean clamd_config_type;
|
||||
gchar *clamd_host;
|
||||
int clamd_port;
|
||||
gchar *clamd_config_folder;
|
||||
};
|
||||
|
||||
ClamAvConfig *clamav_get_config (void);
|
||||
void clamav_save_config (void);
|
||||
void clamav_set_message_callback (MessageCallback callback);
|
||||
Clamd_Stat clamd_prepare(void);
|
||||
gint clamav_gtk_init(void);
|
||||
void clamav_gtk_done(void);
|
||||
|
||||
#endif
|
569
src/plugins/clamd/clamav_plugin_gtk.c
Normal file
569
src/plugins/clamd/clamav_plugin_gtk.c
Normal file
|
@ -0,0 +1,569 @@
|
|||
/*
|
||||
* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 2003-2010 the Claws Mail Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# include "claws-features.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtk/gtkutils.h>
|
||||
|
||||
#include "common/claws.h"
|
||||
#include "common/version.h"
|
||||
#include "plugin.h"
|
||||
#include "utils.h"
|
||||
#include "prefs.h"
|
||||
#include "folder.h"
|
||||
#include "prefs_gtk.h"
|
||||
#include "foldersel.h"
|
||||
#include "clamav_plugin.h"
|
||||
#include "statusbar.h"
|
||||
#include "alertpanel.h"
|
||||
#include "clamd-plugin.h"
|
||||
|
||||
struct ClamAvPage
|
||||
{
|
||||
PrefsPage page;
|
||||
|
||||
GtkWidget *enable_clamav;
|
||||
/* GtkWidget *enable_arc;*/
|
||||
GtkWidget *max_size;
|
||||
GtkWidget *recv_infected;
|
||||
GtkWidget *save_folder;
|
||||
GtkWidget *config_type;
|
||||
GtkWidget *config_folder;
|
||||
GtkWidget *config_host;
|
||||
GtkWidget *config_port;
|
||||
};
|
||||
|
||||
static GtkWidget *hbox_auto1, *hbox_auto2, *hbox_manual1, *hbox_manual2;
|
||||
|
||||
static void foldersel_cb(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
struct ClamAvPage *page = (struct ClamAvPage *) data;
|
||||
FolderItem *item;
|
||||
gchar *item_id;
|
||||
gint newpos = 0;
|
||||
|
||||
item = foldersel_folder_sel(NULL, FOLDER_SEL_MOVE, NULL, FALSE);
|
||||
if (item && (item_id = folder_item_get_identifier(item)) != NULL) {
|
||||
gtk_editable_delete_text(GTK_EDITABLE(page->save_folder), 0, -1);
|
||||
gtk_editable_insert_text(GTK_EDITABLE(page->save_folder), item_id, strlen(item_id), &newpos);
|
||||
g_free(item_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void clamd_folder_cb(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
gchar* file;
|
||||
gint newpos = 0;
|
||||
struct ClamAvPage *page = (struct ClamAvPage *) data;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new(
|
||||
"Select file with clamd configuration [clamd.conf]",
|
||||
NULL,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
|
||||
NULL);
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), "/etc");
|
||||
if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_APPLY) {
|
||||
file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
debug_print("New clamd.conf: %s\n", file);
|
||||
if (file) {
|
||||
gtk_editable_delete_text(GTK_EDITABLE(page->config_folder), 0, -1);
|
||||
gtk_editable_insert_text(GTK_EDITABLE(page->config_folder), file, strlen(file), &newpos);
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
static void check_permission(gchar* folder) {
|
||||
struct stat info;
|
||||
|
||||
g_stat(folder, &info);
|
||||
mode_t perm = info.st_mode & ~(S_IFMT);
|
||||
debug_print("%s: Old file permission: %05o\n", folder, perm);
|
||||
if ((perm & S_IXOTH) != S_IXOTH) {
|
||||
perm = perm | S_IXOTH;
|
||||
g_chmod(folder, perm);
|
||||
}
|
||||
debug_print("%s: New file permission: %05o\n", folder, perm);
|
||||
}
|
||||
|
||||
static void folder_permission_cb(GtkWidget *widget, gpointer data) {
|
||||
static gchar* folders[] = {
|
||||
".claws-mail",
|
||||
".claws-mail/mimetmp",
|
||||
".claws-mail/tmp",
|
||||
NULL};
|
||||
const gchar* home = g_get_home_dir();
|
||||
int i;
|
||||
|
||||
check_permission((gchar *) home);
|
||||
for (i = 0; folders[i]; i++) {
|
||||
gchar* file = g_strdup_printf("%s/%s", home, folders[i]);
|
||||
check_permission(file);
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
static void clamav_show_config(Config* config) {
|
||||
if (config) {
|
||||
if (config->ConfigType == MANUAL) {
|
||||
gtk_widget_hide(hbox_auto1);
|
||||
gtk_widget_hide(hbox_auto2);
|
||||
gtk_widget_show(hbox_manual1);
|
||||
gtk_widget_show(hbox_manual2);
|
||||
}
|
||||
else {
|
||||
gtk_widget_hide(hbox_manual1);
|
||||
gtk_widget_hide(hbox_manual2);
|
||||
gtk_widget_show(hbox_auto1);
|
||||
gtk_widget_show(hbox_auto2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void setting_type_cb(GtkWidget *widget, gpointer data) {
|
||||
gboolean state = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
|
||||
struct ClamAvPage *page = (struct ClamAvPage *) data;
|
||||
Config* c;
|
||||
gint newpos = 0;
|
||||
gboolean tmp_conf = FALSE;
|
||||
|
||||
if (page && page->page.widget) {
|
||||
/* Reset configuration */
|
||||
debug_print("Resetting configuration\n");
|
||||
gtk_editable_delete_text(GTK_EDITABLE(page->config_folder), 0, -1);
|
||||
gtk_editable_delete_text(GTK_EDITABLE(page->config_host), 0, -1);
|
||||
gtk_editable_delete_text(GTK_EDITABLE(page->config_port), 0, -1);
|
||||
clamav_save_config();
|
||||
|
||||
c = clamd_get_config();
|
||||
if (!c) {
|
||||
c = clamd_config_new();
|
||||
tmp_conf = TRUE;
|
||||
}
|
||||
if (state) {
|
||||
/* Automatic configuration */
|
||||
debug_print("Setting clamd to automatic configuration\n");
|
||||
if (clamd_find_socket()) {
|
||||
if (tmp_conf) {
|
||||
Config* clamd_conf = clamd_get_config();
|
||||
if (clamd_conf->automatic.folder)
|
||||
c->automatic.folder = g_strdup(clamd_conf->automatic.folder);
|
||||
else
|
||||
c->automatic.folder = g_strdup("");
|
||||
}
|
||||
if (c->ConfigType == AUTOMATIC) {
|
||||
gtk_editable_insert_text(GTK_EDITABLE(page->config_folder),
|
||||
c->automatic.folder, strlen(c->automatic.folder), &newpos);
|
||||
clamav_save_config();
|
||||
}
|
||||
}
|
||||
c->ConfigType = AUTOMATIC;
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->config_type), TRUE);
|
||||
}
|
||||
else {
|
||||
/* Manual configuration */
|
||||
debug_print("Setting clamd to manual configuration\n");
|
||||
c->ConfigType = MANUAL;
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->config_type), FALSE);
|
||||
}
|
||||
clamav_show_config(c);
|
||||
if (tmp_conf)
|
||||
clamd_config_free(c);
|
||||
}
|
||||
}
|
||||
|
||||
static void clamav_create_widget_func(PrefsPage * _page, GtkWindow *window, gpointer data)
|
||||
{
|
||||
struct ClamAvPage *page = (struct ClamAvPage *) _page;
|
||||
ClamAvConfig *config;
|
||||
Config *clamd_config;
|
||||
|
||||
GtkWidget *vbox1, *vbox2;
|
||||
GtkWidget *enable_clamav;
|
||||
GtkWidget *label1;
|
||||
/* GtkWidget *enable_arc;*/
|
||||
GtkWidget *label2;
|
||||
GtkObject *max_size_adj;
|
||||
GtkWidget *max_size;
|
||||
GtkWidget *hbox1;
|
||||
GtkWidget *recv_infected;
|
||||
GtkWidget *save_folder;
|
||||
GtkWidget *save_folder_select;
|
||||
GtkWidget *clamd_conf_label;
|
||||
GtkWidget *config_folder;
|
||||
GtkWidget *config_host;
|
||||
GtkWidget *config_port;
|
||||
GtkWidget *config_folder_select;
|
||||
GtkWidget *blank;
|
||||
GtkWidget *permission_label;
|
||||
GtkWidget *permission_select;
|
||||
GtkWidget *host_label;
|
||||
GtkWidget *port_label;
|
||||
GtkWidget *setting_type;
|
||||
GtkTooltips *tooltips;
|
||||
|
||||
tooltips = gtk_tooltips_new();
|
||||
enable_clamav = page->enable_clamav;
|
||||
|
||||
vbox1 = gtk_vbox_new (FALSE, VSPACING);
|
||||
gtk_widget_show (vbox1);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (vbox1), VBOX_BORDER);
|
||||
|
||||
vbox2 = gtk_vbox_new (FALSE, 4);
|
||||
gtk_widget_show (vbox2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, FALSE, 0);
|
||||
|
||||
PACK_CHECK_BUTTON (vbox2, enable_clamav, _("Enable virus scanning"));
|
||||
/* PACK_CHECK_BUTTON (vbox2, enable_arc, _("Scan archive contents"));
|
||||
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, enable_arc);*/
|
||||
|
||||
hbox1 = gtk_hbox_new (FALSE, 8);
|
||||
gtk_widget_show (hbox1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 0);
|
||||
/* SET_TOGGLE_SENSITIVITY (enable_arc, hbox1);*/
|
||||
|
||||
label1 = gtk_label_new(_("Maximum attachment size"));
|
||||
gtk_widget_show (label1);
|
||||
gtk_box_pack_start (GTK_BOX (hbox1), label1, FALSE, FALSE, 0);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, label1);
|
||||
|
||||
max_size_adj = gtk_adjustment_new (1, 1, 1024, 1, 10, 0);
|
||||
max_size = gtk_spin_button_new (GTK_ADJUSTMENT (max_size_adj), 1, 0);
|
||||
gtk_widget_show (max_size);
|
||||
gtk_box_pack_start (GTK_BOX (hbox1), max_size, FALSE, FALSE, 0);
|
||||
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (max_size), TRUE);
|
||||
gtk_tooltips_set_tip(tooltips, max_size,
|
||||
_("Message attachments larger than this will not be scanned"),
|
||||
NULL);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, max_size);
|
||||
|
||||
label2 = gtk_label_new(_("MB"));
|
||||
gtk_widget_show (label2);
|
||||
gtk_box_pack_start (GTK_BOX (hbox1), label2, FALSE, FALSE, 0);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, label2);
|
||||
|
||||
hbox1 = gtk_hbox_new (FALSE, 8);
|
||||
gtk_widget_show (hbox1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 0);
|
||||
|
||||
recv_infected = gtk_check_button_new_with_label(_("Save infected mail in"));
|
||||
gtk_widget_show (recv_infected);
|
||||
gtk_box_pack_start (GTK_BOX (hbox1), recv_infected, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip(tooltips, recv_infected,
|
||||
_("Save mail that contains viruses"),
|
||||
NULL);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, recv_infected);
|
||||
|
||||
save_folder = gtk_entry_new ();
|
||||
gtk_widget_show (save_folder);
|
||||
gtk_box_pack_start (GTK_BOX (hbox1), save_folder, TRUE, TRUE, 0);
|
||||
gtk_tooltips_set_tip(tooltips, save_folder,
|
||||
_("Folder for storing infected mail. Leave empty to use the default trash folder"),
|
||||
NULL);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, save_folder);
|
||||
|
||||
save_folder_select = gtkut_get_browse_directory_btn(_("_Browse"));
|
||||
gtk_widget_show (save_folder_select);
|
||||
gtk_box_pack_start (GTK_BOX (hbox1), save_folder_select, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip(tooltips, save_folder_select,
|
||||
_("Click this button to select a folder for storing infected mail"),
|
||||
NULL);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, save_folder_select);
|
||||
|
||||
hbox1 = gtk_hbox_new (FALSE, 8);
|
||||
gtk_widget_show (hbox1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 0);
|
||||
|
||||
setting_type = gtk_check_button_new_with_label(_("Automatic configuration"));
|
||||
/*gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(setting_type), TRUE);*/
|
||||
gtk_widget_show (setting_type);
|
||||
gtk_box_pack_start (GTK_BOX (hbox1), setting_type, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip(tooltips, setting_type,
|
||||
_("Should configuration be done automatic or manual"),
|
||||
NULL);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, setting_type);
|
||||
|
||||
hbox_auto1 = gtk_hbox_new (FALSE, 8);
|
||||
gtk_widget_show (hbox_auto1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), hbox_auto1, FALSE, FALSE, 0);
|
||||
|
||||
clamd_conf_label = gtk_label_new(_("Where is clamd.conf"));
|
||||
gtk_widget_show (clamd_conf_label);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_auto1), clamd_conf_label, FALSE, FALSE, 0);
|
||||
|
||||
config_folder = gtk_entry_new ();
|
||||
gtk_widget_show (config_folder);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_auto1), config_folder, TRUE, TRUE, 0);
|
||||
gtk_tooltips_set_tip(tooltips, config_folder,
|
||||
_("Full path to clamd.conf. If this field is not empty then the plugin has been able to locate the file automatically"),
|
||||
NULL);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, config_folder);
|
||||
|
||||
config_folder_select = gtkut_get_browse_directory_btn(_("Br_owse"));
|
||||
gtk_widget_show (config_folder_select);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_auto1), config_folder_select, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip(tooltips, config_folder_select,
|
||||
_("Click this button to select full path to clamd.conf"),
|
||||
NULL);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, config_folder_select);
|
||||
|
||||
hbox_auto2 = gtk_hbox_new (FALSE, 8);
|
||||
gtk_widget_show (hbox_auto2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), hbox_auto2, FALSE, FALSE, 0);
|
||||
|
||||
permission_label = gtk_label_new(_("Check permission for folders and adjust if necessary"));
|
||||
gtk_widget_show (permission_label);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_auto2), permission_label, FALSE, FALSE, 0);
|
||||
|
||||
blank = gtk_label_new("");
|
||||
gtk_widget_show (blank);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_auto2), blank, TRUE, TRUE, 0);
|
||||
|
||||
permission_select = gtk_button_new_from_stock(GTK_STOCK_FIND_AND_REPLACE);
|
||||
/*gtk_button_new_with_mnemonic(_("_Check Permission"));*/
|
||||
gtk_widget_show (permission_select);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_auto2), permission_select, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip(tooltips, permission_select,
|
||||
_("Click this button to check and adjust folder permissions"),
|
||||
NULL);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, permission_select);
|
||||
|
||||
hbox_manual1 = gtk_hbox_new (FALSE, 8);
|
||||
gtk_widget_show (hbox_manual1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), hbox_manual1, FALSE, FALSE, 0);
|
||||
|
||||
host_label = gtk_label_new(_("Remote Host"));
|
||||
gtk_widget_show (host_label);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_manual1), host_label, FALSE, FALSE, 0);
|
||||
|
||||
config_host = gtk_entry_new ();
|
||||
gtk_widget_show (config_host);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_manual1), config_host, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip(tooltips, config_host,
|
||||
_("Hostname or IP for remote host running clamav daemon"),
|
||||
NULL);
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, config_host);
|
||||
|
||||
blank = gtk_label_new("");
|
||||
gtk_widget_show (blank);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_manual1), blank, TRUE, TRUE, 0);
|
||||
|
||||
hbox_manual2 = gtk_hbox_new (FALSE, 8);
|
||||
gtk_widget_show (hbox_manual2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), hbox_manual2, FALSE, FALSE, 0);
|
||||
|
||||
port_label = gtk_label_new(_("Port"));
|
||||
gtk_widget_show (port_label);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_manual2), port_label, FALSE, FALSE, 0);
|
||||
|
||||
config_port = gtk_entry_new ();
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(config_port), 5);
|
||||
gtk_entry_set_max_length(GTK_ENTRY(config_port), 5);
|
||||
gtk_widget_show (config_port);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_manual2), config_port, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip(tooltips, config_port,
|
||||
_("Port number where clamav daemon is listening"),
|
||||
NULL);
|
||||
|
||||
blank = gtk_label_new("");
|
||||
gtk_widget_show (blank);
|
||||
gtk_box_pack_start (GTK_BOX (hbox_manual2), blank, TRUE, TRUE, 0);
|
||||
|
||||
SET_TOGGLE_SENSITIVITY (enable_clamav, config_port);
|
||||
|
||||
g_signal_connect(G_OBJECT(save_folder_select), "clicked",
|
||||
G_CALLBACK(foldersel_cb), page);
|
||||
g_signal_connect(G_OBJECT(config_folder_select), "clicked",
|
||||
G_CALLBACK(clamd_folder_cb), page);
|
||||
g_signal_connect(G_OBJECT(permission_select), "clicked",
|
||||
G_CALLBACK(folder_permission_cb), page);
|
||||
g_signal_connect(G_OBJECT(setting_type), "clicked",
|
||||
G_CALLBACK(setting_type_cb), page);
|
||||
|
||||
config = clamav_get_config();
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_clamav), config->clamav_enable);
|
||||
/* gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_arc), config->clamav_enable_arc);*/
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(max_size), (float) config->clamav_max_size);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(recv_infected), config->clamav_recv_infected);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(setting_type), config->clamd_config_type);
|
||||
|
||||
clamd_config = clamd_get_config();
|
||||
|
||||
if (config->clamav_save_folder != NULL)
|
||||
gtk_entry_set_text(GTK_ENTRY(save_folder), config->clamav_save_folder);
|
||||
if (!config->clamd_config_type) {
|
||||
/*if (config->clamd_host && strlen(config->clamd_host) > 0 && config->clamd_port > 0) {*/
|
||||
gtk_entry_set_text(GTK_ENTRY(config_host), config->clamd_host);
|
||||
gchar* s = int2char(config->clamd_port);
|
||||
gtk_entry_set_text(GTK_ENTRY(config_port), s);
|
||||
g_free(s);
|
||||
/* activate manual checkbox and blind folder */
|
||||
debug_print("Showing manual configuration and hiding automatic configuration\n");
|
||||
if (! clamd_config) {
|
||||
clamd_config = clamd_config_new();
|
||||
clamd_config->ConfigType = MANUAL;
|
||||
clamav_show_config(clamd_config);
|
||||
clamd_config_free(clamd_config);
|
||||
}
|
||||
else
|
||||
clamav_show_config(clamd_config);
|
||||
}
|
||||
else {
|
||||
//else if (config->clamd_config_folder == NULL || strlen(config->clamd_config_folder) == 0) {
|
||||
if (clamd_find_socket()) {
|
||||
Config* c = clamd_get_config();
|
||||
if (c && c->ConfigType == AUTOMATIC) {
|
||||
config->clamd_config_folder = g_strdup(c->automatic.folder);
|
||||
/* deactivate manual checkbox and blind host and port */
|
||||
debug_print("Showing automatic configuration and hiding manual configuration\n");
|
||||
clamav_show_config(c);
|
||||
gint newpos = 0;
|
||||
gtk_editable_delete_text(GTK_EDITABLE(config_folder), 0, -1);
|
||||
gtk_editable_insert_text(GTK_EDITABLE(config_folder),
|
||||
config->clamd_config_folder, strlen(config->clamd_config_folder), &newpos);
|
||||
}
|
||||
else if (c && c->ConfigType == MANUAL) {
|
||||
/* deactivate automatic automatic configuration */
|
||||
debug_print("Showing manual configuration and hiding automatic configuration\n");
|
||||
clamav_show_config(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* else {
|
||||
gtk_entry_set_text(GTK_ENTRY(config_folder), config->clamd_config_folder);
|
||||
// deactivate manual checkbox and blind host and port
|
||||
debug_print("Showing automatic configuration and hiding manual configuration\n");
|
||||
if (! clamd_config) {
|
||||
clamd_config = clamd_config_new();
|
||||
clamd_config->ConfigType = AUTOMATIC;
|
||||
clamav_show_config(clamd_config);
|
||||
clamd_config_free(clamd_config);
|
||||
}
|
||||
else
|
||||
clamav_show_config(clamd_config);
|
||||
}*/
|
||||
|
||||
page->enable_clamav = enable_clamav;
|
||||
/* page->enable_arc = enable_arc;*/
|
||||
page->max_size = max_size;
|
||||
page->recv_infected = recv_infected;
|
||||
page->save_folder = save_folder;
|
||||
page->config_type = setting_type;
|
||||
page->config_folder = config_folder;
|
||||
page->config_host = config_host;
|
||||
page->config_port = config_port;
|
||||
page->page.widget = vbox1;
|
||||
|
||||
clamav_save_config();
|
||||
}
|
||||
|
||||
static void clamav_destroy_widget_func(PrefsPage *_page)
|
||||
{
|
||||
debug_print("Destroying Clamd widget\n");
|
||||
}
|
||||
|
||||
static void clamav_save_func(PrefsPage *_page)
|
||||
{
|
||||
struct ClamAvPage *page = (struct ClamAvPage *) _page;
|
||||
ClamAvConfig *config;
|
||||
|
||||
debug_print("Saving Clamd Page\n");
|
||||
|
||||
config = clamav_get_config();
|
||||
|
||||
config->clamav_enable = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->enable_clamav));
|
||||
/* config->clamav_enable_arc = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->enable_arc));*/
|
||||
|
||||
config->clamav_max_size = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(page->max_size));
|
||||
config->clamav_recv_infected = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->recv_infected));
|
||||
g_free(config->clamav_save_folder);
|
||||
config->clamav_save_folder = gtk_editable_get_chars(GTK_EDITABLE(page->save_folder), 0, -1);
|
||||
config->clamd_config_type = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->config_type));
|
||||
g_free(config->clamd_config_folder);
|
||||
config->clamd_config_folder = gtk_editable_get_chars(GTK_EDITABLE(page->config_folder), 0, -1);
|
||||
g_free(config->clamd_host);
|
||||
config->clamd_host = gtk_editable_get_chars(GTK_EDITABLE(page->config_host), 0, -1);
|
||||
config->clamd_port = atoi(gtk_entry_get_text(GTK_ENTRY(page->config_port)));
|
||||
|
||||
if (config->clamav_enable) {
|
||||
Clamd_Stat status = clamd_prepare();
|
||||
switch (status) {
|
||||
case NO_SOCKET:
|
||||
g_warning("[New config] No socket information");
|
||||
alertpanel_error(_("New config\nNo socket information.\nAntivirus disabled."));
|
||||
break;
|
||||
case NO_CONNECTION:
|
||||
g_warning("[New config] Clamd does not respond to ping");
|
||||
alertpanel_warning(_("New config\nClamd does not respond to ping.\nIs clamd running?"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
clamav_save_config();
|
||||
}
|
||||
|
||||
static struct ClamAvPage clamav_page;
|
||||
|
||||
static void gtk_message_callback(gchar *message)
|
||||
{
|
||||
statusbar_print_all("%s", message);
|
||||
}
|
||||
|
||||
gint clamav_gtk_init(void)
|
||||
{
|
||||
static gchar *path[3];
|
||||
|
||||
path[0] = _("Plugins");
|
||||
path[1] = _("Clam AntiVirus");
|
||||
path[2] = NULL;
|
||||
|
||||
clamav_page.page.path = path;
|
||||
clamav_page.page.create_widget = clamav_create_widget_func;
|
||||
clamav_page.page.destroy_widget = clamav_destroy_widget_func;
|
||||
clamav_page.page.save_page = clamav_save_func;
|
||||
clamav_page.page.weight = 35.0;
|
||||
|
||||
prefs_gtk_register_page((PrefsPage *) &clamav_page);
|
||||
clamav_set_message_callback(gtk_message_callback);
|
||||
|
||||
debug_print("Clamd GTK plugin loaded\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clamav_gtk_done(void)
|
||||
{
|
||||
prefs_gtk_unregister_page((PrefsPage *) &clamav_page);
|
||||
}
|
20
src/plugins/clamd/libclamd/Makefile.am
Normal file
20
src/plugins/clamd/libclamd/Makefile.am
Normal file
|
@ -0,0 +1,20 @@
|
|||
INCLUDES = @GLIB_CFLAGS@ \
|
||||
@GTK_CFLAGS@ \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_builddir) \
|
||||
$(CLAWS_MAIL_CFLAGS) \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/common \
|
||||
-I$(top_srcdir)/src/gtk
|
||||
|
||||
noinst_LTLIBRARIES = libclamd-plugin.la
|
||||
|
||||
libclamd_plugin_la_SOURCES = \
|
||||
clamd-plugin.h \
|
||||
clamd-plugin.c
|
||||
|
||||
noinst_HEADERS = clamd-plugin.h
|
||||
|
||||
libclamd_plugin_la_LIBADD = \
|
||||
@GLIB_LIBS@ \
|
||||
@GTK_LIBS@
|
689
src/plugins/clamd/libclamd/clamd-plugin.c
Normal file
689
src/plugins/clamd/libclamd/clamd-plugin.c
Normal file
|
@ -0,0 +1,689 @@
|
|||
/* vim: set textwidth=80 tabstop=4: */
|
||||
|
||||
/*
|
||||
* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 1999-2008 Michael Rasmussen and the Claws Mail Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtk/gtkutils.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/un.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "common/claws.h"
|
||||
#include "common/version.h"
|
||||
#include "plugin.h"
|
||||
#include "utils.h"
|
||||
#include "prefs.h"
|
||||
#include "folder.h"
|
||||
#include "prefs_gtk.h"
|
||||
#include "foldersel.h"
|
||||
#include "statusbar.h"
|
||||
#include "alertpanel.h"
|
||||
#include "clamd-plugin.h"
|
||||
|
||||
/* needs to be generic */
|
||||
static const gchar* config_dirs[] = {
|
||||
"/etc",
|
||||
"/usr/local/etc",
|
||||
"/etc/clamav",
|
||||
"/usr/local/etc/clamav",
|
||||
NULL };
|
||||
|
||||
static const gchar* clamd_tokens[] = {
|
||||
"LocalSocket",
|
||||
"TCPSocket",
|
||||
"TCPAddr",
|
||||
NULL };
|
||||
|
||||
static Clamd_Socket* Socket = NULL;
|
||||
static int sock;
|
||||
static Config* config = NULL;
|
||||
|
||||
/**
|
||||
* clamd commands used
|
||||
* prefixing with either z or n is recommended
|
||||
* z <=> null terminated command
|
||||
* n <=> newline terminated command
|
||||
*/
|
||||
static const gchar ping[] = "nPING\n";
|
||||
static const gchar version[] = "nVERSION\n";
|
||||
static const gchar scan[] = "nSCAN";
|
||||
static const gchar contscan[] = "nCONTSCAN";
|
||||
static const gchar instream[10] = "zINSTREAM\0";
|
||||
|
||||
void clamd_create_config_automatic(const gchar* path) {
|
||||
FILE* conf;
|
||||
char buf[1024];
|
||||
gchar* key = NULL;
|
||||
gchar* value = NULL;
|
||||
|
||||
/*debug_set_mode(TRUE);*/
|
||||
/*debug_print("%s : %s\n", folder, path);*/
|
||||
if (! path) {
|
||||
g_warning("Missing path");
|
||||
return;
|
||||
}
|
||||
if (config && config->ConfigType == AUTOMATIC &&
|
||||
config->automatic.folder &&
|
||||
strcmp(config->automatic.folder, path) == 0) {
|
||||
debug_print("%s : %s - Identical. No need to read again\n",
|
||||
config->automatic.folder, path);
|
||||
return;
|
||||
}
|
||||
if (config)
|
||||
clamd_config_free(config);
|
||||
config = clamd_config_new();
|
||||
|
||||
config->ConfigType = AUTOMATIC;
|
||||
config->automatic.folder = g_strdup(path);
|
||||
debug_print("Opening %s to parse config file\n", path);
|
||||
conf = fopen(path, "r");
|
||||
if (!conf) {
|
||||
/*g_error("%s: Unable to open", path);*/
|
||||
alertpanel_error(_("%s: Unable to open\nclamd will be disabled"), path);
|
||||
return;
|
||||
}
|
||||
while (fgets(buf, sizeof(buf), conf)) {
|
||||
g_strstrip(buf);
|
||||
if (buf[0] == '#')
|
||||
continue;
|
||||
const gchar** tokens = clamd_tokens;
|
||||
while (*tokens) {
|
||||
const gchar* token = *tokens++;
|
||||
if ((key = g_strstr_len(buf, strlen(buf), token)) != NULL) {
|
||||
gchar* tmp = &(*(key + strlen(token)));
|
||||
tmp = g_strchug(tmp);
|
||||
gchar* end = index(tmp, '#');
|
||||
if (end)
|
||||
value = g_strndup(tmp, end - tmp);
|
||||
else
|
||||
value = g_strdup(g_strchomp(tmp));
|
||||
if (strcmp(clamd_tokens[0], token) == 0) {
|
||||
/* UNIX socket */
|
||||
Socket = (Clamd_Socket *) malloc(sizeof(Clamd_Socket *));
|
||||
if (Socket) {
|
||||
Socket->socket.path = NULL;
|
||||
Socket->socket.host = NULL;
|
||||
Socket->socket.port = -1;
|
||||
Socket->type = UNIX_SOCKET;
|
||||
Socket->socket.path = g_strdup(value);
|
||||
g_free(value);
|
||||
value = NULL;
|
||||
fclose(conf);
|
||||
debug_print("clamctl: %s\n", Socket->socket.path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (strcmp(clamd_tokens[1], token) == 0) {
|
||||
/* INET socket */
|
||||
if (! Socket) {
|
||||
Socket = (Clamd_Socket *) malloc(sizeof(Clamd_Socket *));
|
||||
if (Socket) {
|
||||
Socket->socket.path = NULL;
|
||||
Socket->socket.host = NULL;
|
||||
Socket->socket.port = -1;
|
||||
Socket->type = INET_SOCKET;
|
||||
Socket->socket.port = atoi(value);
|
||||
Socket->socket.host = g_strdup("localhost");
|
||||
g_free(value);
|
||||
value = NULL;
|
||||
debug_print("clamctl: %s:%d\n",
|
||||
Socket->socket.host, Socket->socket.port);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Socket->type = INET_SOCKET;
|
||||
Socket->socket.port = atoi(value);
|
||||
g_free(value);
|
||||
value = NULL;
|
||||
if (! Socket->socket.host)
|
||||
Socket->socket.host = g_strdup("localhost");
|
||||
debug_print("clamctl: %s:%d\n",
|
||||
Socket->socket.host, Socket->socket.port);
|
||||
}
|
||||
/* We must continue since TCPAddr could also be configured */
|
||||
}
|
||||
else if (strcmp(clamd_tokens[2], token) == 0) {
|
||||
if (! Socket) {
|
||||
Socket = (Clamd_Socket *) malloc(sizeof(Clamd_Socket *));
|
||||
if (Socket) {
|
||||
Socket->socket.path = NULL;
|
||||
Socket->socket.host = NULL;
|
||||
Socket->socket.port = 3310; /* default port */
|
||||
Socket->type = INET_SOCKET;
|
||||
Socket->socket.host = g_strdup(value);
|
||||
g_free(value);
|
||||
value = NULL;
|
||||
debug_print("clamctl: %s:%d\n",
|
||||
Socket->socket.host, Socket->socket.port);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Socket->type = INET_SOCKET;
|
||||
if (Socket->socket.host)
|
||||
g_free(Socket->socket.host);
|
||||
Socket->socket.host = g_strdup(value);
|
||||
g_free(value);
|
||||
value = NULL;
|
||||
if (Socket->socket.port == -1)
|
||||
Socket->socket.port = 3310;
|
||||
debug_print("clamctl: %s:%d\n",
|
||||
Socket->socket.host, Socket->socket.port);
|
||||
}
|
||||
/* We must continue since TCPSocket could also be configured */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(conf);
|
||||
if (! (Socket && (Socket->socket.port || Socket->socket.path))) {
|
||||
/*g_error("%s: Not able to find required information", path);*/
|
||||
alertpanel_error(_("%s: Not able to find required information\nclamd will be disabled"), path);
|
||||
}
|
||||
/*debug_set_mode(FALSE);*/
|
||||
}
|
||||
|
||||
void clamd_create_config_manual(const gchar* host, int port) {
|
||||
if (! host || port < 1) {
|
||||
g_warning("Missing host or port < 1");
|
||||
return;
|
||||
}
|
||||
if (config && config->ConfigType == MANUAL &&
|
||||
config->manual.host && config->manual.port == port &&
|
||||
strcmp(config->manual.host, host) == 0) {
|
||||
debug_print("%s : %s and %d : %d - Identical. No need to read again\n",
|
||||
config->manual.host, host, config->manual.port, port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (config)
|
||||
clamd_config_free(config);
|
||||
config = clamd_config_new();
|
||||
|
||||
config->ConfigType = MANUAL;
|
||||
config->manual.host = g_strdup(host);
|
||||
config->manual.port = port;
|
||||
/* INET socket */
|
||||
Socket = (Clamd_Socket *) malloc(sizeof(Clamd_Socket *));
|
||||
if (Socket) {
|
||||
Socket->type = INET_SOCKET;
|
||||
Socket->socket.port = port;
|
||||
Socket->socket.host = g_strdup(host);
|
||||
}
|
||||
else {
|
||||
/*g_error("%s: Not able to find required information", path);*/
|
||||
alertpanel_error(_("Could not create socket"));
|
||||
}
|
||||
}
|
||||
|
||||
gboolean clamd_find_socket() {
|
||||
const gchar** config_dir = config_dirs;
|
||||
gchar *clamd_conf = NULL;
|
||||
|
||||
while (*config_dir) {
|
||||
clamd_conf = g_strdup_printf("%s/clamd.conf", *config_dir++);
|
||||
debug_print("Looking for %s\n", clamd_conf);
|
||||
if (g_file_test(clamd_conf, G_FILE_TEST_EXISTS))
|
||||
break;
|
||||
g_free(clamd_conf);
|
||||
clamd_conf = NULL;
|
||||
}
|
||||
if (! clamd_conf)
|
||||
return FALSE;
|
||||
|
||||
debug_print("Using %s to find configuration\n", clamd_conf);
|
||||
clamd_create_config_automatic(clamd_conf);
|
||||
g_free(clamd_conf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Config* clamd_get_config() {
|
||||
return config;
|
||||
}
|
||||
|
||||
Clamd_Socket* clamd_get_socket() {
|
||||
return Socket;
|
||||
}
|
||||
|
||||
static void close_socket() {
|
||||
debug_print("Closing socket: %d\n", sock);
|
||||
close(sock);
|
||||
}
|
||||
|
||||
static void create_socket() {
|
||||
struct sockaddr_un addr_u;
|
||||
struct sockaddr_in addr_i;
|
||||
struct hostent *hp;
|
||||
|
||||
/*debug_set_mode(TRUE);*/
|
||||
if (! Socket) {
|
||||
sock = -1;
|
||||
return;
|
||||
}
|
||||
memset(&addr_u, 0, sizeof(addr_u));
|
||||
memset(&addr_i, 0, sizeof(addr_i));
|
||||
debug_print("socket->type: %d\n", Socket->type);
|
||||
switch (Socket->type) {
|
||||
case UNIX_SOCKET:
|
||||
debug_print("socket path: %s\n", Socket->socket.path);
|
||||
sock = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
debug_print("socket file (create): %d\n", sock);
|
||||
if (sock < 0)
|
||||
return;
|
||||
addr_u.sun_family = AF_UNIX;
|
||||
memcpy(addr_u.sun_path, Socket->socket.path,
|
||||
strlen(Socket->socket.path));
|
||||
if (connect(sock, (struct sockaddr *) &addr_u, sizeof(addr_u)) < 0) {
|
||||
perror("connect socket");
|
||||
close_socket();
|
||||
sock = -2;
|
||||
}
|
||||
debug_print("socket file (connect): %d\n", sock);
|
||||
break;
|
||||
case INET_SOCKET:
|
||||
addr_i.sin_family = AF_INET;
|
||||
addr_i.sin_port = htons(Socket->socket.port);
|
||||
hp = gethostbyname(Socket->socket.host);
|
||||
bcopy((void *)hp->h_addr, (void *)&addr_i.sin_addr, hp->h_length);
|
||||
sock = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
return;
|
||||
if (connect(sock, (struct sockaddr *)&addr_i, sizeof(addr_i)) < 0) {
|
||||
perror("connect socket");
|
||||
close_socket();
|
||||
sock = -2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*debug_set_mode(FALSE);*/
|
||||
}
|
||||
|
||||
static void copy_socket(Clamd_Socket* sock) {
|
||||
Socket = (Clamd_Socket *) malloc(sizeof(Clamd_Socket *));
|
||||
Socket->socket.path = NULL;
|
||||
Socket->socket.host = NULL;
|
||||
Socket->type = sock->type;
|
||||
if (Socket->type == UNIX_SOCKET) {
|
||||
Socket->socket.path = g_strdup(sock->socket.path);
|
||||
}
|
||||
else {
|
||||
Socket->socket.host = g_strdup(sock->socket.host);
|
||||
Socket->socket.port = sock->socket.port;
|
||||
}
|
||||
}
|
||||
|
||||
Clamd_Stat clamd_init(Clamd_Socket* config) {
|
||||
gchar buf[BUFSIZ];
|
||||
int n_read;
|
||||
gboolean connect = FALSE;
|
||||
|
||||
/*debug_set_mode(TRUE);*/
|
||||
if (config != NULL && Socket != NULL)
|
||||
return NO_SOCKET;
|
||||
if (config) {
|
||||
debug_print("socket: %s\n", config->socket.path);
|
||||
copy_socket(config);
|
||||
}
|
||||
create_socket();
|
||||
if (sock < 0) {
|
||||
debug_print("no connection\n");
|
||||
return NO_CONNECTION;
|
||||
}
|
||||
if (write(sock, ping, strlen(ping)) == -1) {
|
||||
debug_print("no connection\n");
|
||||
return NO_CONNECTION;
|
||||
}
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
while ((n_read = read(sock, buf, BUFSIZ)) > 0) {
|
||||
if (buf[strlen(buf) - 1] == '\n')
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
debug_print("Ping result: %s\n", buf);
|
||||
if (strcmp("PONG", buf) == 0)
|
||||
connect = TRUE;
|
||||
}
|
||||
close_socket();
|
||||
create_socket();
|
||||
if (sock < 0) {
|
||||
debug_print("no connection\n");
|
||||
return NO_CONNECTION;
|
||||
}
|
||||
if (write(sock, version, strlen(version)) == -1) {
|
||||
debug_print("no connection\n");
|
||||
return NO_CONNECTION;
|
||||
}
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
while ((n_read = read(sock, buf, BUFSIZ)) > 0) {
|
||||
if (buf[strlen(buf) - 1] == '\n')
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
debug_print("Version: %s\n", buf);
|
||||
}
|
||||
close_socket();
|
||||
/*debug_set_mode(FALSE);*/
|
||||
return (connect) ? OK : NO_CONNECTION;
|
||||
}
|
||||
|
||||
static Clamd_Stat clamd_stream_scan(
|
||||
const gchar* path, gchar** res, ssize_t size) {
|
||||
int fd;
|
||||
ssize_t count;
|
||||
gchar buf[BUFSIZ];
|
||||
int n_read;
|
||||
int32_t chunk;
|
||||
|
||||
debug_print("Scanning: %s\n", path);
|
||||
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
|
||||
if (! res || size < 1) {
|
||||
return SCAN_ERROR;
|
||||
}
|
||||
if (! *res)
|
||||
*res = g_new(gchar, size);
|
||||
memset(*res, '\0', size);
|
||||
|
||||
if (! g_file_test(path, G_FILE_TEST_EXISTS)) {
|
||||
*res = g_strconcat("ERROR -> ", path, _(": File does not exist"), NULL);
|
||||
debug_print("res: %s\n", *res);
|
||||
return SCAN_ERROR;
|
||||
}
|
||||
|
||||
#ifdef _LARGE_FILES
|
||||
fd = open(path, O_RDONLY, O_LARGEFILE);
|
||||
#else
|
||||
fd = open(path, O_RDONLY);
|
||||
#endif
|
||||
|
||||
if (fd < 0) {
|
||||
/*g_error("%s: Unable to open", path);*/
|
||||
*res = g_strconcat("ERROR -> ", path, _(": Unable to open"), NULL);
|
||||
return SCAN_ERROR;
|
||||
}
|
||||
|
||||
debug_print("command: %s\n", instream);
|
||||
if (write(sock, instream, strlen(instream) + 1) == -1) {
|
||||
close(fd);
|
||||
return NO_CONNECTION;
|
||||
}
|
||||
|
||||
while ((count = read(fd, (void *) buf, sizeof(buf))) > 0) {
|
||||
if (count == -1) {
|
||||
close(fd);
|
||||
*res = g_strconcat("ERROR -> ", path, _("%s: Error reading"), NULL);
|
||||
return SCAN_ERROR;
|
||||
}
|
||||
if (buf[strlen(buf) - 1] == '\n')
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
debug_print("read: %ld bytes\n", count);
|
||||
|
||||
debug_print("chunk size: %ld\n", count);
|
||||
chunk = htonl(count);
|
||||
if (write(sock, &chunk, 4) == -1) {
|
||||
close(fd);
|
||||
*res = g_strconcat("ERROR -> ", _("Socket write error"), NULL);
|
||||
return SCAN_ERROR;
|
||||
}
|
||||
if (write(sock, buf, count) == -1) {
|
||||
close(fd);
|
||||
*res = g_strconcat("ERROR -> ", _("Socket write error"), NULL);
|
||||
return SCAN_ERROR;
|
||||
}
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
}
|
||||
close(fd);
|
||||
|
||||
chunk = htonl(0);
|
||||
if (write(sock, &chunk, 4) == -1) {
|
||||
*res = g_strconcat("ERROR -> ", _("Socket write error"), NULL);
|
||||
return SCAN_ERROR;
|
||||
}
|
||||
|
||||
debug_print("reading from socket\n");
|
||||
n_read = read(sock, *res, size);
|
||||
if (n_read < 0) {
|
||||
*res = g_strconcat("ERROR -> ", _("Socket read error"), NULL);
|
||||
return SCAN_ERROR;
|
||||
}
|
||||
debug_print("received: %s\n", *res);
|
||||
return OK;
|
||||
}
|
||||
|
||||
Clamd_Stat clamd_verify_email(const gchar* path, response* result) {
|
||||
gchar buf[BUFSIZ];
|
||||
int n_read;
|
||||
gchar* command;
|
||||
Clamd_Stat stat;
|
||||
|
||||
/*debug_set_mode(TRUE);*/
|
||||
if (!result) {
|
||||
result = malloc(sizeof(response *));
|
||||
memset(result, '\0', sizeof(response *));
|
||||
}
|
||||
create_socket();
|
||||
if (sock < 0) {
|
||||
debug_print("no connection\n");
|
||||
return NO_CONNECTION;
|
||||
}
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
if (Socket->type == INET_SOCKET) {
|
||||
gchar* tmp = g_new0(gchar, BUFSIZ);
|
||||
stat = clamd_stream_scan(path, &tmp, BUFSIZ);
|
||||
if (stat != OK) {
|
||||
close_socket();
|
||||
result->msg = g_strdup(tmp);
|
||||
g_free(tmp);
|
||||
debug_print("result: %s\n", result->msg);
|
||||
/*debug_set_mode(FALSE);*/
|
||||
return stat;
|
||||
}
|
||||
debug_print("copy to buf: %s\n", tmp);
|
||||
memcpy(&buf, tmp, BUFSIZ);
|
||||
g_free(tmp);
|
||||
}
|
||||
else {
|
||||
command = g_strconcat(scan, " ", path, "\n", NULL);
|
||||
debug_print("command: %s\n", command);
|
||||
if (write(sock, command, strlen(command)) == -1) {
|
||||
debug_print("no connection\n");
|
||||
stat = NO_CONNECTION;
|
||||
}
|
||||
g_free(command);
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
while ((n_read = read(sock, buf, BUFSIZ)) > 0) {
|
||||
if (buf[strlen(buf) - 1] == '\n')
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
debug_print("response: %s\n", buf);
|
||||
if (strstr(buf, "ERROR")) {
|
||||
stat = SCAN_ERROR;
|
||||
result->msg = g_strdup(buf);
|
||||
}
|
||||
else if (strstr(buf, "FOUND")) {
|
||||
stat = VIRUS;
|
||||
result->msg = g_strdup(buf);
|
||||
}
|
||||
else {
|
||||
stat = OK;
|
||||
result->msg = NULL;
|
||||
}
|
||||
close_socket();
|
||||
/*debug_set_mode(FALSE);*/
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
GSList* clamd_verify_dir(const gchar* path) {
|
||||
gchar buf[BUFSIZ];
|
||||
int n_read;
|
||||
gchar* command;
|
||||
GSList *list = NULL;
|
||||
|
||||
if (Socket->type == INET_SOCKET)
|
||||
return list;
|
||||
|
||||
create_socket();
|
||||
if (sock < 0) {
|
||||
debug_print("No socket\n");
|
||||
return list;
|
||||
}
|
||||
command = g_strconcat(contscan, path, "\n", NULL);
|
||||
debug_print("command: %s\n", command);
|
||||
if (write(sock, command, strlen(command)) == -1) {
|
||||
debug_print("No socket\n");
|
||||
return list;
|
||||
}
|
||||
g_free(command);
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
while ((n_read = read(sock, buf, BUFSIZ)) > 0) {
|
||||
gchar** tmp = g_strsplit(buf, "\n", 0);
|
||||
gchar** head = tmp;
|
||||
while (*tmp) {
|
||||
gchar* file = *tmp++;
|
||||
debug_print("%s\n", file);
|
||||
if (strstr(file, "ERROR")) {
|
||||
g_warning("%s", file);
|
||||
/* dont report files with errors */
|
||||
}
|
||||
else if (strstr(file, "FOUND")) {
|
||||
list = g_slist_append(list, g_strdup(file));
|
||||
}
|
||||
}
|
||||
g_strfreev(head);
|
||||
}
|
||||
close_socket();
|
||||
return list;
|
||||
}
|
||||
|
||||
void clamd_free_gslist(GSList* list) {
|
||||
GSList* tmp = list;
|
||||
while(tmp) {
|
||||
g_free(tmp->data);
|
||||
tmp = g_slist_next(tmp);
|
||||
}
|
||||
g_slist_free(list);
|
||||
}
|
||||
|
||||
gchar* clamd_get_virus_name(gchar* msg) {
|
||||
gchar *head, *tail, *name;
|
||||
|
||||
tail = g_strrstr_len(msg, strlen(msg), "FOUND");
|
||||
if (! tail)
|
||||
return NULL;
|
||||
head = g_strstr_len(msg, strlen(msg), ":");
|
||||
++head;
|
||||
name = g_strndup(head, tail - head);
|
||||
g_strstrip(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
void clamd_free() {
|
||||
/*
|
||||
* struct _Clamd_Socket {
|
||||
* Type type;
|
||||
* union {
|
||||
* struct {
|
||||
* gchar* path;
|
||||
* };
|
||||
* struct {
|
||||
* gchar* host;
|
||||
* int port;
|
||||
* };
|
||||
* } socket;
|
||||
* };
|
||||
*/
|
||||
if (sock > 0) {
|
||||
close_socket();
|
||||
sock = 0;
|
||||
}
|
||||
if (Socket) {
|
||||
switch (Socket->type) {
|
||||
case UNIX_SOCKET:
|
||||
if (Socket->socket.path) {
|
||||
g_free(Socket->socket.path);
|
||||
Socket->socket.path = NULL;
|
||||
}
|
||||
break;
|
||||
case INET_SOCKET:
|
||||
if (Socket->socket.host) {
|
||||
g_free(Socket->socket.host);
|
||||
Socket->socket.host = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
g_free(Socket);
|
||||
Socket = NULL;
|
||||
}
|
||||
if (config) {
|
||||
clamd_config_free(config);
|
||||
config = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Config* clamd_config_new() {
|
||||
return g_new0(Config, 1);
|
||||
}
|
||||
|
||||
void clamd_config_free(Config* c) {
|
||||
if (c->ConfigType == AUTOMATIC) {
|
||||
g_free(c->automatic.folder);
|
||||
c->automatic.folder = NULL;
|
||||
}
|
||||
else {
|
||||
g_free(c->manual.host);
|
||||
c->manual.host = NULL;
|
||||
}
|
||||
g_free(c);
|
||||
}
|
||||
|
||||
gchar* int2char(int i) {
|
||||
gchar* s = g_new0(gchar, 5);
|
||||
|
||||
sprintf(s, "%d", i);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
gchar* long2char(long l) {
|
||||
gchar* s = g_new0(gchar, 5);
|
||||
|
||||
debug_print("l: %ld\n", l);
|
||||
sprintf(s, "%ld", l);
|
||||
debug_print("s: %s\n", s);
|
||||
|
||||
return s;
|
||||
}
|
144
src/plugins/clamd/libclamd/clamd-plugin.h
Normal file
144
src/plugins/clamd/libclamd/clamd-plugin.h
Normal file
|
@ -0,0 +1,144 @@
|
|||
/* vim: set textwidth=80 tabstop=4: */
|
||||
|
||||
/*
|
||||
* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 1999-2008 Michael Rasmussen and the Claws Mail Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CLAMD_PLUGIN_H__
|
||||
#define __CLAMD_PLUGIN_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef enum _Type Type;
|
||||
enum _Type { UNIX_SOCKET, INET_SOCKET };
|
||||
|
||||
typedef enum _Clamd_Stat Clamd_Stat;
|
||||
enum _Clamd_Stat { OK, VIRUS, NO_SOCKET, NO_CONNECTION, SCAN_ERROR };
|
||||
|
||||
typedef struct _Clamd_Socket Clamd_Socket;
|
||||
struct _Clamd_Socket {
|
||||
Type type;
|
||||
union {
|
||||
struct {
|
||||
gchar* path;
|
||||
};
|
||||
struct {
|
||||
gchar* host;
|
||||
int port;
|
||||
};
|
||||
} socket;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
enum { AUTOMATIC, MANUAL } ConfigType;
|
||||
union {
|
||||
struct {
|
||||
gchar* folder;
|
||||
} automatic;
|
||||
struct {
|
||||
gchar* host;
|
||||
int port;
|
||||
} manual;
|
||||
};
|
||||
} Config;
|
||||
|
||||
typedef struct _response response;
|
||||
struct _response {
|
||||
gchar* msg;
|
||||
};
|
||||
|
||||
void clamd_create_config_automatic(const gchar* path);
|
||||
|
||||
void clamd_create_config_manual(const gchar* host, int port);
|
||||
|
||||
gchar* int2char(int i);
|
||||
|
||||
gchar* long2char(long l);
|
||||
|
||||
/**
|
||||
* Function which looks for clamd.conf the default places
|
||||
* and configures the plugin according to the information
|
||||
* found.
|
||||
* @return <b>TRUE</b> if clamd.conf found which means all
|
||||
* information need to make a connection has been found.
|
||||
* <b>FALSE</b> otherwise.
|
||||
*/
|
||||
gboolean clamd_find_socket();
|
||||
|
||||
/**
|
||||
* Function to get current configuration
|
||||
* @return the current configuration for clamd or <b>NULL</b>
|
||||
*/
|
||||
Config* clamd_get_config();
|
||||
|
||||
/**
|
||||
* Function to retrieve virus name from msg
|
||||
* @param msg Message returned from clamd
|
||||
* @return virus name or <b>NULL</b> if no virus name found
|
||||
*/
|
||||
gchar* clamd_get_virus_name(gchar* msg);
|
||||
|
||||
/**
|
||||
* Function to initialize the connection to clamd.
|
||||
* @param config A pointer to a struct _Clamd_Socket having
|
||||
* the required information. If clamd_find_socket returned
|
||||
* TRUE config should be <b>NULL</b> because all the needed
|
||||
* information is already present @see clamd_find_socket.
|
||||
* @return Clamd_Stat. @see _Clamd_Stat.
|
||||
*/
|
||||
Clamd_Stat clamd_init(Clamd_Socket* config);
|
||||
|
||||
/**
|
||||
* Function returning the current socket information.
|
||||
* @return reference to the current Clamd_Socket. @see _Clamd_Socket.
|
||||
*/
|
||||
Clamd_Socket* clamd_get_socket();
|
||||
|
||||
/**
|
||||
* Function which is checks a specific email for known viruses
|
||||
* @param path Absolut path to email to check.
|
||||
* @param msg String to which result of scan will be copied. Will be
|
||||
* <b>NULL</b> if no virus was found.
|
||||
* @return Clamd_Stat. @see _Clamd_Stat.
|
||||
*/
|
||||
Clamd_Stat clamd_verify_email(const gchar* path, response* result);
|
||||
|
||||
/**
|
||||
* Function which is checks files in a specific directory for
|
||||
* known viruses. Dont stop when a virus is found but keeps going
|
||||
* @param path Absolut path to directory to check.
|
||||
* @return list of list with virus or <b>NULL</b>.
|
||||
*/
|
||||
GSList* clamd_verify_dir(const gchar* path);
|
||||
|
||||
/**
|
||||
* Function to free all memory assigned to a GSList
|
||||
* @param list The GSList to free
|
||||
*/
|
||||
void clamd_free_gslist(GSList* list);
|
||||
|
||||
/**
|
||||
* Function which frees all memory assigned to clamd_plugin
|
||||
*/
|
||||
void clamd_free();
|
||||
|
||||
Config* clamd_config_new();
|
||||
|
||||
void clamd_config_free(Config* c);
|
||||
|
||||
#endif
|
|
@ -1 +0,0 @@
|
|||
Placeholder
|
23
src/plugins/fetchinfo/Makefile.am
Normal file
23
src/plugins/fetchinfo/Makefile.am
Normal file
|
@ -0,0 +1,23 @@
|
|||
plugindir = $(pkglibdir)/plugins
|
||||
|
||||
plugin_LTLIBRARIES = fetchinfo_plugin.la
|
||||
|
||||
fetchinfo_plugin_la_SOURCES = \
|
||||
fetchinfo_plugin.c fetchinfo_plugin.h \
|
||||
fetchinfo_plugin_gtk.c
|
||||
|
||||
fetchinfo_plugin_la_LDFLAGS = \
|
||||
-avoid-version -module \
|
||||
$(GTK_LIBS)
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(CLAWS_MAIL_CFLAGS) \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(GTK_CFLAGS)
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/common \
|
||||
-I$(top_srcdir)/src/gtk
|
||||
|
||||
EXTRA_DIST=
|
239
src/plugins/fetchinfo/fetchinfo_plugin.c
Normal file
239
src/plugins/fetchinfo/fetchinfo_plugin.c
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 1999-2003 Hiroyuki Yamamoto and the Claws Mail Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# include "claws-features.h"
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
/* common */
|
||||
#include "version.h"
|
||||
#include "claws.h"
|
||||
#include "plugin.h"
|
||||
#include "utils.h"
|
||||
#include "hooks.h"
|
||||
#include "inc.h"
|
||||
#include "prefs.h"
|
||||
#include "prefs_gtk.h"
|
||||
#include "fetchinfo_plugin.h"
|
||||
/* add headers */
|
||||
#include "pop.h"
|
||||
#include "quoted-printable.h"
|
||||
/* parse headers */
|
||||
#include "procheader.h"
|
||||
#include "plugin.h"
|
||||
|
||||
static guint mail_receive_hook_id;
|
||||
|
||||
static FetchinfoConfig config;
|
||||
|
||||
static PrefParam param[] = {
|
||||
{"fetchinfo_enable", "FALSE", &config.fetchinfo_enable,
|
||||
P_BOOL, NULL, NULL, NULL},
|
||||
{"fetchinfo_uidl", "TRUE", &config.fetchinfo_uidl,
|
||||
P_BOOL, NULL, NULL, NULL},
|
||||
{"fetchinfo_account", "TRUE", &config.fetchinfo_account,
|
||||
P_BOOL, NULL, NULL, NULL},
|
||||
{"fetchinfo_server", "TRUE", &config.fetchinfo_server,
|
||||
P_BOOL, NULL, NULL, NULL},
|
||||
{"fetchinfo_userid", "TRUE", &config.fetchinfo_userid,
|
||||
P_BOOL, NULL, NULL, NULL},
|
||||
{"fetchinfo_time", "TRUE", &config.fetchinfo_time,
|
||||
P_BOOL, NULL, NULL, NULL},
|
||||
|
||||
{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
gchar *fetchinfo_add_header(gchar **data, const gchar *header,const gchar *value)
|
||||
{
|
||||
gchar *line;
|
||||
gchar *qpline;
|
||||
gchar *newdata;
|
||||
|
||||
line = g_strdup_printf("%s: %s", header, value);
|
||||
qpline = g_malloc(strlen(line)*4);
|
||||
qp_encode_line(qpline, line);
|
||||
newdata = g_strconcat(*data, qpline, NULL);
|
||||
g_free(line);
|
||||
g_free(qpline);
|
||||
g_free(*data);
|
||||
*data = newdata;
|
||||
return newdata;
|
||||
}
|
||||
|
||||
static gboolean mail_receive_hook(gpointer source, gpointer data)
|
||||
{
|
||||
MailReceiveData *mail_receive_data = (MailReceiveData *) source;
|
||||
Pop3Session *session;
|
||||
gchar *newheaders;
|
||||
gchar *newdata;
|
||||
gchar date[PREFSBUFSIZE];
|
||||
|
||||
if (!config.fetchinfo_enable) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_return_val_if_fail(
|
||||
mail_receive_data
|
||||
&& mail_receive_data->session
|
||||
&& mail_receive_data->data,
|
||||
FALSE );
|
||||
|
||||
session = mail_receive_data->session;
|
||||
get_rfc822_date(date, PREFSBUFSIZE);
|
||||
newheaders = g_strdup("");
|
||||
|
||||
if (config.fetchinfo_uidl)
|
||||
fetchinfo_add_header(&newheaders, "X-FETCH-UIDL",
|
||||
session->msg[session->cur_msg].uidl);
|
||||
if (config.fetchinfo_account)
|
||||
fetchinfo_add_header(&newheaders, "X-FETCH-ACCOUNT",
|
||||
session->ac_prefs->account_name);
|
||||
if (config.fetchinfo_server)
|
||||
fetchinfo_add_header(&newheaders, "X-FETCH-SERVER",
|
||||
session->ac_prefs->recv_server);
|
||||
if (config.fetchinfo_userid)
|
||||
fetchinfo_add_header(&newheaders, "X-FETCH-USERID",
|
||||
session->ac_prefs->userid);
|
||||
if (config.fetchinfo_time)
|
||||
fetchinfo_add_header(&newheaders, "X-FETCH-TIME",
|
||||
date);
|
||||
|
||||
newdata = g_strconcat(newheaders, mail_receive_data->data, NULL);
|
||||
g_free(newheaders);
|
||||
g_free(mail_receive_data->data);
|
||||
mail_receive_data->data = newdata;
|
||||
mail_receive_data->data_len = strlen(newdata);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FetchinfoConfig *fetchinfo_get_config(void)
|
||||
{
|
||||
return &config;
|
||||
}
|
||||
|
||||
void fetchinfo_save_config(void)
|
||||
{
|
||||
PrefFile *pfile;
|
||||
gchar *rcpath;
|
||||
|
||||
debug_print("Saving Fetchinfo Page\n");
|
||||
|
||||
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
|
||||
pfile = prefs_write_open(rcpath);
|
||||
g_free(rcpath);
|
||||
if (!pfile || (prefs_set_block_label(pfile, "Fetchinfo") < 0))
|
||||
return;
|
||||
|
||||
if (prefs_write_param(param, pfile->fp) < 0) {
|
||||
/* i18n: Possible error message during plugin load */
|
||||
g_warning(_("failed to write Fetchinfo configuration to file\n"));
|
||||
prefs_file_close_revert(pfile);
|
||||
return;
|
||||
}
|
||||
if (fprintf(pfile->fp, "\n") < 0) {
|
||||
FILE_OP_ERROR(rcpath, "fprintf");
|
||||
prefs_file_close_revert(pfile);
|
||||
} else
|
||||
prefs_file_close(pfile);
|
||||
}
|
||||
|
||||
gint plugin_init(gchar **error)
|
||||
{
|
||||
gchar *rcpath;
|
||||
|
||||
if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
|
||||
VERSION_NUMERIC, _("Fetchinfo"), error))
|
||||
return -1;
|
||||
|
||||
mail_receive_hook_id = hooks_register_hook(MAIL_RECEIVE_HOOKLIST, mail_receive_hook, NULL);
|
||||
if (mail_receive_hook_id == (guint)-1) {
|
||||
/* i18n: Possible error message during plugin load */
|
||||
*error = g_strdup(_("Failed to register mail receive hook"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
prefs_set_default(param);
|
||||
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
|
||||
prefs_read_config(param, "Fetchinfo", rcpath, NULL);
|
||||
g_free(rcpath);
|
||||
|
||||
fetchinfo_gtk_init();
|
||||
|
||||
debug_print("Fetchinfo plugin loaded\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean plugin_done(void)
|
||||
{
|
||||
hooks_unregister_hook(MAIL_RECEIVE_HOOKLIST, mail_receive_hook_id);
|
||||
fetchinfo_gtk_done();
|
||||
|
||||
debug_print("Fetchinfo plugin unloaded\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const gchar *plugin_name(void)
|
||||
{
|
||||
return _("Fetchinfo");
|
||||
}
|
||||
|
||||
const gchar *plugin_desc(void)
|
||||
{
|
||||
/* i18n: Description seen in plugins dialog.
|
||||
* Translation of "Plugins" part of preferences path should to be
|
||||
* the same as translation of "Plugins" string in Claws Mail message
|
||||
* catalog. */
|
||||
return _("This plugin modifies the downloaded messages. "
|
||||
"It inserts headers containing some download "
|
||||
"information: UIDL, Claws Mail account name, "
|
||||
"POP server, user ID and retrieval time.\n"
|
||||
"\n"
|
||||
"Options can be found in /Configuration/Preferences/Plugins/Fetchinfo");
|
||||
}
|
||||
|
||||
const gchar *plugin_type(void)
|
||||
{
|
||||
return "GTK2";
|
||||
}
|
||||
|
||||
const gchar *plugin_licence(void)
|
||||
{
|
||||
return "GPL3+";
|
||||
}
|
||||
|
||||
const gchar *plugin_version(void)
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
struct PluginFeature *plugin_provides(void)
|
||||
{
|
||||
static struct PluginFeature features[] =
|
||||
/* i18n: Description of functionality added by this plugin */
|
||||
{ {PLUGIN_UTILITY, N_("Mail marking")},
|
||||
{PLUGIN_NOTHING, NULL}};
|
||||
return features;
|
||||
}
|
42
src/plugins/fetchinfo/fetchinfo_plugin.h
Normal file
42
src/plugins/fetchinfo/fetchinfo_plugin.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 1999-2003 Hiroyuki Yamamoto and the Claws Mail Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FETCHINFO_PLUGIN_H
|
||||
#define FETCHINFO_PLUGIN_H 1
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct _FetchinfoConfig FetchinfoConfig;
|
||||
|
||||
struct _FetchinfoConfig
|
||||
{
|
||||
gboolean fetchinfo_enable;
|
||||
gboolean fetchinfo_uidl;
|
||||
gboolean fetchinfo_account;
|
||||
gboolean fetchinfo_server;
|
||||
gboolean fetchinfo_userid;
|
||||
gboolean fetchinfo_time;
|
||||
};
|
||||
|
||||
FetchinfoConfig *fetchinfo_get_config (void);
|
||||
void fetchinfo_save_config (void);
|
||||
gint fetchinfo_gtk_init(void);
|
||||
void fetchinfo_gtk_done(void);
|
||||
|
||||
#endif
|
198
src/plugins/fetchinfo/fetchinfo_plugin_gtk.c
Normal file
198
src/plugins/fetchinfo/fetchinfo_plugin_gtk.c
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 1999-2003 Hiroyuki Yamamoto and the Claws Mail Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# include "claws-features.h"
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
#include "version.h"
|
||||
#include "claws.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "plugin.h"
|
||||
#include "utils.h"
|
||||
#include "prefs.h"
|
||||
#include "prefs_gtk.h"
|
||||
|
||||
#include "fetchinfo_plugin.h"
|
||||
|
||||
struct FetchinfoPage
|
||||
{
|
||||
PrefsPage page;
|
||||
|
||||
GtkWidget *fetchinfo_enable;
|
||||
GtkWidget *fetchinfo_uidl;
|
||||
GtkWidget *fetchinfo_account;
|
||||
GtkWidget *fetchinfo_server;
|
||||
GtkWidget *fetchinfo_userid;
|
||||
GtkWidget *fetchinfo_time;
|
||||
};
|
||||
|
||||
static void fetchinfo_set_sensitive(struct FetchinfoPage *page, gboolean enable)
|
||||
{
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(page->fetchinfo_uidl), enable);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(page->fetchinfo_account), enable);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(page->fetchinfo_server), enable);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(page->fetchinfo_userid), enable);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(page->fetchinfo_time), enable);
|
||||
}
|
||||
|
||||
static void fetchinfo_enable_cb(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
struct FetchinfoPage *page = (struct FetchinfoPage *) data;
|
||||
|
||||
fetchinfo_set_sensitive(page, gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(page->fetchinfo_enable)));
|
||||
}
|
||||
|
||||
#define ADD_NEW_CHECKBOX(line, button, text) \
|
||||
button = gtk_check_button_new_with_label (text); \
|
||||
gtk_widget_show (button); \
|
||||
gtk_table_attach (GTK_TABLE (table), button, 1, 2, line, line+1, \
|
||||
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), \
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
|
||||
static void fetchinfo_create_widget_func(PrefsPage * _page, GtkWindow *window, gpointer data)
|
||||
{
|
||||
struct FetchinfoPage *page = (struct FetchinfoPage *) _page;
|
||||
FetchinfoConfig *config;
|
||||
GtkWidget *table;
|
||||
GtkWidget *fetchinfo_enable;
|
||||
GtkWidget *fetchinfo_uidl;
|
||||
GtkWidget *fetchinfo_account;
|
||||
GtkWidget *fetchinfo_server;
|
||||
GtkWidget *fetchinfo_userid;
|
||||
GtkWidget *fetchinfo_time;
|
||||
|
||||
table = gtk_table_new (6, 3, FALSE);
|
||||
gtk_widget_show(table);
|
||||
gtk_table_set_row_spacings(GTK_TABLE(table), 4);
|
||||
gtk_table_set_col_spacings(GTK_TABLE(table), 8);
|
||||
|
||||
/* i18n: Heading of a preferences section determining which headers to add */
|
||||
fetchinfo_enable = gtk_check_button_new_with_label (_("Add fetchinfo headers"));
|
||||
gtk_widget_show (fetchinfo_enable);
|
||||
gtk_table_attach (GTK_TABLE (table), fetchinfo_enable, 0, 2, 0, 1,
|
||||
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
|
||||
/* i18n: Description of a header to be added */
|
||||
ADD_NEW_CHECKBOX(1, fetchinfo_uidl, _("UIDL"));
|
||||
/* i18n: Description of a header to be added */
|
||||
ADD_NEW_CHECKBOX(2, fetchinfo_account, _("Account name"));
|
||||
/* i18n: Description of a header to be added */
|
||||
ADD_NEW_CHECKBOX(3, fetchinfo_server, _("Receive server"));
|
||||
/* i18n: Description of a header to be added */
|
||||
ADD_NEW_CHECKBOX(4, fetchinfo_userid, _("UserID"));
|
||||
/* i18n: Description of a header to be added */
|
||||
ADD_NEW_CHECKBOX(5, fetchinfo_time, _("Fetch time"));
|
||||
|
||||
config = fetchinfo_get_config();
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fetchinfo_enable),
|
||||
config->fetchinfo_enable);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fetchinfo_uidl),
|
||||
config->fetchinfo_uidl);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fetchinfo_account),
|
||||
config->fetchinfo_account);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fetchinfo_server),
|
||||
config->fetchinfo_server);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fetchinfo_userid),
|
||||
config->fetchinfo_userid);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fetchinfo_time),
|
||||
config->fetchinfo_time);
|
||||
|
||||
g_signal_connect(G_OBJECT(fetchinfo_enable), "released",
|
||||
G_CALLBACK(fetchinfo_enable_cb), page);
|
||||
|
||||
page->fetchinfo_enable = fetchinfo_enable;
|
||||
page->fetchinfo_uidl = fetchinfo_uidl;
|
||||
page->fetchinfo_account = fetchinfo_account;
|
||||
page->fetchinfo_server = fetchinfo_server;
|
||||
page->fetchinfo_userid = fetchinfo_userid;
|
||||
page->fetchinfo_time = fetchinfo_time;
|
||||
|
||||
page->page.widget = table;
|
||||
|
||||
fetchinfo_set_sensitive(page, config->fetchinfo_enable);
|
||||
}
|
||||
#undef ADD_NEW_CHECKBOX
|
||||
|
||||
static void fetchinfo_destroy_widget_func(PrefsPage *_page)
|
||||
{
|
||||
debug_print("Destroying Fetchinfo widget\n");
|
||||
}
|
||||
|
||||
static void fetchinfo_save_func(PrefsPage *_page)
|
||||
{
|
||||
struct FetchinfoPage *page = (struct FetchinfoPage *) _page;
|
||||
FetchinfoConfig *config;
|
||||
|
||||
debug_print("Saving Fetchinfo Page\n");
|
||||
|
||||
config = fetchinfo_get_config();
|
||||
|
||||
config->fetchinfo_enable = gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(page->fetchinfo_enable) );
|
||||
config->fetchinfo_uidl = gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(page->fetchinfo_uidl) );
|
||||
config->fetchinfo_account = gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(page->fetchinfo_account));
|
||||
config->fetchinfo_server = gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(page->fetchinfo_server) );
|
||||
config->fetchinfo_userid = gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(page->fetchinfo_userid) );
|
||||
config->fetchinfo_time = gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(page->fetchinfo_time) );
|
||||
|
||||
fetchinfo_save_config();
|
||||
}
|
||||
|
||||
static struct FetchinfoPage fetchinfo_page;
|
||||
|
||||
gint fetchinfo_gtk_init(void)
|
||||
{
|
||||
static gchar *path[3];
|
||||
|
||||
path[0] = _("Plugins");
|
||||
path[1] = _("Fetchinfo");
|
||||
path[2] = NULL;
|
||||
|
||||
fetchinfo_page.page.path = path;
|
||||
fetchinfo_page.page.create_widget = fetchinfo_create_widget_func;
|
||||
fetchinfo_page.page.destroy_widget = fetchinfo_destroy_widget_func;
|
||||
fetchinfo_page.page.save_page = fetchinfo_save_func;
|
||||
|
||||
prefs_gtk_register_page((PrefsPage *) &fetchinfo_page);
|
||||
|
||||
debug_print("Fetchinfo GTK plugin loaded\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fetchinfo_gtk_done(void)
|
||||
{
|
||||
prefs_gtk_unregister_page((PrefsPage *) &fetchinfo_page);
|
||||
|
||||
debug_print("Fetchinfo GTK plugin unloaded\n");
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
Placeholder
|
30
src/plugins/gdata/Makefile.am
Normal file
30
src/plugins/gdata/Makefile.am
Normal file
|
@ -0,0 +1,30 @@
|
|||
plugindir = $(pkglibdir)/plugins
|
||||
|
||||
plugin_LTLIBRARIES = gdata_plugin.la
|
||||
|
||||
gdata_plugin_la_SOURCES = \
|
||||
gdata_plugin.c \
|
||||
gdata_plugin.h \
|
||||
cm_gdata_contacts.c \
|
||||
cm_gdata_contacts.h \
|
||||
cm_gdata_prefs.c \
|
||||
cm_gdata_prefs.h
|
||||
|
||||
gdata_plugin_la_LDFLAGS = \
|
||||
-avoid-version -module \
|
||||
$(GTK_LIBS) \
|
||||
$(GDATA_LIBS)
|
||||
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/common \
|
||||
-I$(top_srcdir)/src/gtk
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-Wall \
|
||||
$(CLAWS_MAIL_CFLAGS) \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(GTK_CFLAGS) \
|
||||
$(GDATA_CFLAGS) \
|
||||
-DLOCALEDIR=\""$(localedir)"\"
|
508
src/plugins/gdata/cm_gdata_contacts.c
Normal file
508
src/plugins/gdata/cm_gdata_contacts.c
Normal file
|
@ -0,0 +1,508 @@
|
|||
/* GData plugin for Claws-Mail
|
||||
* Copyright (C) 2011 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# include "claws-features.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "cm_gdata_contacts.h"
|
||||
#include "cm_gdata_prefs.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "addr_compl.h"
|
||||
#include "main.h"
|
||||
#include "prefs_common.h"
|
||||
#include "common/log.h"
|
||||
#include "common/xml.h"
|
||||
|
||||
#include <gdata/gdata.h>
|
||||
|
||||
#define GDATA_CONTACTS_FILENAME "gdata_cache.xml"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar *family_name;
|
||||
const gchar *given_name;
|
||||
const gchar *full_name;
|
||||
const gchar *address;
|
||||
} Contact;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GSList *contacts;
|
||||
} CmGDataContactsCache;
|
||||
|
||||
|
||||
CmGDataContactsCache contacts_cache;
|
||||
gboolean cm_gdata_contacts_query_running = FALSE;
|
||||
gchar *contacts_group_id = NULL;
|
||||
|
||||
static void write_cache_to_file(void)
|
||||
{
|
||||
gchar *path;
|
||||
PrefFile *pfile;
|
||||
XMLTag *tag;
|
||||
XMLNode *xmlnode;
|
||||
GNode *rootnode;
|
||||
GNode *contactsnode;
|
||||
GSList *walk;
|
||||
|
||||
path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, GDATA_CONTACTS_FILENAME, NULL);
|
||||
pfile = prefs_write_open(path);
|
||||
g_free(path);
|
||||
if(pfile == NULL) {
|
||||
debug_print("GData plugin error: Cannot open file " GDATA_CONTACTS_FILENAME " for writing\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* XML declarations */
|
||||
xml_file_put_xml_decl(pfile->fp);
|
||||
|
||||
/* Build up XML tree */
|
||||
|
||||
/* root node */
|
||||
tag = xml_tag_new("gdata");
|
||||
xmlnode = xml_node_new(tag, NULL);
|
||||
rootnode = g_node_new(xmlnode);
|
||||
|
||||
/* contacts node */
|
||||
tag = xml_tag_new("contacts");
|
||||
xmlnode = xml_node_new(tag, NULL);
|
||||
contactsnode = g_node_new(xmlnode);
|
||||
g_node_append(rootnode, contactsnode);
|
||||
|
||||
/* walk contacts cache */
|
||||
for(walk = contacts_cache.contacts; walk; walk = walk->next)
|
||||
{
|
||||
GNode *contactnode;
|
||||
Contact *contact = walk->data;
|
||||
tag = xml_tag_new("contact");
|
||||
xml_tag_add_attr(tag, xml_attr_new("family_name",contact->family_name));
|
||||
xml_tag_add_attr(tag, xml_attr_new("given_name",contact->given_name));
|
||||
xml_tag_add_attr(tag, xml_attr_new("full_name",contact->full_name));
|
||||
xml_tag_add_attr(tag, xml_attr_new("address",contact->address));
|
||||
xmlnode = xml_node_new(tag, NULL);
|
||||
contactnode = g_node_new(xmlnode);
|
||||
g_node_append(contactsnode, contactnode);
|
||||
}
|
||||
|
||||
/* Actual writing and cleanup */
|
||||
xml_write_tree(rootnode, pfile->fp);
|
||||
if(prefs_file_close(pfile) < 0)
|
||||
debug_print("GData plugin error: Failed to write file " GDATA_CONTACTS_FILENAME "\n");
|
||||
|
||||
debug_print("GData plugin error: Wrote cache to file " GDATA_CONTACTS_FILENAME "\n");
|
||||
|
||||
/* Free XML tree */
|
||||
xml_free_tree(rootnode);
|
||||
}
|
||||
|
||||
static int add_gdata_contact_to_cache(GDataContactsContact *contact)
|
||||
{
|
||||
GList *walk;
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
for(walk = gdata_contacts_contact_get_email_addresses(contact); walk; walk = walk->next) {
|
||||
const gchar *email_address;
|
||||
GDataGDEmailAddress *address = GDATA_GD_EMAIL_ADDRESS(walk->data);
|
||||
|
||||
email_address = gdata_gd_email_address_get_address(address);
|
||||
if(email_address && (*email_address != '\0')) {
|
||||
GDataGDName *name;
|
||||
Contact *cached_contact;
|
||||
|
||||
name = gdata_contacts_contact_get_name(contact);
|
||||
|
||||
cached_contact = g_new0(Contact, 1);
|
||||
cached_contact->full_name = g_strdup(gdata_gd_name_get_full_name(name));
|
||||
cached_contact->given_name = g_strdup(gdata_gd_name_get_given_name(name));
|
||||
cached_contact->family_name = g_strdup(gdata_gd_name_get_family_name(name));
|
||||
cached_contact->address = g_strdup(email_address);
|
||||
|
||||
contacts_cache.contacts = g_slist_prepend(contacts_cache.contacts, cached_contact);
|
||||
|
||||
debug_print("GData plugin: Added %s <%s>\n", cached_contact->full_name, cached_contact->address);
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
if(retval == 0)
|
||||
{
|
||||
debug_print("GData plugin: Skipped received contact \"%s\" because it doesn't have an email address\n",
|
||||
gdata_gd_name_get_full_name(gdata_contacts_contact_get_name(contact)));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void free_contact(Contact *contact)
|
||||
{
|
||||
g_free((gpointer)contact->full_name);
|
||||
g_free((gpointer)contact->family_name);
|
||||
g_free((gpointer)contact->given_name);
|
||||
g_free((gpointer)contact->address);
|
||||
g_free(contact);
|
||||
}
|
||||
|
||||
static void clear_contacts_cache(void)
|
||||
{
|
||||
GSList *walk;
|
||||
for(walk = contacts_cache.contacts; walk; walk = walk->next)
|
||||
free_contact(walk->data);
|
||||
g_slist_free(contacts_cache.contacts);
|
||||
contacts_cache.contacts = NULL;
|
||||
}
|
||||
|
||||
static void cm_gdata_query_contacts_ready(GDataContactsService *service, GAsyncResult *res, gpointer data)
|
||||
{
|
||||
GDataFeed *feed;
|
||||
GList *walk;
|
||||
GError *error = NULL;
|
||||
guint num_contacts = 0;
|
||||
guint num_contacts_added = 0;
|
||||
gchar *tmpstr1, *tmpstr2;
|
||||
|
||||
feed = gdata_service_query_finish(GDATA_SERVICE(service), res, &error);
|
||||
cm_gdata_contacts_query_running = FALSE;
|
||||
if(error)
|
||||
{
|
||||
g_object_unref(feed);
|
||||
log_error(LOG_PROTOCOL, _("GData plugin: Error querying for contacts: %s\n"), error->message);
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear cache */
|
||||
clear_contacts_cache();
|
||||
|
||||
/* Iterate through the returned contacts and fill the cache */
|
||||
for(walk = gdata_feed_get_entries(feed); walk; walk = walk->next) {
|
||||
num_contacts_added += add_gdata_contact_to_cache(GDATA_CONTACTS_CONTACT(walk->data));
|
||||
num_contacts++;
|
||||
}
|
||||
g_object_unref(feed);
|
||||
contacts_cache.contacts = g_slist_reverse(contacts_cache.contacts);
|
||||
/* i18n: First part of "Added X of Y contacts to cache" */
|
||||
tmpstr1 = g_strdup_printf(ngettext("Added %d of", "Added %d of", num_contacts_added), num_contacts_added);
|
||||
/* i18n: Second part of "Added X of Y contacts to cache" */
|
||||
tmpstr2 = g_strdup_printf(ngettext("1 contact to the cache", "%d contacts to the cache", num_contacts), num_contacts);
|
||||
log_message(LOG_PROTOCOL, "%s %s\n", tmpstr1, tmpstr2);
|
||||
g_free(tmpstr1);
|
||||
g_free(tmpstr2);
|
||||
}
|
||||
|
||||
static void query_after_auth(GDataContactsService *service)
|
||||
{
|
||||
GDataContactsQuery *query;
|
||||
|
||||
log_message(LOG_PROTOCOL, _("GData plugin: Starting async contacts query\n"));
|
||||
|
||||
query = gdata_contacts_query_new(NULL);
|
||||
gdata_contacts_query_set_group(query, contacts_group_id);
|
||||
gdata_query_set_max_results(GDATA_QUERY(query), cm_gdata_config.max_num_results);
|
||||
gdata_contacts_service_query_contacts_async(service, GDATA_QUERY(query), NULL, NULL, NULL,
|
||||
#ifdef HAVE_GDATA_VERSION_0_9_1
|
||||
NULL,
|
||||
#endif
|
||||
(GAsyncReadyCallback)cm_gdata_query_contacts_ready, NULL);
|
||||
|
||||
g_object_unref(query);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GDATA_VERSION_0_9_1
|
||||
static void cm_gdata_query_groups_ready(GDataContactsService *service, GAsyncResult *res, gpointer data)
|
||||
{
|
||||
GDataFeed *feed;
|
||||
GList *walk;
|
||||
GError *error = NULL;
|
||||
|
||||
feed = gdata_service_query_finish(GDATA_SERVICE(service), res, &error);
|
||||
if(error)
|
||||
{
|
||||
g_object_unref(feed);
|
||||
log_error(LOG_PROTOCOL, _("GData plugin: Error querying for groups: %s\n"), error->message);
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Iterate through the returned groups and search for Contacts group id */
|
||||
for(walk = gdata_feed_get_entries(feed); walk; walk = walk->next) {
|
||||
const gchar *system_group_id;
|
||||
GDataContactsGroup *group = GDATA_CONTACTS_GROUP(walk->data);
|
||||
|
||||
system_group_id = gdata_contacts_group_get_system_group_id(group);
|
||||
if(system_group_id && !strcmp(system_group_id, GDATA_CONTACTS_GROUP_CONTACTS)) {
|
||||
gchar *pos;
|
||||
const gchar *id;
|
||||
|
||||
id = gdata_entry_get_id(GDATA_ENTRY(group));
|
||||
|
||||
/* possibly replace projection "full" by "base" */
|
||||
pos = g_strrstr(id, "/full/");
|
||||
if(pos) {
|
||||
GString *str = g_string_new("\0");
|
||||
int off = pos-id;
|
||||
|
||||
g_string_append_len(str, id, off);
|
||||
g_string_append(str, "/base/");
|
||||
g_string_append(str, id+off+strlen("/full/"));
|
||||
g_string_append_c(str, '\0');
|
||||
contacts_group_id = str->str;
|
||||
g_string_free(str, FALSE);
|
||||
}
|
||||
else
|
||||
contacts_group_id = g_strdup(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_object_unref(feed);
|
||||
|
||||
log_message(LOG_PROTOCOL, _("GData plugin: Groups received\n"));
|
||||
|
||||
query_after_auth(service);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GDATA_VERSION_0_9
|
||||
static void query_for_contacts_group_id(GDataClientLoginAuthorizer *authorizer)
|
||||
{
|
||||
GDataContactsService *service;
|
||||
#ifdef HAVE_GDATA_VERSION_0_9_1
|
||||
|
||||
log_message(LOG_PROTOCOL, _("GData plugin: Starting async groups query\n"));
|
||||
|
||||
service = gdata_contacts_service_new(GDATA_AUTHORIZER(authorizer));
|
||||
gdata_contacts_service_query_groups_async(service, NULL, NULL, NULL, NULL, NULL,
|
||||
(GAsyncReadyCallback)cm_gdata_query_groups_ready, NULL);
|
||||
#else
|
||||
service = gdata_contacts_service_new(GDATA_AUTHORIZER(authorizer));
|
||||
query_after_auth(service);
|
||||
#endif
|
||||
g_object_unref(service);
|
||||
}
|
||||
|
||||
static void cm_gdata_auth_ready(GDataClientLoginAuthorizer *authorizer, GAsyncResult *res, gpointer data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if(gdata_client_login_authorizer_authenticate_finish(authorizer, res, &error) == FALSE)
|
||||
{
|
||||
log_error(LOG_PROTOCOL, _("GData plugin: Authentication error: %s\n"), error->message);
|
||||
g_error_free(error);
|
||||
cm_gdata_contacts_query_running = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
log_message(LOG_PROTOCOL, _("GData plugin: Authenticated\n"));
|
||||
|
||||
if(!contacts_group_id)
|
||||
{
|
||||
query_for_contacts_group_id(authorizer);
|
||||
}
|
||||
else {
|
||||
GDataContactsService *service;
|
||||
service = gdata_contacts_service_new(GDATA_AUTHORIZER(authorizer));
|
||||
query_after_auth(service);
|
||||
g_object_unref(service);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void cm_gdata_auth_ready(GDataContactsService *service, GAsyncResult *res, gpointer data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if(!gdata_service_authenticate_finish(GDATA_SERVICE(service), res, &error))
|
||||
{
|
||||
log_error(LOG_PROTOCOL, _("GData plugin: Authentication error: %s\n"), error->message);
|
||||
g_error_free(error);
|
||||
cm_gdata_contacts_query_running = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
log_message(LOG_PROTOCOL, _("GData plugin: Authenticated\n"));
|
||||
|
||||
query_after_auth(service);
|
||||
}
|
||||
#endif
|
||||
static void query()
|
||||
{
|
||||
|
||||
#ifdef HAVE_GDATA_VERSION_0_9
|
||||
GDataClientLoginAuthorizer *authorizer;
|
||||
#else
|
||||
GDataContactsService *service;
|
||||
#endif
|
||||
|
||||
if(cm_gdata_contacts_query_running)
|
||||
{
|
||||
debug_print("GData plugin: Network query already in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
log_message(LOG_PROTOCOL, _("GData plugin: Starting async authentication\n"));
|
||||
|
||||
#ifdef HAVE_GDATA_VERSION_0_9
|
||||
authorizer = gdata_client_login_authorizer_new(CM_GDATA_CLIENT_ID, GDATA_TYPE_CONTACTS_SERVICE);
|
||||
gdata_client_login_authorizer_authenticate_async(authorizer, cm_gdata_config.username, cm_gdata_config.password, NULL, (GAsyncReadyCallback)cm_gdata_auth_ready, NULL);
|
||||
cm_gdata_contacts_query_running = TRUE;
|
||||
#else
|
||||
service = gdata_contacts_service_new(CM_GDATA_CLIENT_ID);
|
||||
cm_gdata_contacts_query_running = TRUE;
|
||||
gdata_service_authenticate_async(GDATA_SERVICE(service), cm_gdata_config.username, cm_gdata_config.password, NULL,
|
||||
(GAsyncReadyCallback)cm_gdata_auth_ready, NULL);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_GDATA_VERSION_0_9
|
||||
g_object_unref(authorizer);
|
||||
#else
|
||||
g_object_unref(service);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void add_contacts_to_list(GList **address_list, GSList *contacts)
|
||||
{
|
||||
GSList *walk;
|
||||
|
||||
for(walk = contacts; walk; walk = walk->next)
|
||||
{
|
||||
address_entry *ae;
|
||||
Contact *contact = walk->data;
|
||||
|
||||
ae = g_new0(address_entry, 1);
|
||||
ae->name = g_strdup(contact->full_name);
|
||||
ae->address = g_strdup(contact->address);
|
||||
ae->grp_emails = NULL;
|
||||
|
||||
*address_list = g_list_prepend(*address_list, ae);
|
||||
addr_compl_add_address1(ae->address, ae);
|
||||
|
||||
if(contact->given_name && *(contact->given_name) != '\0')
|
||||
addr_compl_add_address1(contact->given_name, ae);
|
||||
|
||||
if(contact->family_name && *(contact->family_name) != '\0')
|
||||
addr_compl_add_address1(contact->family_name, ae);
|
||||
}
|
||||
}
|
||||
|
||||
void cm_gdata_add_contacts(GList **address_list)
|
||||
{
|
||||
add_contacts_to_list(address_list, contacts_cache.contacts);
|
||||
}
|
||||
|
||||
gboolean cm_gdata_update_contacts_cache(void)
|
||||
{
|
||||
if(prefs_common.work_offline)
|
||||
{
|
||||
debug_print("GData plugin: Offline mode\n");
|
||||
}
|
||||
else if(!cm_gdata_config.username || *(cm_gdata_config.username) == '\0' || !cm_gdata_config.password)
|
||||
{
|
||||
/* noop if no credentials are given */
|
||||
debug_print("GData plugin: Empty username or password\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_print("GData plugin: Querying contacts");
|
||||
query();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void cm_gdata_contacts_done(void)
|
||||
{
|
||||
g_free(contacts_group_id);
|
||||
contacts_group_id = NULL;
|
||||
|
||||
write_cache_to_file();
|
||||
if(contacts_cache.contacts && !claws_is_exiting())
|
||||
clear_contacts_cache();
|
||||
}
|
||||
|
||||
void cm_gdata_load_contacts_cache_from_file(void)
|
||||
{
|
||||
gchar *path;
|
||||
GNode *rootnode, *childnode, *contactnode;
|
||||
XMLNode *xmlnode;
|
||||
|
||||
path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, GDATA_CONTACTS_FILENAME, NULL);
|
||||
if(!is_file_exist(path)) {
|
||||
g_free(path);
|
||||
return;
|
||||
}
|
||||
|
||||
/* no merging; make sure the cache is empty (this should be a noop, but just to be safe...) */
|
||||
clear_contacts_cache();
|
||||
|
||||
rootnode = xml_parse_file(path);
|
||||
g_free(path);
|
||||
if(!rootnode)
|
||||
return;
|
||||
xmlnode = rootnode->data;
|
||||
|
||||
/* Check that root entry is "gdata" */
|
||||
if(strcmp2(xmlnode->tag->tag, "gdata") != 0) {
|
||||
g_warning("wrong gdata cache file\n");
|
||||
xml_free_tree(rootnode);
|
||||
return;
|
||||
}
|
||||
|
||||
for(childnode = rootnode->children; childnode; childnode = childnode->next) {
|
||||
GList *attributes;
|
||||
xmlnode = childnode->data;
|
||||
|
||||
if(strcmp2(xmlnode->tag->tag, "contacts") != 0)
|
||||
continue;
|
||||
|
||||
for(contactnode = childnode->children; contactnode; contactnode = contactnode->next)
|
||||
{
|
||||
Contact *cached_contact;
|
||||
|
||||
xmlnode = contactnode->data;
|
||||
|
||||
cached_contact = g_new0(Contact, 1);
|
||||
/* Attributes of the branch nodes */
|
||||
for(attributes = xmlnode->tag->attr; attributes; attributes = attributes->next) {
|
||||
XMLAttr *attr = attributes->data;
|
||||
|
||||
if(attr && attr->name && attr->value) {
|
||||
if(!strcmp2(attr->name, "full_name"))
|
||||
cached_contact->full_name = g_strdup(attr->value);
|
||||
else if(!strcmp2(attr->name, "given_name"))
|
||||
cached_contact->given_name = g_strdup(attr->value);
|
||||
else if(!strcmp2(attr->name, "family_name"))
|
||||
cached_contact->family_name = g_strdup(attr->value);
|
||||
else if(!strcmp2(attr->name, "address"))
|
||||
cached_contact->address = g_strdup(attr->value);
|
||||
}
|
||||
}
|
||||
contacts_cache.contacts = g_slist_prepend(contacts_cache.contacts, cached_contact);
|
||||
debug_print("Read contact from cache: %s\n", cached_contact->full_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free XML tree */
|
||||
xml_free_tree(rootnode);
|
||||
|
||||
contacts_cache.contacts = g_slist_reverse(contacts_cache.contacts);
|
||||
}
|
28
src/plugins/gdata/cm_gdata_contacts.h
Normal file
28
src/plugins/gdata/cm_gdata_contacts.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* GData plugin for Claws-Mail
|
||||
* Copyright (C) 2011 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CM_GDATA_CONTACTS_H
|
||||
#define CM_GDATA_CONTACTS_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void cm_gdata_add_contacts(GList **address_list);
|
||||
void cm_gdata_contacts_done(void);
|
||||
gboolean cm_gdata_update_contacts_cache(void);
|
||||
void cm_gdata_load_contacts_cache_from_file(void);
|
||||
|
||||
#endif /* CM_GDATA_CONTACTS_H */
|
161
src/plugins/gdata/cm_gdata_prefs.c
Normal file
161
src/plugins/gdata/cm_gdata_prefs.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* GData plugin for Claws-Mail
|
||||
* Copyright (C) 2011 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# include "claws-features.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "cm_gdata_prefs.h"
|
||||
#include "gdata_plugin.h"
|
||||
#include "cm_gdata_contacts.h"
|
||||
|
||||
#include "prefs_gtk.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PrefsPage page;
|
||||
GtkWidget *entry_username;
|
||||
GtkWidget *entry_password;
|
||||
GtkWidget *spin_max_num_results;
|
||||
GtkWidget *spin_max_cache_age;
|
||||
} CmGDataPage;
|
||||
|
||||
CmGDataPrefs cm_gdata_config;
|
||||
CmGDataPage gdata_page;
|
||||
|
||||
PrefParam cm_gdata_param[] =
|
||||
{
|
||||
{"username", NULL, &cm_gdata_config.username, P_STRING,
|
||||
&gdata_page.entry_username, prefs_set_data_from_entry, prefs_set_entry},
|
||||
|
||||
{"password", NULL, &cm_gdata_config.password, P_PASSWORD,
|
||||
&gdata_page.entry_password, prefs_set_data_from_entry, prefs_set_entry},
|
||||
|
||||
{ "max_num_results", "1000", &cm_gdata_config.max_num_results, P_INT,
|
||||
&gdata_page.spin_max_num_results, prefs_set_data_from_spinbtn, prefs_set_spinbtn},
|
||||
|
||||
{ "max_cache_age", "300", &cm_gdata_config.max_cache_age, P_INT,
|
||||
&gdata_page.spin_max_cache_age, prefs_set_data_from_spinbtn, prefs_set_spinbtn},
|
||||
|
||||
{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static void gdata_create_prefs_page(PrefsPage *page, GtkWindow *window, gpointer data)
|
||||
{
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *spinner;
|
||||
GtkWidget *table;
|
||||
GtkWidget *label;
|
||||
GtkWidget *entry;
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
|
||||
/* auth frame */
|
||||
frame = gtk_frame_new(_("Authentication"));
|
||||
gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
/* username */
|
||||
table = gtk_table_new(2, 2, FALSE);
|
||||
label = gtk_label_new(_("Username:"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
||||
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 4, 4);
|
||||
entry = gtk_entry_new();
|
||||
gtk_widget_set_size_request(entry, 250, -1);
|
||||
gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 4, 4);
|
||||
gdata_page.entry_username = entry;
|
||||
label = gtk_label_new(_("Password:"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
||||
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 4, 4);
|
||||
entry = gtk_entry_new();
|
||||
gtk_widget_set_size_request(entry, 250, -1);
|
||||
gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
|
||||
gdata_page.entry_password = entry;
|
||||
gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 4, 4);
|
||||
gtk_container_add(GTK_CONTAINER(frame), table);
|
||||
|
||||
table = gtk_table_new(2, 2, FALSE);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
|
||||
label = gtk_label_new(_("Polling interval (seconds):"));
|
||||
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 4, 4);
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
||||
spinner = gtk_spin_button_new_with_range(10, 10000, 10);
|
||||
gtk_table_attach(GTK_TABLE(table), spinner, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 4, 4);
|
||||
gdata_page.spin_max_cache_age = spinner;
|
||||
|
||||
label = gtk_label_new(_("Maximum number of results:"));
|
||||
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 4, 4);
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
||||
spinner = gtk_spin_button_new_with_range(0, G_MAXINT, 50);
|
||||
gtk_table_attach(GTK_TABLE(table), spinner, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 4, 4);
|
||||
gdata_page.spin_max_num_results = spinner;
|
||||
|
||||
gtk_widget_show_all(vbox);
|
||||
page->widget = vbox;
|
||||
|
||||
prefs_set_dialog(cm_gdata_param);
|
||||
}
|
||||
|
||||
static void gdata_destroy_prefs_page(PrefsPage *page)
|
||||
{
|
||||
}
|
||||
|
||||
static void gdata_save_prefs(PrefsPage *page)
|
||||
{
|
||||
int old_max_cache_age = cm_gdata_config.max_cache_age;
|
||||
|
||||
if (!page->page_open)
|
||||
return;
|
||||
|
||||
prefs_set_data_from_dialog(cm_gdata_param);
|
||||
|
||||
cm_gdata_update_contacts_cache();
|
||||
if(old_max_cache_age != cm_gdata_config.max_cache_age)
|
||||
cm_gdata_update_contacts_update_timer();
|
||||
}
|
||||
|
||||
void cm_gdata_prefs_init(void)
|
||||
{
|
||||
static gchar *path[3];
|
||||
|
||||
path[0] = _("Plugins");
|
||||
path[1] = _("GData");
|
||||
path[2] = NULL;
|
||||
|
||||
gdata_page.page.path = path;
|
||||
gdata_page.page.create_widget = gdata_create_prefs_page;
|
||||
gdata_page.page.destroy_widget = gdata_destroy_prefs_page;
|
||||
gdata_page.page.save_page = gdata_save_prefs;
|
||||
prefs_gtk_register_page((PrefsPage*) &gdata_page);
|
||||
}
|
||||
|
||||
void cm_gdata_prefs_done(void)
|
||||
{
|
||||
if(!claws_is_exiting()) {
|
||||
prefs_gtk_unregister_page((PrefsPage*) &gdata_page);
|
||||
}
|
||||
}
|
36
src/plugins/gdata/cm_gdata_prefs.h
Normal file
36
src/plugins/gdata/cm_gdata_prefs.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* GData plugin for Claws-Mail
|
||||
* Copyright (C) 2011 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CM_GDATA_PREFS_H_
|
||||
#define CM_GDATA_PREFS_H_
|
||||
|
||||
#include "prefs_gtk.h"
|
||||
|
||||
typedef struct {
|
||||
char *username;
|
||||
char *password;
|
||||
int max_num_results;
|
||||
int max_cache_age;
|
||||
} CmGDataPrefs;
|
||||
|
||||
extern CmGDataPrefs cm_gdata_config;
|
||||
extern PrefParam cm_gdata_param[];
|
||||
|
||||
void cm_gdata_prefs_init(void);
|
||||
void cm_gdata_prefs_done(void);
|
||||
|
||||
#endif /* CM_GDATA_PREFS_H_ */
|
190
src/plugins/gdata/gdata_plugin.c
Normal file
190
src/plugins/gdata/gdata_plugin.c
Normal file
|
@ -0,0 +1,190 @@
|
|||
/* GData plugin for Claws-Mail
|
||||
* Copyright (C) 2011 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# include "claws-features.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
# include <libintl.h>
|
||||
#endif
|
||||
|
||||
#include "common/plugin.h"
|
||||
#include "common/version.h"
|
||||
#include "common/utils.h"
|
||||
#include "common/hooks.h"
|
||||
#include "common/defs.h"
|
||||
#include "common/prefs.h"
|
||||
#include "main.h"
|
||||
#include "mainwindow.h"
|
||||
#include "addr_compl.h"
|
||||
|
||||
#include "cm_gdata_contacts.h"
|
||||
#include "cm_gdata_prefs.h"
|
||||
|
||||
static guint hook_address_completion;
|
||||
static guint hook_offline_switch;
|
||||
static guint timer_query_contacts = 0;
|
||||
|
||||
static gboolean my_address_completion_build_list_hook(gpointer source, gpointer data)
|
||||
{
|
||||
cm_gdata_add_contacts(source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean my_offline_switch_hook(gpointer source, gpointer data)
|
||||
{
|
||||
cm_gdata_update_contacts_cache();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void cm_gdata_save_config(void)
|
||||
{
|
||||
PrefFile *pfile;
|
||||
gchar *rcpath;
|
||||
|
||||
debug_print("Saving GData plugin configuration...\n");
|
||||
|
||||
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
|
||||
pfile = prefs_write_open(rcpath);
|
||||
g_free(rcpath);
|
||||
if (!pfile || (prefs_set_block_label(pfile, "GDataPlugin") < 0))
|
||||
return;
|
||||
|
||||
if (prefs_write_param(cm_gdata_param, pfile->fp) < 0) {
|
||||
debug_print("failed!\n");
|
||||
g_warning(_("\nGData Plugin: Failed to write plugin configuration to file\n"));
|
||||
prefs_file_close_revert(pfile);
|
||||
return;
|
||||
}
|
||||
if (fprintf(pfile->fp, "\n") < 0) {
|
||||
FILE_OP_ERROR(rcpath, "fprintf");
|
||||
prefs_file_close_revert(pfile);
|
||||
}
|
||||
else
|
||||
prefs_file_close(pfile);
|
||||
debug_print("done.\n");
|
||||
}
|
||||
|
||||
void cm_gdata_update_contacts_update_timer(void)
|
||||
{
|
||||
if(timer_query_contacts != 0)
|
||||
g_source_remove(timer_query_contacts);
|
||||
timer_query_contacts = g_timeout_add_seconds(cm_gdata_config.max_cache_age, (GSourceFunc)cm_gdata_update_contacts_cache, NULL);
|
||||
}
|
||||
|
||||
gint plugin_init(gchar **error)
|
||||
{
|
||||
gchar *rcpath;
|
||||
|
||||
/* Version check */
|
||||
if(!check_plugin_version(MAKE_NUMERIC_VERSION(3,7,1,55),
|
||||
VERSION_NUMERIC, _("GData"), error))
|
||||
return -1;
|
||||
|
||||
hook_address_completion = hooks_register_hook(ADDDRESS_COMPLETION_BUILD_ADDRESS_LIST_HOOKLIST,
|
||||
my_address_completion_build_list_hook, NULL);
|
||||
if(hook_address_completion == (guint) -1) {
|
||||
*error = g_strdup(_("Failed to register address completion hook in the GData plugin"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
hook_offline_switch = hooks_register_hook(OFFLINE_SWITCH_HOOKLIST, my_offline_switch_hook, NULL);
|
||||
if(hook_offline_switch == (guint) -1) {
|
||||
hooks_unregister_hook(ADDDRESS_COMPLETION_BUILD_ADDRESS_LIST_HOOKLIST, hook_address_completion);
|
||||
*error = g_strdup(_("Failed to register offline switch hook in the GData plugin"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configuration */
|
||||
prefs_set_default(cm_gdata_param);
|
||||
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
|
||||
prefs_read_config(cm_gdata_param, "GDataPlugin", rcpath, NULL);
|
||||
g_free(rcpath);
|
||||
|
||||
cm_gdata_prefs_init();
|
||||
|
||||
/* contacts cache */
|
||||
cm_gdata_load_contacts_cache_from_file();
|
||||
cm_gdata_update_contacts_update_timer();
|
||||
cm_gdata_update_contacts_cache();
|
||||
|
||||
debug_print("GData plugin loaded\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean plugin_done(void)
|
||||
{
|
||||
if(!claws_is_exiting()) {
|
||||
hooks_unregister_hook(ADDDRESS_COMPLETION_BUILD_ADDRESS_LIST_HOOKLIST, hook_address_completion);
|
||||
hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline_switch);
|
||||
g_source_remove(timer_query_contacts);
|
||||
}
|
||||
cm_gdata_prefs_done();
|
||||
cm_gdata_contacts_done();
|
||||
|
||||
cm_gdata_save_config();
|
||||
|
||||
debug_print("GData plugin unloaded\n");
|
||||
|
||||
/* returning FALSE because dependant libraries may not be unload-safe. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const gchar *plugin_name(void)
|
||||
{
|
||||
return _("GData");
|
||||
}
|
||||
|
||||
const gchar *plugin_desc(void)
|
||||
{
|
||||
return _("This plugin provides access to the GData protocol "
|
||||
"for Claws Mail.\n\n"
|
||||
"The GData protocol is an interface to Google services.\n"
|
||||
"Currently, the only implemented functionality is to include "
|
||||
"Google Contacts into the Tab-address completion.\n"
|
||||
"\nFeedback to <berndth@gmx.de> is welcome.");
|
||||
}
|
||||
|
||||
const gchar *plugin_type(void)
|
||||
{
|
||||
return "GTK2";
|
||||
}
|
||||
|
||||
const gchar *plugin_licence(void)
|
||||
{
|
||||
return "GPL3+";
|
||||
}
|
||||
|
||||
const gchar *plugin_version(void)
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
struct PluginFeature *plugin_provides(void)
|
||||
{
|
||||
static struct PluginFeature features[] =
|
||||
{ {PLUGIN_UTILITY, N_("GData integration")},
|
||||
{PLUGIN_NOTHING, NULL}};
|
||||
return features;
|
||||
}
|
23
src/plugins/gdata/gdata_plugin.h
Normal file
23
src/plugins/gdata/gdata_plugin.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* GData plugin for Claws-Mail
|
||||
* Copyright (C) 2011 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GDATA_PLUGIN_H_
|
||||
#define GDATA_PLUGIN_H_
|
||||
|
||||
void cm_gdata_update_contacts_update_timer(void);
|
||||
|
||||
#endif /* GDATA_PLUGIN_H_ */
|
|
@ -1 +0,0 @@
|
|||
Placeholder
|
|
@ -1 +0,0 @@
|
|||
Placeholder
|
|
@ -1 +0,0 @@
|
|||
Placeholder
|
42
src/plugins/mailmbox/Makefile.am
Normal file
42
src/plugins/mailmbox/Makefile.am
Normal file
|
@ -0,0 +1,42 @@
|
|||
plugindir = $(pkglibdir)/plugins
|
||||
plugin_LTLIBRARIES = mailmbox.la
|
||||
|
||||
## Mailmbox folder plugin
|
||||
|
||||
mailmbox_la_SOURCES = \
|
||||
plugin.c plugin_gtk.c \
|
||||
carray.c carray.h \
|
||||
chash.c chash.h \
|
||||
clist.c clist.h \
|
||||
mailimf.c mailimf.h \
|
||||
mailimf_types.c mailimf_types.h \
|
||||
mailimf_types_helper.c mailimf_types_helper.h \
|
||||
mailimf_write.c mailimf_write.h \
|
||||
maillock.c maillock.h \
|
||||
mailmbox.c mailmbox.h \
|
||||
mailmbox_folder.c mailmbox_folder.h \
|
||||
mailmbox_parse.c mailmbox_parse.h \
|
||||
mailmbox_types.c mailmbox_types.h \
|
||||
mmapstring.c mmapstring.h \
|
||||
plugin_gtk.h
|
||||
|
||||
mailmbox_la_LDFLAGS = \
|
||||
-avoid-version -module
|
||||
|
||||
mailmbox_la_LIBADD = \
|
||||
$(GTK_LIBS)
|
||||
|
||||
mailmbox_la_CPPFLAGS = \
|
||||
$(CLAWS_MAIL_CFLAGS) \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(GTK_CFLAGS)
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(CLAWS_MAIL_CFLAGS) \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(GTK_CFLAGS)
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/common \
|
||||
-I$(top_srcdir)/src/gtk
|
143
src/plugins/mailmbox/carray.c
Normal file
143
src/plugins/mailmbox/carray.c
Normal file
|
@ -0,0 +1,143 @@
|
|||
|
||||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* carray - Implements simple dynamic pointer arrays
|
||||
*
|
||||
* Copyright (c) 1999-2000, Gaël Roualland <gael.roualland@iname.com>
|
||||
* interface changes - 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "carray.h"
|
||||
|
||||
carray * carray_new(unsigned int initsize) {
|
||||
carray * array;
|
||||
|
||||
array = (carray *) malloc(sizeof(carray));
|
||||
if (!array) return NULL;
|
||||
|
||||
array->len = 0;
|
||||
array->max = initsize;
|
||||
array->array = (void **) malloc(sizeof(void *) * initsize);
|
||||
if (!array->array) {
|
||||
free(array);
|
||||
return NULL;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
int carray_add(carray * array, void * data, unsigned int * index) {
|
||||
int r;
|
||||
|
||||
r = carray_set_size(array, array->len + 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
array->array[array->len - 1] = data;
|
||||
if (index != NULL)
|
||||
* index = array->len - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int carray_set_size(carray * array, unsigned int new_size)
|
||||
{
|
||||
if (new_size > array->max) {
|
||||
unsigned int n = array->max * 2;
|
||||
void * new;
|
||||
|
||||
while (n <= new_size)
|
||||
n *= 2;
|
||||
|
||||
new = (void **) realloc(array->array, sizeof(void *) * n);
|
||||
if (!new)
|
||||
return -1;
|
||||
array->array = new;
|
||||
array->max = n;
|
||||
}
|
||||
array->len = new_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int carray_delete_fast(carray * array, unsigned int indx) {
|
||||
if (indx >= array->len)
|
||||
return -1;
|
||||
|
||||
array->array[indx] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int carray_delete(carray * array, unsigned int indx) {
|
||||
if (indx >= array->len)
|
||||
return -1;
|
||||
|
||||
if (indx != --array->len)
|
||||
array->array[indx] = array->array[array->len];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int carray_delete_slow(carray * array, unsigned int indx) {
|
||||
if (indx >= array->len)
|
||||
return -1;
|
||||
|
||||
if (indx != --array->len)
|
||||
memmove(array->array + indx, array->array + indx + 1,
|
||||
(array->len - indx) * sizeof(void *));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef NO_MACROS
|
||||
void ** carray_data(carray * array) {
|
||||
return array->array;
|
||||
}
|
||||
|
||||
unsigned int carray_count(carray * array) {
|
||||
return array->len;
|
||||
}
|
||||
|
||||
void * carray_get(carray * array, unsigned int indx) {
|
||||
return array->array[indx];
|
||||
}
|
||||
|
||||
void carray_set(carray * array, unsigned int indx, void * value) {
|
||||
array->array[indx] = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
void carray_free(carray * array) {
|
||||
free(array->array);
|
||||
free(array);
|
||||
}
|
126
src/plugins/mailmbox/carray.h
Normal file
126
src/plugins/mailmbox/carray.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
|
||||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* carray - Implements simple dynamic pointer arrays
|
||||
*
|
||||
* Copyright (c) 1999-2000, Gaël Roualland <gael.roualland@iname.com>
|
||||
* interface changes - 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef CARRAY_H
|
||||
#define CARRAY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
struct carray_s {
|
||||
void ** array;
|
||||
unsigned int len;
|
||||
unsigned int max;
|
||||
};
|
||||
|
||||
typedef struct carray_s carray;
|
||||
|
||||
/* Creates a new array of pointers, with initsize preallocated cells */
|
||||
carray * carray_new(unsigned int initsize);
|
||||
|
||||
/* Adds the pointer to data in the array.
|
||||
Returns the index of the pointer in the array or -1 on error */
|
||||
int carray_add(carray * array, void * data, unsigned int * index);
|
||||
|
||||
int carray_set_size(carray * array, unsigned int new_size);
|
||||
|
||||
/* Removes the cell at this index position. Returns TRUE on success.
|
||||
Order of elements in the array IS changed. */
|
||||
int carray_delete(carray * array, unsigned int indx);
|
||||
|
||||
/* Removes the cell at this index position. Returns TRUE on success.
|
||||
Order of elements in the array IS not changed. */
|
||||
int carray_delete_slow(carray * array, unsigned int indx);
|
||||
|
||||
/* remove without decreasing the size of the array */
|
||||
int carray_delete_fast(carray * array, unsigned int indx);
|
||||
|
||||
/* Some of the following routines can be implemented as macros to
|
||||
be faster. If you don't want it, define NO_MACROS */
|
||||
#ifdef NO_MACROS
|
||||
|
||||
/* Returns the array itself */
|
||||
void ** carray_data(carray);
|
||||
|
||||
/* Returns the number of elements in the array */
|
||||
int carray_count(carray);
|
||||
|
||||
/* Returns the contents of one cell */
|
||||
void * carray_get(carray array, unsigned int indx);
|
||||
|
||||
/* Sets the contents of one cell */
|
||||
void carray_set(carray array, unsigned int indx, void * value);
|
||||
|
||||
#else
|
||||
|
||||
#if 0
|
||||
#define carray_data(a) (a->array)
|
||||
#define carray_count(a) (a->len)
|
||||
#define carray_get(a, indx) (a->array[indx])
|
||||
#define carray_set(a, indx, v) do { a->array[indx]=v; } while(0)
|
||||
#endif
|
||||
|
||||
static inline void ** carray_data(carray * array) {
|
||||
return array->array;
|
||||
}
|
||||
|
||||
static inline unsigned int carray_count(carray * array) {
|
||||
return array->len;
|
||||
}
|
||||
|
||||
static inline void * carray_get(carray * array, unsigned int indx) {
|
||||
return array->array[indx];
|
||||
}
|
||||
|
||||
static inline void carray_set(carray * array,
|
||||
unsigned int indx, void * value) {
|
||||
array->array[indx] = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
void carray_free(carray * array);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
395
src/plugins/mailmbox/chash.c
Normal file
395
src/plugins/mailmbox/chash.c
Normal file
|
@ -0,0 +1,395 @@
|
|||
|
||||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* chash - Implements generic hash tables.
|
||||
*
|
||||
* Copyright (c) 1999-2000, Gaël Roualland <gael.roualland@iname.com>
|
||||
* interface changes - 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "chash.h"
|
||||
|
||||
/* This defines the maximum (average) number of entries per bucket.
|
||||
The hash is resized everytime inserting an entry makes the
|
||||
average go over that value. */
|
||||
#define CHASH_MAXDEPTH 3
|
||||
|
||||
static inline unsigned int chash_func(const char * key, unsigned int len) {
|
||||
#if 0
|
||||
register unsigned int c = 0, t;
|
||||
register const char * k = key;
|
||||
|
||||
while (len--) {
|
||||
c += (c << 4) + *k++;
|
||||
if ((t = c & 0xF0000000)) {
|
||||
c ^= t >> 24;
|
||||
c ^= t;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
#endif
|
||||
register unsigned int c = 5381;
|
||||
register const char * k = key;
|
||||
|
||||
while (len--) {
|
||||
c = ((c << 5) + c) + *k++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline char * chash_dup(const void * data, unsigned int len)
|
||||
{
|
||||
void * r;
|
||||
|
||||
r = (char *) malloc(len);
|
||||
if (!r)
|
||||
return NULL;
|
||||
memcpy(r, data, len);
|
||||
return r;
|
||||
}
|
||||
|
||||
chash * chash_new(unsigned int size, int flags)
|
||||
{
|
||||
chash * h;
|
||||
|
||||
h = (chash *) malloc(sizeof(chash));
|
||||
if (h == NULL)
|
||||
return NULL;
|
||||
|
||||
h->count = 0;
|
||||
h->cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *));
|
||||
if (h->cells == NULL) {
|
||||
free(h);
|
||||
return NULL;
|
||||
}
|
||||
h->size = size;
|
||||
h->copykey = flags & CHASH_COPYKEY;
|
||||
h->copyvalue = flags & CHASH_COPYVALUE;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
int chash_get(chash * hash,
|
||||
chashdatum * key, chashdatum * result)
|
||||
{
|
||||
unsigned int func;
|
||||
chashiter * iter;
|
||||
|
||||
func = chash_func(key->data, key->len);
|
||||
|
||||
/* look for the key in existing cells */
|
||||
iter = hash->cells[func % hash->size];
|
||||
while (iter) {
|
||||
if (iter->key.len == key->len && iter->func == func
|
||||
&& !memcmp(iter->key.data, key->data, key->len)) {
|
||||
* result = iter->value; /* found */
|
||||
|
||||
return 0;
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int chash_set(chash * hash,
|
||||
chashdatum * key,
|
||||
chashdatum * value,
|
||||
chashdatum * oldvalue)
|
||||
{
|
||||
unsigned int func, indx;
|
||||
chashiter * iter, * cell;
|
||||
int r;
|
||||
|
||||
if (hash->count > hash->size * CHASH_MAXDEPTH) {
|
||||
r = chash_resize(hash, (hash->count / CHASH_MAXDEPTH) * 2 + 1);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
func = chash_func(key->data, key->len);
|
||||
indx = func % hash->size;
|
||||
|
||||
/* look for the key in existing cells */
|
||||
iter = hash->cells[indx];
|
||||
while (iter) {
|
||||
if (iter->key.len == key->len && iter->func == func
|
||||
&& !memcmp(iter->key.data, key->data, key->len)) {
|
||||
/* found, replacing entry */
|
||||
if (hash->copyvalue) {
|
||||
char * data;
|
||||
|
||||
data = chash_dup(value->data, value->len);
|
||||
if (data == NULL)
|
||||
goto err;
|
||||
|
||||
free(iter->value.data);
|
||||
iter->value.data = data;
|
||||
iter->value.len = value->len;
|
||||
} else {
|
||||
if (oldvalue != NULL) {
|
||||
oldvalue->data = iter->value.data;
|
||||
oldvalue->len = iter->value.len;
|
||||
}
|
||||
iter->value.data = value->data;
|
||||
iter->value.len = value->len;
|
||||
}
|
||||
if (!hash->copykey)
|
||||
iter->key.data = key->data;
|
||||
|
||||
if (oldvalue != NULL) {
|
||||
oldvalue->data = value->data;
|
||||
oldvalue->len = value->len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
if (oldvalue != NULL) {
|
||||
oldvalue->data = NULL;
|
||||
oldvalue->len = 0;
|
||||
}
|
||||
|
||||
/* not found, adding entry */
|
||||
cell = (struct chashcell *) malloc(sizeof(struct chashcell));
|
||||
if (cell == NULL)
|
||||
goto err;
|
||||
|
||||
if (hash->copykey) {
|
||||
cell->key.data = chash_dup(key->data, key->len);
|
||||
if (cell->key.data == NULL)
|
||||
goto free;
|
||||
}
|
||||
else
|
||||
cell->key.data = key->data;
|
||||
|
||||
cell->key.len = key->len;
|
||||
if (hash->copyvalue) {
|
||||
cell->value.data = chash_dup(value->data, value->len);
|
||||
if (cell->value.data == NULL)
|
||||
goto free_key_data;
|
||||
}
|
||||
else
|
||||
cell->value.data = value->data;
|
||||
|
||||
cell->value.len = value->len;
|
||||
cell->func = func;
|
||||
cell->next = hash->cells[indx];
|
||||
hash->cells[indx] = cell;
|
||||
hash->count++;
|
||||
|
||||
return 0;
|
||||
|
||||
free_key_data:
|
||||
if (hash->copykey)
|
||||
free(cell->key.data);
|
||||
free:
|
||||
free(cell);
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int chash_delete(chash * hash, chashdatum * key, chashdatum * oldvalue)
|
||||
{
|
||||
/* chashdatum result = { NULL, TRUE }; */
|
||||
unsigned int func, indx;
|
||||
chashiter * iter, * old;
|
||||
|
||||
/*
|
||||
if (!keylen)
|
||||
keylen = strlen(key) + 1;
|
||||
*/
|
||||
|
||||
func = chash_func(key->data, key->len);
|
||||
indx = func % hash->size;
|
||||
|
||||
/* look for the key in existing cells */
|
||||
old = NULL;
|
||||
iter = hash->cells[indx];
|
||||
while (iter) {
|
||||
if (iter->key.len == key->len && iter->func == func
|
||||
&& !memcmp(iter->key.data, key->data, key->len)) {
|
||||
/* found, deleting */
|
||||
if (old)
|
||||
old->next = iter->next;
|
||||
else
|
||||
hash->cells[indx] = iter->next;
|
||||
if (hash->copykey)
|
||||
free(iter->key.data);
|
||||
if (hash->copyvalue)
|
||||
free(iter->value.data);
|
||||
else {
|
||||
if (oldvalue != NULL) {
|
||||
oldvalue->data = iter->value.data;
|
||||
oldvalue->len = iter->value.len;
|
||||
}
|
||||
}
|
||||
free(iter);
|
||||
hash->count--;
|
||||
return 0;
|
||||
}
|
||||
old = iter;
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
return -1; /* not found */
|
||||
}
|
||||
|
||||
void chash_free(chash * hash) {
|
||||
unsigned int indx;
|
||||
chashiter * iter, * next;
|
||||
|
||||
/* browse the hash table */
|
||||
for(indx = 0; indx < hash->size; indx++) {
|
||||
iter = hash->cells[indx];
|
||||
while (iter) {
|
||||
next = iter->next;
|
||||
if (hash->copykey)
|
||||
free(iter->key.data);
|
||||
if (hash->copyvalue)
|
||||
free(iter->value.data);
|
||||
free(iter);
|
||||
iter = next;
|
||||
}
|
||||
}
|
||||
free(hash->cells);
|
||||
free(hash);
|
||||
}
|
||||
|
||||
void chash_clear(chash * hash) {
|
||||
unsigned int indx;
|
||||
chashiter * iter, * next;
|
||||
|
||||
/* browse the hash table */
|
||||
for(indx = 0; indx < hash->size; indx++) {
|
||||
iter = hash->cells[indx];
|
||||
while (iter) {
|
||||
next = iter->next;
|
||||
if (hash->copykey)
|
||||
free(iter->key.data);
|
||||
if (hash->copyvalue)
|
||||
free(iter->value.data);
|
||||
free(iter);
|
||||
iter = next;
|
||||
}
|
||||
}
|
||||
memset(hash->cells, 0, hash->size * sizeof(* hash->cells));
|
||||
hash->count = 0;
|
||||
}
|
||||
|
||||
chashiter * chash_begin(chash * hash) {
|
||||
chashiter * iter;
|
||||
unsigned int indx = 0;
|
||||
|
||||
iter = hash->cells[0];
|
||||
while(!iter) {
|
||||
indx++;
|
||||
if (indx >= hash->size)
|
||||
return NULL;
|
||||
iter = hash->cells[indx];
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
chashiter * chash_next(chash * hash, chashiter * iter) {
|
||||
unsigned int indx;
|
||||
|
||||
if (!iter)
|
||||
return NULL;
|
||||
|
||||
indx = iter->func % hash->size;
|
||||
iter = iter->next;
|
||||
|
||||
while(!iter) {
|
||||
indx++;
|
||||
if (indx >= hash->size)
|
||||
return NULL;
|
||||
iter = hash->cells[indx];
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
int chash_resize(chash * hash, unsigned int size)
|
||||
{
|
||||
struct chashcell ** cells;
|
||||
unsigned int indx, nindx;
|
||||
chashiter * iter, * next;
|
||||
|
||||
if (hash->size == size)
|
||||
return 0;
|
||||
|
||||
cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *));
|
||||
if (!cells)
|
||||
return -1;
|
||||
|
||||
/* browse initial hash and copy items in second hash */
|
||||
for(indx = 0; indx < hash->size; indx++) {
|
||||
iter = hash->cells[indx];
|
||||
while (iter) {
|
||||
next = iter->next;
|
||||
nindx = iter->func % size;
|
||||
iter->next = cells[nindx];
|
||||
cells[nindx] = iter;
|
||||
iter = next;
|
||||
}
|
||||
}
|
||||
free(hash->cells);
|
||||
hash->size = size;
|
||||
hash->cells = cells;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef NO_MACROS
|
||||
int chash_count(chash * hash) {
|
||||
return hash->count;
|
||||
}
|
||||
|
||||
int chash_size(chash * hash) {
|
||||
return hash->size;
|
||||
}
|
||||
|
||||
void chash_value(chashiter * iter, chashdatum * result) {
|
||||
* result = iter->value;
|
||||
}
|
||||
|
||||
void chash_key(chashiter * iter, chashdatum * result) {
|
||||
* result = iter->key;
|
||||
}
|
||||
#endif
|
166
src/plugins/mailmbox/chash.h
Normal file
166
src/plugins/mailmbox/chash.h
Normal file
|
@ -0,0 +1,166 @@
|
|||
|
||||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* chash - Implements generic hash tables.
|
||||
*
|
||||
* Copyright (c) 1999-2000, Gaël Roualland <gael.roualland@iname.com>
|
||||
* interface changes - 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef CHASH_H
|
||||
#define CHASH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
void * data;
|
||||
unsigned int len;
|
||||
} chashdatum;
|
||||
|
||||
struct chash {
|
||||
unsigned int size;
|
||||
unsigned int count;
|
||||
int copyvalue;
|
||||
int copykey;
|
||||
struct chashcell ** cells;
|
||||
};
|
||||
|
||||
typedef struct chash chash;
|
||||
|
||||
struct chashcell {
|
||||
unsigned int func;
|
||||
chashdatum key;
|
||||
chashdatum value;
|
||||
struct chashcell * next;
|
||||
};
|
||||
|
||||
typedef struct chashcell chashiter;
|
||||
|
||||
#define CHASH_COPYNONE 0
|
||||
#define CHASH_COPYKEY 1
|
||||
#define CHASH_COPYVALUE 2
|
||||
#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE)
|
||||
|
||||
#define CHASH_DEFAULTSIZE 13
|
||||
|
||||
/* Allocates a new (empty) hash using this initial size and the given flags,
|
||||
specifying which data should be copied in the hash.
|
||||
CHASH_COPYNONE : Keys/Values are not copied.
|
||||
CHASH_COPYKEY : Keys are dupped and freed as needed in the hash.
|
||||
CHASH_COPYVALUE : Values are dupped and freed as needed in the hash.
|
||||
CHASH_COPYALL : Both keys and values are dupped in the hash.
|
||||
*/
|
||||
chash * chash_new(unsigned int size, int flags);
|
||||
|
||||
/* Frees a hash */
|
||||
void chash_free(chash * hash);
|
||||
|
||||
/* Removes all elements from a hash */
|
||||
void chash_clear(chash * hash);
|
||||
|
||||
/* Adds an entry in the hash table.
|
||||
Length can be 0 if key/value are strings.
|
||||
If an entry already exists for this key, it is replaced, and its value
|
||||
is returned. Otherwise, the data pointer will be NULL and the length
|
||||
field be set to TRUE or FALSe to indicate success or failure. */
|
||||
int chash_set(chash * hash,
|
||||
chashdatum * key,
|
||||
chashdatum * value,
|
||||
chashdatum * oldvalue);
|
||||
|
||||
/* Retrieves the data associated to the key if it is found in the hash table.
|
||||
The data pointer and the length will be NULL if not found*/
|
||||
int chash_get(chash * hash,
|
||||
chashdatum * key, chashdatum * result);
|
||||
|
||||
/* Removes the entry associated to this key if it is found in the hash table,
|
||||
and returns its contents if not dupped (otherwise, pointer will be NULL
|
||||
and len TRUE). If entry is not found both pointer and len will be NULL. */
|
||||
int chash_delete(chash * hash,
|
||||
chashdatum * key,
|
||||
chashdatum * oldvalue);
|
||||
|
||||
/* Resizes the hash table to the passed size. */
|
||||
int chash_resize(chash * hash, unsigned int size);
|
||||
|
||||
/* Returns an iterator to the first non-empty entry of the hash table */
|
||||
chashiter * chash_begin(chash * hash);
|
||||
|
||||
/* Returns the next non-empty entry of the hash table */
|
||||
chashiter * chash_next(chash * hash, chashiter * iter);
|
||||
|
||||
/* Some of the following routines can be implemented as macros to
|
||||
be faster. If you don't want it, define NO_MACROS */
|
||||
#ifdef NO_MACROS
|
||||
/* Returns the size of the hash table */
|
||||
unsigned int chash_size(chash * hash);
|
||||
|
||||
/* Returns the number of entries in the hash table */
|
||||
unsigned int chash_count(chash * hash);
|
||||
|
||||
/* Returns the key part of the entry pointed by the iterator */
|
||||
void chash_key(chashiter * iter, chashdatum * result);
|
||||
|
||||
/* Returns the value part of the entry pointed by the iterator */
|
||||
void chash_value(chashiter * iter, chashdatum * result);
|
||||
|
||||
#else
|
||||
static inline unsigned int chash_size(chash * hash)
|
||||
{
|
||||
return hash->size;
|
||||
}
|
||||
|
||||
static inline unsigned int chash_count(chash * hash)
|
||||
{
|
||||
return hash->count;
|
||||
}
|
||||
|
||||
static inline void chash_key(chashiter * iter, chashdatum * result)
|
||||
{
|
||||
* result = iter->key;
|
||||
}
|
||||
|
||||
static inline void chash_value(chashiter * iter, chashdatum * result)
|
||||
{
|
||||
* result = iter->value;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
266
src/plugins/mailmbox/clist.c
Normal file
266
src/plugins/mailmbox/clist.c
Normal file
|
@ -0,0 +1,266 @@
|
|||
|
||||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* clist - Implements simple generic double-linked pointer lists
|
||||
*
|
||||
* Copyright (c) 1999-2000, Gaël Roualland <gael.roualland@iname.com>
|
||||
* interface changes - 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "clist.h"
|
||||
|
||||
clist * clist_new() {
|
||||
clist * lst;
|
||||
|
||||
lst = (clist *) malloc(sizeof(clist));
|
||||
if (!lst) return NULL;
|
||||
|
||||
lst->first = lst->last = NULL;
|
||||
lst->count = 0;
|
||||
|
||||
return lst;
|
||||
}
|
||||
|
||||
void clist_free(clist * lst) {
|
||||
clistcell * l1, * l2;
|
||||
|
||||
l1 = lst->first;
|
||||
while (l1) {
|
||||
l2 = l1->next;
|
||||
free(l1);
|
||||
l1 = l2;
|
||||
}
|
||||
|
||||
free(lst);
|
||||
}
|
||||
|
||||
#ifdef NO_MACROS
|
||||
int clist_isempty(clist * lst) {
|
||||
return ((lst->first==lst->last) && (lst->last==NULL));
|
||||
}
|
||||
|
||||
clistiter * clist_begin(clist * lst) {
|
||||
return lst->first;
|
||||
}
|
||||
|
||||
clistiter * clist_end(clist * lst) {
|
||||
return lst->last;
|
||||
}
|
||||
|
||||
clistiter * clist_next(clistiter * iter) {
|
||||
if (iter)
|
||||
return iter->next;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
clistiter * clist_previous(clistiter * iter) {
|
||||
if (iter)
|
||||
return iter->previous;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * clist_content(clistiter * iter) {
|
||||
if (iter)
|
||||
return iter->data;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int clist_count(clist * lst) {
|
||||
return lst->count;
|
||||
}
|
||||
|
||||
int clist_prepend(clist * lst, void * data) {
|
||||
return clist_insert_before(lst, lst->first, data);
|
||||
}
|
||||
|
||||
int clist_append(clist * lst, void * data) {
|
||||
return clist_insert_after(lst, lst->last, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
int clist_insert_before(clist * lst, clistiter * iter, void * data) {
|
||||
clistcell * c;
|
||||
|
||||
c = (clistcell *) malloc(sizeof(clistcell));
|
||||
if (!c) return -1;
|
||||
|
||||
c->data = data;
|
||||
lst->count++;
|
||||
|
||||
if (clist_isempty(lst)) {
|
||||
c->previous = c->next = NULL;
|
||||
lst->first = lst->last = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!iter) {
|
||||
c->previous = lst->last;
|
||||
c->previous->next = c;
|
||||
c->next = NULL;
|
||||
lst->last = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->previous = iter->previous;
|
||||
c->next = iter;
|
||||
c->next->previous = c;
|
||||
if (c->previous)
|
||||
c->previous->next = c;
|
||||
else
|
||||
lst->first = c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clist_insert_after(clist * lst, clistiter * iter, void * data) {
|
||||
clistcell * c;
|
||||
|
||||
c = (clistcell *) malloc(sizeof(clistcell));
|
||||
if (!c) return -1;
|
||||
|
||||
c->data = data;
|
||||
lst->count++;
|
||||
|
||||
if (clist_isempty(lst)) {
|
||||
c->previous = c->next = NULL;
|
||||
lst->first = lst->last = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!iter) {
|
||||
c->previous = lst->last;
|
||||
c->previous->next = c;
|
||||
c->next = NULL;
|
||||
lst->last = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->previous = iter;
|
||||
c->next = iter->next;
|
||||
if (c->next)
|
||||
c->next->previous = c;
|
||||
else
|
||||
lst->last = c;
|
||||
c->previous->next = c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
clistiter * clist_delete(clist * lst, clistiter * iter) {
|
||||
clistiter * ret;
|
||||
|
||||
if (!iter) return NULL;
|
||||
|
||||
if (iter->previous)
|
||||
iter->previous->next = iter->next;
|
||||
else
|
||||
lst->first = iter->next;
|
||||
|
||||
if (iter->next) {
|
||||
iter->next->previous = iter->previous;
|
||||
ret = iter->next;
|
||||
} else {
|
||||
lst->last = iter->previous;
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
free(iter);
|
||||
lst->count--;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void clist_foreach(clist * lst, clist_func func, void * data)
|
||||
{
|
||||
clistiter * cur;
|
||||
|
||||
for(cur = clist_begin(lst) ; cur != NULL ; cur = cur->next)
|
||||
func(cur->data, data);
|
||||
}
|
||||
|
||||
void clist_concat(clist * dest, clist * src)
|
||||
{
|
||||
if (src->first == NULL) {
|
||||
/* do nothing */
|
||||
}
|
||||
else if (dest->last == NULL) {
|
||||
dest->first = src->first;
|
||||
dest->last = src->last;
|
||||
}
|
||||
else {
|
||||
dest->last->next = src->first;
|
||||
src->first->previous = dest->last;
|
||||
dest->last = src->last;
|
||||
}
|
||||
|
||||
dest->count += src->count;
|
||||
src->last = src->first = NULL;
|
||||
}
|
||||
|
||||
static inline clistiter * internal_clist_nth(clist * lst, int index)
|
||||
{
|
||||
clistiter * cur;
|
||||
|
||||
cur = clist_begin(lst);
|
||||
while ((index > 0) && (cur != NULL)) {
|
||||
cur = cur->next;
|
||||
index --;
|
||||
}
|
||||
|
||||
if (cur == NULL)
|
||||
return NULL;
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
void * clist_nth_data(clist * lst, int index)
|
||||
{
|
||||
clistiter * cur;
|
||||
|
||||
cur = internal_clist_nth(lst, index);
|
||||
if (cur == NULL)
|
||||
return NULL;
|
||||
|
||||
return cur->data;
|
||||
}
|
||||
|
||||
clistiter * clist_nth(clist * lst, int index)
|
||||
{
|
||||
return internal_clist_nth(lst, index);
|
||||
}
|
134
src/plugins/mailmbox/clist.h
Normal file
134
src/plugins/mailmbox/clist.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
|
||||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* clist - Implements simple generic double-linked pointer lists
|
||||
*
|
||||
* Copyright (c) 1999-2000, Gaël Roualland <gael.roualland@iname.com>
|
||||
* interface changes - 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef CLIST_H
|
||||
#define CLIST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct clistcell_s {
|
||||
void * data;
|
||||
struct clistcell_s * previous;
|
||||
struct clistcell_s * next;
|
||||
} clistcell;
|
||||
|
||||
struct clist_s {
|
||||
clistcell * first;
|
||||
clistcell * last;
|
||||
int count;
|
||||
};
|
||||
|
||||
typedef struct clist_s clist;
|
||||
typedef clistcell clistiter;
|
||||
|
||||
/* Allocate a new pointer list */
|
||||
clist * clist_new();
|
||||
|
||||
/* Destroys a list. Data pointed by data pointers is NOT freed. */
|
||||
void clist_free(clist *);
|
||||
|
||||
/* Some of the following routines can be implemented as macros to
|
||||
be faster. If you don't want it, define NO_MACROS */
|
||||
#ifdef NO_MACROS
|
||||
|
||||
/* Returns TRUE if list is empty */
|
||||
int clist_isempty(clist *);
|
||||
|
||||
/* Returns the number of elements in the list */
|
||||
int clist_count(clist *);
|
||||
|
||||
/* Returns an iterator to the first element of the list */
|
||||
clistiter * clist_begin(clist *);
|
||||
|
||||
/* Returns an iterator to the last element of the list */
|
||||
clistiter * clist_end(clist *);
|
||||
|
||||
/* Returns an iterator to the next element of the list */
|
||||
clistiter * clist_next(clistiter *);
|
||||
|
||||
/* Returns an iterator to the previous element of the list */
|
||||
clistiter * clist_previous(clistiter *);
|
||||
|
||||
/* Returns the data pointer of this element of the list */
|
||||
void* clist_content(clistiter *);
|
||||
|
||||
/* Inserts this data pointer at the beginning of the list */
|
||||
int clist_prepend(clist *, void *);
|
||||
|
||||
/* Inserts this data pointer at the end of the list */
|
||||
int clist_append(clist *, void *);
|
||||
#else
|
||||
#define clist_isempty(lst) ((lst->first==lst->last) && (lst->last==NULL))
|
||||
#define clist_count(lst) (lst->count)
|
||||
#define clist_begin(lst) (lst->first)
|
||||
#define clist_end(lst) (lst->last)
|
||||
#define clist_next(iter) (iter ? iter->next : NULL)
|
||||
#define clist_previous(iter) (iter ? iter->previous : NULL)
|
||||
#define clist_content(iter) (iter ? iter->data : NULL)
|
||||
#define clist_prepend(lst, data) (clist_insert_before(lst, lst->first, data))
|
||||
#define clist_append(lst, data) (clist_insert_after(lst, lst->last, data))
|
||||
#endif
|
||||
|
||||
/* Inserts this data pointer before the element pointed by the iterator */
|
||||
int clist_insert_before(clist *, clistiter *, void *);
|
||||
|
||||
/* Inserts this data pointer after the element pointed by the iterator */
|
||||
int clist_insert_after(clist *, clistiter *, void *);
|
||||
|
||||
/* Deletes the element pointed by the iterator.
|
||||
Returns an iterator to the next element. */
|
||||
clistiter * clist_delete(clist *, clistiter *);
|
||||
|
||||
typedef void (* clist_func)(void *, void *);
|
||||
|
||||
void clist_foreach(clist * lst, clist_func func, void * data);
|
||||
|
||||
void clist_concat(clist * dest, clist * src);
|
||||
|
||||
void * clist_nth_data(clist * lst, int index);
|
||||
|
||||
clistiter * clist_nth(clist * lst, int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
7585
src/plugins/mailmbox/mailimf.c
Normal file
7585
src/plugins/mailmbox/mailimf.c
Normal file
File diff suppressed because it is too large
Load diff
345
src/plugins/mailmbox/mailimf.h
Normal file
345
src/plugins/mailmbox/mailimf.h
Normal file
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef MAILIMF_H
|
||||
|
||||
#define MAILIMF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mailimf_types.h"
|
||||
#include "mailimf_write.h"
|
||||
#include "mailimf_types_helper.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
mailimf_message_parse will parse the given message
|
||||
|
||||
@param message this is a string containing the message content
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the message in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int mailimf_message_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_message ** result);
|
||||
|
||||
/*
|
||||
mailimf_body_parse will parse the given text part of a message
|
||||
|
||||
@param message this is a string containing the message text part
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the message text part in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int mailimf_body_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_body ** result);
|
||||
|
||||
/*
|
||||
mailimf_fields_parse will parse the given header fields
|
||||
|
||||
@param message this is a string containing the header fields
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the header fields in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int mailimf_fields_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_fields ** result);
|
||||
|
||||
/*
|
||||
mailimf_mailbox_list_parse will parse the given mailbox list
|
||||
|
||||
@param message this is a string containing the mailbox list
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the mailbox list in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int
|
||||
mailimf_mailbox_list_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_mailbox_list ** result);
|
||||
|
||||
/*
|
||||
mailimf_address_list_parse will parse the given address list
|
||||
|
||||
@param message this is a string containing the address list
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the address list in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int
|
||||
mailimf_address_list_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_address_list ** result);
|
||||
|
||||
/*
|
||||
mailimf_address_parse will parse the given address
|
||||
|
||||
@param message this is a string containing the address
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the address in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int mailimf_address_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_address ** result);
|
||||
|
||||
/*
|
||||
mailimf_mailbox_parse will parse the given address
|
||||
|
||||
@param message this is a string containing the mailbox
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the mailbox in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int mailimf_mailbox_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_mailbox ** result);
|
||||
|
||||
/*
|
||||
mailimf_date_time_parse will parse the given RFC 2822 date
|
||||
|
||||
@param message this is a string containing the date
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the date in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int mailimf_date_time_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_date_time ** result);
|
||||
|
||||
/*
|
||||
mailimf_envelope_fields_parse will parse the given fields (Date,
|
||||
From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
|
||||
References and Subject)
|
||||
|
||||
@param message this is a string containing the header fields
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the header fields in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int mailimf_envelope_fields_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_fields ** result);
|
||||
|
||||
/*
|
||||
mailimf_ignore_field_parse will skip the given field
|
||||
|
||||
@param message this is a string containing the header field
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the header field in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
|
||||
int mailimf_ignore_field_parse(const char * message, size_t length,
|
||||
size_t * index);
|
||||
|
||||
/*
|
||||
mailimf_envelope_fields will parse the given fields (Date,
|
||||
From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
|
||||
References and Subject), other fields will be added as optional
|
||||
fields.
|
||||
|
||||
@param message this is a string containing the header fields
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the header fields in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
|
||||
int
|
||||
mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_fields ** result);
|
||||
|
||||
/*
|
||||
mailimf_envelope_fields will parse the given fields as optional
|
||||
fields.
|
||||
|
||||
@param message this is a string containing the header fields
|
||||
@param length this is the size of the given string
|
||||
@param index this is a pointer to the start of the header fields in
|
||||
the given string, (* index) is modified to point at the end
|
||||
of the parsed data
|
||||
@param result the result of the parse operation is stored in
|
||||
(* result)
|
||||
|
||||
@return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
|
||||
*/
|
||||
|
||||
int
|
||||
mailimf_optional_fields_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_fields ** result);
|
||||
|
||||
|
||||
/* internal use, exported for MIME */
|
||||
|
||||
int mailimf_fws_parse(const char * message, size_t length, size_t * index);
|
||||
|
||||
int mailimf_cfws_parse(const char * message, size_t length,
|
||||
size_t * index);
|
||||
|
||||
int mailimf_char_parse(const char * message, size_t length,
|
||||
size_t * index, char token);
|
||||
|
||||
int mailimf_unstrict_char_parse(const char * message, size_t length,
|
||||
size_t * index, char token);
|
||||
|
||||
int mailimf_crlf_parse(const char * message, size_t length, size_t * index);
|
||||
|
||||
int
|
||||
mailimf_custom_string_parse(const char * message, size_t length,
|
||||
size_t * index, char ** result,
|
||||
int (* is_custom_char)(char));
|
||||
|
||||
int
|
||||
mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
|
||||
size_t * index, char * token,
|
||||
size_t token_length);
|
||||
|
||||
#define mailimf_token_case_insensitive_parse(message, length, index, token) \
|
||||
mailimf_token_case_insensitive_len_parse(message, length, index, token, \
|
||||
sizeof(token) - 1)
|
||||
|
||||
int mailimf_quoted_string_parse(const char * message, size_t length,
|
||||
size_t * index, char ** result);
|
||||
|
||||
int
|
||||
mailimf_number_parse(const char * message, size_t length,
|
||||
size_t * index, uint32_t * result);
|
||||
|
||||
int mailimf_msg_id_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
char ** result);
|
||||
|
||||
int mailimf_msg_id_list_parse(const char * message, size_t length,
|
||||
size_t * index, clist ** result);
|
||||
|
||||
int mailimf_word_parse(const char * message, size_t length,
|
||||
size_t * index, char ** result);
|
||||
|
||||
int mailimf_atom_parse(const char * message, size_t length,
|
||||
size_t * index, char ** result);
|
||||
|
||||
int mailimf_fws_atom_parse(const char * message, size_t length,
|
||||
size_t * index, char ** result);
|
||||
|
||||
int mailimf_fws_word_parse(const char * message, size_t length,
|
||||
size_t * index, char ** result);
|
||||
|
||||
int mailimf_fws_quoted_string_parse(const char * message, size_t length,
|
||||
size_t * index, char ** result);
|
||||
|
||||
/* exported for IMAP */
|
||||
|
||||
int mailimf_references_parse(const char * message, size_t length,
|
||||
size_t * index,
|
||||
struct mailimf_references ** result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
868
src/plugins/mailmbox/mailimf_types.c
Normal file
868
src/plugins/mailmbox/mailimf_types.c
Normal file
|
@ -0,0 +1,868 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "mailimf_types.h"
|
||||
#include "mmapstring.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void mailimf_atom_free(char * atom)
|
||||
{
|
||||
free(atom);
|
||||
}
|
||||
|
||||
void mailimf_dot_atom_free(char * dot_atom)
|
||||
{
|
||||
free(dot_atom);
|
||||
}
|
||||
|
||||
void mailimf_dot_atom_text_free(char * dot_atom)
|
||||
{
|
||||
free(dot_atom);
|
||||
}
|
||||
|
||||
void mailimf_quoted_string_free(char * quoted_string)
|
||||
{
|
||||
free(quoted_string);
|
||||
}
|
||||
|
||||
void mailimf_word_free(char * word)
|
||||
{
|
||||
free(word);
|
||||
}
|
||||
|
||||
void mailimf_phrase_free(char * phrase)
|
||||
{
|
||||
free(phrase);
|
||||
}
|
||||
|
||||
void mailimf_unstructured_free(char * unstructured)
|
||||
{
|
||||
free(unstructured);
|
||||
}
|
||||
|
||||
|
||||
struct mailimf_date_time *
|
||||
mailimf_date_time_new(int dt_day, int dt_month, int dt_year,
|
||||
int dt_hour, int dt_min, int dt_sec, int dt_zone)
|
||||
{
|
||||
struct mailimf_date_time * date_time;
|
||||
|
||||
date_time = malloc(sizeof(* date_time));
|
||||
if (date_time == NULL)
|
||||
return NULL;
|
||||
|
||||
date_time->dt_day = dt_day;
|
||||
date_time->dt_month = dt_month;
|
||||
date_time->dt_year = dt_year;
|
||||
date_time->dt_hour = dt_hour;
|
||||
date_time->dt_min = dt_min;
|
||||
date_time->dt_sec = dt_sec;
|
||||
date_time->dt_zone = dt_zone;
|
||||
|
||||
return date_time;
|
||||
}
|
||||
|
||||
|
||||
void mailimf_date_time_free(struct mailimf_date_time * date_time)
|
||||
{
|
||||
free(date_time);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct mailimf_address *
|
||||
mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
|
||||
struct mailimf_group * ad_group)
|
||||
{
|
||||
struct mailimf_address * address;
|
||||
|
||||
address = malloc(sizeof(* address));
|
||||
if (address == NULL)
|
||||
return NULL;
|
||||
|
||||
address->ad_type = ad_type;
|
||||
switch (ad_type) {
|
||||
case MAILIMF_ADDRESS_MAILBOX:
|
||||
address->ad_data.ad_mailbox = ad_mailbox;
|
||||
break;
|
||||
case MAILIMF_ADDRESS_GROUP:
|
||||
address->ad_data.ad_group = ad_group;
|
||||
break;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
void mailimf_address_free(struct mailimf_address * address)
|
||||
{
|
||||
switch (address->ad_type) {
|
||||
case MAILIMF_ADDRESS_MAILBOX:
|
||||
mailimf_mailbox_free(address->ad_data.ad_mailbox);
|
||||
break;
|
||||
case MAILIMF_ADDRESS_GROUP:
|
||||
mailimf_group_free(address->ad_data.ad_group);
|
||||
}
|
||||
free(address);
|
||||
}
|
||||
|
||||
struct mailimf_mailbox *
|
||||
mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec)
|
||||
{
|
||||
struct mailimf_mailbox * mb;
|
||||
|
||||
mb = malloc(sizeof(* mb));
|
||||
if (mb == NULL)
|
||||
return NULL;
|
||||
|
||||
mb->mb_display_name = mb_display_name;
|
||||
mb->mb_addr_spec = mb_addr_spec;
|
||||
|
||||
return mb;
|
||||
}
|
||||
|
||||
void mailimf_mailbox_free(struct mailimf_mailbox * mailbox)
|
||||
{
|
||||
if (mailbox->mb_display_name != NULL)
|
||||
mailimf_display_name_free(mailbox->mb_display_name);
|
||||
mailimf_addr_spec_free(mailbox->mb_addr_spec);
|
||||
free(mailbox);
|
||||
}
|
||||
|
||||
|
||||
void mailimf_angle_addr_free(char * angle_addr)
|
||||
{
|
||||
free(angle_addr);
|
||||
}
|
||||
|
||||
|
||||
struct mailimf_group *
|
||||
mailimf_group_new(char * grp_display_name,
|
||||
struct mailimf_mailbox_list * grp_mb_list)
|
||||
{
|
||||
struct mailimf_group * group;
|
||||
|
||||
group = malloc(sizeof(* group));
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->grp_display_name = grp_display_name;
|
||||
group->grp_mb_list = grp_mb_list;
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
void mailimf_group_free(struct mailimf_group * group)
|
||||
{
|
||||
if (group->grp_mb_list)
|
||||
mailimf_mailbox_list_free(group->grp_mb_list);
|
||||
mailimf_display_name_free(group->grp_display_name);
|
||||
free(group);
|
||||
}
|
||||
|
||||
void mailimf_display_name_free(char * display_name)
|
||||
{
|
||||
mailimf_phrase_free(display_name);
|
||||
}
|
||||
|
||||
|
||||
struct mailimf_mailbox_list *
|
||||
mailimf_mailbox_list_new(clist * mb_list)
|
||||
{
|
||||
struct mailimf_mailbox_list * mbl;
|
||||
|
||||
mbl = malloc(sizeof(* mbl));
|
||||
if (mbl == NULL)
|
||||
return NULL;
|
||||
|
||||
mbl->mb_list = mb_list;
|
||||
|
||||
return mbl;
|
||||
}
|
||||
|
||||
void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list)
|
||||
{
|
||||
clist_foreach(mb_list->mb_list, (clist_func) mailimf_mailbox_free, NULL);
|
||||
clist_free(mb_list->mb_list);
|
||||
free(mb_list);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct mailimf_address_list *
|
||||
mailimf_address_list_new(clist * ad_list)
|
||||
{
|
||||
struct mailimf_address_list * addr_list;
|
||||
|
||||
addr_list = malloc(sizeof(* addr_list));
|
||||
if (addr_list == NULL)
|
||||
return NULL;
|
||||
|
||||
addr_list->ad_list = ad_list;
|
||||
|
||||
return addr_list;
|
||||
}
|
||||
|
||||
void mailimf_address_list_free(struct mailimf_address_list * addr_list)
|
||||
{
|
||||
clist_foreach(addr_list->ad_list, (clist_func) mailimf_address_free, NULL);
|
||||
clist_free(addr_list->ad_list);
|
||||
free(addr_list);
|
||||
}
|
||||
|
||||
|
||||
void mailimf_addr_spec_free(char * addr_spec)
|
||||
{
|
||||
free(addr_spec);
|
||||
}
|
||||
|
||||
void mailimf_local_part_free(char * local_part)
|
||||
{
|
||||
free(local_part);
|
||||
}
|
||||
|
||||
void mailimf_domain_free(char * domain)
|
||||
{
|
||||
free(domain);
|
||||
}
|
||||
|
||||
void mailimf_domain_literal_free(char * domain_literal)
|
||||
{
|
||||
free(domain_literal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct mailimf_message *
|
||||
mailimf_message_new(struct mailimf_fields * msg_fields,
|
||||
struct mailimf_body * msg_body)
|
||||
{
|
||||
struct mailimf_message * message;
|
||||
|
||||
message = malloc(sizeof(* message));
|
||||
if (message == NULL)
|
||||
return NULL;
|
||||
|
||||
message->msg_fields = msg_fields;
|
||||
message->msg_body = msg_body;
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
void mailimf_message_free(struct mailimf_message * message)
|
||||
{
|
||||
mailimf_body_free(message->msg_body);
|
||||
mailimf_fields_free(message->msg_fields);
|
||||
free(message);
|
||||
}
|
||||
|
||||
|
||||
struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size)
|
||||
{
|
||||
struct mailimf_body * body;
|
||||
|
||||
body = malloc(sizeof(* body));
|
||||
if (body == NULL)
|
||||
return NULL;
|
||||
body->bd_text = bd_text;
|
||||
body->bd_size = bd_size;
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
void mailimf_body_free(struct mailimf_body * body)
|
||||
{
|
||||
free(body);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct mailimf_field *
|
||||
mailimf_field_new(int fld_type,
|
||||
struct mailimf_return * fld_return_path,
|
||||
struct mailimf_orig_date * fld_resent_date,
|
||||
struct mailimf_from * fld_resent_from,
|
||||
struct mailimf_sender * fld_resent_sender,
|
||||
struct mailimf_to * fld_resent_to,
|
||||
struct mailimf_cc * fld_resent_cc,
|
||||
struct mailimf_bcc * fld_resent_bcc,
|
||||
struct mailimf_message_id * fld_resent_msg_id,
|
||||
struct mailimf_orig_date * fld_orig_date,
|
||||
struct mailimf_from * fld_from,
|
||||
struct mailimf_sender * fld_sender,
|
||||
struct mailimf_reply_to * fld_reply_to,
|
||||
struct mailimf_to * fld_to,
|
||||
struct mailimf_cc * fld_cc,
|
||||
struct mailimf_bcc * fld_bcc,
|
||||
struct mailimf_message_id * fld_message_id,
|
||||
struct mailimf_in_reply_to * fld_in_reply_to,
|
||||
struct mailimf_references * fld_references,
|
||||
struct mailimf_subject * fld_subject,
|
||||
struct mailimf_comments * fld_comments,
|
||||
struct mailimf_keywords * fld_keywords,
|
||||
struct mailimf_optional_field * fld_optional_field)
|
||||
{
|
||||
struct mailimf_field * field;
|
||||
|
||||
field = malloc(sizeof(* field));
|
||||
if (field == NULL)
|
||||
return NULL;
|
||||
|
||||
field->fld_type = fld_type;
|
||||
switch (fld_type) {
|
||||
case MAILIMF_FIELD_RETURN_PATH:
|
||||
field->fld_data.fld_return_path = fld_return_path;
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_DATE:
|
||||
field->fld_data.fld_resent_date = fld_resent_date;
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_FROM:
|
||||
field->fld_data.fld_resent_from = fld_resent_from;
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_SENDER:
|
||||
field->fld_data.fld_resent_sender = fld_resent_sender;
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_TO:
|
||||
field->fld_data.fld_resent_to = fld_resent_to;
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_CC:
|
||||
field->fld_data.fld_resent_cc = fld_resent_cc;
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_BCC:
|
||||
field->fld_data.fld_resent_bcc = fld_resent_bcc;
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_MSG_ID:
|
||||
field->fld_data.fld_resent_msg_id = fld_resent_msg_id;
|
||||
break;
|
||||
case MAILIMF_FIELD_ORIG_DATE:
|
||||
field->fld_data.fld_orig_date = fld_orig_date;
|
||||
break;
|
||||
case MAILIMF_FIELD_FROM:
|
||||
field->fld_data.fld_from = fld_from;
|
||||
break;
|
||||
case MAILIMF_FIELD_SENDER:
|
||||
field->fld_data.fld_sender = fld_sender;
|
||||
break;
|
||||
case MAILIMF_FIELD_REPLY_TO:
|
||||
field->fld_data.fld_reply_to = fld_reply_to;
|
||||
break;
|
||||
case MAILIMF_FIELD_TO:
|
||||
field->fld_data.fld_to = fld_to;
|
||||
break;
|
||||
case MAILIMF_FIELD_CC:
|
||||
field->fld_data.fld_cc = fld_cc;
|
||||
break;
|
||||
case MAILIMF_FIELD_BCC:
|
||||
field->fld_data.fld_bcc = fld_bcc;
|
||||
break;
|
||||
case MAILIMF_FIELD_MESSAGE_ID:
|
||||
field->fld_data.fld_message_id = fld_message_id;
|
||||
break;
|
||||
case MAILIMF_FIELD_IN_REPLY_TO:
|
||||
field->fld_data.fld_in_reply_to = fld_in_reply_to;
|
||||
break;
|
||||
case MAILIMF_FIELD_REFERENCES:
|
||||
field->fld_data.fld_references = fld_references;
|
||||
break;
|
||||
case MAILIMF_FIELD_SUBJECT:
|
||||
field->fld_data.fld_subject = fld_subject;
|
||||
break;
|
||||
case MAILIMF_FIELD_COMMENTS:
|
||||
field->fld_data.fld_comments = fld_comments;
|
||||
break;
|
||||
case MAILIMF_FIELD_KEYWORDS:
|
||||
field->fld_data.fld_keywords = fld_keywords;
|
||||
break;
|
||||
case MAILIMF_FIELD_OPTIONAL_FIELD:
|
||||
field->fld_data.fld_optional_field = fld_optional_field;
|
||||
break;
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
void mailimf_field_free(struct mailimf_field * field)
|
||||
{
|
||||
switch (field->fld_type) {
|
||||
case MAILIMF_FIELD_RETURN_PATH:
|
||||
mailimf_return_free(field->fld_data.fld_return_path);
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_DATE:
|
||||
mailimf_orig_date_free(field->fld_data.fld_resent_date);
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_FROM:
|
||||
mailimf_from_free(field->fld_data.fld_resent_from);
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_SENDER:
|
||||
mailimf_sender_free(field->fld_data.fld_resent_sender);
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_TO:
|
||||
mailimf_to_free(field->fld_data.fld_resent_to);
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_CC:
|
||||
mailimf_cc_free(field->fld_data.fld_resent_cc);
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_BCC:
|
||||
mailimf_bcc_free(field->fld_data.fld_resent_bcc);
|
||||
break;
|
||||
case MAILIMF_FIELD_RESENT_MSG_ID:
|
||||
mailimf_message_id_free(field->fld_data.fld_resent_msg_id);
|
||||
break;
|
||||
case MAILIMF_FIELD_ORIG_DATE:
|
||||
mailimf_orig_date_free(field->fld_data.fld_orig_date);
|
||||
break;
|
||||
case MAILIMF_FIELD_FROM:
|
||||
mailimf_from_free(field->fld_data.fld_from);
|
||||
break;
|
||||
case MAILIMF_FIELD_SENDER:
|
||||
mailimf_sender_free(field->fld_data.fld_sender);
|
||||
break;
|
||||
case MAILIMF_FIELD_REPLY_TO:
|
||||
mailimf_reply_to_free(field->fld_data.fld_reply_to);
|
||||
break;
|
||||
case MAILIMF_FIELD_TO:
|
||||
mailimf_to_free(field->fld_data.fld_to);
|
||||
break;
|
||||
case MAILIMF_FIELD_CC:
|
||||
mailimf_cc_free(field->fld_data.fld_cc);
|
||||
break;
|
||||
case MAILIMF_FIELD_BCC:
|
||||
mailimf_bcc_free(field->fld_data.fld_bcc);
|
||||
break;
|
||||
case MAILIMF_FIELD_MESSAGE_ID:
|
||||
mailimf_message_id_free(field->fld_data.fld_message_id);
|
||||
break;
|
||||
case MAILIMF_FIELD_IN_REPLY_TO:
|
||||
mailimf_in_reply_to_free(field->fld_data.fld_in_reply_to);
|
||||
break;
|
||||
case MAILIMF_FIELD_REFERENCES:
|
||||
mailimf_references_free(field->fld_data.fld_references);
|
||||
break;
|
||||
case MAILIMF_FIELD_SUBJECT:
|
||||
mailimf_subject_free(field->fld_data.fld_subject);
|
||||
break;
|
||||
case MAILIMF_FIELD_COMMENTS:
|
||||
mailimf_comments_free(field->fld_data.fld_comments);
|
||||
break;
|
||||
case MAILIMF_FIELD_KEYWORDS:
|
||||
mailimf_keywords_free(field->fld_data.fld_keywords);
|
||||
break;
|
||||
case MAILIMF_FIELD_OPTIONAL_FIELD:
|
||||
mailimf_optional_field_free(field->fld_data.fld_optional_field);
|
||||
break;
|
||||
}
|
||||
|
||||
free(field);
|
||||
}
|
||||
|
||||
struct mailimf_fields * mailimf_fields_new(clist * fld_list)
|
||||
{
|
||||
struct mailimf_fields * fields;
|
||||
|
||||
fields = malloc(sizeof(* fields));
|
||||
if (fields == NULL)
|
||||
return NULL;
|
||||
|
||||
fields->fld_list = fld_list;
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
void mailimf_fields_free(struct mailimf_fields * fields)
|
||||
{
|
||||
if (fields->fld_list != NULL) {
|
||||
clist_foreach(fields->fld_list, (clist_func) mailimf_field_free, NULL);
|
||||
clist_free(fields->fld_list);
|
||||
}
|
||||
free(fields);
|
||||
}
|
||||
|
||||
|
||||
struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
|
||||
dt_date_time)
|
||||
{
|
||||
struct mailimf_orig_date * orig_date;
|
||||
|
||||
orig_date = malloc(sizeof(* orig_date));
|
||||
if (orig_date == NULL)
|
||||
return NULL;
|
||||
|
||||
orig_date->dt_date_time = dt_date_time;
|
||||
|
||||
return orig_date;
|
||||
}
|
||||
|
||||
void mailimf_orig_date_free(struct mailimf_orig_date * orig_date)
|
||||
{
|
||||
if (orig_date->dt_date_time != NULL)
|
||||
mailimf_date_time_free(orig_date->dt_date_time);
|
||||
free(orig_date);
|
||||
}
|
||||
|
||||
struct mailimf_from *
|
||||
mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list)
|
||||
{
|
||||
struct mailimf_from * from;
|
||||
|
||||
from = malloc(sizeof(* from));
|
||||
if (from == NULL)
|
||||
return NULL;
|
||||
|
||||
from->frm_mb_list = frm_mb_list;
|
||||
|
||||
return from;
|
||||
}
|
||||
|
||||
void mailimf_from_free(struct mailimf_from * from)
|
||||
{
|
||||
if (from->frm_mb_list != NULL)
|
||||
mailimf_mailbox_list_free(from->frm_mb_list);
|
||||
free(from);
|
||||
}
|
||||
|
||||
struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb)
|
||||
{
|
||||
struct mailimf_sender * sender;
|
||||
|
||||
sender = malloc(sizeof(* sender));
|
||||
if (sender == NULL)
|
||||
return NULL;
|
||||
|
||||
sender->snd_mb = snd_mb;
|
||||
|
||||
return sender;
|
||||
}
|
||||
|
||||
void mailimf_sender_free(struct mailimf_sender * sender)
|
||||
{
|
||||
if (sender->snd_mb != NULL)
|
||||
mailimf_mailbox_free(sender->snd_mb);
|
||||
free(sender);
|
||||
}
|
||||
|
||||
struct mailimf_reply_to *
|
||||
mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list)
|
||||
{
|
||||
struct mailimf_reply_to * reply_to;
|
||||
|
||||
reply_to = malloc(sizeof(* reply_to));
|
||||
if (reply_to == NULL)
|
||||
return NULL;
|
||||
|
||||
reply_to->rt_addr_list = rt_addr_list;
|
||||
|
||||
return reply_to;
|
||||
}
|
||||
|
||||
void mailimf_reply_to_free(struct mailimf_reply_to * reply_to)
|
||||
{
|
||||
if (reply_to->rt_addr_list != NULL)
|
||||
mailimf_address_list_free(reply_to->rt_addr_list);
|
||||
free(reply_to);
|
||||
}
|
||||
|
||||
struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list)
|
||||
{
|
||||
struct mailimf_to * to;
|
||||
|
||||
to = malloc(sizeof(* to));
|
||||
if (to == NULL)
|
||||
return NULL;
|
||||
|
||||
to->to_addr_list = to_addr_list;
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
void mailimf_to_free(struct mailimf_to * to)
|
||||
{
|
||||
if (to->to_addr_list != NULL)
|
||||
mailimf_address_list_free(to->to_addr_list);
|
||||
free(to);
|
||||
}
|
||||
|
||||
struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list)
|
||||
{
|
||||
struct mailimf_cc * cc;
|
||||
|
||||
cc = malloc(sizeof(* cc));
|
||||
if (cc == NULL)
|
||||
return NULL;
|
||||
|
||||
cc->cc_addr_list = cc_addr_list;
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
void mailimf_cc_free(struct mailimf_cc * cc)
|
||||
{
|
||||
if (cc->cc_addr_list != NULL)
|
||||
mailimf_address_list_free(cc->cc_addr_list);
|
||||
free(cc);
|
||||
}
|
||||
|
||||
struct mailimf_bcc *
|
||||
mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list)
|
||||
{
|
||||
struct mailimf_bcc * bcc;
|
||||
|
||||
bcc = malloc(sizeof(* bcc));
|
||||
if (bcc == NULL)
|
||||
return NULL;
|
||||
|
||||
bcc->bcc_addr_list = bcc_addr_list;
|
||||
|
||||
return bcc;
|
||||
}
|
||||
|
||||
void mailimf_bcc_free(struct mailimf_bcc * bcc)
|
||||
{
|
||||
if (bcc->bcc_addr_list != NULL)
|
||||
mailimf_address_list_free(bcc->bcc_addr_list);
|
||||
free(bcc);
|
||||
}
|
||||
|
||||
struct mailimf_message_id * mailimf_message_id_new(char * mid_value)
|
||||
{
|
||||
struct mailimf_message_id * message_id;
|
||||
|
||||
message_id = malloc(sizeof(* message_id));
|
||||
if (message_id == NULL)
|
||||
return NULL;
|
||||
|
||||
message_id->mid_value = mid_value;
|
||||
|
||||
return message_id;
|
||||
}
|
||||
|
||||
void mailimf_message_id_free(struct mailimf_message_id * message_id)
|
||||
{
|
||||
if (message_id->mid_value != NULL)
|
||||
mailimf_msg_id_free(message_id->mid_value);
|
||||
free(message_id);
|
||||
}
|
||||
|
||||
struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list)
|
||||
{
|
||||
struct mailimf_in_reply_to * in_reply_to;
|
||||
|
||||
in_reply_to = malloc(sizeof(* in_reply_to));
|
||||
if (in_reply_to == NULL)
|
||||
return NULL;
|
||||
|
||||
in_reply_to->mid_list = mid_list;
|
||||
|
||||
return in_reply_to;
|
||||
}
|
||||
|
||||
void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to)
|
||||
{
|
||||
clist_foreach(in_reply_to->mid_list,
|
||||
(clist_func) mailimf_msg_id_free, NULL);
|
||||
clist_free(in_reply_to->mid_list);
|
||||
free(in_reply_to);
|
||||
}
|
||||
|
||||
struct mailimf_references * mailimf_references_new(clist * mid_list)
|
||||
{
|
||||
struct mailimf_references * ref;
|
||||
|
||||
ref = malloc(sizeof(* ref));
|
||||
if (ref == NULL)
|
||||
return NULL;
|
||||
|
||||
ref->mid_list = mid_list;
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
void mailimf_references_free(struct mailimf_references * references)
|
||||
{
|
||||
clist_foreach(references->mid_list,
|
||||
(clist_func) mailimf_msg_id_free, NULL);
|
||||
clist_free(references->mid_list);
|
||||
free(references);
|
||||
}
|
||||
|
||||
void mailimf_msg_id_free(char * msg_id)
|
||||
{
|
||||
free(msg_id);
|
||||
}
|
||||
|
||||
void mailimf_id_left_free(char * id_left)
|
||||
{
|
||||
free(id_left);
|
||||
}
|
||||
|
||||
void mailimf_id_right_free(char * id_right)
|
||||
{
|
||||
free(id_right);
|
||||
}
|
||||
|
||||
void mailimf_no_fold_quote_free(char * nfq)
|
||||
{
|
||||
free(nfq);
|
||||
}
|
||||
|
||||
void mailimf_no_fold_literal_free(char * nfl)
|
||||
{
|
||||
free(nfl);
|
||||
}
|
||||
|
||||
struct mailimf_subject * mailimf_subject_new(char * sbj_value)
|
||||
{
|
||||
struct mailimf_subject * subject;
|
||||
|
||||
subject = malloc(sizeof(* subject));
|
||||
if (subject == NULL)
|
||||
return NULL;
|
||||
|
||||
subject->sbj_value = sbj_value;
|
||||
|
||||
return subject;
|
||||
}
|
||||
|
||||
void mailimf_subject_free(struct mailimf_subject * subject)
|
||||
{
|
||||
mailimf_unstructured_free(subject->sbj_value);
|
||||
free(subject);
|
||||
}
|
||||
|
||||
struct mailimf_comments * mailimf_comments_new(char * cm_value)
|
||||
{
|
||||
struct mailimf_comments * comments;
|
||||
|
||||
comments = malloc(sizeof(* comments));
|
||||
if (comments == NULL)
|
||||
return NULL;
|
||||
|
||||
comments->cm_value = cm_value;
|
||||
|
||||
return comments;
|
||||
}
|
||||
|
||||
void mailimf_comments_free(struct mailimf_comments * comments)
|
||||
{
|
||||
mailimf_unstructured_free(comments->cm_value);
|
||||
free(comments);
|
||||
}
|
||||
|
||||
struct mailimf_keywords * mailimf_keywords_new(clist * kw_list)
|
||||
{
|
||||
struct mailimf_keywords * keywords;
|
||||
|
||||
keywords = malloc(sizeof(* keywords));
|
||||
if (keywords == NULL)
|
||||
return NULL;
|
||||
|
||||
keywords->kw_list = kw_list;
|
||||
|
||||
return keywords;
|
||||
}
|
||||
|
||||
void mailimf_keywords_free(struct mailimf_keywords * keywords)
|
||||
{
|
||||
clist_foreach(keywords->kw_list, (clist_func) mailimf_phrase_free, NULL);
|
||||
clist_free(keywords->kw_list);
|
||||
free(keywords);
|
||||
}
|
||||
|
||||
struct mailimf_return *
|
||||
mailimf_return_new(struct mailimf_path * ret_path)
|
||||
{
|
||||
struct mailimf_return * return_path;
|
||||
|
||||
return_path = malloc(sizeof(* return_path));
|
||||
if (return_path == NULL)
|
||||
return NULL;
|
||||
|
||||
return_path->ret_path = ret_path;
|
||||
|
||||
return return_path;
|
||||
}
|
||||
|
||||
void mailimf_return_free(struct mailimf_return * return_path)
|
||||
{
|
||||
mailimf_path_free(return_path->ret_path);
|
||||
free(return_path);
|
||||
}
|
||||
|
||||
|
||||
struct mailimf_path * mailimf_path_new(char * pt_addr_spec)
|
||||
{
|
||||
struct mailimf_path * path;
|
||||
|
||||
path = malloc(sizeof(* path));
|
||||
if (path == NULL)
|
||||
return NULL;
|
||||
|
||||
path->pt_addr_spec = pt_addr_spec;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void mailimf_path_free(struct mailimf_path * path)
|
||||
{
|
||||
if (path->pt_addr_spec != NULL)
|
||||
mailimf_addr_spec_free(path->pt_addr_spec);
|
||||
free(path);
|
||||
}
|
||||
|
||||
struct mailimf_optional_field *
|
||||
mailimf_optional_field_new(char * fld_name, char * fld_value)
|
||||
{
|
||||
struct mailimf_optional_field * opt_field;
|
||||
|
||||
opt_field = malloc(sizeof(* opt_field));
|
||||
if (opt_field == NULL)
|
||||
return NULL;
|
||||
|
||||
opt_field->fld_name = fld_name;
|
||||
opt_field->fld_value = fld_value;
|
||||
|
||||
return opt_field;
|
||||
}
|
||||
|
||||
void mailimf_optional_field_free(struct mailimf_optional_field * opt_field)
|
||||
{
|
||||
mailimf_field_name_free(opt_field->fld_name);
|
||||
mailimf_unstructured_free(opt_field->fld_value);
|
||||
free(opt_field);
|
||||
}
|
||||
|
||||
void mailimf_field_name_free(char * field_name)
|
||||
{
|
||||
free(field_name);
|
||||
}
|
797
src/plugins/mailmbox/mailimf_types.h
Normal file
797
src/plugins/mailmbox/mailimf_types.h
Normal file
|
@ -0,0 +1,797 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001 - 2003 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef MAILIMF_TYPES_H
|
||||
|
||||
#define MAILIMF_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "clist.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
IMPORTANT NOTE:
|
||||
|
||||
All allocation functions will take as argument allocated data
|
||||
and will store these data in the structure they will allocate.
|
||||
Data should be persistant during all the use of the structure
|
||||
and will be freed by the free function of the structure
|
||||
|
||||
allocation functions will return NULL on failure
|
||||
*/
|
||||
|
||||
/*
|
||||
mailimf_date_time is a date
|
||||
|
||||
- day is the day of month (1 to 31)
|
||||
|
||||
- month (1 to 12)
|
||||
|
||||
- year (4 digits)
|
||||
|
||||
- hour (0 to 23)
|
||||
|
||||
- min (0 to 59)
|
||||
|
||||
- sec (0 to 59)
|
||||
|
||||
- zone (this is the decimal value that we can read, for example:
|
||||
for "-0200", the value is -200)
|
||||
*/
|
||||
|
||||
struct mailimf_date_time {
|
||||
int dt_day;
|
||||
int dt_month;
|
||||
int dt_year;
|
||||
int dt_hour;
|
||||
int dt_min;
|
||||
int dt_sec;
|
||||
int dt_zone;
|
||||
};
|
||||
|
||||
struct mailimf_date_time *
|
||||
mailimf_date_time_new(int dt_day, int dt_month, int dt_year,
|
||||
int dt_hour, int dt_min, int dt_sec, int dt_zone);
|
||||
|
||||
void mailimf_date_time_free(struct mailimf_date_time * date_time);
|
||||
|
||||
|
||||
|
||||
/* this is the type of address */
|
||||
|
||||
enum {
|
||||
MAILIMF_ADDRESS_ERROR, /* on parse error */
|
||||
MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */
|
||||
MAILIMF_ADDRESS_GROUP, /* if this is a group
|
||||
(group_name: address1@domain1,
|
||||
address2@domain2; ) */
|
||||
};
|
||||
|
||||
/*
|
||||
mailimf_address is an address
|
||||
|
||||
- type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP
|
||||
|
||||
- mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX
|
||||
|
||||
- group is a group if type is MAILIMF_ADDRESS_GROUP
|
||||
*/
|
||||
|
||||
struct mailimf_address {
|
||||
int ad_type;
|
||||
union {
|
||||
struct mailimf_mailbox * ad_mailbox; /* can be NULL */
|
||||
struct mailimf_group * ad_group; /* can be NULL */
|
||||
} ad_data;
|
||||
};
|
||||
|
||||
|
||||
struct mailimf_address *
|
||||
mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
|
||||
struct mailimf_group * ad_group);
|
||||
|
||||
void mailimf_address_free(struct mailimf_address * address);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_mailbox is a mailbox
|
||||
|
||||
- display_name is the name that will be displayed for this mailbox,
|
||||
for example 'name' in '"name" <mailbox@domain>,
|
||||
should be allocated with malloc()
|
||||
|
||||
- addr_spec is the mailbox, for example 'mailbox@domain'
|
||||
in '"name" <mailbox@domain>, should be allocated with malloc()
|
||||
*/
|
||||
|
||||
struct mailimf_mailbox {
|
||||
char * mb_display_name; /* can be NULL */
|
||||
char * mb_addr_spec; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_mailbox *
|
||||
mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec);
|
||||
|
||||
void mailimf_mailbox_free(struct mailimf_mailbox * mailbox);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_group is a group
|
||||
|
||||
- display_name is the name that will be displayed for this group,
|
||||
for example 'group_name' in
|
||||
'group_name: address1@domain1, address2@domain2;', should be allocated
|
||||
with malloc()
|
||||
|
||||
- mb_list is a list of mailboxes
|
||||
*/
|
||||
|
||||
struct mailimf_group {
|
||||
char * grp_display_name; /* != NULL */
|
||||
struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */
|
||||
};
|
||||
|
||||
struct mailimf_group *
|
||||
mailimf_group_new(char * grp_display_name,
|
||||
struct mailimf_mailbox_list * grp_mb_list);
|
||||
|
||||
void mailimf_group_free(struct mailimf_group * group);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_mailbox_list is a list of mailboxes
|
||||
|
||||
- list is a list of mailboxes
|
||||
*/
|
||||
|
||||
struct mailimf_mailbox_list {
|
||||
clist * mb_list; /* list of (struct mailimf_mailbox *) */
|
||||
/* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_mailbox_list *
|
||||
mailimf_mailbox_list_new(clist * mb_list);
|
||||
|
||||
void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_address_list is a list of addresses
|
||||
|
||||
- list is a list of addresses
|
||||
*/
|
||||
|
||||
struct mailimf_address_list {
|
||||
clist * ad_list; /* list of (struct mailimf_address *) */
|
||||
/* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_address_list *
|
||||
mailimf_address_list_new(clist * ad_list);
|
||||
|
||||
void mailimf_address_list_free(struct mailimf_address_list * addr_list);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_body is the text part of a message
|
||||
|
||||
- text is the beginning of the text part, it is a substring
|
||||
of an other string
|
||||
|
||||
- size is the size of the text part
|
||||
*/
|
||||
|
||||
struct mailimf_body {
|
||||
const char * bd_text; /* != NULL */
|
||||
size_t bd_size;
|
||||
};
|
||||
|
||||
struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size);
|
||||
|
||||
void mailimf_body_free(struct mailimf_body * body);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_message is the content of the message
|
||||
|
||||
- fields is the header fields of the message
|
||||
|
||||
- body is the text part of the message
|
||||
*/
|
||||
|
||||
struct mailimf_message {
|
||||
struct mailimf_fields * msg_fields; /* != NULL */
|
||||
struct mailimf_body * msg_body; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_message *
|
||||
mailimf_message_new(struct mailimf_fields * msg_fields,
|
||||
struct mailimf_body * msg_body);
|
||||
|
||||
void mailimf_message_free(struct mailimf_message * message);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_fields is a list of header fields
|
||||
|
||||
- list is a list of header fields
|
||||
*/
|
||||
|
||||
struct mailimf_fields {
|
||||
clist * fld_list; /* list of (struct mailimf_field *) */
|
||||
/* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_fields * mailimf_fields_new(clist * fld_list);
|
||||
|
||||
void mailimf_fields_free(struct mailimf_fields * fields);
|
||||
|
||||
|
||||
|
||||
/* this is a type of field */
|
||||
|
||||
enum {
|
||||
MAILIMF_FIELD_NONE, /* on parse error */
|
||||
MAILIMF_FIELD_RETURN_PATH, /* Return-Path */
|
||||
MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */
|
||||
MAILIMF_FIELD_RESENT_FROM, /* Resent-From */
|
||||
MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */
|
||||
MAILIMF_FIELD_RESENT_TO, /* Resent-To */
|
||||
MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */
|
||||
MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */
|
||||
MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */
|
||||
MAILIMF_FIELD_ORIG_DATE, /* Date */
|
||||
MAILIMF_FIELD_FROM, /* From */
|
||||
MAILIMF_FIELD_SENDER, /* Sender */
|
||||
MAILIMF_FIELD_REPLY_TO, /* Reply-To */
|
||||
MAILIMF_FIELD_TO, /* To */
|
||||
MAILIMF_FIELD_CC, /* Cc */
|
||||
MAILIMF_FIELD_BCC, /* Bcc */
|
||||
MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */
|
||||
MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */
|
||||
MAILIMF_FIELD_REFERENCES, /* References */
|
||||
MAILIMF_FIELD_SUBJECT, /* Subject */
|
||||
MAILIMF_FIELD_COMMENTS, /* Comments */
|
||||
MAILIMF_FIELD_KEYWORDS, /* Keywords */
|
||||
MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */
|
||||
};
|
||||
|
||||
/*
|
||||
mailimf_field is a field
|
||||
|
||||
- type is the type of the field
|
||||
|
||||
- return_path is the parsed content of the Return-Path field if type is
|
||||
MAILIMF_FIELD_RETURN_PATH
|
||||
|
||||
- resent_date is the parsed content of the Resent-Date field if type is
|
||||
MAILIMF_FIELD_RESENT_DATE
|
||||
|
||||
- resent_from is the parsed content of the Resent-From field
|
||||
|
||||
- resent_sender is the parsed content of the Resent-Sender field
|
||||
|
||||
- resent_to is the parsed content of the Resent-To field
|
||||
|
||||
- resent_cc is the parsed content of the Resent-Cc field
|
||||
|
||||
- resent_bcc is the parsed content of the Resent-Bcc field
|
||||
|
||||
- resent_msg_id is the parsed content of the Resent-Message-ID field
|
||||
|
||||
- orig_date is the parsed content of the Date field
|
||||
|
||||
- from is the parsed content of the From field
|
||||
|
||||
- sender is the parsed content of the Sender field
|
||||
|
||||
- reply_to is the parsed content of the Reply-To field
|
||||
|
||||
- to is the parsed content of the To field
|
||||
|
||||
- cc is the parsed content of the Cc field
|
||||
|
||||
- bcc is the parsed content of the Bcc field
|
||||
|
||||
- message_id is the parsed content of the Message-ID field
|
||||
|
||||
- in_reply_to is the parsed content of the In-Reply-To field
|
||||
|
||||
- references is the parsed content of the References field
|
||||
|
||||
- subject is the content of the Subject field
|
||||
|
||||
- comments is the content of the Comments field
|
||||
|
||||
- keywords is the parsed content of the Keywords field
|
||||
|
||||
- optional_field is an other field and is not parsed
|
||||
*/
|
||||
|
||||
#define LIBETPAN_MAILIMF_FIELD_UNION
|
||||
|
||||
struct mailimf_field {
|
||||
int fld_type;
|
||||
union {
|
||||
struct mailimf_return * fld_return_path; /* can be NULL */
|
||||
struct mailimf_orig_date * fld_resent_date; /* can be NULL */
|
||||
struct mailimf_from * fld_resent_from; /* can be NULL */
|
||||
struct mailimf_sender * fld_resent_sender; /* can be NULL */
|
||||
struct mailimf_to * fld_resent_to; /* can be NULL */
|
||||
struct mailimf_cc * fld_resent_cc; /* can be NULL */
|
||||
struct mailimf_bcc * fld_resent_bcc; /* can be NULL */
|
||||
struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */
|
||||
struct mailimf_orig_date * fld_orig_date; /* can be NULL */
|
||||
struct mailimf_from * fld_from; /* can be NULL */
|
||||
struct mailimf_sender * fld_sender; /* can be NULL */
|
||||
struct mailimf_reply_to * fld_reply_to; /* can be NULL */
|
||||
struct mailimf_to * fld_to; /* can be NULL */
|
||||
struct mailimf_cc * fld_cc; /* can be NULL */
|
||||
struct mailimf_bcc * fld_bcc; /* can be NULL */
|
||||
struct mailimf_message_id * fld_message_id; /* can be NULL */
|
||||
struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */
|
||||
struct mailimf_references * fld_references; /* can be NULL */
|
||||
struct mailimf_subject * fld_subject; /* can be NULL */
|
||||
struct mailimf_comments * fld_comments; /* can be NULL */
|
||||
struct mailimf_keywords * fld_keywords; /* can be NULL */
|
||||
struct mailimf_optional_field * fld_optional_field; /* can be NULL */
|
||||
} fld_data;
|
||||
};
|
||||
|
||||
struct mailimf_field *
|
||||
mailimf_field_new(int fld_type,
|
||||
struct mailimf_return * fld_return_path,
|
||||
struct mailimf_orig_date * fld_resent_date,
|
||||
struct mailimf_from * fld_resent_from,
|
||||
struct mailimf_sender * fld_resent_sender,
|
||||
struct mailimf_to * fld_resent_to,
|
||||
struct mailimf_cc * fld_resent_cc,
|
||||
struct mailimf_bcc * fld_resent_bcc,
|
||||
struct mailimf_message_id * fld_resent_msg_id,
|
||||
struct mailimf_orig_date * fld_orig_date,
|
||||
struct mailimf_from * fld_from,
|
||||
struct mailimf_sender * fld_sender,
|
||||
struct mailimf_reply_to * fld_reply_to,
|
||||
struct mailimf_to * fld_to,
|
||||
struct mailimf_cc * fld_cc,
|
||||
struct mailimf_bcc * fld_bcc,
|
||||
struct mailimf_message_id * fld_message_id,
|
||||
struct mailimf_in_reply_to * fld_in_reply_to,
|
||||
struct mailimf_references * fld_references,
|
||||
struct mailimf_subject * fld_subject,
|
||||
struct mailimf_comments * fld_comments,
|
||||
struct mailimf_keywords * fld_keywords,
|
||||
struct mailimf_optional_field * fld_optional_field);
|
||||
|
||||
void mailimf_field_free(struct mailimf_field * field);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_orig_date is the parsed Date field
|
||||
|
||||
- date_time is the parsed date
|
||||
*/
|
||||
|
||||
struct mailimf_orig_date {
|
||||
struct mailimf_date_time * dt_date_time; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
|
||||
dt_date_time);
|
||||
|
||||
void mailimf_orig_date_free(struct mailimf_orig_date * orig_date);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_from is the parsed From field
|
||||
|
||||
- mb_list is the parsed mailbox list
|
||||
*/
|
||||
|
||||
struct mailimf_from {
|
||||
struct mailimf_mailbox_list * frm_mb_list; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_from *
|
||||
mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list);
|
||||
|
||||
void mailimf_from_free(struct mailimf_from * from);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_sender is the parsed Sender field
|
||||
|
||||
- mb is the parsed mailbox
|
||||
*/
|
||||
|
||||
struct mailimf_sender {
|
||||
struct mailimf_mailbox * snd_mb; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb);
|
||||
|
||||
void mailimf_sender_free(struct mailimf_sender * sender);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_reply_to is the parsed Reply-To field
|
||||
|
||||
- addr_list is the parsed address list
|
||||
*/
|
||||
|
||||
struct mailimf_reply_to {
|
||||
struct mailimf_address_list * rt_addr_list; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_reply_to *
|
||||
mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list);
|
||||
|
||||
void mailimf_reply_to_free(struct mailimf_reply_to * reply_to);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_to is the parsed To field
|
||||
|
||||
- addr_list is the parsed address list
|
||||
*/
|
||||
|
||||
struct mailimf_to {
|
||||
struct mailimf_address_list * to_addr_list; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list);
|
||||
|
||||
void mailimf_to_free(struct mailimf_to * to);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_cc is the parsed Cc field
|
||||
|
||||
- addr_list is the parsed addres list
|
||||
*/
|
||||
|
||||
struct mailimf_cc {
|
||||
struct mailimf_address_list * cc_addr_list; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list);
|
||||
|
||||
void mailimf_cc_free(struct mailimf_cc * cc);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_bcc is the parsed Bcc field
|
||||
|
||||
- addr_list is the parsed addres list
|
||||
*/
|
||||
|
||||
struct mailimf_bcc {
|
||||
struct mailimf_address_list * bcc_addr_list; /* can be NULL */
|
||||
};
|
||||
|
||||
struct mailimf_bcc *
|
||||
mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list);
|
||||
|
||||
void mailimf_bcc_free(struct mailimf_bcc * bcc);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_message_id is the parsed Message-ID field
|
||||
|
||||
- value is the message identifier
|
||||
*/
|
||||
|
||||
struct mailimf_message_id {
|
||||
char * mid_value; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_message_id * mailimf_message_id_new(char * mid_value);
|
||||
|
||||
void mailimf_message_id_free(struct mailimf_message_id * message_id);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_in_reply_to is the parsed In-Reply-To field
|
||||
|
||||
- msg_id_list is the list of message identifers
|
||||
*/
|
||||
|
||||
struct mailimf_in_reply_to {
|
||||
clist * mid_list; /* list of (char *) */
|
||||
/* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list);
|
||||
|
||||
void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_references is the parsed References field
|
||||
|
||||
- msg_id_list is the list of message identifiers
|
||||
*/
|
||||
|
||||
struct mailimf_references {
|
||||
clist * mid_list; /* list of (char *) */
|
||||
/* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_references * mailimf_references_new(clist * mid_list);
|
||||
|
||||
void mailimf_references_free(struct mailimf_references * references);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
mailimf_subject is the parsed Subject field
|
||||
|
||||
- value is the value of the field
|
||||
*/
|
||||
|
||||
struct mailimf_subject {
|
||||
char * sbj_value; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_subject * mailimf_subject_new(char * sbj_value);
|
||||
|
||||
void mailimf_subject_free(struct mailimf_subject * subject);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_comments is the parsed Comments field
|
||||
|
||||
- value is the value of the field
|
||||
*/
|
||||
|
||||
struct mailimf_comments {
|
||||
char * cm_value; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_comments * mailimf_comments_new(char * cm_value);
|
||||
|
||||
void mailimf_comments_free(struct mailimf_comments * comments);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_keywords is the parsed Keywords field
|
||||
|
||||
- list is the list of keywords
|
||||
*/
|
||||
|
||||
struct mailimf_keywords {
|
||||
clist * kw_list; /* list of (char *) */
|
||||
/* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_keywords * mailimf_keywords_new(clist * kw_list);
|
||||
|
||||
void mailimf_keywords_free(struct mailimf_keywords * keywords);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_return is the parsed Return-Path field
|
||||
|
||||
- path is the parsed value of Return-Path
|
||||
*/
|
||||
|
||||
struct mailimf_return {
|
||||
struct mailimf_path * ret_path; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_return *
|
||||
mailimf_return_new(struct mailimf_path * ret_path);
|
||||
|
||||
void mailimf_return_free(struct mailimf_return * return_path);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_path is the parsed value of Return-Path
|
||||
|
||||
- addr_spec is a mailbox
|
||||
*/
|
||||
|
||||
struct mailimf_path {
|
||||
char * pt_addr_spec; /* can be NULL */
|
||||
};
|
||||
|
||||
struct mailimf_path * mailimf_path_new(char * pt_addr_spec);
|
||||
|
||||
void mailimf_path_free(struct mailimf_path * path);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_optional_field is a non-parsed field
|
||||
|
||||
- name is the name of the field
|
||||
|
||||
- value is the value of the field
|
||||
*/
|
||||
|
||||
struct mailimf_optional_field {
|
||||
char * fld_name; /* != NULL */
|
||||
char * fld_value; /* != NULL */
|
||||
};
|
||||
|
||||
struct mailimf_optional_field *
|
||||
mailimf_optional_field_new(char * fld_name, char * fld_value);
|
||||
|
||||
void mailimf_optional_field_free(struct mailimf_optional_field * opt_field);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_fields is the native structure that IMF module will use,
|
||||
this module will provide an easier structure to use when parsing fields.
|
||||
|
||||
mailimf_single_fields is an easier structure to get parsed fields,
|
||||
rather than iteration over the list of fields
|
||||
|
||||
- orig_date is the parsed "Date" field
|
||||
|
||||
- from is the parsed "From" field
|
||||
|
||||
- sender is the parsed "Sender "field
|
||||
|
||||
- reply_to is the parsed "Reply-To" field
|
||||
|
||||
- to is the parsed "To" field
|
||||
|
||||
- cc is the parsed "Cc" field
|
||||
|
||||
- bcc is the parsed "Bcc" field
|
||||
|
||||
- message_id is the parsed "Message-ID" field
|
||||
|
||||
- in_reply_to is the parsed "In-Reply-To" field
|
||||
|
||||
- references is the parsed "References" field
|
||||
|
||||
- subject is the parsed "Subject" field
|
||||
|
||||
- comments is the parsed "Comments" field
|
||||
|
||||
- keywords is the parsed "Keywords" field
|
||||
*/
|
||||
|
||||
struct mailimf_single_fields {
|
||||
struct mailimf_orig_date * fld_orig_date; /* can be NULL */
|
||||
struct mailimf_from * fld_from; /* can be NULL */
|
||||
struct mailimf_sender * fld_sender; /* can be NULL */
|
||||
struct mailimf_reply_to * fld_reply_to; /* can be NULL */
|
||||
struct mailimf_to * fld_to; /* can be NULL */
|
||||
struct mailimf_cc * fld_cc; /* can be NULL */
|
||||
struct mailimf_bcc * fld_bcc; /* can be NULL */
|
||||
struct mailimf_message_id * fld_message_id; /* can be NULL */
|
||||
struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */
|
||||
struct mailimf_references * fld_references; /* can be NULL */
|
||||
struct mailimf_subject * fld_subject; /* can be NULL */
|
||||
struct mailimf_comments * fld_comments; /* can be NULL */
|
||||
struct mailimf_keywords * fld_keywords; /* can be NULL */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* internal use */
|
||||
|
||||
void mailimf_atom_free(char * atom);
|
||||
|
||||
void mailimf_dot_atom_free(char * dot_atom);
|
||||
|
||||
void mailimf_dot_atom_text_free(char * dot_atom);
|
||||
|
||||
void mailimf_quoted_string_free(char * quoted_string);
|
||||
|
||||
void mailimf_word_free(char * word);
|
||||
|
||||
void mailimf_phrase_free(char * phrase);
|
||||
|
||||
void mailimf_unstructured_free(char * unstructured);
|
||||
|
||||
void mailimf_angle_addr_free(char * angle_addr);
|
||||
|
||||
void mailimf_display_name_free(char * display_name);
|
||||
|
||||
void mailimf_addr_spec_free(char * addr_spec);
|
||||
|
||||
void mailimf_local_part_free(char * local_part);
|
||||
|
||||
void mailimf_domain_free(char * domain);
|
||||
|
||||
void mailimf_domain_literal_free(char * domain);
|
||||
|
||||
void mailimf_msg_id_free(char * msg_id);
|
||||
|
||||
void mailimf_id_left_free(char * id_left);
|
||||
|
||||
void mailimf_id_right_free(char * id_right);
|
||||
|
||||
void mailimf_no_fold_quote_free(char * nfq);
|
||||
|
||||
void mailimf_no_fold_literal_free(char * nfl);
|
||||
|
||||
void mailimf_field_name_free(char * field_name);
|
||||
|
||||
|
||||
|
||||
/* these are the possible returned error codes */
|
||||
|
||||
enum {
|
||||
MAILIMF_NO_ERROR = 0,
|
||||
MAILIMF_ERROR_PARSE,
|
||||
MAILIMF_ERROR_MEMORY,
|
||||
MAILIMF_ERROR_INVAL,
|
||||
MAILIMF_ERROR_FILE,
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
1636
src/plugins/mailmbox/mailimf_types_helper.c
Normal file
1636
src/plugins/mailmbox/mailimf_types_helper.c
Normal file
File diff suppressed because it is too large
Load diff
370
src/plugins/mailmbox/mailimf_types_helper.h
Normal file
370
src/plugins/mailmbox/mailimf_types_helper.h
Normal file
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef MAILIMF_TYPES_HELPER
|
||||
|
||||
#define MAILIMF_TYPES_HELPER
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mailimf_types.h"
|
||||
|
||||
/*
|
||||
IMPORTANT NOTE:
|
||||
|
||||
All allocation functions will take as argument allocated data
|
||||
and will store these data in the structure they will allocate.
|
||||
Data should be persistant during all the use of the structure
|
||||
and will be freed by the free function of the structure
|
||||
|
||||
allocation functions will return NULL on failure
|
||||
*/
|
||||
|
||||
/*
|
||||
mailimf_mailbox_list_new_empty creates an empty list of mailboxes
|
||||
*/
|
||||
|
||||
struct mailimf_mailbox_list *
|
||||
mailimf_mailbox_list_new_empty();
|
||||
|
||||
/*
|
||||
mailimf_mailbox_list_add adds a mailbox to the list of mailboxes
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list,
|
||||
struct mailimf_mailbox * mb);
|
||||
|
||||
/*
|
||||
mailimf_mailbox_list_add_parse parse the given string
|
||||
into a mailimf_mailbox structure and adds it to the list of mailboxes
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list,
|
||||
char * mb_str);
|
||||
|
||||
/*
|
||||
mailimf_mailbox creates a mailimf_mailbox structure with the given
|
||||
arguments and adds it to the list of mailboxes
|
||||
|
||||
- display_name is the name that will be displayed for this mailbox,
|
||||
for example 'name' in '"name" <mailbox@domain>,
|
||||
should be allocated with malloc()
|
||||
|
||||
- address is the mailbox, for example 'mailbox@domain'
|
||||
in '"name" <mailbox@domain>, should be allocated with malloc()
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list,
|
||||
char * display_name, char * address);
|
||||
|
||||
/*
|
||||
mailimf_address_list_new_empty creates an empty list of addresses
|
||||
*/
|
||||
|
||||
struct mailimf_address_list *
|
||||
mailimf_address_list_new_empty();
|
||||
|
||||
/*
|
||||
mailimf_address_list_add adds a mailbox to the list of addresses
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
int mailimf_address_list_add(struct mailimf_address_list * address_list,
|
||||
struct mailimf_address * addr);
|
||||
|
||||
/*
|
||||
mailimf_address_list_add_parse parse the given string
|
||||
into a mailimf_address structure and adds it to the list of addresses
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
int mailimf_address_list_add_parse(struct mailimf_address_list * address_list,
|
||||
char * addr_str);
|
||||
|
||||
/*
|
||||
mailimf_address_list_add_mb creates a mailbox mailimf_address
|
||||
with the given arguments and adds it to the list of addresses
|
||||
|
||||
- display_name is the name that will be displayed for this mailbox,
|
||||
for example 'name' in '"name" <mailbox@domain>,
|
||||
should be allocated with malloc()
|
||||
|
||||
- address is the mailbox, for example 'mailbox@domain'
|
||||
in '"name" <mailbox@domain>, should be allocated with malloc()
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
int mailimf_address_list_add_mb(struct mailimf_address_list * address_list,
|
||||
char * display_name, char * address);
|
||||
|
||||
/*
|
||||
mailimf_resent_fields_add_data adds a set of resent fields in the
|
||||
given mailimf_fields structure.
|
||||
|
||||
if you don't want a given field in the set to be added in the list
|
||||
of fields, you can give NULL as argument
|
||||
|
||||
@param resent_msg_id sould be allocated with malloc()
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
mailimf_resent_fields_add_data(struct mailimf_fields * fields,
|
||||
struct mailimf_date_time * resent_date,
|
||||
struct mailimf_mailbox_list * resent_from,
|
||||
struct mailimf_mailbox * resent_sender,
|
||||
struct mailimf_address_list * resent_to,
|
||||
struct mailimf_address_list * resent_cc,
|
||||
struct mailimf_address_list * resent_bcc,
|
||||
char * resent_msg_id);
|
||||
|
||||
/*
|
||||
mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
|
||||
structure with a set of resent fields
|
||||
|
||||
if you don't want a given field in the set to be added in the list
|
||||
of fields, you can give NULL as argument
|
||||
|
||||
@param resent_msg_id sould be allocated with malloc()
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
struct mailimf_fields *
|
||||
mailimf_resent_fields_new_with_data_all(struct mailimf_date_time *
|
||||
resent_date, struct mailimf_mailbox_list * resent_from,
|
||||
struct mailimf_mailbox * resent_sender,
|
||||
struct mailimf_address_list * resent_to,
|
||||
struct mailimf_address_list * resent_cc,
|
||||
struct mailimf_address_list * resent_bcc,
|
||||
char * resent_msg_id);
|
||||
|
||||
/*
|
||||
mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
|
||||
structure with a set of resent fields.
|
||||
Resent-Date and Resent-Message-ID fields will be generated for you.
|
||||
|
||||
if you don't want a given field in the set to be added in the list
|
||||
of fields, you can give NULL as argument
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
struct mailimf_fields *
|
||||
mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from,
|
||||
struct mailimf_mailbox * sender,
|
||||
struct mailimf_address_list * to,
|
||||
struct mailimf_address_list * cc,
|
||||
struct mailimf_address_list * bcc);
|
||||
|
||||
/*
|
||||
this function creates a new mailimf_fields structure with no fields
|
||||
*/
|
||||
|
||||
struct mailimf_fields *
|
||||
mailimf_fields_new_empty(void);
|
||||
|
||||
|
||||
/*
|
||||
this function adds a field to the mailimf_fields structure
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
int mailimf_fields_add(struct mailimf_fields * fields,
|
||||
struct mailimf_field * field);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_fields_add_data adds a set of fields in the
|
||||
given mailimf_fields structure.
|
||||
|
||||
if you don't want a given field in the set to be added in the list
|
||||
of fields, you can give NULL as argument
|
||||
|
||||
@param msg_id sould be allocated with malloc()
|
||||
@param subject should be allocated with malloc()
|
||||
@param in_reply_to each elements of this list should be allocated
|
||||
with malloc()
|
||||
@param references each elements of this list should be allocated
|
||||
with malloc()
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
int mailimf_fields_add_data(struct mailimf_fields * fields,
|
||||
struct mailimf_date_time * date,
|
||||
struct mailimf_mailbox_list * from,
|
||||
struct mailimf_mailbox * sender,
|
||||
struct mailimf_address_list * reply_to,
|
||||
struct mailimf_address_list * to,
|
||||
struct mailimf_address_list * cc,
|
||||
struct mailimf_address_list * bcc,
|
||||
char * msg_id,
|
||||
clist * in_reply_to,
|
||||
clist * references,
|
||||
char * subject);
|
||||
|
||||
/*
|
||||
mailimf_fields_new_with_data_all creates a new mailimf_fields
|
||||
structure with a set of fields
|
||||
|
||||
if you don't want a given field in the set to be added in the list
|
||||
of fields, you can give NULL as argument
|
||||
|
||||
@param message_id sould be allocated with malloc()
|
||||
@param subject should be allocated with malloc()
|
||||
@param in_reply_to each elements of this list should be allocated
|
||||
with malloc()
|
||||
@param references each elements of this list should be allocated
|
||||
with malloc()
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
struct mailimf_fields *
|
||||
mailimf_fields_new_with_data_all(struct mailimf_date_time * date,
|
||||
struct mailimf_mailbox_list * from,
|
||||
struct mailimf_mailbox * sender,
|
||||
struct mailimf_address_list * reply_to,
|
||||
struct mailimf_address_list * to,
|
||||
struct mailimf_address_list * cc,
|
||||
struct mailimf_address_list * bcc,
|
||||
char * message_id,
|
||||
clist * in_reply_to,
|
||||
clist * references,
|
||||
char * subject);
|
||||
|
||||
/*
|
||||
mailimf_fields_new_with_data creates a new mailimf_fields
|
||||
structure with a set of fields
|
||||
Date and Message-ID fields will be generated for you.
|
||||
|
||||
if you don't want a given field in the set to be added in the list
|
||||
of fields, you can give NULL as argument
|
||||
|
||||
@param subject should be allocated with malloc()
|
||||
@param in_reply_to each elements of this list should be allocated
|
||||
with malloc()
|
||||
@param references each elements of this list should be allocated
|
||||
with malloc()
|
||||
|
||||
@return MAILIMF_NO_ERROR will be returned on success,
|
||||
other code will be returned otherwise
|
||||
*/
|
||||
|
||||
struct mailimf_fields *
|
||||
mailimf_fields_new_with_data(struct mailimf_mailbox_list * from,
|
||||
struct mailimf_mailbox * sender,
|
||||
struct mailimf_address_list * reply_to,
|
||||
struct mailimf_address_list * to,
|
||||
struct mailimf_address_list * cc,
|
||||
struct mailimf_address_list * bcc,
|
||||
clist * in_reply_to,
|
||||
clist * references,
|
||||
char * subject);
|
||||
|
||||
/*
|
||||
this function returns an allocated message identifier to
|
||||
use in a Message-ID or Resent-Message-ID field
|
||||
*/
|
||||
|
||||
char * mailimf_get_message_id(void);
|
||||
|
||||
/*
|
||||
this function returns a mailimf_date_time structure to
|
||||
use in a Date or Resent-Date field
|
||||
*/
|
||||
|
||||
struct mailimf_date_time * mailimf_get_current_date(void);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_single_fields_init fills a mailimf_single_fields structure
|
||||
with the content of a mailimf_fields structure
|
||||
*/
|
||||
|
||||
void mailimf_single_fields_init(struct mailimf_single_fields * single_fields,
|
||||
struct mailimf_fields * fields);
|
||||
|
||||
/*
|
||||
mailimf_single_fields_new creates a new mailimf_single_fields and
|
||||
fills the structure with mailimf_fields
|
||||
*/
|
||||
|
||||
struct mailimf_single_fields *
|
||||
mailimf_single_fields_new(struct mailimf_fields * fields);
|
||||
|
||||
void mailimf_single_fields_free(struct mailimf_single_fields *
|
||||
single_fields);
|
||||
|
||||
/*
|
||||
mailimf_field_new_custom creates a new field of type optional
|
||||
|
||||
@param name should be allocated with malloc()
|
||||
@param value should be allocated with malloc()
|
||||
*/
|
||||
|
||||
struct mailimf_field * mailimf_field_new_custom(char * name, char * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
2021
src/plugins/mailmbox/mailimf_write.c
Normal file
2021
src/plugins/mailmbox/mailimf_write.c
Normal file
File diff suppressed because it is too large
Load diff
134
src/plugins/mailmbox/mailimf_write.h
Normal file
134
src/plugins/mailmbox/mailimf_write.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef MAILIMF_WRITE_H
|
||||
|
||||
#define MAILIMF_WRITE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "mailimf_types.h"
|
||||
|
||||
/*
|
||||
mailimf_string_write writes a string to a given stream
|
||||
|
||||
@param f is the stream
|
||||
@param col (* col) is the column number where we will start to
|
||||
write the text, the ending column will be stored in (* col)
|
||||
@param str is the string to write
|
||||
*/
|
||||
|
||||
int mailimf_string_write(FILE * f, int * col,
|
||||
const char * str, size_t length);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_fields_write writes the fields to a given stream
|
||||
|
||||
@param f is the stream
|
||||
@param col (* col) is the column number where we will start to
|
||||
write the text, the ending column will be stored in (* col)
|
||||
@param fields is the fields to write
|
||||
*/
|
||||
|
||||
int mailimf_fields_write(FILE * f, int * col,
|
||||
struct mailimf_fields * fields);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_envelope_fields_write writes only some fields to a given stream
|
||||
|
||||
@param f is the stream
|
||||
@param col (* col) is the column number where we will start to
|
||||
write the text, the ending column will be stored in (* col)
|
||||
@param fields is the fields to write
|
||||
*/
|
||||
|
||||
int mailimf_envelope_fields_write(FILE * f, int * col,
|
||||
struct mailimf_fields * fields);
|
||||
|
||||
|
||||
/*
|
||||
mailimf_field_write writes a field to a given stream
|
||||
|
||||
@param f is the stream
|
||||
@param col (* col) is the column number where we will start to
|
||||
write the text, the ending column will be stored in (* col)
|
||||
@param field is the field to write
|
||||
*/
|
||||
|
||||
int mailimf_field_write(FILE * f, int * col,
|
||||
struct mailimf_field * field);
|
||||
|
||||
/*
|
||||
mailimf_quoted_string_write writes a string that is quoted
|
||||
to a given stream
|
||||
|
||||
@param f is the stream
|
||||
@param col (* col) is the column number where we will start to
|
||||
write the text, the ending column will be stored in (* col)
|
||||
@param string is the string to quote and write
|
||||
*/
|
||||
|
||||
int mailimf_quoted_string_write(FILE * f, int * col,
|
||||
const char * string, size_t len);
|
||||
|
||||
int mailimf_address_list_write(FILE * f, int * col,
|
||||
struct mailimf_address_list * addr_list);
|
||||
|
||||
int mailimf_mailbox_list_write(FILE * f, int * col,
|
||||
struct mailimf_mailbox_list * mb_list);
|
||||
|
||||
/*
|
||||
mailimf_header_string_write writes a header value and fold the header
|
||||
if needed.
|
||||
|
||||
@param f is the stream
|
||||
@param col (* col) is the column number where we will start to
|
||||
write the text, the ending column will be stored in (* col)
|
||||
@param str is the string to write
|
||||
*/
|
||||
|
||||
int mailimf_header_string_write(FILE * f, int * col,
|
||||
const char * str, size_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
284
src/plugins/mailmbox/maillock.c
Normal file
284
src/plugins/mailmbox/maillock.c
Normal file
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id $
|
||||
*/
|
||||
|
||||
#include "maillock.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ********************************************************************** */
|
||||
|
||||
/* lock primitives */
|
||||
|
||||
/* the lock code is modified from the dot lock file code from mail.local.c */
|
||||
|
||||
/*
|
||||
SENDMAIL LICENSE
|
||||
|
||||
The following license terms and conditions apply, unless a different
|
||||
license is obtained from Sendmail, Inc., 6425 Christie Ave, Fourth Floor,
|
||||
Emeryville, CA 94608, or by electronic mail at license@sendmail.com.
|
||||
|
||||
License Terms:
|
||||
|
||||
Use, Modification and Redistribution (including distribution of any
|
||||
modified or derived work) in source and binary forms is permitted only if
|
||||
each of the following conditions is met:
|
||||
|
||||
1. Redistributions qualify as "freeware" or "Open Source Software" under
|
||||
one of the following terms:
|
||||
|
||||
(a) Redistributions are made at no charge beyond the reasonable cost of
|
||||
materials and delivery.
|
||||
|
||||
(b) Redistributions are accompanied by a copy of the Source Code or by an
|
||||
irrevocable offer to provide a copy of the Source Code for up to three
|
||||
years at the cost of materials and delivery. Such redistributions
|
||||
must allow further use, modification, and redistribution of the Source
|
||||
Code under substantially the same terms as this license. For the
|
||||
purposes of redistribution "Source Code" means the complete compilable
|
||||
and linkable source code of sendmail including all modifications.
|
||||
|
||||
2. Redistributions of source code must retain the copyright notices as they
|
||||
appear in each source code file, these license terms, and the
|
||||
disclaimer/limitation of liability set forth as paragraph 6 below.
|
||||
|
||||
3. Redistributions in binary form must reproduce the Copyright Notice,
|
||||
these license terms, and the disclaimer/limitation of liability set
|
||||
forth as paragraph 6 below, in the documentation and/or other materials
|
||||
provided with the distribution. For the purposes of binary distribution
|
||||
the "Copyright Notice" refers to the following language:
|
||||
"Copyright (c) 1998-2002 Sendmail, Inc. All rights reserved."
|
||||
|
||||
4. Neither the name of Sendmail, Inc. nor the University of California nor
|
||||
the names of their contributors may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission. The name "sendmail" is a trademark of Sendmail, Inc.
|
||||
|
||||
5. All redistributions must comply with the conditions imposed by the
|
||||
University of California on certain embedded code, whose copyright
|
||||
notice and conditions for redistribution are as follows:
|
||||
|
||||
(a) Copyright (c) 1988, 1993 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
(b) Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
(i) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(ii) Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
(iii) Neither the name of the University nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY
|
||||
SENDMAIL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
NO EVENT SHALL SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF
|
||||
CALIFORNIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
/*
|
||||
TODO : lock, prefer fcntl() over flock()
|
||||
AND use dotlock code above
|
||||
*/
|
||||
|
||||
#define LOCKTO_RM 300 /* timeout for stale lockfile removal */
|
||||
#define LOCKTO_GLOB 400 /* global timeout for lockfile creation */
|
||||
|
||||
static int lock_common(const char * filename, int fd, short locktype)
|
||||
{
|
||||
char lockfilename[PATH_MAX];
|
||||
struct flock lock;
|
||||
/* dot lock file */
|
||||
int statfailed = 0;
|
||||
time_t start;
|
||||
int r;
|
||||
int res;
|
||||
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
lock.l_pid = getpid();
|
||||
lock.l_type = locktype;
|
||||
lock.l_whence = SEEK_SET;
|
||||
|
||||
r = fcntl(fd, F_SETLKW, &lock);
|
||||
if (r < 0) {
|
||||
/* WARNING POSIX lock could not be applied */
|
||||
}
|
||||
|
||||
/* dot lock file */
|
||||
|
||||
if (strlen(filename) + 6 > PATH_MAX) {
|
||||
res = -1;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
snprintf(lockfilename, PATH_MAX, "%s.lock", filename);
|
||||
|
||||
time(&start);
|
||||
while (1) {
|
||||
int fd;
|
||||
struct stat st;
|
||||
time_t now;
|
||||
|
||||
/* global timeout */
|
||||
time(&now);
|
||||
if (now > start + LOCKTO_GLOB) {
|
||||
res = -1;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
fd = open(lockfilename, O_WRONLY|O_EXCL|O_CREAT, 0);
|
||||
if (fd >= 0) {
|
||||
/* defeat lock checking programs which test pid */
|
||||
write(fd, "0", 2);
|
||||
close(fd);
|
||||
break;
|
||||
}
|
||||
|
||||
/* libEtPan! - adds a delay of 5 seconds between each tries */
|
||||
sleep(5);
|
||||
|
||||
if (stat(lockfilename, &st) < 0) {
|
||||
if (statfailed++ > 5) {
|
||||
res = -1;
|
||||
goto unlock;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
statfailed = 0;
|
||||
time(&now);
|
||||
|
||||
if (now < st.st_ctime + LOCKTO_RM)
|
||||
continue;
|
||||
|
||||
/* try to remove stale lockfile */
|
||||
if (unlink(lockfilename) < 0) {
|
||||
res = -1;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
libEtPan! - removes this delay of 5 seconds,
|
||||
maybe it was misplaced ?
|
||||
*/
|
||||
#if 0
|
||||
sleep(5);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
unlock:
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
lock.l_pid = getpid();
|
||||
lock.l_type = F_UNLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
|
||||
r = fcntl(fd, F_SETLK, &lock);
|
||||
if (r < 0) {
|
||||
/* WARNING POSIX lock could not be applied */
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unlock_common(const char * filename, int fd)
|
||||
{
|
||||
char lockfilename[PATH_MAX];
|
||||
struct flock lock;
|
||||
int r;
|
||||
|
||||
if (strlen(filename) + 6 > PATH_MAX)
|
||||
return -1;
|
||||
|
||||
snprintf(lockfilename, PATH_MAX, "%s.lock", filename);
|
||||
|
||||
unlink(lockfilename);
|
||||
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
lock.l_pid = getpid();
|
||||
lock.l_type = F_UNLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
|
||||
r = fcntl(fd, F_SETLK, &lock);
|
||||
if (r < 0) {
|
||||
/* WARNING POSIX lock could not be applied */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int maillock_read_lock(const char * filename, int fd)
|
||||
{
|
||||
return lock_common(filename, fd, F_RDLCK);
|
||||
}
|
||||
|
||||
int maillock_read_unlock(const char * filename, int fd)
|
||||
{
|
||||
return unlock_common(filename, fd);
|
||||
}
|
||||
|
||||
int maillock_write_lock(const char * filename, int fd)
|
||||
{
|
||||
return lock_common(filename, fd, F_WRLCK);
|
||||
}
|
||||
|
||||
int maillock_write_unlock(const char * filename, int fd)
|
||||
{
|
||||
return unlock_common(filename, fd);
|
||||
}
|
53
src/plugins/mailmbox/maillock.h
Normal file
53
src/plugins/mailmbox/maillock.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef MAILLOCK_H
|
||||
|
||||
#define MAILLOCK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int maillock_read_lock(const char * filename, int fd);
|
||||
int maillock_read_unlock(const char * filename, int fd);
|
||||
int maillock_write_lock(const char * filename, int fd);
|
||||
int maillock_write_unlock(const char * filename, int fd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
1473
src/plugins/mailmbox/mailmbox.c
Normal file
1473
src/plugins/mailmbox/mailmbox.c
Normal file
File diff suppressed because it is too large
Load diff
140
src/plugins/mailmbox/mailmbox.h
Normal file
140
src/plugins/mailmbox/mailmbox.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef MAILMBOX_H
|
||||
|
||||
#define MAILMBOX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mailmbox_types.h"
|
||||
|
||||
int
|
||||
claws_mailmbox_append_message_list(struct claws_mailmbox_folder * folder,
|
||||
carray * append_tab);
|
||||
|
||||
int
|
||||
claws_mailmbox_append_message(struct claws_mailmbox_folder * folder,
|
||||
const char * data, size_t len);
|
||||
|
||||
int claws_mailmbox_fetch_msg(struct claws_mailmbox_folder * folder,
|
||||
uint32_t num, const char ** result,
|
||||
size_t * result_len);
|
||||
|
||||
int claws_mailmbox_fetch_msg_headers(struct claws_mailmbox_folder * folder,
|
||||
uint32_t num, const char ** result,
|
||||
size_t * result_len);
|
||||
|
||||
void claws_mailmbox_fetch_result_free(char * msg);
|
||||
|
||||
int claws_mailmbox_copy_msg_list(struct claws_mailmbox_folder * dest_folder,
|
||||
struct claws_mailmbox_folder * src_folder,
|
||||
carray * tab);
|
||||
|
||||
int claws_mailmbox_copy_msg(struct claws_mailmbox_folder * dest_folder,
|
||||
struct claws_mailmbox_folder * src_folder,
|
||||
uint32_t uid);
|
||||
|
||||
int claws_mailmbox_expunge(struct claws_mailmbox_folder * folder);
|
||||
|
||||
int claws_mailmbox_delete_msg(struct claws_mailmbox_folder * folder, uint32_t uid);
|
||||
|
||||
int claws_mailmbox_init(const char * filename,
|
||||
int force_readonly,
|
||||
int force_no_uid,
|
||||
uint32_t default_written_uid,
|
||||
struct claws_mailmbox_folder ** result_folder);
|
||||
|
||||
void claws_mailmbox_done(struct claws_mailmbox_folder * folder);
|
||||
|
||||
/* low-level access primitives */
|
||||
|
||||
int claws_mailmbox_write_lock(struct claws_mailmbox_folder * folder);
|
||||
|
||||
int claws_mailmbox_write_unlock(struct claws_mailmbox_folder * folder);
|
||||
|
||||
int claws_mailmbox_read_lock(struct claws_mailmbox_folder * folder);
|
||||
|
||||
int claws_mailmbox_read_unlock(struct claws_mailmbox_folder * folder);
|
||||
|
||||
|
||||
/* memory map */
|
||||
|
||||
int claws_mailmbox_map(struct claws_mailmbox_folder * folder);
|
||||
|
||||
void claws_mailmbox_unmap(struct claws_mailmbox_folder * folder);
|
||||
|
||||
void claws_mailmbox_sync(struct claws_mailmbox_folder * folder);
|
||||
|
||||
|
||||
/* open & close file */
|
||||
|
||||
int claws_mailmbox_open(struct claws_mailmbox_folder * folder);
|
||||
|
||||
void claws_mailmbox_close(struct claws_mailmbox_folder * folder);
|
||||
|
||||
|
||||
/* validate cache */
|
||||
|
||||
int claws_mailmbox_validate_write_lock(struct claws_mailmbox_folder * folder);
|
||||
|
||||
int claws_mailmbox_validate_read_lock(struct claws_mailmbox_folder * folder);
|
||||
|
||||
|
||||
/* fetch message */
|
||||
|
||||
int claws_mailmbox_fetch_msg_no_lock(struct claws_mailmbox_folder * folder,
|
||||
uint32_t num, const char ** result,
|
||||
size_t * result_len);
|
||||
|
||||
int claws_mailmbox_fetch_msg_headers_no_lock(struct claws_mailmbox_folder * folder,
|
||||
uint32_t num, const char ** result,
|
||||
size_t * result_len);
|
||||
|
||||
/* append message */
|
||||
|
||||
int
|
||||
claws_mailmbox_append_message_list_no_lock(struct claws_mailmbox_folder * folder,
|
||||
carray * append_tab);
|
||||
|
||||
int claws_mailmbox_expunge_no_lock(struct claws_mailmbox_folder * folder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
1142
src/plugins/mailmbox/mailmbox_folder.c
Normal file
1142
src/plugins/mailmbox/mailmbox_folder.c
Normal file
File diff suppressed because it is too large
Load diff
39
src/plugins/mailmbox/mailmbox_folder.h
Normal file
39
src/plugins/mailmbox/mailmbox_folder.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 1999-2003 Hiroyuki Yamamoto
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MAILMBOX_FOLDER_H__
|
||||
#define __MAILMBOX_FOLDER_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "folder.h"
|
||||
#include "localfolder.h"
|
||||
|
||||
typedef struct _MAILMBOXFolder MAILMBOXFolder;
|
||||
|
||||
#define MAILMBOX_FOLDER(obj) ((MAILMBOXFolder *)obj)
|
||||
|
||||
struct _MAILMBOXFolder
|
||||
{
|
||||
LocalFolder lfolder;
|
||||
};
|
||||
|
||||
FolderClass *claws_mailmbox_get_class (void);
|
||||
|
||||
#endif /* __MH_H__ */
|
1
src/plugins/mailmbox/mailmbox_gtk.deps
Normal file
1
src/plugins/mailmbox/mailmbox_gtk.deps
Normal file
|
@ -0,0 +1 @@
|
|||
mailmbox
|
624
src/plugins/mailmbox/mailmbox_parse.c
Normal file
624
src/plugins/mailmbox/mailmbox_parse.c
Normal file
|
@ -0,0 +1,624 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "mailmbox_parse.h"
|
||||
|
||||
#include "mailmbox.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define UID_HEADER "X-LibEtPan-UID:"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
enum {
|
||||
UNSTRUCTURED_START,
|
||||
UNSTRUCTURED_CR,
|
||||
UNSTRUCTURED_LF,
|
||||
UNSTRUCTURED_WSP,
|
||||
UNSTRUCTURED_OUT
|
||||
};
|
||||
|
||||
static inline int
|
||||
claws_mailmbox_fields_parse(char * str, size_t length,
|
||||
size_t * index,
|
||||
uint32_t * puid,
|
||||
size_t * phlen)
|
||||
{
|
||||
size_t cur_token;
|
||||
int r;
|
||||
size_t hlen;
|
||||
size_t uid;
|
||||
int end;
|
||||
|
||||
cur_token = * index;
|
||||
|
||||
end = FALSE;
|
||||
uid = 0;
|
||||
while (!end) {
|
||||
size_t begin;
|
||||
|
||||
begin = cur_token;
|
||||
|
||||
r = mailimf_ignore_field_parse(str, length, &cur_token);
|
||||
switch (r) {
|
||||
case MAILIMF_NO_ERROR:
|
||||
if (str[begin] == 'X') {
|
||||
|
||||
if (strncasecmp(str + begin, UID_HEADER, strlen(UID_HEADER)) == 0) {
|
||||
begin += strlen(UID_HEADER);
|
||||
|
||||
while (str[begin] == ' ')
|
||||
begin ++;
|
||||
|
||||
uid = strtoul(str + begin, NULL, 10);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case MAILIMF_ERROR_PARSE:
|
||||
default:
|
||||
end = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hlen = cur_token - * index;
|
||||
|
||||
* phlen = hlen;
|
||||
* puid = uid;
|
||||
* index = cur_token;
|
||||
|
||||
return MAILMBOX_NO_ERROR;
|
||||
}
|
||||
|
||||
enum {
|
||||
IN_MAIL,
|
||||
FIRST_CR,
|
||||
FIRST_LF,
|
||||
SECOND_CR,
|
||||
SECOND_LF,
|
||||
PARSING_F,
|
||||
PARSING_R,
|
||||
PARSING_O,
|
||||
PARSING_M,
|
||||
OUT_MAIL
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static inline int
|
||||
claws_mailmbox_single_parse(char * str, size_t length,
|
||||
size_t * index,
|
||||
size_t * pstart,
|
||||
size_t * pstart_len,
|
||||
size_t * pheaders,
|
||||
size_t * pheaders_len,
|
||||
size_t * pbody,
|
||||
size_t * pbody_len,
|
||||
size_t * psize,
|
||||
size_t * ppadding,
|
||||
uint32_t * puid)
|
||||
{
|
||||
size_t cur_token;
|
||||
size_t start;
|
||||
size_t start_len;
|
||||
size_t headers;
|
||||
size_t headers_len;
|
||||
size_t body;
|
||||
size_t end;
|
||||
size_t next;
|
||||
size_t message_length;
|
||||
uint32_t uid;
|
||||
int r;
|
||||
#if 0
|
||||
int in_mail_data;
|
||||
#endif
|
||||
#if 0
|
||||
size_t begin;
|
||||
#endif
|
||||
|
||||
int state;
|
||||
|
||||
cur_token = * index;
|
||||
|
||||
if (cur_token >= length)
|
||||
return MAILMBOX_ERROR_PARSE;
|
||||
|
||||
start = cur_token;
|
||||
start_len = 0;
|
||||
headers = cur_token;
|
||||
|
||||
if (cur_token + 5 < length) {
|
||||
if (strncmp(str + cur_token, "From ", 5) == 0) {
|
||||
cur_token += 5;
|
||||
while (str[cur_token] != '\n') {
|
||||
cur_token ++;
|
||||
if (cur_token >= length)
|
||||
break;
|
||||
}
|
||||
if (cur_token < length) {
|
||||
cur_token ++;
|
||||
headers = cur_token;
|
||||
start_len = headers - start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
next = length;
|
||||
|
||||
r = claws_mailmbox_fields_parse(str, length, &cur_token,
|
||||
&uid, &headers_len);
|
||||
if (r != MAILMBOX_NO_ERROR)
|
||||
return r;
|
||||
|
||||
/* save position */
|
||||
#if 0
|
||||
begin = cur_token;
|
||||
#endif
|
||||
|
||||
mailimf_crlf_parse(str, length, &cur_token);
|
||||
|
||||
#if 0
|
||||
if (str[cur_token] == 'F') {
|
||||
printf("start !\n");
|
||||
printf("%50.50s\n", str + cur_token);
|
||||
getchar();
|
||||
}
|
||||
#endif
|
||||
|
||||
body = cur_token;
|
||||
|
||||
/* restore position */
|
||||
/* cur_token = begin; */
|
||||
|
||||
state = FIRST_LF;
|
||||
|
||||
end = length;
|
||||
|
||||
#if 0
|
||||
in_mail_data = 0;
|
||||
#endif
|
||||
while (state != OUT_MAIL) {
|
||||
|
||||
if (cur_token >= length) {
|
||||
if (state == IN_MAIL)
|
||||
end = length;
|
||||
next = length;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(state) {
|
||||
case IN_MAIL:
|
||||
switch(str[cur_token]) {
|
||||
case '\r':
|
||||
state = FIRST_CR;
|
||||
break;
|
||||
case '\n':
|
||||
state = FIRST_LF;
|
||||
break;
|
||||
case 'F':
|
||||
if (cur_token == body) {
|
||||
end = cur_token;
|
||||
next = cur_token;
|
||||
state = PARSING_F;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
default:
|
||||
in_mail_data = 1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRST_CR:
|
||||
end = cur_token;
|
||||
switch(str[cur_token]) {
|
||||
case '\r':
|
||||
state = SECOND_CR;
|
||||
break;
|
||||
case '\n':
|
||||
state = FIRST_LF;
|
||||
break;
|
||||
default:
|
||||
state = IN_MAIL;
|
||||
#if 0
|
||||
in_mail_data = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRST_LF:
|
||||
end = cur_token;
|
||||
switch(str[cur_token]) {
|
||||
case '\r':
|
||||
state = SECOND_CR;
|
||||
break;
|
||||
case '\n':
|
||||
state = SECOND_LF;
|
||||
break;
|
||||
default:
|
||||
state = IN_MAIL;
|
||||
#if 0
|
||||
in_mail_data = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SECOND_CR:
|
||||
switch(str[cur_token]) {
|
||||
case '\r':
|
||||
end = cur_token;
|
||||
break;
|
||||
case '\n':
|
||||
state = SECOND_LF;
|
||||
break;
|
||||
case 'F':
|
||||
next = cur_token;
|
||||
state = PARSING_F;
|
||||
break;
|
||||
default:
|
||||
state = IN_MAIL;
|
||||
#if 0
|
||||
in_mail_data = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SECOND_LF:
|
||||
switch(str[cur_token]) {
|
||||
case '\r':
|
||||
state = SECOND_CR;
|
||||
break;
|
||||
case '\n':
|
||||
end = cur_token;
|
||||
break;
|
||||
case 'F':
|
||||
next = cur_token;
|
||||
state = PARSING_F;
|
||||
break;
|
||||
default:
|
||||
state = IN_MAIL;
|
||||
#if 0
|
||||
in_mail_data = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PARSING_F:
|
||||
switch(str[cur_token]) {
|
||||
case 'r':
|
||||
state = PARSING_R;
|
||||
break;
|
||||
default:
|
||||
state = IN_MAIL;
|
||||
#if 0
|
||||
in_mail_data = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PARSING_R:
|
||||
switch(str[cur_token]) {
|
||||
case 'o':
|
||||
state = PARSING_O;
|
||||
break;
|
||||
default:
|
||||
state = IN_MAIL;
|
||||
#if 0
|
||||
in_mail_data = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PARSING_O:
|
||||
switch(str[cur_token]) {
|
||||
case 'm':
|
||||
state = PARSING_M;
|
||||
break;
|
||||
default:
|
||||
state = IN_MAIL;
|
||||
#if 0
|
||||
in_mail_data = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PARSING_M:
|
||||
switch(str[cur_token]) {
|
||||
case ' ':
|
||||
state = OUT_MAIL;
|
||||
break;
|
||||
default:
|
||||
state = IN_MAIL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cur_token ++;
|
||||
}
|
||||
|
||||
message_length = end - start;
|
||||
|
||||
* pstart = start;
|
||||
* pstart_len = start_len;
|
||||
* pheaders = headers;
|
||||
* pheaders_len = headers_len;
|
||||
* pbody = body;
|
||||
* pbody_len = end - body;
|
||||
* psize = message_length;
|
||||
* ppadding = next - end;
|
||||
* puid = uid;
|
||||
|
||||
* index = next;
|
||||
|
||||
return MAILMBOX_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
claws_mailmbox_parse_additionnal(struct claws_mailmbox_folder * folder,
|
||||
size_t * index)
|
||||
{
|
||||
size_t cur_token;
|
||||
|
||||
size_t start;
|
||||
size_t start_len;
|
||||
size_t headers;
|
||||
size_t headers_len;
|
||||
size_t body;
|
||||
size_t body_len;
|
||||
size_t size;
|
||||
size_t padding;
|
||||
uint32_t uid;
|
||||
int r;
|
||||
int res;
|
||||
|
||||
uint32_t max_uid;
|
||||
uint32_t first_index;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
|
||||
cur_token = * index;
|
||||
|
||||
/* remove temporary UID that we will parse */
|
||||
|
||||
first_index = carray_count(folder->mb_tab);
|
||||
|
||||
for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
|
||||
struct claws_mailmbox_msg_info * info;
|
||||
|
||||
info = carray_get(folder->mb_tab, i);
|
||||
|
||||
if (info->msg_start < cur_token) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!info->msg_written_uid) {
|
||||
chashdatum key;
|
||||
|
||||
key.data = &info->msg_uid;
|
||||
key.len = sizeof(info->msg_uid);
|
||||
|
||||
chash_delete(folder->mb_hash, &key, NULL);
|
||||
carray_delete_fast(folder->mb_tab, i);
|
||||
claws_mailmbox_msg_info_free(info);
|
||||
if (i < first_index)
|
||||
first_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* make a sequence in the table */
|
||||
|
||||
max_uid = folder->mb_written_uid;
|
||||
|
||||
i = 0;
|
||||
j = 0;
|
||||
while (i < carray_count(folder->mb_tab)) {
|
||||
struct claws_mailmbox_msg_info * info;
|
||||
|
||||
info = carray_get(folder->mb_tab, i);
|
||||
if (info != NULL) {
|
||||
carray_set(folder->mb_tab, j, info);
|
||||
|
||||
if (info->msg_uid > max_uid)
|
||||
max_uid = info->msg_uid;
|
||||
|
||||
info->msg_index = j;
|
||||
j ++;
|
||||
}
|
||||
i ++;
|
||||
}
|
||||
carray_set_size(folder->mb_tab, j);
|
||||
|
||||
/* parse content */
|
||||
|
||||
first_index = j;
|
||||
|
||||
while (1) {
|
||||
struct claws_mailmbox_msg_info * info;
|
||||
chashdatum key;
|
||||
chashdatum data;
|
||||
|
||||
r = claws_mailmbox_single_parse(folder->mb_mapping, folder->mb_mapping_size,
|
||||
&cur_token,
|
||||
&start, &start_len,
|
||||
&headers, &headers_len,
|
||||
&body, &body_len,
|
||||
&size, &padding, &uid);
|
||||
if (r == MAILMBOX_NO_ERROR) {
|
||||
/* do nothing */
|
||||
}
|
||||
else if (r == MAILMBOX_ERROR_PARSE) {
|
||||
break;
|
||||
} else {
|
||||
res = r;
|
||||
goto err;
|
||||
}
|
||||
|
||||
key.data = &uid;
|
||||
key.len = sizeof(uid);
|
||||
|
||||
r = chash_get(folder->mb_hash, &key, &data);
|
||||
if (r == 0) {
|
||||
info = data.data;
|
||||
|
||||
if (!info->msg_written_uid) {
|
||||
/* some new mail has been written and override an
|
||||
existing temporary UID */
|
||||
|
||||
chash_delete(folder->mb_hash, &key, NULL);
|
||||
info->msg_uid = 0;
|
||||
|
||||
if (info->msg_index < first_index)
|
||||
first_index = info->msg_index;
|
||||
}
|
||||
else
|
||||
uid = 0;
|
||||
}
|
||||
|
||||
if (uid > max_uid)
|
||||
max_uid = uid;
|
||||
|
||||
r = claws_mailmbox_msg_info_update(folder,
|
||||
start, start_len, headers, headers_len,
|
||||
body, body_len, size, padding, uid);
|
||||
if (r != MAILMBOX_NO_ERROR) {
|
||||
debug_print("claws_mailmbox_msg_info_update failed with %d\n", r);
|
||||
res = r;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
* index = cur_token;
|
||||
|
||||
folder->mb_written_uid = max_uid;
|
||||
|
||||
/* attribute uid */
|
||||
|
||||
for(i = first_index ; i < carray_count(folder->mb_tab) ; i ++) {
|
||||
struct claws_mailmbox_msg_info * info;
|
||||
chashdatum key;
|
||||
chashdatum data;
|
||||
|
||||
info = carray_get(folder->mb_tab, i);
|
||||
|
||||
if (info->msg_uid != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
max_uid ++;
|
||||
info->msg_uid = max_uid;
|
||||
|
||||
key.data = &info->msg_uid;
|
||||
key.len = sizeof(info->msg_uid);
|
||||
data.data = info;
|
||||
data.len = 0;
|
||||
|
||||
r = chash_set(folder->mb_hash, &key, &data, NULL);
|
||||
if (r < 0) {
|
||||
debug_print("chash_set failed with %d\n", r);
|
||||
res = MAILMBOX_ERROR_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
folder->mb_max_uid = max_uid;
|
||||
|
||||
return MAILMBOX_NO_ERROR;
|
||||
|
||||
err:
|
||||
return res;
|
||||
}
|
||||
|
||||
static void flush_uid(struct claws_mailmbox_folder * folder)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
|
||||
struct claws_mailmbox_msg_info * info;
|
||||
|
||||
info = carray_get(folder->mb_tab, i);
|
||||
if (info != NULL)
|
||||
claws_mailmbox_msg_info_free(info);
|
||||
}
|
||||
|
||||
chash_clear(folder->mb_hash);
|
||||
carray_set_size(folder->mb_tab, 0);
|
||||
}
|
||||
|
||||
int claws_mailmbox_parse(struct claws_mailmbox_folder * folder)
|
||||
{
|
||||
int r;
|
||||
int res;
|
||||
size_t cur_token;
|
||||
|
||||
flush_uid(folder);
|
||||
|
||||
cur_token = 0;
|
||||
|
||||
r = claws_mailmbox_parse_additionnal(folder, &cur_token);
|
||||
|
||||
if (r != MAILMBOX_NO_ERROR) {
|
||||
res = r;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return MAILMBOX_NO_ERROR;
|
||||
|
||||
err:
|
||||
return res;
|
||||
}
|
56
src/plugins/mailmbox/mailmbox_parse.h
Normal file
56
src/plugins/mailmbox/mailmbox_parse.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef MAILMBOX_PARSE_H
|
||||
|
||||
#define MAILMBOX_PARSE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mailmbox_types.h"
|
||||
|
||||
int claws_mailmbox_parse(struct claws_mailmbox_folder * folder);
|
||||
|
||||
int
|
||||
claws_mailmbox_parse_additionnal(struct claws_mailmbox_folder * folder,
|
||||
size_t * index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
250
src/plugins/mailmbox/mailmbox_types.c
Normal file
250
src/plugins/mailmbox/mailmbox_types.c
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "mailmbox_types.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/* *********************************************************************** */
|
||||
|
||||
int claws_mailmbox_msg_info_update(struct claws_mailmbox_folder * folder,
|
||||
size_t msg_start, size_t msg_start_len,
|
||||
size_t msg_headers, size_t msg_headers_len,
|
||||
size_t msg_body, size_t msg_body_len,
|
||||
size_t msg_size, size_t msg_padding,
|
||||
uint32_t msg_uid)
|
||||
{
|
||||
struct claws_mailmbox_msg_info * info;
|
||||
int res;
|
||||
chashdatum key;
|
||||
chashdatum data;
|
||||
int r;
|
||||
|
||||
key.data = &msg_uid;
|
||||
key.len = sizeof(msg_uid);
|
||||
r = chash_get(folder->mb_hash, &key, &data);
|
||||
if (r < 0) {
|
||||
unsigned int index;
|
||||
|
||||
info = claws_mailmbox_msg_info_new(msg_start, msg_start_len,
|
||||
msg_headers, msg_headers_len,
|
||||
msg_body, msg_body_len, msg_size, msg_padding, msg_uid);
|
||||
if (info == NULL) {
|
||||
res = MAILMBOX_ERROR_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = carray_add(folder->mb_tab, info, &index);
|
||||
if (r < 0) {
|
||||
claws_mailmbox_msg_info_free(info);
|
||||
res = MAILMBOX_ERROR_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (msg_uid != 0) {
|
||||
chashdatum key;
|
||||
chashdatum data;
|
||||
|
||||
key.data = &msg_uid;
|
||||
key.len = sizeof(msg_uid);
|
||||
data.data = info;
|
||||
data.len = 0;
|
||||
|
||||
r = chash_set(folder->mb_hash, &key, &data, NULL);
|
||||
if (r < 0) {
|
||||
claws_mailmbox_msg_info_free(info);
|
||||
carray_delete(folder->mb_tab, index);
|
||||
res = MAILMBOX_ERROR_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
info->msg_index = index;
|
||||
}
|
||||
else {
|
||||
info = data.data;
|
||||
|
||||
info->msg_start = msg_start;
|
||||
info->msg_start_len = msg_start_len;
|
||||
info->msg_headers = msg_headers;
|
||||
info->msg_headers_len = msg_headers_len;
|
||||
info->msg_body = msg_body;
|
||||
info->msg_body_len = msg_body_len;
|
||||
info->msg_size = msg_size;
|
||||
info->msg_padding = msg_padding;
|
||||
}
|
||||
|
||||
return MAILMBOX_NO_ERROR;
|
||||
|
||||
err:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
struct claws_mailmbox_msg_info *
|
||||
claws_mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len,
|
||||
size_t msg_headers, size_t msg_headers_len,
|
||||
size_t msg_body, size_t msg_body_len,
|
||||
size_t msg_size, size_t msg_padding,
|
||||
uint32_t msg_uid)
|
||||
{
|
||||
struct claws_mailmbox_msg_info * info;
|
||||
|
||||
info = malloc(sizeof(* info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
info->msg_index = 0;
|
||||
info->msg_uid = msg_uid;
|
||||
if (msg_uid != 0)
|
||||
info->msg_written_uid = TRUE;
|
||||
else
|
||||
info->msg_written_uid = FALSE;
|
||||
info->msg_deleted = FALSE;
|
||||
|
||||
info->msg_start = msg_start;
|
||||
info->msg_start_len = msg_start_len;
|
||||
|
||||
info->msg_headers = msg_headers;
|
||||
info->msg_headers_len = msg_headers_len;
|
||||
|
||||
info->msg_body = msg_body;
|
||||
info->msg_body_len = msg_body_len;
|
||||
|
||||
info->msg_size = msg_size;
|
||||
|
||||
info->msg_padding = msg_padding;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void claws_mailmbox_msg_info_free(struct claws_mailmbox_msg_info * info)
|
||||
{
|
||||
free(info);
|
||||
}
|
||||
|
||||
|
||||
/* append info */
|
||||
|
||||
struct claws_mailmbox_append_info *
|
||||
claws_mailmbox_append_info_new(const char * ai_message, size_t ai_size)
|
||||
{
|
||||
struct claws_mailmbox_append_info * info;
|
||||
|
||||
info = malloc(sizeof(* info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
info->ai_message = ai_message;
|
||||
info->ai_size = ai_size;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void claws_mailmbox_append_info_free(struct claws_mailmbox_append_info * info)
|
||||
{
|
||||
free(info);
|
||||
}
|
||||
|
||||
struct claws_mailmbox_folder * claws_mailmbox_folder_new(const char * mb_filename)
|
||||
{
|
||||
struct claws_mailmbox_folder * folder;
|
||||
|
||||
folder = malloc(sizeof(* folder));
|
||||
if (folder == NULL)
|
||||
goto err;
|
||||
|
||||
strncpy(folder->mb_filename, mb_filename, PATH_MAX);
|
||||
|
||||
folder->mb_mtime = (time_t) -1;
|
||||
|
||||
folder->mb_fd = -1;
|
||||
folder->mb_read_only = TRUE;
|
||||
folder->mb_no_uid = TRUE;
|
||||
|
||||
folder->mb_changed = FALSE;
|
||||
folder->mb_deleted_count = 0;
|
||||
|
||||
folder->mb_mapping = NULL;
|
||||
folder->mb_mapping_size = 0;
|
||||
|
||||
folder->mb_written_uid = 0;
|
||||
folder->mb_max_uid = 0;
|
||||
|
||||
folder->mb_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
|
||||
if (folder->mb_hash == NULL)
|
||||
goto free;
|
||||
|
||||
folder->mb_tab = carray_new(128);
|
||||
if (folder->mb_tab == NULL)
|
||||
goto free_hash;
|
||||
|
||||
return folder;
|
||||
|
||||
free_hash:
|
||||
chash_free(folder->mb_hash);
|
||||
free:
|
||||
free(folder);
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void claws_mailmbox_folder_free(struct claws_mailmbox_folder * folder)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
|
||||
struct claws_mailmbox_msg_info * info;
|
||||
|
||||
info = carray_get(folder->mb_tab, i);
|
||||
if (info != NULL)
|
||||
claws_mailmbox_msg_info_free(info);
|
||||
}
|
||||
|
||||
carray_free(folder->mb_tab);
|
||||
|
||||
chash_free(folder->mb_hash);
|
||||
|
||||
free(folder);
|
||||
}
|
141
src/plugins/mailmbox/mailmbox_types.h
Normal file
141
src/plugins/mailmbox/mailmbox_types.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef MAILMBOX_TYPES_H
|
||||
|
||||
#define MAILMBOX_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "mailimf.h"
|
||||
#include "carray.h"
|
||||
#include "chash.h"
|
||||
|
||||
enum {
|
||||
MAILMBOX_NO_ERROR = 0,
|
||||
MAILMBOX_ERROR_PARSE,
|
||||
MAILMBOX_ERROR_INVAL,
|
||||
MAILMBOX_ERROR_FILE_NOT_FOUND,
|
||||
MAILMBOX_ERROR_MEMORY,
|
||||
MAILMBOX_ERROR_TEMPORARY_FILE,
|
||||
MAILMBOX_ERROR_FILE,
|
||||
MAILMBOX_ERROR_MSG_NOT_FOUND,
|
||||
MAILMBOX_ERROR_READONLY,
|
||||
};
|
||||
|
||||
|
||||
struct claws_mailmbox_folder {
|
||||
char mb_filename[PATH_MAX];
|
||||
|
||||
time_t mb_mtime;
|
||||
|
||||
int mb_fd;
|
||||
int mb_read_only;
|
||||
int mb_no_uid;
|
||||
|
||||
int mb_changed;
|
||||
unsigned int mb_deleted_count;
|
||||
|
||||
char * mb_mapping;
|
||||
size_t mb_mapping_size;
|
||||
|
||||
uint32_t mb_written_uid;
|
||||
uint32_t mb_max_uid;
|
||||
|
||||
chash * mb_hash;
|
||||
carray * mb_tab;
|
||||
};
|
||||
|
||||
struct claws_mailmbox_folder * claws_mailmbox_folder_new(const char * mb_filename);
|
||||
void claws_mailmbox_folder_free(struct claws_mailmbox_folder * folder);
|
||||
|
||||
|
||||
struct claws_mailmbox_msg_info {
|
||||
unsigned int msg_index;
|
||||
uint32_t msg_uid;
|
||||
int msg_written_uid;
|
||||
int msg_deleted;
|
||||
|
||||
size_t msg_start;
|
||||
size_t msg_start_len;
|
||||
|
||||
size_t msg_headers;
|
||||
size_t msg_headers_len;
|
||||
|
||||
size_t msg_body;
|
||||
size_t msg_body_len;
|
||||
|
||||
size_t msg_size;
|
||||
|
||||
size_t msg_padding;
|
||||
};
|
||||
|
||||
|
||||
int claws_mailmbox_msg_info_update(struct claws_mailmbox_folder * folder,
|
||||
size_t msg_start, size_t msg_start_len,
|
||||
size_t msg_headers, size_t msg_headers_len,
|
||||
size_t msg_body, size_t msg_body_len,
|
||||
size_t msg_size, size_t msg_padding,
|
||||
uint32_t msg_uid);
|
||||
|
||||
struct claws_mailmbox_msg_info *
|
||||
claws_mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len,
|
||||
size_t msg_headers, size_t msg_headers_len,
|
||||
size_t msg_body, size_t msg_body_len,
|
||||
size_t msg_size, size_t msg_padding,
|
||||
uint32_t msg_uid);
|
||||
|
||||
void claws_mailmbox_msg_info_free(struct claws_mailmbox_msg_info * info);
|
||||
|
||||
struct claws_mailmbox_append_info {
|
||||
const char * ai_message;
|
||||
size_t ai_size;
|
||||
};
|
||||
|
||||
struct claws_mailmbox_append_info *
|
||||
claws_mailmbox_append_info_new(const char * ai_message, size_t ai_size);
|
||||
|
||||
void claws_mailmbox_append_info_free(struct claws_mailmbox_append_info * info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
525
src/plugins/mailmbox/mmapstring.c
Normal file
525
src/plugins/mailmbox/mmapstring.c
Normal file
|
@ -0,0 +1,525 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "mmapstring.h"
|
||||
|
||||
#include "chash.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define MMAP_STRING_DEFAULT_CEIL (8 * 1024 * 1024)
|
||||
|
||||
#define DEFAULT_TMP_PATH "/tmp"
|
||||
|
||||
static char tmpdir[PATH_MAX] = DEFAULT_TMP_PATH;
|
||||
|
||||
static size_t mmap_string_ceil = MMAP_STRING_DEFAULT_CEIL;
|
||||
|
||||
/* MMAPString references */
|
||||
|
||||
static pthread_mutex_t mmapstring_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static chash * mmapstring_hashtable = NULL;
|
||||
|
||||
static void mmapstring_hashtable_init()
|
||||
{
|
||||
mmapstring_hashtable = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
|
||||
}
|
||||
|
||||
void mmap_string_set_tmpdir(char * directory)
|
||||
{
|
||||
strncpy(tmpdir, directory, PATH_MAX);
|
||||
tmpdir[PATH_MAX - 1] = 0;
|
||||
}
|
||||
|
||||
|
||||
int mmap_string_ref(MMAPString * string)
|
||||
{
|
||||
chash * ht;
|
||||
int r;
|
||||
chashdatum key;
|
||||
chashdatum data;
|
||||
|
||||
pthread_mutex_lock(&mmapstring_lock);
|
||||
if (mmapstring_hashtable == NULL) {
|
||||
mmapstring_hashtable_init();
|
||||
}
|
||||
ht = mmapstring_hashtable;
|
||||
|
||||
if (ht == NULL) {
|
||||
pthread_mutex_unlock(&mmapstring_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
key.data = &string->str;
|
||||
key.len = sizeof(string->str);
|
||||
data.data = string;
|
||||
data.len = 0;
|
||||
|
||||
r = chash_set(mmapstring_hashtable, &key, &data, NULL);
|
||||
pthread_mutex_unlock(&mmapstring_lock);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmap_string_unref(char * str)
|
||||
{
|
||||
MMAPString * string;
|
||||
chash * ht;
|
||||
chashdatum key;
|
||||
chashdatum data;
|
||||
int r;
|
||||
|
||||
pthread_mutex_lock(&mmapstring_lock);
|
||||
ht = mmapstring_hashtable;
|
||||
|
||||
if (ht == NULL) {
|
||||
pthread_mutex_unlock(&mmapstring_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
key.data = &str;
|
||||
key.len = sizeof(str);
|
||||
|
||||
r = chash_get(ht, &key, &data);
|
||||
if (r < 0)
|
||||
string = NULL;
|
||||
else
|
||||
string = data.data;
|
||||
|
||||
if (string != NULL) {
|
||||
chash_delete(ht, &key, NULL);
|
||||
if (chash_count(ht) == 0) {
|
||||
chash_free(ht);
|
||||
mmapstring_hashtable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mmapstring_lock);
|
||||
|
||||
if (string != NULL) {
|
||||
mmap_string_free(string);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* MMAPString */
|
||||
|
||||
#define MY_MAXSIZE ((size_t) -1)
|
||||
|
||||
static inline size_t
|
||||
nearest_power (size_t base, size_t num)
|
||||
{
|
||||
if (num > MY_MAXSIZE / 2) {
|
||||
return MY_MAXSIZE;
|
||||
}
|
||||
else {
|
||||
size_t n = base;
|
||||
|
||||
while (n < num)
|
||||
n <<= 1;
|
||||
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
void mmap_string_set_ceil(size_t ceil)
|
||||
{
|
||||
mmap_string_ceil = ceil;
|
||||
}
|
||||
|
||||
/* Strings.
|
||||
*/
|
||||
|
||||
static MMAPString * mmap_string_realloc_file(MMAPString * string)
|
||||
{
|
||||
char * data;
|
||||
|
||||
if (string->fd == -1) {
|
||||
char tmpfilename[PATH_MAX];
|
||||
int fd;
|
||||
|
||||
* tmpfilename = 0;
|
||||
strcat(tmpfilename, tmpdir);
|
||||
strcat(tmpfilename, "/libetpan-mmapstring-XXXXXX");
|
||||
|
||||
fd = mkstemp(tmpfilename);
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
|
||||
if (unlink(tmpfilename) == -1) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ftruncate(fd, string->allocated_len) == -1) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ,
|
||||
MAP_SHARED, fd, 0);
|
||||
|
||||
if (data == MAP_FAILED) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (string->str != NULL)
|
||||
memcpy(data, string->str, string->len + 1);
|
||||
|
||||
string->fd = fd;
|
||||
string->mmapped_size = string->allocated_len;
|
||||
free(string->str);
|
||||
string->str = data;
|
||||
}
|
||||
else {
|
||||
if (munmap(string->str, string->mmapped_size) == -1)
|
||||
return NULL;
|
||||
|
||||
if (ftruncate(string->fd, string->allocated_len) == -1)
|
||||
return NULL;
|
||||
|
||||
data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ,
|
||||
MAP_SHARED, string->fd, 0);
|
||||
|
||||
if (data == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
string->mmapped_size = string->allocated_len;
|
||||
string->str = data;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
static MMAPString * mmap_string_realloc_memory(MMAPString * string)
|
||||
{
|
||||
char * tmp;
|
||||
|
||||
tmp = realloc (string->str, string->allocated_len);
|
||||
|
||||
if (tmp == NULL)
|
||||
string = NULL;
|
||||
else
|
||||
string->str = tmp;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
static MMAPString *
|
||||
mmap_string_maybe_expand (MMAPString* string,
|
||||
size_t len)
|
||||
{
|
||||
if (string->len + len >= string->allocated_len)
|
||||
{
|
||||
size_t old_size;
|
||||
MMAPString * newstring;
|
||||
|
||||
old_size = string->allocated_len;
|
||||
|
||||
string->allocated_len = nearest_power (1, string->len + len + 1);
|
||||
|
||||
#ifndef MMAP_UNAVAILABLE
|
||||
if (string->allocated_len > mmap_string_ceil)
|
||||
newstring = mmap_string_realloc_file(string);
|
||||
else {
|
||||
#endif
|
||||
newstring = mmap_string_realloc_memory(string);
|
||||
#ifndef MMAP_UNAVAILABLE
|
||||
if (newstring == NULL)
|
||||
newstring = mmap_string_realloc_file(string);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (newstring == NULL)
|
||||
string->allocated_len = old_size;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_sized_new (size_t dfl_size)
|
||||
{
|
||||
MMAPString *string;
|
||||
|
||||
string = malloc(sizeof(* string));
|
||||
if (string == NULL)
|
||||
return NULL;
|
||||
|
||||
string->allocated_len = 0;
|
||||
string->len = 0;
|
||||
string->str = NULL;
|
||||
string->fd = -1;
|
||||
string->mmapped_size = 0;
|
||||
|
||||
if (mmap_string_maybe_expand (string, MAX (dfl_size, 2)) == NULL)
|
||||
return NULL;
|
||||
|
||||
string->str[0] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_new (const char *init)
|
||||
{
|
||||
MMAPString *string;
|
||||
|
||||
string = mmap_string_sized_new (init ? strlen (init) + 2 : 2);
|
||||
if (string == NULL)
|
||||
return NULL;
|
||||
|
||||
if (init)
|
||||
mmap_string_append (string, init);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_new_len (const char *init,
|
||||
size_t len)
|
||||
{
|
||||
MMAPString *string;
|
||||
|
||||
if (len <= 0)
|
||||
return mmap_string_new (init);
|
||||
else
|
||||
{
|
||||
string = mmap_string_sized_new (len);
|
||||
|
||||
if (init)
|
||||
mmap_string_append_len (string, init, len);
|
||||
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mmap_string_free (MMAPString *string)
|
||||
{
|
||||
if (string == NULL)
|
||||
return;
|
||||
|
||||
if (string->fd != -1) {
|
||||
munmap(string->str, string->mmapped_size);
|
||||
close(string->fd);
|
||||
}
|
||||
else {
|
||||
free (string->str);
|
||||
}
|
||||
free(string);
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_assign (MMAPString *string,
|
||||
const char *rval)
|
||||
{
|
||||
mmap_string_truncate (string, 0);
|
||||
if (mmap_string_append (string, rval) == NULL)
|
||||
return NULL;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_truncate (MMAPString *string,
|
||||
size_t len)
|
||||
{
|
||||
string->len = MIN (len, string->len);
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmap_string_set_size:
|
||||
* @string: a #MMAPString
|
||||
* @len: the new length
|
||||
*
|
||||
* Sets the length of a #MMAPString. If the length is less than
|
||||
* the current length, the string will be truncated. If the
|
||||
* length is greater than the current length, the contents
|
||||
* of the newly added area are undefined. (However, as
|
||||
* always, string->str[string->len] will be a nul byte.)
|
||||
*
|
||||
* Return value: @string
|
||||
**/
|
||||
MMAPString*
|
||||
mmap_string_set_size (MMAPString *string,
|
||||
size_t len)
|
||||
{
|
||||
if (len >= string->allocated_len)
|
||||
if (mmap_string_maybe_expand (string, len - string->len) == NULL)
|
||||
return NULL;
|
||||
|
||||
string->len = len;
|
||||
string->str[len] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/*
|
||||
static int in_mapped_zone(MMAPString * string, char * val)
|
||||
{
|
||||
return (val >= string->str) && (val < string->str + string->mmapped_size);
|
||||
}
|
||||
*/
|
||||
|
||||
MMAPString*
|
||||
mmap_string_insert_len (MMAPString *string,
|
||||
size_t pos,
|
||||
const char *val,
|
||||
size_t len)
|
||||
{
|
||||
if (mmap_string_maybe_expand (string, len) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (pos < string->len)
|
||||
memmove (string->str + pos + len, string->str + pos, string->len - pos);
|
||||
|
||||
/* insert the new string */
|
||||
memmove (string->str + pos, val, len);
|
||||
|
||||
string->len += len;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_append (MMAPString *string,
|
||||
const char *val)
|
||||
{
|
||||
return mmap_string_insert_len (string, string->len, val, strlen(val));
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_append_len (MMAPString *string,
|
||||
const char *val,
|
||||
size_t len)
|
||||
{
|
||||
return mmap_string_insert_len (string, string->len, val, len);
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_append_c (MMAPString *string,
|
||||
char c)
|
||||
{
|
||||
return mmap_string_insert_c (string, string->len, c);
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_prepend (MMAPString *string,
|
||||
const char *val)
|
||||
{
|
||||
return mmap_string_insert_len (string, 0, val, strlen(val));
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_prepend_len (MMAPString *string,
|
||||
const char *val,
|
||||
size_t len)
|
||||
{
|
||||
return mmap_string_insert_len (string, 0, val, len);
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_prepend_c (MMAPString *string,
|
||||
char c)
|
||||
{
|
||||
return mmap_string_insert_c (string, 0, c);
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_insert (MMAPString *string,
|
||||
size_t pos,
|
||||
const char *val)
|
||||
{
|
||||
return mmap_string_insert_len (string, pos, val, strlen(val));
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_insert_c (MMAPString *string,
|
||||
size_t pos,
|
||||
char c)
|
||||
{
|
||||
if (mmap_string_maybe_expand (string, 1) == NULL)
|
||||
return NULL;
|
||||
|
||||
/* If not just an append, move the old stuff */
|
||||
if (pos < string->len)
|
||||
memmove (string->str + pos + 1, string->str + pos, string->len - pos);
|
||||
|
||||
string->str[pos] = c;
|
||||
|
||||
string->len += 1;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
MMAPString*
|
||||
mmap_string_erase (MMAPString *string,
|
||||
size_t pos,
|
||||
size_t len)
|
||||
{
|
||||
if ((pos + len) < string->len)
|
||||
memmove (string->str + pos, string->str + pos + len,
|
||||
string->len - (pos + len));
|
||||
|
||||
string->len -= len;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return string;
|
||||
}
|
136
src/plugins/mailmbox/mmapstring.h
Normal file
136
src/plugins/mailmbox/mmapstring.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2002 - DINH Viet Hoa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the libEtPan! project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __MMAP_STRING_H__
|
||||
|
||||
#define __MMAP_STRING_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define TMPDIR "/tmp"
|
||||
*/
|
||||
|
||||
typedef struct _MMAPString MMAPString;
|
||||
|
||||
struct _MMAPString
|
||||
{
|
||||
char * str;
|
||||
size_t len;
|
||||
size_t allocated_len;
|
||||
int fd;
|
||||
size_t mmapped_size;
|
||||
/*
|
||||
char * old_non_mmapped_str;
|
||||
*/
|
||||
};
|
||||
|
||||
/* configure location of mmaped files */
|
||||
|
||||
void mmap_string_set_tmpdir(char * directory);
|
||||
|
||||
/* Strings
|
||||
*/
|
||||
|
||||
MMAPString * mmap_string_new (const char * init);
|
||||
|
||||
MMAPString * mmap_string_new_len (const char * init,
|
||||
size_t len);
|
||||
|
||||
MMAPString * mmap_string_sized_new (size_t dfl_size);
|
||||
|
||||
void mmap_string_free (MMAPString * string);
|
||||
|
||||
MMAPString * mmap_string_assign (MMAPString * string,
|
||||
const char * rval);
|
||||
|
||||
MMAPString * mmap_string_truncate (MMAPString *string,
|
||||
size_t len);
|
||||
|
||||
MMAPString * mmap_string_set_size (MMAPString * string,
|
||||
size_t len);
|
||||
|
||||
MMAPString * mmap_string_insert_len (MMAPString * string,
|
||||
size_t pos,
|
||||
const char * val,
|
||||
size_t len);
|
||||
|
||||
MMAPString * mmap_string_append (MMAPString * string,
|
||||
const char * val);
|
||||
|
||||
MMAPString * mmap_string_append_len (MMAPString * string,
|
||||
const char * val,
|
||||
size_t len);
|
||||
|
||||
MMAPString * mmap_string_append_c (MMAPString * string,
|
||||
char c);
|
||||
|
||||
MMAPString * mmap_string_prepend (MMAPString * string,
|
||||
const char * val);
|
||||
|
||||
MMAPString * mmap_string_prepend_c (MMAPString * string,
|
||||
char c);
|
||||
|
||||
MMAPString * mmap_string_prepend_len (MMAPString * string,
|
||||
const char * val,
|
||||
size_t len);
|
||||
|
||||
MMAPString * mmap_string_insert (MMAPString * string,
|
||||
size_t pos,
|
||||
const char * val);
|
||||
|
||||
MMAPString * mmap_string_insert_c (MMAPString *string,
|
||||
size_t pos,
|
||||
char c);
|
||||
|
||||
MMAPString * mmap_string_erase(MMAPString * string,
|
||||
size_t pos,
|
||||
size_t len);
|
||||
|
||||
void mmap_string_set_ceil(size_t ceil);
|
||||
|
||||
int mmap_string_ref(MMAPString * string);
|
||||
int mmap_string_unref(char * str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __MMAP_STRING_H__ */
|
|
@ -1 +0,0 @@
|
|||
Placeholder
|
87
src/plugins/mailmbox/plugin.c
Normal file
87
src/plugins/mailmbox/plugin.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* mailmbox Plugin -- mbox support for Sylpheed
|
||||
* Copyright (C) 2003 Christoph Hohmann
|
||||
* Copyright (C) 2003-2005 Hoa v. Dinh, Alfons Hoogervorst
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# include "claws-features.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include "plugin.h"
|
||||
#include "folder.h"
|
||||
#include "mailmbox_folder.h"
|
||||
#include "common/version.h"
|
||||
#include "plugin_gtk.h"
|
||||
#include "plugin.h"
|
||||
#include "main.h"
|
||||
|
||||
gint plugin_init(gchar **error)
|
||||
{
|
||||
if (!check_plugin_version(MAKE_NUMERIC_VERSION(3,8,1,46),
|
||||
VERSION_NUMERIC, "Mailmbox", error))
|
||||
return -1;
|
||||
|
||||
folder_register_class(claws_mailmbox_get_class());
|
||||
plugin_gtk_init(error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean plugin_done(void)
|
||||
{
|
||||
plugin_gtk_done();
|
||||
if (!claws_is_exiting())
|
||||
folder_unregister_class(claws_mailmbox_get_class());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const gchar *plugin_name(void)
|
||||
{
|
||||
return _("mailmbox folder (etPan!)");
|
||||
}
|
||||
|
||||
const gchar *plugin_desc(void)
|
||||
{
|
||||
return _("This is a plugin to handle mailboxes in mbox format.");
|
||||
}
|
||||
|
||||
const gchar *plugin_type(void)
|
||||
{
|
||||
return "GTK2";
|
||||
}
|
||||
|
||||
const gchar *plugin_licence(void)
|
||||
{
|
||||
return "GPL3+";
|
||||
}
|
||||
|
||||
const gchar *plugin_version(void)
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
struct PluginFeature *plugin_provides(void)
|
||||
{
|
||||
static struct PluginFeature features[] =
|
||||
{ {PLUGIN_FOLDERCLASS, N_("MBOX")},
|
||||
{PLUGIN_NOTHING, NULL}};
|
||||
return features;
|
||||
}
|
455
src/plugins/mailmbox/plugin_gtk.c
Normal file
455
src/plugins/mailmbox/plugin_gtk.c
Normal file
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* mailmbox Plugin -- mbox support for Sylpheed
|
||||
* Copyright (C) 2003-2005 Christoph Hohmann,
|
||||
* Hoa v. Dinh,
|
||||
* Alfons Hoogervorst
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# include "claws-features.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "plugin.h"
|
||||
#include "folder.h"
|
||||
#include "mailmbox_folder.h"
|
||||
#include "mainwindow.h"
|
||||
#include "folderview.h"
|
||||
#include "inputdialog.h"
|
||||
#include "foldersel.h"
|
||||
#include "alertpanel.h"
|
||||
#include "main.h"
|
||||
#include "menu.h"
|
||||
#include "account.h"
|
||||
#include "prefs_actions.h"
|
||||
#include "summaryview.h"
|
||||
#include "folder_item_prefs.h"
|
||||
|
||||
static void add_mailbox(GtkAction *action, gpointer callback_data);
|
||||
static void new_folder_cb(GtkAction *action, gpointer data);
|
||||
static void delete_folder_cb(GtkAction *action, gpointer data);
|
||||
static void rename_folder_cb(GtkAction *action, gpointer data);
|
||||
static void move_folder_cb(GtkAction *action, gpointer data);
|
||||
static void copy_folder_cb(GtkAction *action, gpointer data);
|
||||
static void update_tree_cb(GtkAction *action, gpointer data);
|
||||
static void remove_mailbox_cb(GtkAction *action, gpointer data);
|
||||
|
||||
static GtkActionEntry claws_mailmbox_popup_entries[] =
|
||||
{
|
||||
{"FolderViewPopup/CreateNewFolder", NULL, N_("Create _new folder..."), NULL, NULL, G_CALLBACK(new_folder_cb) },
|
||||
{"FolderViewPopup/RenameFolder", NULL, N_("_Rename folder..."), NULL, NULL, G_CALLBACK(rename_folder_cb) },
|
||||
{"FolderViewPopup/MoveFolder", NULL, N_("M_ove folder..."), NULL, NULL, G_CALLBACK(move_folder_cb) },
|
||||
{"FolderViewPopup/CopyFolder", NULL, N_("Cop_y folder..."), NULL, NULL, G_CALLBACK(copy_folder_cb) },
|
||||
{"FolderViewPopup/DeleteFolder", NULL, N_("_Delete folder..."), NULL, NULL, G_CALLBACK(delete_folder_cb) },
|
||||
{"FolderViewPopup/CheckNewMessages", NULL, N_("_Check for new messages"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*0*/
|
||||
{"FolderViewPopup/CheckNewFolders", NULL, N_("C_heck for new folders"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*1*/
|
||||
{"FolderViewPopup/RebuildTree", NULL, N_("R_ebuild folder tree"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*2*/
|
||||
{"FolderViewPopup/RemoveMailbox", NULL, N_("Remove _mailbox..."), NULL, NULL, G_CALLBACK(remove_mailbox_cb) },
|
||||
};
|
||||
static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *item);
|
||||
static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item);
|
||||
|
||||
static FolderViewPopup claws_mailmbox_popup =
|
||||
{
|
||||
"mailmbox",
|
||||
"<MailmboxFolder>",
|
||||
claws_mailmbox_popup_entries,
|
||||
G_N_ELEMENTS(claws_mailmbox_popup_entries),
|
||||
NULL, 0,
|
||||
NULL, 0, 0, NULL,
|
||||
add_menuitems,
|
||||
set_sensitivity
|
||||
};
|
||||
|
||||
static GtkActionEntry mainwindow_add_mailbox[] = {{
|
||||
"File/AddMailbox/Mbox",
|
||||
NULL, N_("mbox (etPan!)..."), NULL, NULL, G_CALLBACK(add_mailbox)
|
||||
}};
|
||||
|
||||
static guint main_menu_id = 0;
|
||||
|
||||
gint plugin_gtk_init(gchar **error)
|
||||
{
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
|
||||
folderview_register_popup(&claws_mailmbox_popup);
|
||||
|
||||
gtk_action_group_add_actions(mainwin->action_group, mainwindow_add_mailbox,
|
||||
1, (gpointer)mainwin);
|
||||
MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menu/File/AddMailbox", "Mbox",
|
||||
"File/AddMailbox/Mbox", GTK_UI_MANAGER_MENUITEM,
|
||||
main_menu_id)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void plugin_gtk_done(void)
|
||||
{
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
|
||||
if (mainwin == NULL || claws_is_exiting())
|
||||
return;
|
||||
|
||||
folderview_unregister_popup(&claws_mailmbox_popup);
|
||||
|
||||
MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "File/AddMailbox/RSSyl", main_menu_id);
|
||||
main_menu_id = 0;
|
||||
}
|
||||
|
||||
static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item)
|
||||
{
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CreateNewFolder", "FolderViewPopup/CreateNewFolder", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RenameFolder", "FolderViewPopup/RenameFolder", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "MoveFolder", "FolderViewPopup/MoveFolder", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CopyFolder", "FolderViewPopup/CopyFolder", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox2", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "DeleteFolder", "FolderViewPopup/DeleteFolder", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox3", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CheckNewMessages", "FolderViewPopup/CheckNewMessages", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CheckNewFolders", "FolderViewPopup/CheckNewFolders", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RebuildTree", "FolderViewPopup/RebuildTree", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox4", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RemoveMailbox", "FolderViewPopup/RemoveMailbox", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox5", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
|
||||
}
|
||||
|
||||
static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *item)
|
||||
{
|
||||
gboolean folder_is_normal =
|
||||
item != NULL &&
|
||||
item->stype == F_NORMAL &&
|
||||
!folder_has_parent_of_type(item, F_OUTBOX) &&
|
||||
!folder_has_parent_of_type(item, F_DRAFT) &&
|
||||
!folder_has_parent_of_type(item, F_QUEUE) &&
|
||||
!folder_has_parent_of_type(item, F_TRASH);
|
||||
#define SET_SENS(name, sens) \
|
||||
cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)
|
||||
|
||||
SET_SENS("FolderViewPopup/CreateNewFolder", item->stype != F_INBOX);
|
||||
SET_SENS("FolderViewPopup/RenameFolder", item->stype == F_NORMAL && folder_item_parent(item) != NULL);
|
||||
SET_SENS("FolderViewPopup/MoveFolder", folder_is_normal && folder_item_parent(item) != NULL);
|
||||
SET_SENS("FolderViewPopup/DeleteFolder", item->stype == F_NORMAL && folder_item_parent(item) != NULL);
|
||||
|
||||
SET_SENS("FolderViewPopup/CheckNewMessages", folder_item_parent(item) == NULL);
|
||||
SET_SENS("FolderViewPopup/CheckNewFolders", folder_item_parent(item) == NULL);
|
||||
SET_SENS("FolderViewPopup/RebuildTree", folder_item_parent(item) == NULL);
|
||||
|
||||
SET_SENS("FolderViewPopup/RemoveMailbox", folder_item_parent(item) == NULL);
|
||||
|
||||
#undef SET_SENS
|
||||
}
|
||||
|
||||
#define DO_ACTION(name, act) { if (!strcmp(a_name, name)) act; }
|
||||
|
||||
static void update_tree_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
FolderView *folderview = (FolderView *)data;
|
||||
FolderItem *item;
|
||||
const gchar *a_name = gtk_action_get_name(action);
|
||||
|
||||
item = folderview_get_selected_item(folderview);
|
||||
g_return_if_fail(item != NULL);
|
||||
|
||||
summary_show(folderview->summaryview, NULL);
|
||||
|
||||
g_return_if_fail(item->folder != NULL);
|
||||
|
||||
DO_ACTION("FolderViewPopup/CheckNewMessages", folderview_check_new(item->folder));
|
||||
DO_ACTION("FolderViewPopup/CheckNewFolders", folderview_rescan_tree(item->folder, FALSE));
|
||||
DO_ACTION("FolderViewPopup/RebuildTree", folderview_rescan_tree(item->folder, TRUE));
|
||||
}
|
||||
|
||||
static void add_mailbox(GtkAction *action, gpointer callback_data)
|
||||
{
|
||||
MainWindow *mainwin = (MainWindow *) callback_data;
|
||||
gchar *path, *basename;
|
||||
Folder *folder;
|
||||
|
||||
path = input_dialog(_("Add mailbox"),
|
||||
_("Input the location of mailbox.\n"
|
||||
"If the existing mailbox is specified, it will be\n"
|
||||
"scanned automatically."),
|
||||
"Mail");
|
||||
if (!path) return;
|
||||
if (folder_find_from_path(path)) {
|
||||
alertpanel_error(_("The mailbox `%s' already exists."), path);
|
||||
g_free(path);
|
||||
return;
|
||||
}
|
||||
basename = g_path_get_basename(path);
|
||||
folder = folder_new(folder_get_class_from_string("mailmbox"),
|
||||
!strcmp(path, "Mail") ? _("Mailbox") : basename,
|
||||
path);
|
||||
g_free(basename);
|
||||
g_free(path);
|
||||
|
||||
|
||||
if (folder->klass->create_tree(folder) < 0) {
|
||||
alertpanel_error(_("Creation of the mailbox failed.\n"
|
||||
"Maybe some files already exist, or you don't have the permission to write there."));
|
||||
folder_destroy(folder);
|
||||
return;
|
||||
}
|
||||
|
||||
folder_add(folder);
|
||||
folder_scan_tree(folder, TRUE);
|
||||
|
||||
folderview_set(mainwin->folderview);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void new_folder_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
FolderView *folderview = (FolderView *)data;
|
||||
GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
|
||||
FolderItem *item;
|
||||
FolderItem *new_item;
|
||||
gchar *new_folder;
|
||||
gchar *name;
|
||||
gchar *p;
|
||||
|
||||
if (!folderview->selected) return;
|
||||
|
||||
item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
|
||||
g_return_if_fail(item != NULL);
|
||||
g_return_if_fail(item->folder != NULL);
|
||||
|
||||
new_folder = input_dialog(_("New folder"),
|
||||
_("Input the name of new folder:"),
|
||||
_("NewFolder"));
|
||||
if (!new_folder) return;
|
||||
AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
|
||||
|
||||
p = strchr(new_folder, G_DIR_SEPARATOR);
|
||||
if (p == NULL)
|
||||
p = strchr(new_folder, '.');
|
||||
if (p) {
|
||||
alertpanel_error(_("`%c' can't be included in folder name."),
|
||||
p[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
name = trim_string(new_folder, 32);
|
||||
AUTORELEASE_STR(name, {g_free(name); return;});
|
||||
|
||||
/* find whether the directory already exists */
|
||||
p = g_strconcat(item->path ? item->path : "", ".", new_folder, NULL);
|
||||
if (folder_find_child_item_by_name(item, p)) {
|
||||
g_free(p);
|
||||
alertpanel_error(_("The folder `%s' already exists."), name);
|
||||
return;
|
||||
}
|
||||
g_free(p);
|
||||
|
||||
new_item = folder_create_folder(item, new_folder);
|
||||
if (!new_item) {
|
||||
alertpanel_error(_("Can't create the folder `%s'."), name);
|
||||
return;
|
||||
}
|
||||
|
||||
folder_write_list();
|
||||
}
|
||||
|
||||
static void remove_mailbox_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
FolderView *folderview = (FolderView *)data;
|
||||
FolderItem *item;
|
||||
gchar *name;
|
||||
gchar *message;
|
||||
AlertValue avalue;
|
||||
|
||||
item = folderview_get_selected_item(folderview);
|
||||
g_return_if_fail(item != NULL);
|
||||
g_return_if_fail(item->folder != NULL);
|
||||
if (folder_item_parent(item)) return;
|
||||
|
||||
name = trim_string(item->folder->name, 32);
|
||||
message = g_strdup_printf
|
||||
(_("Really remove the mailbox `%s' ?\n"
|
||||
"(The messages are NOT deleted from the disk)"), name);
|
||||
avalue = alertpanel_full(_("Remove mailbox"), message,
|
||||
GTK_STOCK_CANCEL, _("_Remove"), NULL, FALSE,
|
||||
NULL, ALERT_WARNING, G_ALERTDEFAULT);
|
||||
g_free(message);
|
||||
g_free(name);
|
||||
if (avalue != G_ALERTALTERNATE) return;
|
||||
|
||||
folderview_unselect(folderview);
|
||||
summary_clear_all(folderview->summaryview);
|
||||
|
||||
folder_destroy(item->folder);
|
||||
}
|
||||
|
||||
static void delete_folder_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
FolderView *folderview = (FolderView *)data;
|
||||
GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
|
||||
FolderItem *item;
|
||||
gchar *message, *name;
|
||||
AlertValue avalue;
|
||||
gchar *old_path;
|
||||
gchar *old_id;
|
||||
|
||||
item = folderview_get_selected_item(folderview);
|
||||
g_return_if_fail(item != NULL);
|
||||
g_return_if_fail(item->path != NULL);
|
||||
g_return_if_fail(item->folder != NULL);
|
||||
|
||||
name = trim_string(item->name, 32);
|
||||
AUTORELEASE_STR(name, {g_free(name); return;});
|
||||
message = g_strdup_printf
|
||||
(_("All folder(s) and message(s) under `%s' will be deleted.\n"
|
||||
"Do you really want to delete?"), name);
|
||||
avalue = alertpanel_full(_("Delete folder"), message,
|
||||
GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, FALSE,
|
||||
NULL, ALERT_NOTICE, G_ALERTDEFAULT);
|
||||
g_free(message);
|
||||
if (avalue != G_ALERTALTERNATE) return;
|
||||
|
||||
Xstrdup_a(old_path, item->path, return);
|
||||
old_id = folder_item_get_identifier(item);
|
||||
|
||||
if (folderview->opened == folderview->selected ||
|
||||
gtk_cmctree_is_ancestor(ctree,
|
||||
folderview->selected,
|
||||
folderview->opened)) {
|
||||
summary_clear_all(folderview->summaryview);
|
||||
folderview->opened = NULL;
|
||||
}
|
||||
|
||||
if (item->folder->klass->remove_folder(item->folder, item) < 0) {
|
||||
alertpanel_error(_("Can't remove the folder `%s'."), name);
|
||||
if (folderview->opened == folderview->selected)
|
||||
summary_show(folderview->summaryview,
|
||||
folderview->summaryview->folder_item);
|
||||
g_free(old_id);
|
||||
return;
|
||||
}
|
||||
|
||||
folder_write_list();
|
||||
|
||||
prefs_filtering_delete_path(old_id);
|
||||
g_free(old_id);
|
||||
|
||||
}
|
||||
|
||||
static void move_folder_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
FolderView *folderview = (FolderView *)data;
|
||||
FolderItem *from_folder = NULL, *to_folder = NULL;
|
||||
|
||||
from_folder = folderview_get_selected_item(folderview);
|
||||
if (!from_folder || from_folder->folder->klass != claws_mailmbox_get_class())
|
||||
return;
|
||||
|
||||
to_folder = foldersel_folder_sel(from_folder->folder, FOLDER_SEL_MOVE, NULL, FALSE);
|
||||
if (!to_folder)
|
||||
return;
|
||||
|
||||
folderview_move_folder(folderview, from_folder, to_folder, 0);
|
||||
}
|
||||
|
||||
static void copy_folder_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
FolderView *folderview = (FolderView *)data;
|
||||
FolderItem *from_folder = NULL, *to_folder = NULL;
|
||||
|
||||
from_folder = folderview_get_selected_item(folderview);
|
||||
if (!from_folder || from_folder->folder->klass != claws_mailmbox_get_class())
|
||||
return;
|
||||
|
||||
to_folder = foldersel_folder_sel(from_folder->folder, FOLDER_SEL_MOVE, NULL, FALSE);
|
||||
if (!to_folder)
|
||||
return;
|
||||
|
||||
folderview_move_folder(folderview, from_folder, to_folder, 1);
|
||||
}
|
||||
|
||||
static void rename_folder_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
FolderView *folderview = (FolderView *)data;
|
||||
FolderItem *item, *parent;
|
||||
gchar *new_folder;
|
||||
gchar *name;
|
||||
gchar *message;
|
||||
gchar *old_path;
|
||||
gchar *old_id;
|
||||
gchar *new_id;
|
||||
gchar *p;
|
||||
|
||||
item = folderview_get_selected_item(folderview);
|
||||
g_return_if_fail(item != NULL);
|
||||
g_return_if_fail(item->path != NULL);
|
||||
g_return_if_fail(item->folder != NULL);
|
||||
|
||||
name = trim_string(item->name, 32);
|
||||
message = g_strdup_printf(_("Input new name for `%s':"), name);
|
||||
new_folder = input_dialog(_("Rename folder"), message, item->name);
|
||||
g_free(message);
|
||||
g_free(name);
|
||||
if (!new_folder) return;
|
||||
AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
|
||||
|
||||
p = strchr(new_folder, G_DIR_SEPARATOR);
|
||||
if (p == NULL)
|
||||
p = strchr(new_folder, '.');
|
||||
if (p) {
|
||||
alertpanel_error(_("`%c' can't be included in folder name."),
|
||||
p[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
parent = folder_item_parent(item);
|
||||
p = g_strconcat(parent->path ? parent->path : "", ".", new_folder, NULL);
|
||||
if (folder_find_child_item_by_name(parent, p)) {
|
||||
name = trim_string(new_folder, 32);
|
||||
alertpanel_error(_("The folder `%s' already exists."), name);
|
||||
g_free(name);
|
||||
return;
|
||||
}
|
||||
|
||||
Xstrdup_a(old_path, item->path, {g_free(new_folder); return;});
|
||||
|
||||
old_id = folder_item_get_identifier(item);
|
||||
|
||||
if (folder_item_rename(item, new_folder) < 0) {
|
||||
alertpanel_error(_("The folder could not be renamed.\n"
|
||||
"The new folder name is not allowed."));
|
||||
g_free(old_id);
|
||||
return;
|
||||
}
|
||||
|
||||
new_id = folder_item_get_identifier(item);
|
||||
prefs_filtering_rename_path(old_id, new_id);
|
||||
account_rename_path(old_id, new_id);
|
||||
prefs_actions_rename_path(old_id, new_id);
|
||||
|
||||
g_free(old_id);
|
||||
g_free(new_id);
|
||||
|
||||
folder_item_prefs_save_config_recursive(item);
|
||||
folder_write_list();
|
||||
}
|
||||
|
30
src/plugins/mailmbox/plugin_gtk.h
Normal file
30
src/plugins/mailmbox/plugin_gtk.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* mailmbox Plugin -- mbox support for Sylpheed
|
||||
* Copyright (C) 2003-2005 Christoph Hohmann,
|
||||
* Hoa v. Dinh,
|
||||
* Alfons Hoogervorst
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PLUGIN_GTK_H__
|
||||
#define __PLUGIN_GTK_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
gint plugin_gtk_init(gchar **error);
|
||||
void plugin_gtk_done(void);
|
||||
|
||||
#endif
|
19
src/plugins/newmail/Makefile.am
Normal file
19
src/plugins/newmail/Makefile.am
Normal file
|
@ -0,0 +1,19 @@
|
|||
plugindir = $(pkglibdir)/plugins
|
||||
|
||||
plugin_LTLIBRARIES = newmail.la
|
||||
|
||||
newmail_la_SOURCES = \
|
||||
newmail.c
|
||||
|
||||
newmail_la_LDFLAGS = \
|
||||
-avoid-version -module
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(CLAWS_MAIL_CFLAGS) \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(GTK_CFLAGS)
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/common \
|
||||
-I$(top_srcdir)/src/gtk
|
168
src/plugins/newmail/newmail.c
Normal file
168
src/plugins/newmail/newmail.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* newmail - A plugin for Claws Mail
|
||||
*
|
||||
* Copyright (C) 2005-2005 H.Merijn Brand and the Claws Mail Team
|
||||
*
|
||||
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
|
||||
* Copyright (C) 1999-2012 the Claws Mail Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "version.h"
|
||||
#include "claws.h"
|
||||
#include "plugin.h"
|
||||
#include "utils.h"
|
||||
#include "hooks.h"
|
||||
#include "procmsg.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
static guint hook_id;
|
||||
|
||||
static FILE *NewLog = NULL;
|
||||
static char *LogName = NULL;
|
||||
static int truncLog = 1;
|
||||
|
||||
static gchar *defstr (gchar *s)
|
||||
{
|
||||
return s ? s : "(null)";
|
||||
} /* defstr */
|
||||
|
||||
gboolean newmail_hook (gpointer source, gpointer data)
|
||||
{
|
||||
auto MsgInfo *msginfo = (MsgInfo *)source;
|
||||
auto FolderItem *tof;
|
||||
|
||||
if (!msginfo) return (FALSE);
|
||||
|
||||
tof = msginfo->folder;
|
||||
(void)fprintf (NewLog, "---\n"
|
||||
"Date:\t%s\n"
|
||||
"Subject:\t%s\n"
|
||||
"From:\t%s\n"
|
||||
"To:\t%s\n"
|
||||
"Cc:\t%s\n"
|
||||
"Size:\t%jd\n"
|
||||
"Path:\t%s\n"
|
||||
"Message:\t%d\n"
|
||||
"Folder:\t%s\n",
|
||||
defstr (msginfo->date),
|
||||
defstr (msginfo->subject),
|
||||
defstr (msginfo->from),
|
||||
defstr (msginfo->to),
|
||||
defstr (msginfo->cc),
|
||||
(intmax_t) msginfo->size,
|
||||
defstr (procmsg_get_message_file_path (msginfo)),
|
||||
msginfo->msgnum,
|
||||
tof ? defstr (tof->name) : "(null)");
|
||||
|
||||
return (FALSE);
|
||||
} /* newmail_hook */
|
||||
|
||||
gboolean plugin_done (void)
|
||||
{
|
||||
if (NewLog) {
|
||||
(void)fclose (NewLog);
|
||||
NewLog = NULL;
|
||||
LogName = NULL;
|
||||
}
|
||||
hooks_unregister_hook (MAIL_POSTFILTERING_HOOKLIST, hook_id);
|
||||
|
||||
printf (_("Newmail plugin unloaded\n"));
|
||||
return TRUE;
|
||||
} /* plugin_done */
|
||||
|
||||
gint plugin_init (gchar **error)
|
||||
{
|
||||
if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
|
||||
VERSION_NUMERIC, _("NewMail"), error))
|
||||
return -1;
|
||||
|
||||
hook_id = hooks_register_hook (MAIL_POSTFILTERING_HOOKLIST, newmail_hook, NULL);
|
||||
if (hook_id == -1) {
|
||||
*error = g_strdup (_("Failed to register newmail hook"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (!NewLog) {
|
||||
auto char *mode = truncLog ? "w" : "a";
|
||||
if (!LogName) {
|
||||
auto size_t l;
|
||||
auto char name[260];
|
||||
(void)snprintf (name, 256, "%s/Mail/NewLog", getenv ("HOME"));
|
||||
l = strlen (name);
|
||||
if (l > 255 || !(LogName = (char *)malloc (l + 1))) {
|
||||
*error = g_strdup (_("Cannot load plugin NewMail\n"
|
||||
"$HOME is too long\n"));
|
||||
plugin_done ();
|
||||
return (-1);
|
||||
}
|
||||
(void)strcpy (LogName, name);
|
||||
}
|
||||
if (!(NewLog = fopen (LogName, mode))) {
|
||||
*error = g_strdup (sys_errlist[errno]);
|
||||
plugin_done ();
|
||||
return (-1);
|
||||
}
|
||||
setbuf (NewLog, NULL);
|
||||
}
|
||||
|
||||
printf (_("Newmail plugin loaded\n"
|
||||
"Message header summaries written to %s\n"), LogName);
|
||||
return (0);
|
||||
} /* plugin_init */
|
||||
|
||||
const gchar *plugin_name (void)
|
||||
{
|
||||
return _("NewMail");
|
||||
} /* plugin_name */
|
||||
|
||||
const gchar *plugin_desc (void)
|
||||
{
|
||||
return _("This Plugin writes a header summary to a log file for each "
|
||||
"mail received after sorting.\n\n"
|
||||
"Default is ~/Mail/NewLog");
|
||||
} /* plugin_desc */
|
||||
|
||||
const gchar *plugin_type (void)
|
||||
{
|
||||
return ("Common");
|
||||
} /* plugin_type */
|
||||
|
||||
const gchar *plugin_licence (void)
|
||||
{
|
||||
return ("GPL3+");
|
||||
} /* plugin_licence */
|
||||
|
||||
const gchar *plugin_version (void)
|
||||
{
|
||||
return (VERSION);
|
||||
} /* plugin_version */
|
||||
|
||||
struct PluginFeature *plugin_provides(void)
|
||||
{
|
||||
static struct PluginFeature features[] =
|
||||
{ {PLUGIN_NOTIFIER, N_("Log file")},
|
||||
{PLUGIN_NOTHING, NULL}};
|
||||
return features;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
Placeholder
|
106
src/plugins/notification/Makefile.am
Normal file
106
src/plugins/notification/Makefile.am
Normal file
|
@ -0,0 +1,106 @@
|
|||
if BUILD_HOTKEYS
|
||||
hotkey_lib = libcmnpgtkhotkey.la
|
||||
hotkey_lib_path = $(top_builddir)/src/plugins/notification/gtkhotkey/libcmnpgtkhotkey.la
|
||||
else
|
||||
hotkey_lib =
|
||||
hotkey_lib_path =
|
||||
endif
|
||||
|
||||
|
||||
EXTRA_DIST = claws.def plugin.def version.rc
|
||||
CFLAGS += "-Wall"
|
||||
|
||||
if OS_WIN32
|
||||
|
||||
LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RC) \
|
||||
`echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \
|
||||
sed -e 's/-I/--include-dir /g;s/-D/--define /g'`
|
||||
|
||||
%.lo : %.rc
|
||||
$(LTRCCOMPILE) -i $< -o $@
|
||||
|
||||
plugin_res = version.lo
|
||||
plugin_res_ldflag = -Wl,.libs/version.o
|
||||
|
||||
export_symbols = -export-symbols $(srcdir)/plugin.def
|
||||
|
||||
plugin_deps = libclaws.a $(plugin_res) plugin.def $(hotkey_lib)
|
||||
|
||||
libclaws.a: claws.def
|
||||
$(DLLTOOL) --output-lib $@ --def $<
|
||||
|
||||
plugin_ldadd = -L. -lclaws
|
||||
|
||||
else
|
||||
plugin_res =
|
||||
plugin_res_ldflag =
|
||||
export_symbols =
|
||||
plugin_deps =
|
||||
plugin_ldadd =
|
||||
endif
|
||||
|
||||
if PLATFORM_WIN32
|
||||
no_undefined = -no-undefined
|
||||
else
|
||||
no_undefined =
|
||||
endif
|
||||
|
||||
if CYGWIN
|
||||
cygwin_export_lib = -L$(top_builddir)/src -lclaws-mail
|
||||
else
|
||||
cygwin_export_lib =
|
||||
endif
|
||||
|
||||
plugindir = $(pkglibdir)/plugins
|
||||
|
||||
plugin_LTLIBRARIES = notification_plugin.la
|
||||
|
||||
notification_plugin_la_SOURCES = \
|
||||
gettext.h \
|
||||
notification_plugin.c notification_plugin.h \
|
||||
notification_core.c notification_core.h \
|
||||
notification_popup.c notification_popup.h \
|
||||
notification_banner.c notification_banner.h \
|
||||
notification_command.c notification_command.h \
|
||||
notification_lcdproc.c notification_lcdproc.h \
|
||||
notification_trayicon.c notification_trayicon.h \
|
||||
notification_indicator.c notification_indicator.h \
|
||||
notification_hotkeys.c notification_hotkeys.h \
|
||||
notification_prefs.c notification_prefs.h \
|
||||
notification_foldercheck.c notification_foldercheck.h \
|
||||
notification_pixbuf.c notification_pixbuf.h \
|
||||
raw_claws_mail_logo_64x64.h
|
||||
|
||||
notification_plugin_la_LDFLAGS = \
|
||||
$(plugin_res_ldflag) $(no_undefined) $(export_symbols) \
|
||||
-avoid-version -module
|
||||
|
||||
notification_plugin_la_DEPENDENCIES = $(plugin_deps) \
|
||||
$(hotkey_lib_path)
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src/plugins/notification/gtkhotkey \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/common \
|
||||
-I$(top_srcdir)/src/gtk
|
||||
|
||||
|
||||
notification_plugin_la_LIBADD = $(plugin_ldadd) $(cygwin_export_lib) \
|
||||
$(GTK_LIBS) \
|
||||
$(libnotify_LIBS) \
|
||||
$(libindicate_LIBS) \
|
||||
$(libcanberra_gtk_LIBS) \
|
||||
$(hotkey_lib_path)
|
||||
|
||||
notification_plugin_la_CPPFLAGS = \
|
||||
$(NOTIFY_CFLAGS) \
|
||||
$(CLAWS_MAIL_CFLAGS) \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(GTK_CFLAGS) \
|
||||
-DLOCALEDIR=\""$(localedir)"\" \
|
||||
$(libnotify_CFLAGS) \
|
||||
$(libindicate_CFLAGS) \
|
||||
$(libcanberra_gtk_CFLAGS)
|
||||
|
||||
clean-local:
|
||||
rm -f libclaws.a
|
73
src/plugins/notification/claws.def
Normal file
73
src/plugins/notification/claws.def
Normal file
|
@ -0,0 +1,73 @@
|
|||
LIBRARY CLAWS-MAIL.EXE
|
||||
EXPORTS
|
||||
get_locale_dir
|
||||
check_plugin_version
|
||||
debug_print_real
|
||||
debug_srcname
|
||||
hooks_register_hook
|
||||
hooks_unregister_hook
|
||||
account_get_list
|
||||
addressbook_open
|
||||
alertpanel
|
||||
app_will_exit
|
||||
claws_is_exiting
|
||||
claws_is_starting
|
||||
compose_mail_cb
|
||||
compose_new
|
||||
compose_reply_from_messageview
|
||||
execute_command_line
|
||||
file_exist
|
||||
folder_find_item_from_identifier
|
||||
folder_func_to_all_folders
|
||||
folder_get_list
|
||||
folder_has_parent_of_type
|
||||
folder_item_get_identifier
|
||||
folder_item_get_msg_list
|
||||
folder_item_get_name
|
||||
get_rc_dir
|
||||
gtkut_convert_int_to_gdk_color
|
||||
gtkut_stock_button_set_create
|
||||
gtkut_window_new
|
||||
inc_all_account_mail_cb
|
||||
main_set_show_at_startup
|
||||
mainwindow_get_mainwindow
|
||||
main_window_hide
|
||||
main_window_empty_trash
|
||||
mainwindow_is_obscured
|
||||
mainwindow_jump_to
|
||||
main_window_show
|
||||
main_window_toggle_work_offline
|
||||
manage_window_destroy
|
||||
manage_window_focus_in
|
||||
manage_window_focus_out
|
||||
manage_window_set_transient
|
||||
manage_window_unmap
|
||||
cm_menu_create_action_group_full
|
||||
gtkut_ui_manager
|
||||
cm_menu_create_action_group
|
||||
cm_toggle_menu_set_active
|
||||
cm_menu_set_sensitive
|
||||
prefs_common_get_prefs
|
||||
prefs_common_translated_header_name
|
||||
prefs_file_close
|
||||
prefs_file_close_revert
|
||||
prefs_gtk_register_page
|
||||
prefs_gtk_unregister_page
|
||||
prefs_read_config
|
||||
prefs_set_block_label
|
||||
prefs_set_default
|
||||
prefs_write_open
|
||||
prefs_write_param
|
||||
procmsg_get_message_file_path
|
||||
procmsg_msg_list_free
|
||||
stock_pixbuf_gdk
|
||||
stock_pixbuf_gdk follow
|
||||
strcmp2
|
||||
xml_attr_new
|
||||
xml_file_put_xml_decl
|
||||
xml_free_tree
|
||||
xml_node_new
|
||||
xml_parse_file
|
||||
xml_tag_add_attr
|
||||
xml_tag_new
|
||||
xml_write_tree
|
503
src/plugins/notification/notification_banner.c
Normal file
503
src/plugins/notification/notification_banner.c
Normal file
|
@ -0,0 +1,503 @@
|
|||
/* Notification plugin for Claws Mail
|
||||
* Copyright (C) 2005-2008 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gtk/gtkutils.h"
|
||||
|
||||
#include "prefs_common.h"
|
||||
#include "mainwindow.h"
|
||||
#include "menu.h"
|
||||
#include "procmsg.h"
|
||||
#include "messageview.h"
|
||||
#include "compose.h"
|
||||
#include "menu.h"
|
||||
|
||||
#include "notification_core.h"
|
||||
#include "notification_prefs.h"
|
||||
#include "notification_banner.h"
|
||||
|
||||
typedef struct {
|
||||
GtkWidget *table;
|
||||
} NotificationBannerEntry;
|
||||
|
||||
typedef struct {
|
||||
GtkWidget *window;
|
||||
GtkWidget *scrolled_win;
|
||||
GtkWidget *viewport;
|
||||
|
||||
NotificationBannerEntry *entries;
|
||||
guint timeout_id;
|
||||
gboolean scrolling;
|
||||
} NotificationBanner;
|
||||
|
||||
typedef struct {
|
||||
gint banner_width;
|
||||
GtkAdjustment *adj;
|
||||
} ScrollingData;
|
||||
|
||||
|
||||
static void notification_banner_create(GSList*);
|
||||
static gboolean scroller(gpointer data);
|
||||
static GtkWidget* create_entrybox(GSList*);
|
||||
static gboolean notification_banner_configure(GtkWidget*, GdkEventConfigure*,
|
||||
gpointer);
|
||||
static gboolean notification_banner_swap_colors(GtkWidget*,GdkEventCrossing*,gpointer);
|
||||
static gboolean notification_banner_button_press(GtkWidget*,GdkEventButton*,gpointer);
|
||||
static void notification_banner_show_popup(GtkWidget*,GdkEventButton*);
|
||||
static void notification_banner_popup_done(GtkMenuShell*,gpointer);
|
||||
|
||||
static void banner_menu_reply_cb(GtkAction *,gpointer);
|
||||
|
||||
|
||||
static NotificationBanner banner;
|
||||
static ScrollingData sdata;
|
||||
|
||||
static GtkWidget *banner_popup;
|
||||
static GtkUIManager *banner_ui_manager;
|
||||
static GtkActionGroup *banner_action_group;
|
||||
|
||||
static gboolean banner_popup_open = FALSE;
|
||||
|
||||
static MsgInfo *current_msginfo = NULL;
|
||||
|
||||
/* Corresponding mutexes */
|
||||
G_LOCK_DEFINE_STATIC(banner);
|
||||
G_LOCK_DEFINE_STATIC(sdata);
|
||||
|
||||
static GtkActionEntry banner_popup_entries[] =
|
||||
{
|
||||
{"BannerPopup", NULL, "BannerPopup" },
|
||||
{"BannerPopup/Reply", NULL, N_("_Reply"), NULL, NULL, G_CALLBACK(banner_menu_reply_cb) },
|
||||
};
|
||||
|
||||
|
||||
void notification_banner_show(GSList *msg_list)
|
||||
{
|
||||
G_LOCK(banner);
|
||||
if((notify_config.banner_show != NOTIFY_BANNER_SHOW_NEVER) &&
|
||||
(g_slist_length(msg_list) ||
|
||||
(notify_config.banner_show == NOTIFY_BANNER_SHOW_ALWAYS)))
|
||||
notification_banner_create(msg_list);
|
||||
else
|
||||
notification_banner_destroy();
|
||||
G_UNLOCK(banner);
|
||||
}
|
||||
|
||||
void notification_banner_destroy(void)
|
||||
{
|
||||
if(banner.window) {
|
||||
if(banner.entries) {
|
||||
g_free(banner.entries);
|
||||
banner.entries = NULL;
|
||||
}
|
||||
gtk_widget_destroy(banner.window);
|
||||
banner.window = NULL;
|
||||
G_LOCK(sdata);
|
||||
sdata.adj = NULL;
|
||||
sdata.banner_width = 0;
|
||||
G_UNLOCK(sdata);
|
||||
if(banner.timeout_id) {
|
||||
g_source_remove(banner.timeout_id);
|
||||
banner.timeout_id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void notification_banner_create(GSList *msg_list)
|
||||
{
|
||||
GtkRequisition requisition, requisition_after;
|
||||
GtkWidget *viewport;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *entrybox;
|
||||
GdkColor bg;
|
||||
gint banner_width;
|
||||
|
||||
/* Window */
|
||||
if(!banner.window) {
|
||||
|
||||
banner.window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "notification_banner");
|
||||
gtk_window_set_decorated(GTK_WINDOW(banner.window), FALSE);
|
||||
if(notify_config.banner_width > 0)
|
||||
gtk_widget_set_size_request(banner.window, notify_config.banner_width, -1);
|
||||
else
|
||||
gtk_widget_set_size_request(banner.window, gdk_screen_width(), -1);
|
||||
gtk_window_set_keep_above(GTK_WINDOW(banner.window), TRUE);
|
||||
gtk_window_set_accept_focus(GTK_WINDOW(banner.window), FALSE);
|
||||
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(banner.window), TRUE);
|
||||
gtk_window_move(GTK_WINDOW(banner.window),
|
||||
notify_config.banner_root_x, notify_config.banner_root_y);
|
||||
g_signal_connect(banner.window, "configure-event",
|
||||
G_CALLBACK(notification_banner_configure), NULL);
|
||||
}
|
||||
else {
|
||||
if(banner.entries) {
|
||||
g_free(banner.entries);
|
||||
banner.entries = NULL;
|
||||
}
|
||||
gtk_widget_destroy(banner.scrolled_win);
|
||||
}
|
||||
if(notify_config.banner_sticky)
|
||||
gtk_window_stick(GTK_WINDOW(banner.window));
|
||||
else
|
||||
gtk_window_unstick(GTK_WINDOW(banner.window));
|
||||
|
||||
/* Scrolled window */
|
||||
banner.scrolled_win = gtk_scrolled_window_new(NULL, NULL);
|
||||
gtk_container_add(GTK_CONTAINER(banner.window), banner.scrolled_win);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(banner.scrolled_win),
|
||||
GTK_POLICY_NEVER, GTK_POLICY_NEVER);
|
||||
|
||||
/* Viewport */
|
||||
viewport = gtk_viewport_new(NULL,NULL);
|
||||
banner.viewport = viewport;
|
||||
gtk_container_add(GTK_CONTAINER(banner.scrolled_win),viewport);
|
||||
if(notify_config.banner_enable_colors) {
|
||||
gtkut_convert_int_to_gdk_color(notify_config.banner_color_bg,&bg);
|
||||
gtk_widget_modify_bg(viewport,GTK_STATE_NORMAL,&bg);
|
||||
}
|
||||
|
||||
/* Hbox */
|
||||
hbox = gtk_hbox_new(FALSE, 5);
|
||||
gtk_container_add(GTK_CONTAINER(viewport),hbox);
|
||||
|
||||
/* Entrybox */
|
||||
entrybox = create_entrybox(msg_list);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), entrybox, FALSE, FALSE, 0);
|
||||
|
||||
gtk_widget_show_all(banner.window);
|
||||
|
||||
/* Scrolling */
|
||||
gtk_widget_size_request(hbox, &requisition);
|
||||
if(notify_config.banner_width > 0)
|
||||
banner_width = notify_config.banner_width;
|
||||
else
|
||||
banner_width = gdk_screen_width();
|
||||
if(requisition.width > banner_width) {
|
||||
/* Line is too big for screen! */
|
||||
/* Double the entrybox into hbox */
|
||||
GtkWidget *separator, *second_entrybox;
|
||||
|
||||
separator = gtk_vseparator_new();
|
||||
gtk_box_pack_start(GTK_BOX(hbox), separator,
|
||||
FALSE, FALSE, 0);
|
||||
second_entrybox = create_entrybox(msg_list);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), second_entrybox, FALSE, FALSE, 0);
|
||||
|
||||
gtk_widget_show_all(banner.window);
|
||||
gtk_widget_size_request(hbox, &requisition_after);
|
||||
|
||||
G_LOCK(sdata);
|
||||
sdata.banner_width = requisition_after.width - requisition.width;
|
||||
sdata.adj =
|
||||
gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW
|
||||
(banner.scrolled_win));
|
||||
G_UNLOCK(sdata);
|
||||
|
||||
banner.scrolling = TRUE;
|
||||
if(banner.timeout_id) {
|
||||
g_source_remove(banner.timeout_id);
|
||||
banner.timeout_id = 0;
|
||||
}
|
||||
banner.timeout_id =
|
||||
g_timeout_add(notify_config.banner_speed, scroller, NULL);
|
||||
}
|
||||
else {
|
||||
banner.scrolling = FALSE;
|
||||
if(banner.timeout_id) {
|
||||
g_source_remove(banner.timeout_id);
|
||||
banner.timeout_id = 0;
|
||||
}
|
||||
G_LOCK(sdata);
|
||||
sdata.banner_width = 0;
|
||||
sdata.adj = NULL;
|
||||
G_UNLOCK(sdata);
|
||||
}
|
||||
|
||||
/* menu */
|
||||
banner_ui_manager = gtk_ui_manager_new();
|
||||
banner_action_group = cm_menu_create_action_group_full(banner_ui_manager,"BannerPopup", banner_popup_entries,
|
||||
G_N_ELEMENTS(banner_popup_entries), (gpointer)NULL);
|
||||
MENUITEM_ADDUI_MANAGER(banner_ui_manager, "/", "Menus", "Menus", GTK_UI_MANAGER_MENUBAR)
|
||||
MENUITEM_ADDUI_MANAGER(banner_ui_manager, "/Menus", "BannerPopup", "BannerPopup", GTK_UI_MANAGER_MENU)
|
||||
MENUITEM_ADDUI_MANAGER(banner_ui_manager, "/Menus/BannerPopup", "Reply", "BannerPopup/Reply", GTK_UI_MANAGER_MENUITEM)
|
||||
|
||||
banner_popup = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
|
||||
gtk_ui_manager_get_widget(banner_ui_manager, "/Menus/BannerPopup")) );
|
||||
g_signal_connect(banner_popup,"selection-done",
|
||||
G_CALLBACK(notification_banner_popup_done), NULL);
|
||||
}
|
||||
|
||||
static gboolean notification_banner_configure(GtkWidget *widget,
|
||||
GdkEventConfigure *event,
|
||||
gpointer data)
|
||||
{
|
||||
gtk_window_get_position(GTK_WINDOW(gtk_widget_get_toplevel(widget)),
|
||||
&(notify_config.banner_root_x),
|
||||
&(notify_config.banner_root_y));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean scroller(gpointer data)
|
||||
{
|
||||
// don't scroll during popup open
|
||||
if(banner_popup_open)
|
||||
return banner.scrolling;
|
||||
|
||||
while(gtk_events_pending())
|
||||
gtk_main_iteration();
|
||||
G_LOCK(sdata);
|
||||
if(sdata.adj && GTK_IS_ADJUSTMENT(sdata.adj)) {
|
||||
if(sdata.adj->value != sdata.banner_width)
|
||||
gtk_adjustment_set_value(sdata.adj, sdata.adj->value + 1);
|
||||
else
|
||||
gtk_adjustment_set_value(sdata.adj, 0);
|
||||
gtk_adjustment_value_changed(sdata.adj);
|
||||
}
|
||||
G_UNLOCK(sdata);
|
||||
while(gtk_events_pending())
|
||||
gtk_main_iteration();
|
||||
return banner.scrolling;
|
||||
}
|
||||
|
||||
static GtkWidget* create_entrybox(GSList *msg_list)
|
||||
{
|
||||
GtkWidget *entrybox;
|
||||
GdkColor fg;
|
||||
GdkColor bg;
|
||||
gint list_length;
|
||||
|
||||
list_length = g_slist_length(msg_list);
|
||||
|
||||
if(notify_config.banner_enable_colors) {
|
||||
gtkut_convert_int_to_gdk_color(notify_config.banner_color_bg,&bg);
|
||||
gtkut_convert_int_to_gdk_color(notify_config.banner_color_fg,&fg);
|
||||
}
|
||||
|
||||
if(banner.entries) {
|
||||
g_free(banner.entries);
|
||||
banner.entries = NULL;
|
||||
}
|
||||
|
||||
entrybox = gtk_hbox_new(FALSE, 5);
|
||||
if(list_length) {
|
||||
GSList *walk;
|
||||
gint ii = 0;
|
||||
banner.entries = g_new(NotificationBannerEntry, list_length);
|
||||
for(walk = msg_list; walk != NULL; walk = g_slist_next(walk)) {
|
||||
GtkWidget *label1;
|
||||
GtkWidget *label2;
|
||||
GtkWidget *label3;
|
||||
GtkWidget *label4;
|
||||
GtkWidget *label5;
|
||||
GtkWidget *label6;
|
||||
GtkWidget *ebox;
|
||||
CollectedMsg *cmsg = walk->data;
|
||||
|
||||
if(ii > 0) {
|
||||
GtkWidget *separator;
|
||||
separator = gtk_vseparator_new();
|
||||
gtk_box_pack_start(GTK_BOX(entrybox), separator, FALSE, FALSE, 0);
|
||||
}
|
||||
|
||||
ebox = gtk_event_box_new();
|
||||
gtk_box_pack_start(GTK_BOX(entrybox), ebox, FALSE, FALSE, 0);
|
||||
gtk_widget_set_events(ebox,
|
||||
GDK_POINTER_MOTION_MASK |
|
||||
GDK_BUTTON_PRESS_MASK);
|
||||
|
||||
if(notify_config.banner_enable_colors)
|
||||
gtk_widget_modify_bg(ebox,GTK_STATE_NORMAL,&bg);
|
||||
|
||||
banner.entries[ii].table = gtk_table_new(3, 2, FALSE);
|
||||
gtk_container_add(GTK_CONTAINER(ebox),banner.entries[ii].table);
|
||||
g_signal_connect(ebox, "enter-notify-event",
|
||||
G_CALLBACK(notification_banner_swap_colors),
|
||||
banner.entries[ii].table);
|
||||
g_signal_connect(ebox, "leave-notify-event",
|
||||
G_CALLBACK(notification_banner_swap_colors),
|
||||
banner.entries[ii].table);
|
||||
g_signal_connect(ebox, "button-press-event",
|
||||
G_CALLBACK(notification_banner_button_press),
|
||||
cmsg);
|
||||
|
||||
label1 = gtk_label_new(prefs_common_translated_header_name("From:"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label1), 0, 0.5);
|
||||
gtk_table_attach_defaults(GTK_TABLE(banner.entries[ii].table),
|
||||
label1, 0, 1, 0, 1);
|
||||
label2 = gtk_label_new(prefs_common_translated_header_name("Subject:"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label2), 0, 0.5);
|
||||
gtk_table_attach_defaults(GTK_TABLE(banner.entries[ii].table),
|
||||
label2, 0, 1, 1, 2);
|
||||
label3 = gtk_label_new(_("Folder:"));
|
||||
gtk_misc_set_alignment(GTK_MISC(label3), 0, 0.5);
|
||||
gtk_table_attach_defaults(GTK_TABLE(banner.entries[ii].table),
|
||||
label3, 0, 1, 2, 3);
|
||||
|
||||
label4 = gtk_label_new(cmsg->from);
|
||||
gtk_misc_set_alignment(GTK_MISC(label4), 0, 0.5);
|
||||
gtk_table_attach_defaults(GTK_TABLE(banner.entries[ii].table),
|
||||
label4, 1, 2, 0, 1);
|
||||
label5 = gtk_label_new(cmsg->subject);
|
||||
gtk_misc_set_alignment(GTK_MISC(label5), 0, 0.5);
|
||||
gtk_table_attach_defaults(GTK_TABLE(banner.entries[ii].table),
|
||||
label5, 1, 2, 1, 2);
|
||||
label6 = gtk_label_new(cmsg->folderitem_name);
|
||||
gtk_misc_set_alignment(GTK_MISC(label6), 0, 0.5);
|
||||
gtk_table_attach_defaults(GTK_TABLE(banner.entries[ii].table),
|
||||
label6, 1, 2, 2, 3);
|
||||
gtk_table_set_col_spacings(GTK_TABLE(banner.entries[ii].table), 5);
|
||||
ii++;
|
||||
/* Color */
|
||||
if(notify_config.banner_enable_colors) {
|
||||
gtk_widget_modify_fg(label1,GTK_STATE_NORMAL,&fg);
|
||||
gtk_widget_modify_fg(label2,GTK_STATE_NORMAL,&fg);
|
||||
gtk_widget_modify_fg(label3,GTK_STATE_NORMAL,&fg);
|
||||
gtk_widget_modify_fg(label4,GTK_STATE_NORMAL,&fg);
|
||||
gtk_widget_modify_fg(label5,GTK_STATE_NORMAL,&fg);
|
||||
gtk_widget_modify_fg(label6,GTK_STATE_NORMAL,&fg);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* We have an empty list -- create an empty dummy element */
|
||||
GtkWidget *label;
|
||||
|
||||
banner.entries = g_new(NotificationBannerEntry, 1);
|
||||
banner.entries[0].table = gtk_table_new(3, 1, FALSE);
|
||||
label = gtk_label_new("");
|
||||
gtk_table_attach_defaults(GTK_TABLE(banner.entries[0].table),
|
||||
label, 0, 1, 0, 1);
|
||||
label = gtk_label_new("");
|
||||
gtk_table_attach_defaults(GTK_TABLE(banner.entries[0].table),
|
||||
label, 0, 1, 1, 2);
|
||||
label = gtk_label_new("");
|
||||
gtk_table_attach_defaults(GTK_TABLE(banner.entries[0].table),
|
||||
label, 0, 1, 2, 3);
|
||||
gtk_box_pack_start(GTK_BOX(entrybox), banner.entries[0].table,
|
||||
FALSE, FALSE, 0);
|
||||
}
|
||||
return entrybox;
|
||||
}
|
||||
|
||||
static gboolean notification_banner_swap_colors(GtkWidget *widget,
|
||||
GdkEventCrossing *event,
|
||||
gpointer data)
|
||||
{
|
||||
GList *children;
|
||||
GList *walk;
|
||||
GdkColor *old_bg;
|
||||
|
||||
children = gtk_container_get_children(GTK_CONTAINER(data));
|
||||
|
||||
old_bg = gdk_color_copy(&(gtk_widget_get_style(widget)->bg[GTK_STATE_NORMAL]));
|
||||
if(children)
|
||||
gtk_widget_modify_bg(widget,GTK_STATE_NORMAL,
|
||||
&(gtk_widget_get_style(GTK_WIDGET(children->data))->fg[GTK_STATE_NORMAL]));
|
||||
|
||||
for(walk = children; walk; walk = walk->next)
|
||||
gtk_widget_modify_fg(GTK_WIDGET(walk->data),GTK_STATE_NORMAL,old_bg);
|
||||
|
||||
g_list_free(children);
|
||||
gdk_color_free(old_bg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean notification_banner_button_press(GtkWidget *widget,
|
||||
GdkEventButton *button,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean done;
|
||||
done = FALSE;
|
||||
if(button->type == GDK_BUTTON_PRESS) {
|
||||
CollectedMsg *cmsg = (CollectedMsg*) data;
|
||||
if(button->button == 1) {
|
||||
/* jump to that message */
|
||||
if(cmsg->msginfo) {
|
||||
gchar *path;
|
||||
path = procmsg_get_message_file_path(cmsg->msginfo);
|
||||
mainwindow_jump_to(path, TRUE);
|
||||
g_free(path);
|
||||
}
|
||||
done = TRUE;
|
||||
}
|
||||
else if(button->button == 2) {
|
||||
gtk_window_begin_move_drag(GTK_WINDOW(gtk_widget_get_toplevel(widget)),
|
||||
button->button, button->x_root, button->y_root,
|
||||
button->time);
|
||||
}
|
||||
else if(button->button == 3) {
|
||||
current_msginfo = cmsg->msginfo;
|
||||
notification_banner_show_popup(widget, button);
|
||||
banner_popup_open = TRUE;
|
||||
done = TRUE;
|
||||
}
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
static void notification_banner_show_popup(GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
int button, event_time;
|
||||
|
||||
if(event) {
|
||||
button = event->button;
|
||||
event_time = event->time;
|
||||
}
|
||||
else {
|
||||
button = 0;
|
||||
event_time = gtk_get_current_event_time();
|
||||
}
|
||||
|
||||
gtk_menu_popup(GTK_MENU(banner_popup), NULL, NULL, NULL, NULL,
|
||||
button, event_time);
|
||||
}
|
||||
|
||||
static void notification_banner_popup_done(GtkMenuShell *menushell,
|
||||
gpointer user_data)
|
||||
{
|
||||
current_msginfo = NULL;
|
||||
banner_popup_open = FALSE;
|
||||
}
|
||||
|
||||
static void banner_menu_reply_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
MainWindow *mainwin;
|
||||
MessageView *messageview;
|
||||
GSList *msginfo_list = NULL;
|
||||
|
||||
if(!(mainwin = mainwindow_get_mainwindow()))
|
||||
return;
|
||||
|
||||
if(!(messageview = (MessageView*)mainwin->messageview))
|
||||
return;
|
||||
|
||||
g_return_if_fail(current_msginfo);
|
||||
|
||||
msginfo_list = g_slist_prepend(msginfo_list, current_msginfo);
|
||||
compose_reply_from_messageview(messageview, msginfo_list,
|
||||
prefs_common_get_prefs()->reply_with_quote ?
|
||||
COMPOSE_REPLY_WITH_QUOTE : COMPOSE_REPLY_WITHOUT_QUOTE);
|
||||
g_slist_free(msginfo_list);
|
||||
}
|
||||
|
||||
#endif /* NOTIFICATION_BANNER */
|
32
src/plugins/notification/notification_banner.h
Normal file
32
src/plugins/notification/notification_banner.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_BANNER_H
|
||||
#define NOTIFICATION_BANNER_H NOTIFICATION_BANNER_H
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
|
||||
#define BANNER_SPECIFIC_FOLDER_ID_STR "banner"
|
||||
|
||||
void notification_banner_show(GSList*);
|
||||
void notification_banner_destroy(void);
|
||||
|
||||
#endif /* NOTIFICATION_BANNER */
|
||||
|
||||
#endif /* NOTIFICATION_BANNER_H */
|
119
src/plugins/notification/notification_command.c
Normal file
119
src/plugins/notification/notification_command.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_COMMAND
|
||||
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
#include "common/utils.h"
|
||||
#include "folder.h"
|
||||
#include "notification_command.h"
|
||||
#include "notification_prefs.h"
|
||||
#include "notification_foldercheck.h"
|
||||
|
||||
typedef struct {
|
||||
gboolean blocked;
|
||||
guint timeout_id;
|
||||
} NotificationCommand;
|
||||
|
||||
static gboolean command_timeout_fun(gpointer data);
|
||||
|
||||
static NotificationCommand command;
|
||||
|
||||
G_LOCK_DEFINE_STATIC(command);
|
||||
|
||||
void notification_command_msg(MsgInfo *msginfo)
|
||||
{
|
||||
gchar *ret_str, *buf;
|
||||
gsize by_read = 0, by_written = 0;
|
||||
FolderType ftype;
|
||||
|
||||
if(!msginfo || !notify_config.command_enabled || !MSG_IS_NEW(msginfo->flags))
|
||||
return;
|
||||
|
||||
if(!notify_config.command_enabled || !MSG_IS_NEW(msginfo->flags))
|
||||
return;
|
||||
|
||||
if(notify_config.command_folder_specific) {
|
||||
guint id;
|
||||
GSList *list;
|
||||
gchar *identifier;
|
||||
gboolean found = FALSE;
|
||||
|
||||
if(!(msginfo->folder))
|
||||
return;
|
||||
|
||||
identifier = folder_item_get_identifier(msginfo->folder);
|
||||
|
||||
id =
|
||||
notification_register_folder_specific_list(COMMAND_SPECIFIC_FOLDER_ID_STR);
|
||||
list = notification_foldercheck_get_list(id);
|
||||
for(; (list != NULL) && !found; list = g_slist_next(list)) {
|
||||
gchar *list_identifier;
|
||||
FolderItem *list_item = (FolderItem*) list->data;
|
||||
|
||||
list_identifier = folder_item_get_identifier(list_item);
|
||||
if(!strcmp2(list_identifier, identifier))
|
||||
found = TRUE;
|
||||
|
||||
g_free(list_identifier);
|
||||
}
|
||||
g_free(identifier);
|
||||
|
||||
if(!found)
|
||||
return;
|
||||
} /* folder specific */
|
||||
|
||||
ftype = msginfo->folder->folder->klass->type;
|
||||
|
||||
buf = g_strdup(notify_config.command_line);
|
||||
|
||||
G_LOCK(command);
|
||||
|
||||
if(!command.blocked) {
|
||||
/* execute command */
|
||||
command.blocked = TRUE;
|
||||
ret_str = g_locale_from_utf8(buf,strlen(buf),&by_read,&by_written,NULL);
|
||||
if(ret_str && by_written) {
|
||||
g_free(buf);
|
||||
buf = ret_str;
|
||||
}
|
||||
execute_command_line(buf, TRUE);
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
/* block further execution for some time,
|
||||
no matter if it was blocked or not */
|
||||
if(command.timeout_id)
|
||||
g_source_remove(command.timeout_id);
|
||||
command.timeout_id = g_timeout_add(notify_config.command_timeout,
|
||||
command_timeout_fun, NULL);
|
||||
G_UNLOCK(command);
|
||||
}
|
||||
|
||||
static gboolean command_timeout_fun(gpointer data)
|
||||
{
|
||||
G_LOCK(command);
|
||||
command.timeout_id = 0;
|
||||
command.blocked = FALSE;
|
||||
G_UNLOCK(command);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif /* NOTIFICATION_COMMAND */
|
33
src/plugins/notification/notification_command.h
Normal file
33
src/plugins/notification/notification_command.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_COMMAND_H
|
||||
#define NOTIFICATION_COMMAND_H NOTIFICATION_COMMAND_H
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_COMMAND
|
||||
|
||||
#include "procmsg.h"
|
||||
|
||||
#define COMMAND_SPECIFIC_FOLDER_ID_STR "command"
|
||||
|
||||
void notification_command_msg(MsgInfo*);
|
||||
|
||||
#endif /* NOTIFICATION_COMMAND */
|
||||
|
||||
#endif /* include guard */
|
699
src/plugins/notification/notification_core.c
Normal file
699
src/plugins/notification/notification_core.c
Normal file
|
@ -0,0 +1,699 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#include "folder.h"
|
||||
#include "folderview.h"
|
||||
#include "codeconv.h"
|
||||
#include "gtk/gtkutils.h"
|
||||
|
||||
#include "notification_core.h"
|
||||
#include "notification_plugin.h"
|
||||
#include "notification_prefs.h"
|
||||
#include "notification_banner.h"
|
||||
#include "notification_popup.h"
|
||||
#include "notification_command.h"
|
||||
#include "notification_lcdproc.h"
|
||||
#include "notification_trayicon.h"
|
||||
#include "notification_indicator.h"
|
||||
|
||||
#ifdef HAVE_LIBCANBERRA_GTK
|
||||
# include <canberra-gtk.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
GSList *collected_msgs;
|
||||
GSList *folder_items;
|
||||
gboolean unread_also;
|
||||
gint max_msgs;
|
||||
gint num_msgs;
|
||||
} TraverseCollect;
|
||||
|
||||
static gboolean notification_traverse_collect(GNode*, gpointer);
|
||||
static void notification_new_unnotified_do_msg(MsgInfo*);
|
||||
static gboolean notification_traverse_hash_startup(GNode*, gpointer);
|
||||
|
||||
static GHashTable *msg_count_hash;
|
||||
static NotificationMsgCount msg_count;
|
||||
|
||||
#ifdef HAVE_LIBCANBERRA_GTK
|
||||
static gboolean canberra_new_email_is_playing = FALSE;
|
||||
#endif
|
||||
|
||||
static void msg_count_hash_update_func(FolderItem*, gpointer);
|
||||
static void msg_count_update_from_hash(gpointer, gpointer, gpointer);
|
||||
static void msg_count_clear(NotificationMsgCount*);
|
||||
static void msg_count_add(NotificationMsgCount*,NotificationMsgCount*);
|
||||
static void msg_count_copy(NotificationMsgCount*,NotificationMsgCount*);
|
||||
|
||||
void notification_core_global_includes_changed(void)
|
||||
{
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
notification_update_banner();
|
||||
#endif
|
||||
|
||||
if(msg_count_hash) {
|
||||
g_hash_table_destroy(msg_count_hash);
|
||||
msg_count_hash = NULL;
|
||||
}
|
||||
notification_update_msg_counts(NULL);
|
||||
}
|
||||
|
||||
/* Hide/show main window */
|
||||
void notification_toggle_hide_show_window(void)
|
||||
{
|
||||
MainWindow *mainwin;
|
||||
if((mainwin = mainwindow_get_mainwindow()) == NULL)
|
||||
return;
|
||||
|
||||
if(gtk_widget_get_visible(GTK_WIDGET(mainwin->window))) {
|
||||
if((gdk_window_get_state(GTK_WIDGET(mainwin->window)->window)&GDK_WINDOW_STATE_ICONIFIED)
|
||||
|| mainwindow_is_obscured()) {
|
||||
notification_show_mainwindow(mainwin);
|
||||
}
|
||||
else {
|
||||
main_window_hide(mainwin);
|
||||
}
|
||||
}
|
||||
else {
|
||||
notification_show_mainwindow(mainwin);
|
||||
}
|
||||
}
|
||||
|
||||
void notification_update_msg_counts(FolderItem *removed_item)
|
||||
{
|
||||
if(!msg_count_hash)
|
||||
msg_count_hash = g_hash_table_new_full(g_str_hash,g_str_equal,
|
||||
g_free,g_free);
|
||||
|
||||
folder_func_to_all_folders(msg_count_hash_update_func, msg_count_hash);
|
||||
|
||||
if(removed_item) {
|
||||
gchar *identifier;
|
||||
identifier = folder_item_get_identifier(removed_item);
|
||||
if(identifier) {
|
||||
g_hash_table_remove(msg_count_hash, identifier);
|
||||
g_free(identifier);
|
||||
}
|
||||
}
|
||||
msg_count_clear(&msg_count);
|
||||
g_hash_table_foreach(msg_count_hash, msg_count_update_from_hash, NULL);
|
||||
#ifdef NOTIFICATION_LCDPROC
|
||||
notification_update_lcdproc();
|
||||
#endif
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
notification_update_trayicon();
|
||||
#endif
|
||||
#ifdef NOTIFICATION_INDICATOR
|
||||
notification_update_indicator();
|
||||
#endif
|
||||
notification_update_urgency_hint();
|
||||
}
|
||||
|
||||
static void msg_count_clear(NotificationMsgCount *count)
|
||||
{
|
||||
count->new_msgs = 0;
|
||||
count->unread_msgs = 0;
|
||||
count->unreadmarked_msgs = 0;
|
||||
count->marked_msgs = 0;
|
||||
count->total_msgs = 0;
|
||||
}
|
||||
|
||||
/* c1 += c2 */
|
||||
static void msg_count_add(NotificationMsgCount *c1,NotificationMsgCount *c2)
|
||||
{
|
||||
c1->new_msgs += c2->new_msgs;
|
||||
c1->unread_msgs += c2->unread_msgs;
|
||||
c1->unreadmarked_msgs += c2->unreadmarked_msgs;
|
||||
c1->marked_msgs += c2->marked_msgs;
|
||||
c1->total_msgs += c2->total_msgs;
|
||||
}
|
||||
|
||||
/* c1 = c2 */
|
||||
static void msg_count_copy(NotificationMsgCount *c1,NotificationMsgCount *c2)
|
||||
{
|
||||
c1->new_msgs = c2->new_msgs;
|
||||
c1->unread_msgs = c2->unread_msgs;
|
||||
c1->unreadmarked_msgs = c2->unreadmarked_msgs;
|
||||
c1->marked_msgs = c2->marked_msgs;
|
||||
c1->total_msgs = c2->total_msgs;
|
||||
}
|
||||
|
||||
gboolean get_flat_gslist_from_nodes_traverse_func(GNode *node, gpointer data)
|
||||
{
|
||||
if(node->data) {
|
||||
GSList **list = data;
|
||||
*list = g_slist_prepend(*list, node->data);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GSList* get_flat_gslist_from_nodes(GNode *node)
|
||||
{
|
||||
GSList *retval = NULL;
|
||||
|
||||
g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, get_flat_gslist_from_nodes_traverse_func, &retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void notification_core_get_msg_count_of_foldername(gchar *foldername, NotificationMsgCount *count)
|
||||
{
|
||||
GList *list;
|
||||
Folder *walk_folder;
|
||||
Folder *folder = NULL;
|
||||
|
||||
for(list = folder_get_list(); list != NULL; list = list->next) {
|
||||
walk_folder = list->data;
|
||||
if(strcmp2(foldername, walk_folder->name) == 0) {
|
||||
folder = walk_folder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!folder) {
|
||||
debug_print("Notification plugin: Error: Could not find folder %s\n", foldername);
|
||||
return;
|
||||
}
|
||||
|
||||
msg_count_clear(count);
|
||||
notification_core_get_msg_count(get_flat_gslist_from_nodes(folder->node), count);
|
||||
}
|
||||
|
||||
void notification_core_get_msg_count(GSList *folder_list,
|
||||
NotificationMsgCount *count)
|
||||
{
|
||||
GSList *walk;
|
||||
|
||||
if(!folder_list)
|
||||
msg_count_copy(count,&msg_count);
|
||||
else {
|
||||
msg_count_clear(count);
|
||||
for(walk = folder_list; walk; walk = walk->next) {
|
||||
gchar *identifier;
|
||||
NotificationMsgCount *item_count;
|
||||
FolderItem *item = (FolderItem*) walk->data;
|
||||
identifier = folder_item_get_identifier(item);
|
||||
if(identifier) {
|
||||
item_count = g_hash_table_lookup(msg_count_hash,identifier);
|
||||
g_free(identifier);
|
||||
if(item_count)
|
||||
msg_count_add(count, item_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void msg_count_hash_update_func(FolderItem *item, gpointer data)
|
||||
{
|
||||
gchar *identifier;
|
||||
NotificationMsgCount *count;
|
||||
GHashTable *hash = data;
|
||||
|
||||
if(!notify_include_folder_type(item->folder->klass->type,
|
||||
item->folder->klass->uistr))
|
||||
return;
|
||||
|
||||
identifier = folder_item_get_identifier(item);
|
||||
if(!identifier)
|
||||
return;
|
||||
|
||||
count = g_hash_table_lookup(hash, identifier);
|
||||
|
||||
if(!count) {
|
||||
count = g_new0(NotificationMsgCount,1);
|
||||
g_hash_table_insert(hash, identifier, count);
|
||||
}
|
||||
else
|
||||
g_free(identifier);
|
||||
|
||||
count->new_msgs = item->new_msgs;
|
||||
count->unread_msgs = item->unread_msgs;
|
||||
count->unreadmarked_msgs = item->unreadmarked_msgs;
|
||||
count->marked_msgs = item->marked_msgs;
|
||||
count->total_msgs = item->total_msgs;
|
||||
}
|
||||
|
||||
static void msg_count_update_from_hash(gpointer key, gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
NotificationMsgCount *count = value;
|
||||
msg_count_add(&msg_count,count);
|
||||
}
|
||||
|
||||
|
||||
/* Replacement for the post-filtering hook:
|
||||
Pseudocode by Colin:
|
||||
hook on FOLDER_ITEM_UPDATE_HOOKLIST
|
||||
if hook flags & F_ITEM_UPDATE_MSGCOUNT
|
||||
scan mails (folder_item_get_msg_list)
|
||||
if MSG_IS_NEW(msginfo->flags) and not in hashtable
|
||||
notify()
|
||||
add to hashtable
|
||||
procmsg_msg_list_free
|
||||
|
||||
hook on MSGINFO_UPDATE_HOOKLIST
|
||||
if hook flags & MSGINFO_UPDATE_FLAGS
|
||||
if !MSG_IS_NEW(msginfo->flags)
|
||||
remove from hashtable, it's now useless
|
||||
*/
|
||||
|
||||
/* This hash table holds all mails that we already notified about,
|
||||
and that still are marked as "new". The keys are the msgid's,
|
||||
the values are just 1's stored in a pointer. */
|
||||
static GHashTable *notified_hash = NULL;
|
||||
|
||||
|
||||
/* Remove message from the notified_hash if
|
||||
* - the message flags changed
|
||||
* - the message is not new
|
||||
* - the message is in the hash
|
||||
*/
|
||||
gboolean notification_notified_hash_msginfo_update(MsgInfoUpdate *msg_update)
|
||||
{
|
||||
g_return_val_if_fail(msg_update != NULL, FALSE);
|
||||
|
||||
if((msg_update->flags & MSGINFO_UPDATE_FLAGS) &&
|
||||
!MSG_IS_NEW(msg_update->msginfo->flags)) {
|
||||
|
||||
MsgInfo *msg;
|
||||
gchar *msgid;
|
||||
|
||||
msg = msg_update->msginfo;
|
||||
if(msg->msgid)
|
||||
msgid = msg->msgid;
|
||||
else {
|
||||
debug_print("Notification Plugin: Message has no message ID!\n");
|
||||
msgid = "";
|
||||
}
|
||||
|
||||
g_return_val_if_fail(msg != NULL, FALSE);
|
||||
|
||||
if(g_hash_table_lookup(notified_hash, msgid) != NULL) {
|
||||
|
||||
debug_print("Notification Plugin: Removing message id %s from hash "
|
||||
"table\n", msgid);
|
||||
g_hash_table_remove(notified_hash, msgid);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* On startup, mark all new mails as already notified
|
||||
* (by including them in the hash) */
|
||||
void notification_notified_hash_startup_init(void)
|
||||
{
|
||||
GList *folder_list, *walk;
|
||||
Folder *folder;
|
||||
|
||||
if(!notified_hash) {
|
||||
notified_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
debug_print("Notification Plugin: Hash table created\n");
|
||||
}
|
||||
|
||||
folder_list = folder_get_list();
|
||||
for(walk = folder_list; walk != NULL; walk = g_list_next(walk)) {
|
||||
folder = walk->data;
|
||||
|
||||
g_node_traverse(folder->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
|
||||
notification_traverse_hash_startup, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean notification_traverse_hash_startup(GNode *node, gpointer data)
|
||||
{
|
||||
GSList *walk;
|
||||
GSList *msg_list;
|
||||
FolderItem *item = (FolderItem*) node->data;
|
||||
gint new_msgs_left;
|
||||
|
||||
if(!(item->new_msgs))
|
||||
return FALSE;
|
||||
|
||||
new_msgs_left = item->new_msgs;
|
||||
msg_list = folder_item_get_msg_list(item);
|
||||
|
||||
for(walk = msg_list; walk; walk = g_slist_next(walk)) {
|
||||
MsgInfo *msg = (MsgInfo*) walk->data;
|
||||
if(MSG_IS_NEW(msg->flags)) {
|
||||
gchar *msgid;
|
||||
|
||||
if(msg->msgid)
|
||||
msgid = msg->msgid;
|
||||
else {
|
||||
debug_print("Notification Plugin: Message has no message ID!\n");
|
||||
msgid = "";
|
||||
}
|
||||
|
||||
/* If the message id is not yet in the hash, add it */
|
||||
g_hash_table_insert(notified_hash, g_strdup(msgid),
|
||||
GINT_TO_POINTER(1));
|
||||
debug_print("Notification Plugin: Init: Added msg id %s to the hash\n",
|
||||
msgid);
|
||||
/* Decrement left count and check if we're already done */
|
||||
new_msgs_left--;
|
||||
if(new_msgs_left == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
procmsg_msg_list_free(msg_list);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void notification_core_free(void)
|
||||
{
|
||||
if(notified_hash) {
|
||||
g_hash_table_destroy(notified_hash);
|
||||
notified_hash = NULL;
|
||||
}
|
||||
if(msg_count_hash) {
|
||||
g_hash_table_destroy(msg_count_hash);
|
||||
msg_count_hash = NULL;
|
||||
}
|
||||
debug_print("Notification Plugin: Freed internal data\n");
|
||||
}
|
||||
|
||||
void notification_new_unnotified_msgs(FolderItemUpdateData *update_data)
|
||||
{
|
||||
GSList *msg_list, *walk;
|
||||
|
||||
g_return_if_fail(notified_hash != NULL);
|
||||
|
||||
msg_list = folder_item_get_msg_list(update_data->item);
|
||||
|
||||
for(walk = msg_list; walk; walk = g_slist_next(walk)) {
|
||||
MsgInfo *msg;
|
||||
msg = (MsgInfo*) walk->data;
|
||||
|
||||
if(MSG_IS_NEW(msg->flags)) {
|
||||
gchar *msgid;
|
||||
|
||||
if(msg->msgid)
|
||||
msgid = msg->msgid;
|
||||
else {
|
||||
debug_print("Notification Plugin: Message has not message ID!\n");
|
||||
msgid = "";
|
||||
}
|
||||
|
||||
debug_print("Notification Plugin: Found msg %s, "
|
||||
"checking if it is in hash...\n", msgid);
|
||||
/* Check if message is in hash table */
|
||||
if(g_hash_table_lookup(notified_hash, msgid) != NULL)
|
||||
debug_print("yes.\n");
|
||||
else {
|
||||
/* Add to hashtable */
|
||||
g_hash_table_insert(notified_hash, g_strdup(msgid),
|
||||
GINT_TO_POINTER(1));
|
||||
debug_print("no, added to table.\n");
|
||||
|
||||
/* Do the notification */
|
||||
notification_new_unnotified_do_msg(msg);
|
||||
}
|
||||
|
||||
} /* msg is 'new' */
|
||||
} /* for all messages */
|
||||
procmsg_msg_list_free(msg_list);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBCANBERRA_GTK
|
||||
static void canberra_finished_cb(ca_context *c, uint32_t id, int error, void *data)
|
||||
{
|
||||
canberra_new_email_is_playing = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void notification_new_unnotified_do_msg(MsgInfo *msg)
|
||||
{
|
||||
#ifdef NOTIFICATION_POPUP
|
||||
notification_popup_msg(msg);
|
||||
#endif
|
||||
#ifdef NOTIFICATION_COMMAND
|
||||
notification_command_msg(msg);
|
||||
#endif
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
notification_trayicon_msg(msg);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBCANBERRA_GTK
|
||||
/* canberra */
|
||||
if(notify_config.canberra_play_sounds && !canberra_new_email_is_playing) {
|
||||
MainWindow *mainwin;
|
||||
ca_proplist *proplist;
|
||||
mainwin = mainwindow_get_mainwindow();
|
||||
ca_proplist_create(&proplist);
|
||||
ca_proplist_sets(proplist,CA_PROP_EVENT_ID ,"message-new-email");
|
||||
canberra_new_email_is_playing = TRUE;
|
||||
ca_context_play_full(ca_gtk_context_get(), 0, proplist, canberra_finished_cb, NULL);
|
||||
ca_proplist_destroy(proplist);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If folders is not NULL, then consider only those folder items
|
||||
* If max_msgs is not 0, stop after collecting msg_msgs messages
|
||||
*/
|
||||
GSList* notification_collect_msgs(gboolean unread_also, GSList *folder_items,
|
||||
gint max_msgs)
|
||||
{
|
||||
GList *folder_list, *walk;
|
||||
Folder *folder;
|
||||
TraverseCollect collect_data;
|
||||
|
||||
collect_data.unread_also = unread_also;
|
||||
collect_data.collected_msgs = NULL;
|
||||
collect_data.folder_items = folder_items;
|
||||
collect_data.max_msgs = max_msgs;
|
||||
collect_data.num_msgs = 0;
|
||||
|
||||
folder_list = folder_get_list();
|
||||
for(walk = folder_list; walk != NULL; walk = g_list_next(walk)) {
|
||||
folder = walk->data;
|
||||
|
||||
g_node_traverse(folder->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
|
||||
notification_traverse_collect, &collect_data);
|
||||
}
|
||||
return collect_data.collected_msgs;
|
||||
}
|
||||
|
||||
void notification_collected_msgs_free(GSList *collected_msgs)
|
||||
{
|
||||
if(collected_msgs) {
|
||||
GSList *walk;
|
||||
for(walk = collected_msgs; walk != NULL; walk = g_slist_next(walk)) {
|
||||
CollectedMsg *msg = walk->data;
|
||||
if(msg->from)
|
||||
g_free(msg->from);
|
||||
if(msg->subject)
|
||||
g_free(msg->subject);
|
||||
if(msg->folderitem_name)
|
||||
g_free(msg->folderitem_name);
|
||||
msg->msginfo = NULL;
|
||||
g_free(msg);
|
||||
}
|
||||
g_slist_free(collected_msgs);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean notification_traverse_collect(GNode *node, gpointer data)
|
||||
{
|
||||
TraverseCollect *cdata = data;
|
||||
FolderItem *item = node->data;
|
||||
gchar *folder_id_cur;
|
||||
|
||||
/* Obey global folder type limitations */
|
||||
if(!notify_include_folder_type(item->folder->klass->type,
|
||||
item->folder->klass->uistr))
|
||||
return FALSE;
|
||||
|
||||
/* If a folder_items list was given, check it first */
|
||||
if((cdata->folder_items) && (item->path != NULL) &&
|
||||
((folder_id_cur = folder_item_get_identifier(item)) != NULL)) {
|
||||
FolderItem *list_item;
|
||||
GSList *walk;
|
||||
gchar *folder_id_list;
|
||||
gboolean eq;
|
||||
gboolean folder_in_list = FALSE;
|
||||
|
||||
for(walk = cdata->folder_items; walk != NULL; walk = g_slist_next(walk)) {
|
||||
list_item = walk->data;
|
||||
folder_id_list = folder_item_get_identifier(list_item);
|
||||
eq = !strcmp2(folder_id_list,folder_id_cur);
|
||||
g_free(folder_id_list);
|
||||
if(eq) {
|
||||
folder_in_list = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free(folder_id_cur);
|
||||
if(!folder_in_list)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(item->new_msgs || (cdata->unread_also && item->unread_msgs)) {
|
||||
GSList *msg_list = folder_item_get_msg_list(item);
|
||||
GSList *walk;
|
||||
for(walk = msg_list; walk != NULL; walk = g_slist_next(walk)) {
|
||||
MsgInfo *msg_info = walk->data;
|
||||
CollectedMsg *cmsg;
|
||||
|
||||
if((cdata->max_msgs != 0) && (cdata->num_msgs >= cdata->max_msgs))
|
||||
return FALSE;
|
||||
|
||||
if(MSG_IS_NEW(msg_info->flags) ||
|
||||
(MSG_IS_UNREAD(msg_info->flags) && cdata->unread_also)) {
|
||||
|
||||
cmsg = g_new(CollectedMsg, 1);
|
||||
cmsg->from = g_strdup(msg_info->from ? msg_info->from : "");
|
||||
cmsg->subject = g_strdup(msg_info->subject ? msg_info->subject : "");
|
||||
if(msg_info->folder && msg_info->folder->name)
|
||||
cmsg->folderitem_name = g_strdup(msg_info->folder->path);
|
||||
else
|
||||
cmsg->folderitem_name = g_strdup("");
|
||||
|
||||
cmsg->msginfo = msg_info;
|
||||
|
||||
cdata->collected_msgs = g_slist_prepend(cdata->collected_msgs, cmsg);
|
||||
cdata->num_msgs++;
|
||||
}
|
||||
}
|
||||
procmsg_msg_list_free(msg_list);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean notify_include_folder_type(FolderType ftype, gchar *uistr)
|
||||
{
|
||||
gboolean retval;
|
||||
|
||||
retval = FALSE;
|
||||
switch(ftype) {
|
||||
case F_MH:
|
||||
case F_MBOX:
|
||||
case F_MAILDIR:
|
||||
case F_IMAP:
|
||||
if(notify_config.include_mail)
|
||||
retval = TRUE;
|
||||
break;
|
||||
case F_NEWS:
|
||||
if(notify_config.include_news)
|
||||
retval = TRUE;
|
||||
break;
|
||||
case F_UNKNOWN:
|
||||
if(uistr == NULL)
|
||||
retval = FALSE;
|
||||
else if(!strcmp(uistr, "vCalendar")) {
|
||||
if(notify_config.include_calendar)
|
||||
retval = TRUE;
|
||||
}
|
||||
else if(!strcmp(uistr, "RSSyl")) {
|
||||
if(notify_config.include_rss)
|
||||
retval = TRUE;
|
||||
}
|
||||
else
|
||||
debug_print("Notification Plugin: Unknown folder type %d\n",ftype);
|
||||
break;
|
||||
default:
|
||||
debug_print("Notification Plugin: Unknown folder type %d\n",ftype);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void fix_folderview_scroll(MainWindow *mainwin)
|
||||
{
|
||||
static gboolean fix_done = FALSE;
|
||||
|
||||
if (fix_done)
|
||||
return;
|
||||
|
||||
gtk_widget_queue_resize(mainwin->folderview->ctree);
|
||||
|
||||
fix_done = TRUE;
|
||||
}
|
||||
|
||||
void notification_show_mainwindow(MainWindow *mainwin)
|
||||
{
|
||||
gtk_window_deiconify(GTK_WINDOW(mainwin->window));
|
||||
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(mainwin->window), FALSE);
|
||||
main_window_show(mainwin);
|
||||
gtk_window_present(GTK_WINDOW(mainwin->window));
|
||||
fix_folderview_scroll(mainwin);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
#define STR_MAX_LEN 511
|
||||
/* Returns a newly allocated string which needs to be freed */
|
||||
gchar* notification_libnotify_sanitize_str(gchar *in)
|
||||
{
|
||||
gint i_out;
|
||||
gchar tmp_str[STR_MAX_LEN+1];
|
||||
|
||||
if(in == NULL) return NULL;
|
||||
|
||||
i_out = 0;
|
||||
while(*in) {
|
||||
if(*in == '<') {
|
||||
if(i_out+3 >= STR_MAX_LEN) break;
|
||||
memcpy(&(tmp_str[i_out]),"<",4);
|
||||
in++; i_out += 4;
|
||||
}
|
||||
else if(*in == '>') {
|
||||
if(i_out+3 >= STR_MAX_LEN) break;
|
||||
memcpy(&(tmp_str[i_out]),">",4);
|
||||
in++; i_out += 4;
|
||||
}
|
||||
else if(*in == '&') {
|
||||
if(i_out+4 >= STR_MAX_LEN) break;
|
||||
memcpy(&(tmp_str[i_out]),"&",5);
|
||||
in++; i_out += 5;
|
||||
}
|
||||
else {
|
||||
if(i_out >= STR_MAX_LEN) break;
|
||||
tmp_str[i_out++] = *in++;
|
||||
}
|
||||
}
|
||||
tmp_str[i_out] = '\0';
|
||||
return strdup(tmp_str);
|
||||
}
|
||||
|
||||
gchar* notification_validate_utf8_str(gchar *text)
|
||||
{
|
||||
gchar *utf8_str = NULL;
|
||||
|
||||
if(!g_utf8_validate(text, -1, NULL)) {
|
||||
debug_print("Notification plugin: String is not valid utf8, "
|
||||
"trying to fix it...\n");
|
||||
/* fix it */
|
||||
utf8_str = conv_codeset_strdup(text,
|
||||
conv_get_locale_charset_str_no_utf8(),
|
||||
CS_INTERNAL);
|
||||
/* check if the fix worked */
|
||||
if(utf8_str == NULL || !g_utf8_validate(utf8_str, -1, NULL)) {
|
||||
debug_print("Notification plugin: String is still not valid utf8, "
|
||||
"sanitizing...\n");
|
||||
utf8_str = g_malloc(strlen(text)*2+1);
|
||||
conv_localetodisp(utf8_str, strlen(text)*2+1, text);
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug_print("Notification plugin: String is valid utf8\n");
|
||||
utf8_str = g_strdup(text);
|
||||
}
|
||||
return utf8_str;
|
||||
}
|
||||
#endif
|
79
src/plugins/notification/notification_core.h
Normal file
79
src/plugins/notification/notification_core.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_CORE_H
|
||||
#define NOTIFICATION_CORE_H NOTIFICATION_CORE_H
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "folder.h"
|
||||
#include "procmsg.h"
|
||||
|
||||
typedef struct {
|
||||
gchar *from;
|
||||
gchar *subject;
|
||||
FolderItem *folder_item;
|
||||
gchar *folderitem_name;
|
||||
MsgInfo *msginfo;
|
||||
} CollectedMsg;
|
||||
|
||||
typedef enum {
|
||||
F_TYPE_MAIL=0,
|
||||
F_TYPE_NEWS,
|
||||
F_TYPE_CALENDAR,
|
||||
F_TYPE_RSS,
|
||||
F_TYPE_LAST
|
||||
} NotificationFolderType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint new_msgs;
|
||||
guint unread_msgs;
|
||||
guint unreadmarked_msgs;
|
||||
guint marked_msgs;
|
||||
guint total_msgs;
|
||||
} NotificationMsgCount;
|
||||
|
||||
/* Collect new and possibly unread messages in all folders */
|
||||
GSList* notification_collect_msgs(gboolean, GSList*, gint);
|
||||
void notification_collected_msgs_free(GSList*);
|
||||
|
||||
void notification_core_global_includes_changed(void);
|
||||
void notification_core_free(void);
|
||||
void notification_update_msg_counts(FolderItem*);
|
||||
void notification_core_get_msg_count(GSList*,NotificationMsgCount*);
|
||||
void notification_core_get_msg_count_of_foldername(gchar*, NotificationMsgCount*);
|
||||
void notification_new_unnotified_msgs(FolderItemUpdateData*);
|
||||
gboolean notification_notified_hash_msginfo_update(MsgInfoUpdate*);
|
||||
void notification_notified_hash_startup_init(void);
|
||||
|
||||
void notification_show_mainwindow(MainWindow *mainwin);
|
||||
/* folder type specific settings */
|
||||
gboolean notify_include_folder_type(FolderType, gchar*);
|
||||
|
||||
void notification_toggle_hide_show_window(void);
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
/* Sanitize a string to use with libnotify. Returns a freshly
|
||||
* allocated string that must be freed by the user. */
|
||||
gchar* notification_libnotify_sanitize_str(gchar*);
|
||||
/* Returns a freshly allocated copy of the input string, which
|
||||
* is guaranteed to be valid UTF8. The returned string has to
|
||||
* be freed. */
|
||||
gchar* notification_validate_utf8_str(gchar*);
|
||||
#endif
|
||||
|
||||
#endif /* NOTIFICATION_CORE_H */
|
1002
src/plugins/notification/notification_foldercheck.c
Normal file
1002
src/plugins/notification/notification_foldercheck.c
Normal file
File diff suppressed because it is too large
Load diff
32
src/plugins/notification/notification_foldercheck.h
Normal file
32
src/plugins/notification/notification_foldercheck.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_FOLDERCHECK_H
|
||||
#define NOTIFICATION_FOLDERCHECK_H NOTIFICATION_FOLDERCHECK_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
void notification_foldercheck_sel_folders_cb(GtkButton*, gpointer);
|
||||
guint notification_register_folder_specific_list(gchar*);
|
||||
GSList* notification_foldercheck_get_list(guint);
|
||||
void notification_free_folder_specific_array(void);
|
||||
void notification_foldercheck_write_array(void);
|
||||
gboolean notification_foldercheck_read_array(void);
|
||||
|
||||
#endif /* NOTIFICATION_FOLDERCHECK_H */
|
116
src/plugins/notification/notification_hotkeys.c
Normal file
116
src/plugins/notification/notification_hotkeys.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2009 Holger Berndt and the Claws Mail Team.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_HOTKEYS
|
||||
|
||||
#include "notification_hotkeys.h"
|
||||
#include "notification_prefs.h"
|
||||
#include "notification_core.h"
|
||||
|
||||
#include "gtkhotkey.h"
|
||||
|
||||
#define HOTKEYS_APP_ID "claws-mail"
|
||||
#define HOTKEY_KEY_ID_TOGGLED "toggle-mainwindow"
|
||||
|
||||
static GtkHotkeyInfo *hotkey_toggle_mainwindow = NULL;
|
||||
|
||||
static void hotkey_toggle_mainwindow_activated(GtkHotkeyInfo *hotkey, guint event_time, gpointer data)
|
||||
{
|
||||
g_return_if_fail(GTK_HOTKEY_IS_INFO(hotkey));
|
||||
debug_print("Notification plugin: Toggled hide/show window due to hotkey %s activation\n", gtk_hotkey_info_get_signature(hotkey));
|
||||
notification_toggle_hide_show_window();
|
||||
}
|
||||
|
||||
static void unbind_toggle_mainwindow()
|
||||
{
|
||||
GError *error;
|
||||
GtkHotkeyRegistry *registry;
|
||||
|
||||
/* clean up old hotkey */
|
||||
if(hotkey_toggle_mainwindow) {
|
||||
if(gtk_hotkey_info_is_bound(hotkey_toggle_mainwindow)) {
|
||||
error = NULL;
|
||||
gtk_hotkey_info_unbind(hotkey_toggle_mainwindow, &error);
|
||||
if(error) {
|
||||
debug_print("Notification plugin: Failed to unbind toggle hotkey\n");
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
g_object_unref(hotkey_toggle_mainwindow);
|
||||
hotkey_toggle_mainwindow = NULL;
|
||||
}
|
||||
registry = gtk_hotkey_registry_get_default();
|
||||
if(gtk_hotkey_registry_has_hotkey(registry, HOTKEYS_APP_ID, HOTKEY_KEY_ID_TOGGLED)) {
|
||||
error = NULL;
|
||||
gtk_hotkey_registry_delete_hotkey(registry, HOTKEYS_APP_ID, HOTKEY_KEY_ID_TOGGLED, &error);
|
||||
if(error) {
|
||||
debug_print("Notification plugin: Failed to unregister toggle hotkey: %s\n", error->message);
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_hotkey_binding_toggle_mainwindow()
|
||||
{
|
||||
GError *error;
|
||||
|
||||
/* don't do anything if no signature is given */
|
||||
if(!notify_config.hotkeys_toggle_mainwindow || !strcmp(notify_config.hotkeys_toggle_mainwindow, ""))
|
||||
return;
|
||||
|
||||
unbind_toggle_mainwindow();
|
||||
|
||||
/* (re)create hotkey info */
|
||||
hotkey_toggle_mainwindow = gtk_hotkey_info_new(HOTKEYS_APP_ID, HOTKEY_KEY_ID_TOGGLED, notify_config.hotkeys_toggle_mainwindow, NULL);
|
||||
if(!hotkey_toggle_mainwindow) {
|
||||
debug_print("Notification plugin: Failed to create toggle hotkey for '%s'\n", notify_config.hotkeys_toggle_mainwindow);
|
||||
return;
|
||||
}
|
||||
|
||||
/* try to register hotkey */
|
||||
error = NULL;
|
||||
gtk_hotkey_info_bind(hotkey_toggle_mainwindow, &error);
|
||||
if(error) {
|
||||
debug_print("Notification plugin: Failed to bind toggle hotkey to '%s': %s\n", notify_config.hotkeys_toggle_mainwindow, error->message);
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_signal_connect(hotkey_toggle_mainwindow, "activated", G_CALLBACK(hotkey_toggle_mainwindow_activated), NULL);
|
||||
}
|
||||
|
||||
void notification_hotkeys_update_bindings()
|
||||
{
|
||||
debug_print("Notification plugin: Updating keybindings..\n");
|
||||
if(notify_config.hotkeys_enabled) {
|
||||
update_hotkey_binding_toggle_mainwindow();
|
||||
}
|
||||
else
|
||||
notification_hotkeys_unbind_all();
|
||||
}
|
||||
|
||||
void notification_hotkeys_unbind_all()
|
||||
{
|
||||
debug_print("Notification plugin: Unbinding all keybindings..\n");
|
||||
unbind_toggle_mainwindow();
|
||||
}
|
||||
|
||||
#endif /* NOTIFICATION_HOTKEYS */
|
31
src/plugins/notification/notification_hotkeys.h
Normal file
31
src/plugins/notification/notification_hotkeys.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2009 Holger Berndt and the Claws Mail Team.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_HOTKEYS_H
|
||||
#define NOTIFICATION_HOTKEYS_H NOTIFICATION_HOTKEYS_H
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_HOTKEYS
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void notification_hotkeys_update_bindings();
|
||||
void notification_hotkeys_unbind_all();
|
||||
|
||||
#endif /* NOTIFICATION_HOTKEYS */
|
||||
#endif /* NOTIFICATION_HOTKEYS_H */
|
174
src/plugins/notification/notification_indicator.c
Normal file
174
src/plugins/notification/notification_indicator.c
Normal file
|
@ -0,0 +1,174 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2009 Holger Berndt and the Claws Mail Team.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_INDICATOR
|
||||
|
||||
#include "notification_indicator.h"
|
||||
#include "notification_prefs.h"
|
||||
#include "notification_core.h"
|
||||
|
||||
#include "folder.h"
|
||||
#include "common/utils.h"
|
||||
|
||||
#include <libindicate/server.h>
|
||||
#include <libindicate/indicator.h>
|
||||
#include <libindicate/indicator-messages.h>
|
||||
|
||||
static IndicateServer *server = NULL;
|
||||
static GHashTable *indicators = NULL;
|
||||
static gulong mainwin_state_changed_signal_id = 0;
|
||||
|
||||
void notification_indicator_destroy(void)
|
||||
{
|
||||
if(indicators) {
|
||||
g_hash_table_destroy(indicators);
|
||||
indicators = NULL;
|
||||
}
|
||||
if(server) {
|
||||
indicate_server_hide(server);
|
||||
g_object_unref(server);
|
||||
server = NULL;
|
||||
}
|
||||
if(mainwin_state_changed_signal_id != 0) {
|
||||
MainWindow *mainwin;
|
||||
if((mainwin = mainwindow_get_mainwindow()) != NULL)
|
||||
g_signal_handler_disconnect(mainwin->window, mainwin_state_changed_signal_id);
|
||||
mainwin_state_changed_signal_id = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void show_claws_mail(IndicateIndicator *indicator, guint dummy, gpointer data)
|
||||
{
|
||||
MainWindow *mainwin;
|
||||
|
||||
if((mainwin = mainwindow_get_mainwindow()) == NULL)
|
||||
return;
|
||||
|
||||
notification_show_mainwindow(mainwin);
|
||||
if(data) {
|
||||
Folder *folder = data;
|
||||
FolderItem *item = folder->inbox;
|
||||
|
||||
gchar *path = folder_item_get_identifier(item);
|
||||
mainwindow_jump_to(path, FALSE);
|
||||
g_free(path);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_indicator_unread_count(IndicateIndicator *indicator, gint new, gint unread)
|
||||
{
|
||||
gchar *count_str;
|
||||
|
||||
count_str = g_strdup_printf("%d / %d", new, unread);
|
||||
indicate_indicator_set_property(indicator, INDICATE_INDICATOR_MESSAGES_PROP_COUNT, count_str);
|
||||
g_free(count_str);
|
||||
}
|
||||
|
||||
static void create_indicators(void)
|
||||
{
|
||||
IndicateIndicator *indicator;
|
||||
GList *cur_mb;
|
||||
|
||||
indicators = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
|
||||
for(cur_mb = folder_get_list(); cur_mb; cur_mb = cur_mb->next) {
|
||||
gchar *name;
|
||||
Folder *folder = cur_mb->data;
|
||||
|
||||
if(!folder->name) {
|
||||
debug_print("Notification plugin: Warning: Ignoring unnamed mailbox in indicator applet\n");
|
||||
continue;
|
||||
}
|
||||
name = g_strdup(folder->name);
|
||||
|
||||
indicator = indicate_indicator_new();
|
||||
indicate_indicator_set_property(indicator, INDICATE_INDICATOR_MESSAGES_PROP_NAME, name);
|
||||
set_indicator_unread_count(indicator, 0, 0);
|
||||
g_object_set_data(G_OBJECT(indicator), "new_msgs", GINT_TO_POINTER(0));
|
||||
g_object_set_data(G_OBJECT(indicator), "unread_msgs", GINT_TO_POINTER(0));
|
||||
g_signal_connect(indicator, "user-display", G_CALLBACK (show_claws_mail), folder);
|
||||
indicate_indicator_show(indicator);
|
||||
g_hash_table_insert(indicators, name, indicator);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean mainwin_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
|
||||
{
|
||||
if(notify_config.indicator_hide_minimized) {
|
||||
MainWindow *mainwin;
|
||||
|
||||
if((mainwin = mainwindow_get_mainwindow()) == NULL)
|
||||
return FALSE;
|
||||
|
||||
if((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) && (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
|
||||
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(mainwin->window), TRUE);
|
||||
}
|
||||
else if((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) && !(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
|
||||
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(mainwin->window), FALSE);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void notification_update_indicator(void)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
if(!mainwin_state_changed_signal_id) {
|
||||
MainWindow *mainwin;
|
||||
|
||||
if((mainwin = mainwindow_get_mainwindow()) != NULL)
|
||||
mainwin_state_changed_signal_id = g_signal_connect(G_OBJECT(mainwin->window), "window-state-event", G_CALLBACK(mainwin_state_event), NULL);
|
||||
}
|
||||
|
||||
|
||||
if(!notify_config.indicator_enabled)
|
||||
return;
|
||||
|
||||
if(!server) {
|
||||
server = indicate_server_ref_default();
|
||||
indicate_server_set_type (server, "message.mail");
|
||||
indicate_server_set_desktop_file(server, get_desktop_file());
|
||||
g_signal_connect(server, "server-display", G_CALLBACK(show_claws_mail), NULL);
|
||||
indicate_server_show(server);
|
||||
}
|
||||
|
||||
if(!indicators)
|
||||
create_indicators();
|
||||
|
||||
/* check accounts for new/unread counts */
|
||||
g_hash_table_iter_init(&iter, indicators);
|
||||
while(g_hash_table_iter_next(&iter, &key, &value)) {
|
||||
NotificationMsgCount count;
|
||||
gchar *foldername = key;
|
||||
IndicateIndicator *indicator = value;
|
||||
|
||||
notification_core_get_msg_count_of_foldername(foldername, &count);
|
||||
|
||||
set_indicator_unread_count(indicator, count.new_msgs, count.unread_msgs);
|
||||
indicate_indicator_set_property(indicator, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION,
|
||||
(count.new_msgs > 0) ? "true" : "false");
|
||||
g_object_set_data(G_OBJECT(indicator), "new_msgs", GINT_TO_POINTER(count.new_msgs));
|
||||
g_object_set_data(G_OBJECT(indicator), "unread_msgs", GINT_TO_POINTER(count.unread_msgs));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* NOTIFICATION_INDICATOR */
|
31
src/plugins/notification/notification_indicator.h
Normal file
31
src/plugins/notification/notification_indicator.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2009 Holger Berndt and the Claws Mail Team.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_INDICATOR_H
|
||||
#define NOTIFICATION_INDICATOR_H NOTIFICATION_INDICATOR_H
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_INDICATOR
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void notification_update_indicator(void);
|
||||
void notification_indicator_destroy(void);
|
||||
|
||||
#endif /* NOTIFICATION_INDICATOR */
|
||||
#endif /* NOTIFICATION_INDICATOR_H */
|
172
src/plugins/notification/notification_lcdproc.c
Normal file
172
src/plugins/notification/notification_lcdproc.c
Normal file
|
@ -0,0 +1,172 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_LCDPROC
|
||||
|
||||
#include "notification_lcdproc.h"
|
||||
#include "notification_prefs.h"
|
||||
#include "notification_core.h"
|
||||
|
||||
#include "common/socket.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define NOTIFICATION_LCDPROC_BUFFER_SIZE 8192
|
||||
|
||||
void notification_sock_puts(SockInfo*, gchar*);
|
||||
void notification_lcdproc_send(gchar*);
|
||||
|
||||
static SockInfo *sock = NULL;
|
||||
|
||||
void notification_lcdproc_connect(void)
|
||||
{
|
||||
gint len, count;
|
||||
gchar buf[NOTIFICATION_LCDPROC_BUFFER_SIZE];
|
||||
|
||||
if(!notify_config.lcdproc_enabled)
|
||||
return;
|
||||
|
||||
if(sock)
|
||||
notification_lcdproc_disconnect();
|
||||
|
||||
sock = sock_connect(notify_config.lcdproc_hostname,
|
||||
notify_config.lcdproc_port);
|
||||
/*
|
||||
* Quietly return when a connection fails; next attempt
|
||||
* will be made when some folder info has been changed.
|
||||
*/
|
||||
if(sock == NULL || sock->state == CONN_FAILED) {
|
||||
debug_print("Could not connect to LCDd\n");
|
||||
if(sock && sock->state == CONN_FAILED) {
|
||||
sock_close(sock);
|
||||
sock = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
debug_print("Connected to LCDd\n");
|
||||
|
||||
sock_set_nonblocking_mode(sock, TRUE);
|
||||
|
||||
/* Friendly people say "hello" first */
|
||||
notification_sock_puts(sock, "hello");
|
||||
|
||||
/* FIXME: Ouch. Is this really the way to go? */
|
||||
count = 50;
|
||||
len = 0;
|
||||
while((len <= 0) && (count-- >= 0)) {
|
||||
g_usleep(125000);
|
||||
len = sock_read(sock, buf, NOTIFICATION_LCDPROC_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This might not be a LCDProc server.
|
||||
* FIXME: check LCD size, LCDd version etc
|
||||
*/
|
||||
|
||||
if (len <= 0) {
|
||||
debug_print("Notification plugin: Can't communicate with "
|
||||
"LCDd server! Are you sure that "
|
||||
"there is a LCDd server running on %s:%d?\n",
|
||||
notify_config.lcdproc_hostname, notify_config.lcdproc_port);
|
||||
notification_lcdproc_disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
notification_lcdproc_send("client_set -name \"{Claws-Mail}\"");
|
||||
|
||||
notification_lcdproc_send("screen_add msg_counts");
|
||||
notification_lcdproc_send("screen_set msg_counts -name {Claws-Mail Message Count}");
|
||||
|
||||
notification_lcdproc_send("widget_add msg_counts title title");
|
||||
notification_lcdproc_send("widget_set msg_counts title {Claws-Mail}");
|
||||
notification_lcdproc_send("widget_add msg_counts line1 string");
|
||||
notification_lcdproc_send("widget_add msg_counts line2 string");
|
||||
notification_lcdproc_send("widget_add msg_counts line3 string");
|
||||
|
||||
notification_update_msg_counts(NULL);
|
||||
}
|
||||
|
||||
void notification_lcdproc_disconnect(void)
|
||||
{
|
||||
if(sock) {
|
||||
#ifndef G_OS_WIN32
|
||||
shutdown(sock->sock, SHUT_RDWR);
|
||||
#endif
|
||||
sock_close(sock);
|
||||
sock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void notification_update_lcdproc(void)
|
||||
{
|
||||
NotificationMsgCount count;
|
||||
gchar *buf;
|
||||
|
||||
if(!notify_config.lcdproc_enabled || !sock)
|
||||
return;
|
||||
|
||||
if(!sock || sock->state == CONN_FAILED) {
|
||||
notification_lcdproc_connect();
|
||||
return;
|
||||
}
|
||||
|
||||
notification_core_get_msg_count(NULL, &count);
|
||||
|
||||
if((count.new_msgs + count.unread_msgs) > 0) {
|
||||
buf =
|
||||
g_strdup_printf("widget_set msg_counts line1 1 2 {%s: %d}",_("New"),
|
||||
count.new_msgs);
|
||||
notification_lcdproc_send(buf);
|
||||
buf =
|
||||
g_strdup_printf("widget_set msg_counts line2 1 3 {%s: %d}",_("Unread"),
|
||||
count.unread_msgs);
|
||||
notification_lcdproc_send(buf);
|
||||
buf =
|
||||
g_strdup_printf("widget_set msg_counts line3 1 4 {%s: %d}",_("Total"),
|
||||
count.total_msgs);
|
||||
notification_lcdproc_send(buf);
|
||||
}
|
||||
else {
|
||||
buf = g_strdup_printf("widget_set msg_counts line1 1 2 {%s}",
|
||||
_("No new messages"));
|
||||
notification_lcdproc_send(buf);
|
||||
buf = g_strdup_printf("widget_set msg_counts line2 1 3 {}");
|
||||
notification_lcdproc_send(buf);
|
||||
buf = g_strdup_printf("widget_set msg_counts line3 1 4 {}");
|
||||
notification_lcdproc_send(buf);
|
||||
}
|
||||
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
void notification_sock_puts(SockInfo *socket, gchar *string)
|
||||
{
|
||||
sock_write(socket, string, strlen(string));
|
||||
sock_write(socket, "\n", 1);
|
||||
}
|
||||
|
||||
void notification_lcdproc_send(gchar *string)
|
||||
{
|
||||
notification_sock_puts(sock, string);
|
||||
/* TODO: Check return message from LCDd */
|
||||
}
|
||||
|
||||
#endif /* NOTIFICATION_LCDPROC */
|
34
src/plugins/notification/notification_lcdproc.h
Normal file
34
src/plugins/notification/notification_lcdproc.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_LCDPROC_H
|
||||
#define NOTIFICATION_LCDPROC_H NOTIFICATION_LCDPROC_H
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_LCDPROC
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void notification_lcdproc_connect(void);
|
||||
void notification_lcdproc_disconnect(void);
|
||||
|
||||
void notification_update_lcdproc(void);
|
||||
|
||||
#endif /* NOTIFICATION_LCDPROC */
|
||||
|
||||
#endif /* include guard */
|
97
src/plugins/notification/notification_pixbuf.c
Normal file
97
src/plugins/notification/notification_pixbuf.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "notification_pixbuf.h"
|
||||
|
||||
/* The following files were created from the respective .png or
|
||||
* xpm files with the command
|
||||
* gdk-pixbuf-csource --raw --name=<name> file.png > <name>.h
|
||||
*/
|
||||
/* From the Claws-Mail distribution */
|
||||
#include "raw_claws_mail_logo_64x64.h"
|
||||
|
||||
#include "stock_pixmap.h"
|
||||
|
||||
static GdkPixbuf* notification_pixbuf[NOTIFICATION_PIXBUF_LAST];
|
||||
|
||||
GdkPixbuf* notification_pixbuf_get(NotificationPixbuf wanted)
|
||||
{
|
||||
if(!notification_pixbuf[wanted]) {
|
||||
switch(wanted) {
|
||||
case NOTIFICATION_CM_LOGO_64x64:
|
||||
notification_pixbuf[wanted] =
|
||||
gdk_pixbuf_new_from_inline(-1, raw_claws_mail_logo_64x64,
|
||||
FALSE, NULL);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_NEWMAIL:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_NEWMAIL, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_NEWMAIL_OFFLINE:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_NEWMAIL_OFFLINE, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_NEWMARKEDMAIL:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_NEWMARKEDMAIL, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_NEWMARKEDMAIL_OFFLINE:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_NEWMARKEDMAIL_OFFLINE, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_NOMAIL:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_NOMAIL, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_NOMAIL_OFFLINE:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_NOMAIL_OFFLINE, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_UNREADMAIL:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_UNREADMAIL, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_UNREADMAIL_OFFLINE:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_UNREADMAIL_OFFLINE, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_UNREADMARKEDMAIL:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_UNREADMARKEDMAIL, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_TRAYICON_UNREADMARKEDMAIL_OFFLINE:
|
||||
stock_pixbuf_gdk(NULL, STOCK_PIXMAP_TRAY_UNREADMARKEDMAIL_OFFLINE, &(notification_pixbuf[wanted]));
|
||||
g_object_ref(notification_pixbuf[wanted]);
|
||||
break;
|
||||
case NOTIFICATION_PIXBUF_LAST:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return notification_pixbuf[wanted];
|
||||
}
|
||||
|
||||
void notification_pixbuf_free_all(void)
|
||||
{
|
||||
gint ii;
|
||||
|
||||
for(ii = NOTIFICATION_CM_LOGO_64x64; ii < NOTIFICATION_PIXBUF_LAST; ii++) {
|
||||
if(notification_pixbuf[ii]) {
|
||||
g_object_unref(notification_pixbuf[ii]);
|
||||
notification_pixbuf[ii] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
47
src/plugins/notification/notification_pixbuf.h
Normal file
47
src/plugins/notification/notification_pixbuf.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_PIXBUF_H
|
||||
#define NOTIFICATION_PIXBUF_H NOTIFICATION_PIXBUF_H
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
/* By convention, the online icons for the trayicon are
|
||||
* immediately followed by the offline icons, so one can do
|
||||
* offline = array[online+1] */
|
||||
typedef enum {
|
||||
NOTIFICATION_CM_LOGO_64x64 = 0,
|
||||
NOTIFICATION_TRAYICON_NEWMAIL,
|
||||
NOTIFICATION_TRAYICON_NEWMAIL_OFFLINE,
|
||||
NOTIFICATION_TRAYICON_NEWMARKEDMAIL,
|
||||
NOTIFICATION_TRAYICON_NEWMARKEDMAIL_OFFLINE,
|
||||
NOTIFICATION_TRAYICON_NOMAIL,
|
||||
NOTIFICATION_TRAYICON_NOMAIL_OFFLINE,
|
||||
NOTIFICATION_TRAYICON_UNREADMAIL,
|
||||
NOTIFICATION_TRAYICON_UNREADMAIL_OFFLINE,
|
||||
NOTIFICATION_TRAYICON_UNREADMARKEDMAIL,
|
||||
NOTIFICATION_TRAYICON_UNREADMARKEDMAIL_OFFLINE,
|
||||
NOTIFICATION_PIXBUF_LAST
|
||||
} NotificationPixbuf;
|
||||
|
||||
/* The reference to the returned GdkPixbuf's belongs to notification_pixbuf,
|
||||
* and shall not be removed outside. */
|
||||
GdkPixbuf* notification_pixbuf_get(NotificationPixbuf);
|
||||
|
||||
void notification_pixbuf_free_all(void);
|
||||
|
||||
#endif /* NOTIFICATION_PIXBUF_H */
|
479
src/plugins/notification/notification_plugin.c
Normal file
479
src/plugins/notification/notification_plugin.c
Normal file
|
@ -0,0 +1,479 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#include "common/claws.h"
|
||||
#include "common/version.h"
|
||||
#include "common/utils.h"
|
||||
#include "common/defs.h"
|
||||
#include "folder.h"
|
||||
#include "common/hooks.h"
|
||||
#include "procmsg.h"
|
||||
#include "mainwindow.h"
|
||||
#include "main.h"
|
||||
#include "gtk/gtkutils.h"
|
||||
|
||||
#include "notification_plugin.h"
|
||||
#include "notification_core.h"
|
||||
#include "notification_prefs.h"
|
||||
#include "notification_banner.h"
|
||||
#include "notification_lcdproc.h"
|
||||
#include "notification_trayicon.h"
|
||||
#include "notification_indicator.h"
|
||||
#include "notification_hotkeys.h"
|
||||
#include "notification_foldercheck.h"
|
||||
#include "notification_pixbuf.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#if HAVE_LIBNOTIFY
|
||||
# include <libnotify/notify.h>
|
||||
#endif
|
||||
|
||||
|
||||
static gboolean my_folder_item_update_hook(gpointer, gpointer);
|
||||
static gboolean my_folder_update_hook(gpointer, gpointer);
|
||||
static gboolean my_msginfo_update_hook(gpointer, gpointer);
|
||||
static gboolean my_offline_switch_hook(gpointer, gpointer);
|
||||
static gboolean my_main_window_close_hook(gpointer, gpointer);
|
||||
static gboolean my_main_window_got_iconified_hook(gpointer, gpointer);
|
||||
static gboolean my_account_list_changed_hook(gpointer, gpointer);
|
||||
static gboolean my_update_theme_hook(gpointer, gpointer);
|
||||
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
static gboolean trayicon_startup_idle(gpointer);
|
||||
#endif
|
||||
|
||||
static guint hook_f_item;
|
||||
static guint hook_f;
|
||||
static guint hook_m_info;
|
||||
static guint hook_offline;
|
||||
static guint hook_mw_close;
|
||||
static guint hook_got_iconified;
|
||||
static guint hook_account;
|
||||
static guint hook_theme_changed;
|
||||
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
static GSList* banner_collected_msgs;
|
||||
#endif
|
||||
|
||||
void notification_update_urgency_hint(void)
|
||||
{
|
||||
MainWindow *mainwin;
|
||||
mainwin = mainwindow_get_mainwindow();
|
||||
if(mainwin) {
|
||||
NotificationMsgCount count;
|
||||
gboolean active;
|
||||
active = FALSE;
|
||||
if(notify_config.urgency_hint_new || notify_config.urgency_hint_unread) {
|
||||
notification_core_get_msg_count(NULL, &count);
|
||||
if(notify_config.urgency_hint_new)
|
||||
active = (active || (count.new_msgs > 0));
|
||||
if(notify_config.urgency_hint_unread)
|
||||
active = (active || (count.unread_msgs > 0));
|
||||
}
|
||||
gtk_window_set_urgency_hint(GTK_WINDOW(mainwin->window), active);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean my_account_list_changed_hook(gpointer source,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean retVal = FALSE;
|
||||
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
notification_update_msg_counts(NULL);
|
||||
retVal = notification_trayicon_account_list_changed(source, data);
|
||||
|
||||
#endif
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static gboolean my_update_theme_hook(gpointer source, gpointer data)
|
||||
{
|
||||
notification_pixbuf_free_all();
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
notification_update_trayicon();
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean my_main_window_got_iconified_hook(gpointer source,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean retVal = FALSE;
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
notification_update_msg_counts(NULL);
|
||||
retVal = notification_trayicon_main_window_got_iconified(source, data);
|
||||
#endif
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static gboolean my_main_window_close_hook(gpointer source, gpointer data)
|
||||
{
|
||||
gboolean retVal = FALSE;
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
notification_update_msg_counts(NULL);
|
||||
retVal = notification_trayicon_main_window_close(source, data);
|
||||
#endif
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static gboolean my_offline_switch_hook(gpointer source, gpointer data)
|
||||
{
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
notification_update_msg_counts(NULL);
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean my_folder_item_update_hook(gpointer source, gpointer data)
|
||||
{
|
||||
FolderItemUpdateData *update_data = source;
|
||||
FolderType ftype;
|
||||
gchar *uistr;
|
||||
|
||||
g_return_val_if_fail(source != NULL, FALSE);
|
||||
|
||||
#if defined(NOTIFICATION_LCDPROC) || defined(NOTIFICATION_TRAYICON) || defined(NOTIFICATION_INDICATOR)
|
||||
notification_update_msg_counts(NULL);
|
||||
#else
|
||||
if(notify_config.urgency_hint)
|
||||
notification_update_msg_counts(NULL);
|
||||
#endif
|
||||
|
||||
/* Check if the folder types is to be notified about */
|
||||
ftype = update_data->item->folder->klass->type;
|
||||
uistr = update_data->item->folder->klass->uistr;
|
||||
if(!notify_include_folder_type(ftype, uistr))
|
||||
return FALSE;
|
||||
|
||||
if(update_data->update_flags & F_ITEM_UPDATE_MSGCNT) {
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
notification_update_banner();
|
||||
#endif
|
||||
#if defined(NOTIFICATION_POPUP) || defined(NOTIFICATION_COMMAND)
|
||||
notification_new_unnotified_msgs(update_data);
|
||||
#endif
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean my_folder_update_hook(gpointer source, gpointer data)
|
||||
{
|
||||
FolderUpdateData *hookdata;
|
||||
|
||||
g_return_val_if_fail(source != NULL, FALSE);
|
||||
hookdata = source;
|
||||
|
||||
#if defined(NOTIFICATION_LCDPROC) || defined(NOTIFICATION_TRAYICON)
|
||||
if(hookdata->update_flags & FOLDER_REMOVE_FOLDERITEM)
|
||||
notification_update_msg_counts(hookdata->item);
|
||||
else
|
||||
notification_update_msg_counts(NULL);
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static gboolean my_msginfo_update_hook(gpointer source, gpointer data)
|
||||
{
|
||||
return notification_notified_hash_msginfo_update((MsgInfoUpdate*)source);
|
||||
}
|
||||
|
||||
gint plugin_init(gchar **error)
|
||||
{
|
||||
gchar *rcpath;
|
||||
|
||||
/* Version check */
|
||||
/* No be able to test against new-contacts */
|
||||
if(!check_plugin_version(MAKE_NUMERIC_VERSION(3,8,1,46),
|
||||
VERSION_NUMERIC, _("Notification"), error))
|
||||
return -1;
|
||||
|
||||
/* Check if threading is enabled */
|
||||
if(!g_thread_supported()) {
|
||||
*error = g_strdup(_("The Notification plugin needs threading support."));
|
||||
return -1;
|
||||
}
|
||||
|
||||
hook_f_item = hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST,
|
||||
my_folder_item_update_hook, NULL);
|
||||
if(hook_f_item == (guint) -1) {
|
||||
*error = g_strdup(_("Failed to register folder item update hook in the "
|
||||
"Notification plugin"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
hook_f = hooks_register_hook(FOLDER_UPDATE_HOOKLIST,
|
||||
my_folder_update_hook, NULL);
|
||||
if(hook_f == (guint) -1) {
|
||||
*error = g_strdup(_("Failed to register folder update hook in the "
|
||||
"Notification plugin"));
|
||||
hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
hook_m_info = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST,
|
||||
my_msginfo_update_hook, NULL);
|
||||
if(hook_m_info == (guint) -1) {
|
||||
*error = g_strdup(_("Failed to register msginfo update hook in the "
|
||||
"Notification plugin"));
|
||||
hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
|
||||
hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hook_offline = hooks_register_hook(OFFLINE_SWITCH_HOOKLIST,
|
||||
my_offline_switch_hook, NULL);
|
||||
if(hook_offline == (guint) -1) {
|
||||
*error = g_strdup(_("Failed to register offline switch hook in the "
|
||||
"Notification plugin"));
|
||||
hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
|
||||
hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
|
||||
hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hook_mw_close = hooks_register_hook(MAIN_WINDOW_CLOSE,
|
||||
my_main_window_close_hook, NULL);
|
||||
if(hook_mw_close == (guint) -1) {
|
||||
*error = g_strdup(_("Failed to register main window close hook in the "
|
||||
"Notification plugin"));
|
||||
hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
|
||||
hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
|
||||
hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
|
||||
hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hook_got_iconified = hooks_register_hook(MAIN_WINDOW_GOT_ICONIFIED,
|
||||
my_main_window_got_iconified_hook,
|
||||
NULL);
|
||||
if(hook_got_iconified == (guint) -1) {
|
||||
*error = g_strdup(_("Failed to register got iconified hook in the "
|
||||
"Notification plugin"));
|
||||
hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
|
||||
hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
|
||||
hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
|
||||
hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
|
||||
hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hook_account = hooks_register_hook(ACCOUNT_LIST_CHANGED_HOOKLIST,
|
||||
my_account_list_changed_hook, NULL);
|
||||
if (hook_account == (guint) -1) {
|
||||
*error = g_strdup(_("Failed to register account list changed hook in the "
|
||||
"Notification plugin"));
|
||||
hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
|
||||
hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
|
||||
hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
|
||||
hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
|
||||
hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
|
||||
hooks_unregister_hook(MAIN_WINDOW_GOT_ICONIFIED, hook_got_iconified);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hook_theme_changed = hooks_register_hook(THEME_CHANGED_HOOKLIST, my_update_theme_hook, NULL);
|
||||
if(hook_theme_changed == (guint)-1) {
|
||||
*error = g_strdup(_("Failed to register theme change hook int the "
|
||||
"Notification plugin"));
|
||||
hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
|
||||
hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
|
||||
hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
|
||||
hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
|
||||
hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
|
||||
hooks_unregister_hook(MAIN_WINDOW_GOT_ICONIFIED, hook_got_iconified);
|
||||
hooks_unregister_hook(ACCOUNT_LIST_CHANGED_HOOKLIST, hook_account);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configuration */
|
||||
prefs_set_default(notify_param);
|
||||
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
|
||||
prefs_read_config(notify_param, "NotificationPlugin", rcpath, NULL);
|
||||
g_free(rcpath);
|
||||
|
||||
/* Folder specific stuff */
|
||||
notification_foldercheck_read_array();
|
||||
|
||||
notification_notified_hash_startup_init();
|
||||
|
||||
notify_gtk_init();
|
||||
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
notification_update_banner();
|
||||
#endif
|
||||
#ifdef NOTIFICATION_LCDPROC
|
||||
notification_lcdproc_connect();
|
||||
#endif
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
if(notify_config.trayicon_enabled &&
|
||||
notify_config.trayicon_hide_at_startup && claws_is_starting()) {
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
|
||||
g_idle_add(trayicon_startup_idle,NULL);
|
||||
if(mainwin && gtk_widget_get_visible(GTK_WIDGET(mainwin->window)))
|
||||
main_window_hide(mainwin);
|
||||
main_set_show_at_startup(FALSE);
|
||||
}
|
||||
#endif
|
||||
my_account_list_changed_hook(NULL,NULL);
|
||||
|
||||
if(notify_config.urgency_hint_new || notify_config.urgency_hint_unread)
|
||||
notification_update_msg_counts(NULL);
|
||||
|
||||
#ifdef NOTIFICATION_HOTKEYS
|
||||
notification_hotkeys_update_bindings();
|
||||
#endif
|
||||
|
||||
debug_print("Notification plugin loaded\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean plugin_done(void)
|
||||
{
|
||||
hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_f_item);
|
||||
hooks_unregister_hook(FOLDER_UPDATE_HOOKLIST, hook_f);
|
||||
hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, hook_m_info);
|
||||
hooks_unregister_hook(OFFLINE_SWITCH_HOOKLIST, hook_offline);
|
||||
hooks_unregister_hook(MAIN_WINDOW_CLOSE, hook_mw_close);
|
||||
hooks_unregister_hook(MAIN_WINDOW_GOT_ICONIFIED, hook_got_iconified);
|
||||
hooks_unregister_hook(ACCOUNT_LIST_CHANGED_HOOKLIST, hook_account);
|
||||
hooks_unregister_hook(THEME_CHANGED_HOOKLIST, hook_theme_changed);
|
||||
|
||||
notify_save_config();
|
||||
|
||||
notify_gtk_done();
|
||||
|
||||
/* foldercheck cleanup */
|
||||
notification_foldercheck_write_array();
|
||||
notification_free_folder_specific_array();
|
||||
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
notification_collected_msgs_free(banner_collected_msgs);
|
||||
banner_collected_msgs = NULL;
|
||||
notification_banner_destroy();
|
||||
#endif
|
||||
#ifdef NOTIFICATION_LCDPROC
|
||||
notification_lcdproc_disconnect();
|
||||
#endif
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
notification_trayicon_destroy();
|
||||
#endif
|
||||
#ifdef NOTIFICATION_INDICATOR
|
||||
notification_indicator_destroy();
|
||||
#endif
|
||||
notification_core_free();
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
if(notify_is_initted())
|
||||
notify_uninit();
|
||||
#endif
|
||||
|
||||
#ifdef NOTIFICATION_HOTKEYS
|
||||
notification_hotkeys_unbind_all();
|
||||
#endif
|
||||
|
||||
notification_pixbuf_free_all();
|
||||
|
||||
debug_print("Notification plugin unloaded\n");
|
||||
|
||||
/* Returning FALSE here means that g_module_close() will not be called on the plugin.
|
||||
* This is necessary, as needed libraries are not designed to be unloaded. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const gchar *plugin_name(void)
|
||||
{
|
||||
return _("Notification");
|
||||
}
|
||||
|
||||
const gchar *plugin_desc(void)
|
||||
{
|
||||
return _("This plugin provides various ways "
|
||||
"to notify the user of new and unread email.\n"
|
||||
"The plugin is extensively configurable in the "
|
||||
"plugins section of the preferences dialog.\n\n"
|
||||
"Feedback to <berndth@gmx.de> is welcome.");
|
||||
}
|
||||
|
||||
const gchar *plugin_type(void)
|
||||
{
|
||||
return "GTK2";
|
||||
}
|
||||
|
||||
const gchar *plugin_licence(void)
|
||||
{
|
||||
return "GPL3+";
|
||||
}
|
||||
|
||||
const gchar *plugin_version(void)
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
struct PluginFeature *plugin_provides(void)
|
||||
{
|
||||
static struct PluginFeature features[] =
|
||||
{ {PLUGIN_NOTIFIER, N_("Various tools")},
|
||||
{PLUGIN_NOTHING, NULL}};
|
||||
return features;
|
||||
}
|
||||
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
void notification_update_banner(void)
|
||||
{
|
||||
notification_collected_msgs_free(banner_collected_msgs);
|
||||
banner_collected_msgs = NULL;
|
||||
|
||||
if(notify_config.banner_show != NOTIFY_BANNER_SHOW_NEVER) {
|
||||
guint id;
|
||||
GSList *folder_list = NULL;
|
||||
|
||||
if(notify_config.banner_folder_specific) {
|
||||
id = notification_register_folder_specific_list
|
||||
(BANNER_SPECIFIC_FOLDER_ID_STR);
|
||||
folder_list = notification_foldercheck_get_list(id);
|
||||
}
|
||||
|
||||
if(!(notify_config.banner_folder_specific && (folder_list == NULL)))
|
||||
banner_collected_msgs =
|
||||
notification_collect_msgs(notify_config.banner_include_unread,
|
||||
notify_config.banner_folder_specific ?
|
||||
folder_list : NULL, notify_config.banner_max_msgs);
|
||||
}
|
||||
|
||||
notification_banner_show(banner_collected_msgs);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
static gboolean trayicon_startup_idle(gpointer data)
|
||||
{
|
||||
/* if the trayicon is not available,
|
||||
simulate click on it to show mainwindow */
|
||||
if(!notification_trayicon_is_available())
|
||||
notification_trayicon_on_activate(NULL,data);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
29
src/plugins/notification/notification_plugin.h
Normal file
29
src/plugins/notification/notification_plugin.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_PLUGIN_H
|
||||
#define NOTIFICATION_PLUGIN_H NOTIFICATION_PLUGIN_H
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
void notification_update_banner(void);
|
||||
#endif
|
||||
|
||||
void notification_update_urgency_hint(void);
|
||||
|
||||
#endif /* NOTIFICATION_PLUGIN_H */
|
677
src/plugins/notification/notification_popup.c
Normal file
677
src/plugins/notification/notification_popup.c
Normal file
|
@ -0,0 +1,677 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_POPUP
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "procmsg.h"
|
||||
#include "folder.h"
|
||||
#ifndef USE_NEW_ADDRBOOK
|
||||
#include "addrindex.h"
|
||||
#endif
|
||||
#include "common/utils.h"
|
||||
#include "gtk/gtkutils.h"
|
||||
|
||||
#include "notification_popup.h"
|
||||
#include "notification_prefs.h"
|
||||
#include "notification_foldercheck.h"
|
||||
#include "notification_pixbuf.h"
|
||||
#include "notification_core.h"
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
# include <libnotify/notify.h>
|
||||
#endif
|
||||
|
||||
#ifndef NOTIFY_CHECK_VERSION
|
||||
# define NOTIFY_CHECK_VERSION(a,b,c) 0
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
gint count;
|
||||
gchar *msg_path;
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
NotifyNotification *notification;
|
||||
GError *error;
|
||||
#else /* !HAVE_LIBNOTIFY */
|
||||
guint timeout_id;
|
||||
GtkWidget *window;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *event_box;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *label1;
|
||||
GtkWidget *label2;
|
||||
#endif
|
||||
} NotificationPopup;
|
||||
|
||||
G_LOCK_DEFINE_STATIC(popup);
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
static NotificationPopup popup[F_TYPE_LAST];
|
||||
|
||||
static void popup_timeout_fun(NotifyNotification*, gpointer data);
|
||||
|
||||
static gboolean notification_libnotify_create(MsgInfo*, NotificationFolderType);
|
||||
static gboolean notification_libnotify_add_msg(MsgInfo*, NotificationFolderType);
|
||||
static void default_action_cb(NotifyNotification*, const char*,void*);
|
||||
static void notification_libnotify_free_func(gpointer);
|
||||
|
||||
#else
|
||||
static NotificationPopup popup;
|
||||
|
||||
static gboolean popup_timeout_fun(gpointer data);
|
||||
|
||||
static gboolean notification_popup_add_msg(MsgInfo*);
|
||||
static gboolean notification_popup_create(MsgInfo*);
|
||||
static gboolean notification_popup_button(GtkWidget*, GdkEventButton*, gpointer);
|
||||
#endif
|
||||
|
||||
|
||||
void notification_popup_msg(MsgInfo *msginfo)
|
||||
{
|
||||
gboolean retval;
|
||||
FolderType ftype;
|
||||
NotificationPopup *ppopup;
|
||||
#if HAVE_LIBNOTIFY
|
||||
gchar *uistr;
|
||||
#endif
|
||||
NotificationFolderType nftype;
|
||||
|
||||
nftype = F_TYPE_MAIL;
|
||||
|
||||
if(!msginfo || !notify_config.popup_show)
|
||||
return;
|
||||
|
||||
if(notify_config.popup_folder_specific) {
|
||||
guint id;
|
||||
GSList *list;
|
||||
gchar *identifier;
|
||||
gboolean found = FALSE;
|
||||
|
||||
if(!(msginfo->folder))
|
||||
return;
|
||||
|
||||
identifier = folder_item_get_identifier(msginfo->folder);
|
||||
|
||||
id =
|
||||
notification_register_folder_specific_list(POPUP_SPECIFIC_FOLDER_ID_STR);
|
||||
list = notification_foldercheck_get_list(id);
|
||||
for(; (list != NULL) && !found; list = g_slist_next(list)) {
|
||||
gchar *list_identifier;
|
||||
FolderItem *list_item = (FolderItem*) list->data;
|
||||
|
||||
list_identifier = folder_item_get_identifier(list_item);
|
||||
if(!strcmp2(list_identifier, identifier))
|
||||
found = TRUE;
|
||||
|
||||
g_free(list_identifier);
|
||||
}
|
||||
g_free(identifier);
|
||||
|
||||
if(!found)
|
||||
return;
|
||||
}
|
||||
|
||||
ftype = msginfo->folder->folder->klass->type;
|
||||
|
||||
G_LOCK(popup);
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
/* Check out which type to notify about */
|
||||
switch(ftype) {
|
||||
case F_MH:
|
||||
case F_MBOX:
|
||||
case F_MAILDIR:
|
||||
case F_IMAP:
|
||||
nftype = F_TYPE_MAIL;
|
||||
break;
|
||||
case F_NEWS:
|
||||
nftype = F_TYPE_NEWS;
|
||||
break;
|
||||
case F_UNKNOWN:
|
||||
if((uistr = msginfo->folder->folder->klass->uistr) == NULL) {
|
||||
G_UNLOCK(popup);
|
||||
return;
|
||||
}
|
||||
else if(!strcmp(uistr, "vCalendar"))
|
||||
nftype = F_TYPE_CALENDAR;
|
||||
else if(!strcmp(uistr, "RSSyl"))
|
||||
nftype = F_TYPE_RSS;
|
||||
else {
|
||||
debug_print("Notification Plugin: Unknown folder type %d\n",ftype);
|
||||
G_UNLOCK(popup);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
debug_print("Notification Plugin: Unknown folder type %d\n",ftype);
|
||||
G_UNLOCK(popup);
|
||||
return;
|
||||
}
|
||||
|
||||
ppopup = &(popup[nftype]);
|
||||
retval = notification_libnotify_add_msg(msginfo, nftype);
|
||||
#else /* !HAVE_LIBNOTIFY */
|
||||
ppopup = &popup;
|
||||
retval = notification_popup_add_msg(msginfo);
|
||||
|
||||
/* Renew timeout only when the above call was successful */
|
||||
if(retval) {
|
||||
if(ppopup->timeout_id)
|
||||
g_source_remove(ppopup->timeout_id);
|
||||
ppopup->timeout_id = g_timeout_add(notify_config.popup_timeout,
|
||||
popup_timeout_fun,
|
||||
GINT_TO_POINTER(nftype));
|
||||
}
|
||||
|
||||
#endif /* !HAVE_LIBNOTIFY */
|
||||
|
||||
G_UNLOCK(popup);
|
||||
|
||||
#ifndef HAVE_LIBNOTIFY
|
||||
/* GUI update */
|
||||
while(gtk_events_pending())
|
||||
gtk_main_iteration();
|
||||
#endif /* !HAVE_LIBNOTIFY */
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
static void popup_timeout_fun(NotifyNotification *nn, gpointer data)
|
||||
{
|
||||
NotificationPopup *ppopup;
|
||||
NotificationFolderType nftype;
|
||||
|
||||
nftype = GPOINTER_TO_INT(data);
|
||||
|
||||
G_LOCK(popup);
|
||||
|
||||
ppopup = &(popup[nftype]);
|
||||
|
||||
g_object_unref(G_OBJECT(ppopup->notification));
|
||||
ppopup->notification = NULL;
|
||||
g_clear_error(&(ppopup->error));
|
||||
|
||||
if(ppopup->msg_path) {
|
||||
g_free(ppopup->msg_path);
|
||||
ppopup->msg_path = NULL;
|
||||
}
|
||||
ppopup->count = 0;
|
||||
G_UNLOCK(popup);
|
||||
debug_print("Notification Plugin: Popup closed due to timeout.\n");
|
||||
}
|
||||
|
||||
#else
|
||||
static gboolean popup_timeout_fun(gpointer data)
|
||||
{
|
||||
NotificationPopup *ppopup;
|
||||
NotificationFolderType nftype;
|
||||
|
||||
nftype = GPOINTER_TO_INT(data);
|
||||
|
||||
G_LOCK(popup);
|
||||
|
||||
ppopup = &popup;
|
||||
if(ppopup->window) {
|
||||
gtk_widget_destroy(ppopup->window);
|
||||
ppopup->window = NULL;
|
||||
}
|
||||
ppopup->timeout_id = 0;
|
||||
|
||||
if(ppopup->msg_path) {
|
||||
g_free(ppopup->msg_path);
|
||||
ppopup->msg_path = NULL;
|
||||
}
|
||||
ppopup->count = 0;
|
||||
G_UNLOCK(popup);
|
||||
debug_print("Notification Plugin: Popup closed due to timeout.\n");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
static void default_action_cb(NotifyNotification *notification,
|
||||
const char *action,
|
||||
void *user_data)
|
||||
{
|
||||
if(strcmp("default", action))
|
||||
return;
|
||||
|
||||
MainWindow *mainwin;
|
||||
mainwin = mainwindow_get_mainwindow();
|
||||
if(mainwin) {
|
||||
NotificationFolderType nftype;
|
||||
|
||||
/* Let mainwindow pop up */
|
||||
notification_show_mainwindow(mainwin);
|
||||
/* If there is only one new mail message, jump to this message */
|
||||
nftype = (NotificationFolderType)GPOINTER_TO_INT(user_data);
|
||||
if(nftype == F_TYPE_MAIL) {
|
||||
if(popup[F_TYPE_MAIL].count == 1) {
|
||||
gchar *select_str;
|
||||
G_LOCK(popup);
|
||||
select_str = g_strdup(popup[F_TYPE_MAIL].msg_path);
|
||||
G_UNLOCK(popup);
|
||||
debug_print("Select message %s\n", select_str);
|
||||
mainwindow_jump_to(select_str, FALSE);
|
||||
g_free(select_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean notification_libnotify_create(MsgInfo *msginfo,
|
||||
NotificationFolderType nftype)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
NotificationPopup *ppopup;
|
||||
gchar *summary = NULL;
|
||||
gchar *text = NULL;
|
||||
gchar *utf8_str = NULL;
|
||||
gchar *subj = NULL;
|
||||
gchar *from = NULL;
|
||||
gchar *foldname = NULL;
|
||||
GList *caps = NULL;
|
||||
gboolean support_actions = FALSE;
|
||||
|
||||
g_return_val_if_fail(msginfo, FALSE);
|
||||
|
||||
ppopup = &(popup[nftype]);
|
||||
|
||||
/* init libnotify if necessary */
|
||||
if(!notify_is_initted()) {
|
||||
if(!notify_init("claws-mail")) {
|
||||
debug_print("Notification Plugin: Failed to initialize libnotify. "
|
||||
"No popup will be shown.\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
switch(nftype) {
|
||||
case F_TYPE_MAIL:
|
||||
summary = _("New Mail message");
|
||||
from = notification_libnotify_sanitize_str(msginfo->from ?
|
||||
msginfo->from : _("(No From)"));
|
||||
subj = notification_libnotify_sanitize_str(msginfo->subject ?
|
||||
msginfo->subject : _("(No Subject)"));
|
||||
if (notify_config.popup_display_folder_name) {
|
||||
foldname = notification_libnotify_sanitize_str(msginfo->folder->path);
|
||||
text = g_strconcat(from,"\n\n", subj, "\n\n", foldname, NULL);
|
||||
}
|
||||
else
|
||||
text = g_strconcat(from, "\n\n",subj, NULL);
|
||||
|
||||
/* Make sure text is valid UTF8 */
|
||||
utf8_str = notification_validate_utf8_str(text);
|
||||
g_free(text);
|
||||
|
||||
if(from) g_free(from);
|
||||
if(subj) g_free(subj);
|
||||
if(foldname) g_free(foldname);
|
||||
break;
|
||||
case F_TYPE_NEWS:
|
||||
summary = _("New News post");
|
||||
utf8_str = g_strdup(_("A new message arrived"));
|
||||
break;
|
||||
case F_TYPE_CALENDAR:
|
||||
summary = _("New Calendar message");
|
||||
utf8_str = g_strdup(_("A new calendar message arrived"));
|
||||
break;
|
||||
case F_TYPE_RSS:
|
||||
summary = _("New RSS feed article");
|
||||
utf8_str = g_strdup(_("A new article in a RSS feed arrived"));
|
||||
break;
|
||||
default:
|
||||
summary = _("New unknown message");
|
||||
utf8_str = g_strdup(_("Unknown message type arrived"));
|
||||
break;
|
||||
}
|
||||
|
||||
ppopup->notification = notify_notification_new(summary, utf8_str, NULL
|
||||
#if !NOTIFY_CHECK_VERSION(0, 7, 0)
|
||||
, NULL
|
||||
#endif
|
||||
);
|
||||
g_free(utf8_str);
|
||||
if(ppopup->notification == NULL) {
|
||||
debug_print("Notification Plugin: Failed to create a new "
|
||||
"notification.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
caps = notify_get_server_caps();
|
||||
if(caps != NULL) {
|
||||
GList *c;
|
||||
for(c = caps; c != NULL; c = c->next) {
|
||||
if(strcmp((char*)c->data, "actions") == 0 ) {
|
||||
support_actions = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_list_foreach(caps, (GFunc)g_free, NULL);
|
||||
g_list_free(caps);
|
||||
}
|
||||
|
||||
/* Default action */
|
||||
if (support_actions)
|
||||
notify_notification_add_action(ppopup->notification,
|
||||
"default", "Present main window",
|
||||
(NotifyActionCallback)default_action_cb,
|
||||
GINT_TO_POINTER(nftype),
|
||||
notification_libnotify_free_func);
|
||||
|
||||
/* Icon */
|
||||
pixbuf = NULL;
|
||||
#ifndef USE_NEW_ADDRBOOK
|
||||
if(msginfo && msginfo->from) {
|
||||
gchar *icon_path;
|
||||
icon_path = addrindex_get_picture_file(msginfo->from);
|
||||
if(is_file_exist(icon_path)) {
|
||||
GError *error = NULL;
|
||||
gint w, h;
|
||||
|
||||
gdk_pixbuf_get_file_info(icon_path, &w, &h);
|
||||
if((w > 64) || (h > 64))
|
||||
pixbuf = gdk_pixbuf_new_from_file_at_scale(icon_path,
|
||||
64, 64, TRUE, &error);
|
||||
else
|
||||
pixbuf = gdk_pixbuf_new_from_file(icon_path, &error);
|
||||
|
||||
if(!pixbuf) {
|
||||
debug_print("Could not load picture file: %s\n",
|
||||
error ? error->message : "no details");
|
||||
g_error_free(error);
|
||||
}
|
||||
}
|
||||
else
|
||||
debug_print("Picture path does not exist: %s\n",icon_path);
|
||||
g_free(icon_path);
|
||||
}
|
||||
#endif
|
||||
if(!pixbuf)
|
||||
pixbuf = g_object_ref(notification_pixbuf_get(NOTIFICATION_CM_LOGO_64x64));
|
||||
|
||||
if(pixbuf) {
|
||||
notify_notification_set_icon_from_pixbuf(ppopup->notification, pixbuf);
|
||||
g_object_unref(pixbuf);
|
||||
}
|
||||
else /* This is not fatal */
|
||||
debug_print("Notification plugin: Icon could not be loaded.\n");
|
||||
|
||||
/* timeout */
|
||||
notify_notification_set_timeout(ppopup->notification, notify_config.popup_timeout);
|
||||
|
||||
/* Category */
|
||||
notify_notification_set_category(ppopup->notification, "email.arrived");
|
||||
|
||||
/* get notified on bubble close */
|
||||
g_signal_connect(G_OBJECT(popup->notification), "closed", G_CALLBACK(popup_timeout_fun), NULL);
|
||||
|
||||
/* Show the popup */
|
||||
notify_notification_set_hint_string(ppopup->notification, "desktop-entry", "claws-mail");
|
||||
if(!notify_notification_show(ppopup->notification, &(ppopup->error))) {
|
||||
debug_print("Notification Plugin: Failed to send notification: %s\n",
|
||||
ppopup->error->message);
|
||||
g_clear_error(&(ppopup->error));
|
||||
g_object_unref(G_OBJECT(ppopup->notification));
|
||||
ppopup->notification = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
debug_print("Notification Plugin: Popup created with libnotify.\n");
|
||||
ppopup->count = 1;
|
||||
|
||||
/* Store path to message */
|
||||
if(nftype == F_TYPE_MAIL) {
|
||||
if(msginfo->folder && msginfo->folder) {
|
||||
gchar *ident;
|
||||
ident = folder_item_get_identifier(msginfo->folder);
|
||||
ppopup->msg_path = g_strdup_printf("%s%s%u", ident,G_DIR_SEPARATOR_S,
|
||||
msginfo->msgnum);
|
||||
g_free(ident);
|
||||
}
|
||||
else
|
||||
ppopup->msg_path = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean notification_libnotify_add_msg(MsgInfo *msginfo,
|
||||
NotificationFolderType nftype)
|
||||
{
|
||||
gchar *summary;
|
||||
gchar *text;
|
||||
gboolean retval;
|
||||
NotificationPopup *ppopup;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
ppopup = &(popup[nftype]);
|
||||
|
||||
if(!ppopup->notification)
|
||||
return notification_libnotify_create(msginfo,nftype);
|
||||
|
||||
ppopup->count++;
|
||||
|
||||
if(ppopup->msg_path) {
|
||||
g_free(ppopup->msg_path);
|
||||
ppopup->msg_path = NULL;
|
||||
}
|
||||
|
||||
/* make sure we show a logo on many msg arrival */
|
||||
pixbuf = notification_pixbuf_get(NOTIFICATION_CM_LOGO_64x64);
|
||||
if(pixbuf)
|
||||
notify_notification_set_icon_from_pixbuf(ppopup->notification, pixbuf);
|
||||
|
||||
switch(nftype) {
|
||||
case F_TYPE_MAIL:
|
||||
summary = _("Mail message");
|
||||
text = g_strdup_printf(ngettext("%d new message arrived",
|
||||
"%d new messages arrived",
|
||||
ppopup->count), ppopup->count);
|
||||
break;
|
||||
case F_TYPE_NEWS:
|
||||
summary = _("News message");
|
||||
text = g_strdup_printf(ngettext("%d new message arrived",
|
||||
"%d new messages arrived",
|
||||
ppopup->count), ppopup->count);
|
||||
break;
|
||||
case F_TYPE_CALENDAR:
|
||||
summary = _("Calendar message");
|
||||
text = g_strdup_printf(ngettext("%d new calendar message arrived",
|
||||
"%d new calendar messages arrived",
|
||||
ppopup->count), ppopup->count);
|
||||
break;
|
||||
case F_TYPE_RSS:
|
||||
summary = _("RSS news feed");
|
||||
text = g_strdup_printf(ngettext("%d new article in a RSS feed arrived",
|
||||
"%d new articles in a RSS feed arrived",
|
||||
ppopup->count), ppopup->count);
|
||||
break;
|
||||
default:
|
||||
/* Should not happen */
|
||||
debug_print("Notification Plugin: Unknown folder type ignored\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
retval = notify_notification_update(ppopup->notification, summary,
|
||||
text, NULL);
|
||||
g_free(text);
|
||||
if(!retval) {
|
||||
debug_print("Notification Plugin: Failed to update notification.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Show the popup */
|
||||
notify_notification_set_hint_string(ppopup->notification, "desktop-entry", "claws-mail");
|
||||
if(!notify_notification_show(ppopup->notification, &(ppopup->error))) {
|
||||
debug_print("Notification Plugin: Failed to send updated notification: "
|
||||
"%s\n", ppopup->error->message);
|
||||
g_clear_error(&(ppopup->error));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
debug_print("Notification Plugin: Popup successfully modified "
|
||||
"with libnotify.\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void notification_libnotify_free_func(gpointer data)
|
||||
{
|
||||
if(popup[F_TYPE_MAIL].msg_path) {
|
||||
g_free(popup[F_TYPE_MAIL].msg_path);
|
||||
popup[F_TYPE_MAIL].msg_path = NULL;
|
||||
}
|
||||
debug_print("Freed notification data\n");
|
||||
}
|
||||
|
||||
#else /* !HAVE_LIBNOTIFY */
|
||||
static gboolean notification_popup_add_msg(MsgInfo *msginfo)
|
||||
{
|
||||
gchar *message;
|
||||
NotificationPopup *ppopup;
|
||||
|
||||
ppopup = &popup;
|
||||
|
||||
if(!ppopup->window)
|
||||
return notification_popup_create(msginfo);
|
||||
|
||||
ppopup->count++;
|
||||
|
||||
if(ppopup->msg_path) {
|
||||
g_free(ppopup->msg_path);
|
||||
ppopup->msg_path = NULL;
|
||||
}
|
||||
|
||||
if(ppopup->label2)
|
||||
gtk_widget_destroy(ppopup->label2);
|
||||
|
||||
message = g_strdup_printf(ngettext("%d new message",
|
||||
"%d new messages",
|
||||
ppopup->count), ppopup->count);
|
||||
gtk_label_set_text(GTK_LABEL(ppopup->label1), message);
|
||||
g_free(message);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean notification_popup_create(MsgInfo *msginfo)
|
||||
{
|
||||
GdkColor bg;
|
||||
GdkColor fg;
|
||||
NotificationPopup *ppopup;
|
||||
|
||||
g_return_val_if_fail(msginfo, FALSE);
|
||||
|
||||
ppopup = &popup;
|
||||
|
||||
/* Window */
|
||||
ppopup->window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "notification_popup");
|
||||
gtk_window_set_decorated(GTK_WINDOW(ppopup->window), FALSE);
|
||||
gtk_window_set_keep_above(GTK_WINDOW(ppopup->window), TRUE);
|
||||
gtk_window_set_accept_focus(GTK_WINDOW(ppopup->window), FALSE);
|
||||
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(ppopup->window), TRUE);
|
||||
gtk_window_set_skip_pager_hint(GTK_WINDOW(ppopup->window), TRUE);
|
||||
gtk_window_move(GTK_WINDOW(ppopup->window), notify_config.popup_root_x,
|
||||
notify_config.popup_root_y);
|
||||
gtk_window_resize(GTK_WINDOW(ppopup->window), notify_config.popup_width, 1);
|
||||
if(notify_config.popup_sticky)
|
||||
gtk_window_stick(GTK_WINDOW(ppopup->window));
|
||||
/* Signals */
|
||||
gtk_widget_set_events(ppopup->window,
|
||||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
|
||||
g_signal_connect(ppopup->window, "button_press_event",
|
||||
G_CALLBACK(notification_popup_button), NULL);
|
||||
|
||||
/* Event box */
|
||||
ppopup->event_box = gtk_event_box_new();
|
||||
gtk_container_add(GTK_CONTAINER(ppopup->window), ppopup->event_box);
|
||||
|
||||
/* Frame */
|
||||
ppopup->frame = gtk_frame_new(NULL);
|
||||
gtk_frame_set_shadow_type(GTK_FRAME(ppopup->frame), GTK_SHADOW_ETCHED_OUT);
|
||||
gtk_container_add(GTK_CONTAINER(ppopup->event_box), ppopup->frame);
|
||||
|
||||
/* Vbox with labels */
|
||||
ppopup->vbox = gtk_vbox_new(FALSE, 2);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(ppopup->vbox), 5);
|
||||
ppopup->label1 = gtk_label_new(msginfo->from ?
|
||||
msginfo->from : _("(No From)"));
|
||||
gtk_box_pack_start(GTK_BOX(ppopup->vbox), ppopup->label1, FALSE, FALSE, 0);
|
||||
|
||||
ppopup->label2 = gtk_label_new(msginfo->subject ?
|
||||
msginfo->subject : _("(No Subject)"));
|
||||
gtk_box_pack_start(GTK_BOX(ppopup->vbox), ppopup->label2, FALSE, FALSE, 0);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(ppopup->frame), ppopup->vbox);
|
||||
gtk_widget_set_size_request(ppopup->vbox, notify_config.popup_width, -1);
|
||||
|
||||
/* Color */
|
||||
if(notify_config.popup_enable_colors) {
|
||||
gtkut_convert_int_to_gdk_color(notify_config.popup_color_bg,&bg);
|
||||
gtkut_convert_int_to_gdk_color(notify_config.popup_color_fg,&fg);
|
||||
gtk_widget_modify_bg(ppopup->event_box,GTK_STATE_NORMAL,&bg);
|
||||
gtk_widget_modify_fg(ppopup->label1,GTK_STATE_NORMAL,&fg);
|
||||
gtk_widget_modify_fg(ppopup->label2,GTK_STATE_NORMAL,&fg);
|
||||
}
|
||||
|
||||
gtk_widget_show_all(ppopup->window);
|
||||
|
||||
ppopup->count = 1;
|
||||
|
||||
if(msginfo->folder && msginfo->folder->name) {
|
||||
gchar *ident;
|
||||
ident = folder_item_get_identifier(msginfo->folder);
|
||||
ppopup->msg_path = g_strdup_printf("%s%s%u", ident,G_DIR_SEPARATOR_S,
|
||||
msginfo->msgnum);
|
||||
g_free(ident);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean notification_popup_button(GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
gpointer data)
|
||||
{
|
||||
if(event->type == GDK_BUTTON_PRESS) {
|
||||
if(event->button == 1) {
|
||||
MainWindow *mainwin;
|
||||
/* Let mainwindow pop up */
|
||||
mainwin = mainwindow_get_mainwindow();
|
||||
if(!mainwin)
|
||||
return TRUE;
|
||||
notification_show_mainwindow(mainwin);
|
||||
/* If there is only one new mail message, jump to this message */
|
||||
if(popup.count == 1) {
|
||||
gchar *select_str;
|
||||
G_LOCK(popup);
|
||||
select_str = g_strdup(popup.msg_path);
|
||||
G_UNLOCK(popup);
|
||||
debug_print("Select message %s\n", select_str);
|
||||
mainwindow_jump_to(select_str, FALSE);
|
||||
g_free(select_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* !HAVE_LIBNOTIFY */
|
||||
|
||||
#endif /* NOTIFICATION_POPUP */
|
33
src/plugins/notification/notification_popup.h
Normal file
33
src/plugins/notification/notification_popup.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_POPUP_H
|
||||
#define NOTIFICATION_POPUP_H NOTIFICATION_POPUP_H
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_POPUP
|
||||
|
||||
#include "procmsg.h"
|
||||
|
||||
#define POPUP_SPECIFIC_FOLDER_ID_STR "popup"
|
||||
|
||||
void notification_popup_msg(MsgInfo*);
|
||||
|
||||
#endif /* NOTIFICATION_POPUP */
|
||||
|
||||
#endif /* NOTIFICATION_POPUP_H */
|
1952
src/plugins/notification/notification_prefs.c
Normal file
1952
src/plugins/notification/notification_prefs.c
Normal file
File diff suppressed because it is too large
Load diff
118
src/plugins/notification/notification_prefs.h
Normal file
118
src/plugins/notification/notification_prefs.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_PREFS_H
|
||||
#define NOTIFICATION_PREFS_H NOTIFICATION_PREFS_H
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "prefs_gtk.h"
|
||||
|
||||
#include "notification_banner.h"
|
||||
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
typedef enum {
|
||||
NOTIFY_BANNER_SHOW_NEVER = 0,
|
||||
NOTIFY_BANNER_SHOW_ALWAYS,
|
||||
NOTIFY_BANNER_SHOW_NONEMPTY
|
||||
} NotifyBannerShow;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
gboolean include_mail;
|
||||
gboolean include_news;
|
||||
gboolean include_rss;
|
||||
gboolean include_calendar;
|
||||
gboolean urgency_hint_new;
|
||||
gboolean urgency_hint_unread;
|
||||
#ifdef HAVE_LIBCANBERRA_GTK
|
||||
gboolean canberra_play_sounds;
|
||||
#endif
|
||||
#ifdef NOTIFICATION_BANNER
|
||||
NotifyBannerShow banner_show;
|
||||
gint banner_speed;
|
||||
gboolean banner_include_unread;
|
||||
gint banner_max_msgs;
|
||||
gboolean banner_sticky;
|
||||
gint banner_root_x;
|
||||
gint banner_root_y;
|
||||
gboolean banner_folder_specific;
|
||||
gboolean banner_enable_colors;
|
||||
gulong banner_color_bg;
|
||||
gulong banner_color_fg;
|
||||
gint banner_width;
|
||||
#endif
|
||||
#ifdef NOTIFICATION_POPUP
|
||||
gboolean popup_show;
|
||||
gint popup_timeout;
|
||||
gboolean popup_folder_specific;
|
||||
#ifndef HAVE_LIBNOTIFY
|
||||
gboolean popup_sticky;
|
||||
gint popup_root_x;
|
||||
gint popup_root_y;
|
||||
gint popup_width;
|
||||
gboolean popup_enable_colors;
|
||||
gulong popup_color_bg;
|
||||
gulong popup_color_fg;
|
||||
#else /* HAVE_LIBNOTIFY */
|
||||
gboolean popup_display_folder_name;
|
||||
#endif /* HAVE_LIBNOTIFY */
|
||||
#endif /* Popup */
|
||||
#ifdef NOTIFICATION_COMMAND
|
||||
gboolean command_enabled;
|
||||
gint command_timeout;
|
||||
gboolean command_folder_specific;
|
||||
gchar* command_line;
|
||||
#endif
|
||||
#ifdef NOTIFICATION_LCDPROC
|
||||
gboolean lcdproc_enabled;
|
||||
gchar* lcdproc_hostname;
|
||||
guint lcdproc_port;
|
||||
|
||||
#endif
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
gboolean trayicon_enabled;
|
||||
gboolean trayicon_hide_at_startup;
|
||||
gboolean trayicon_close_to_tray;
|
||||
gboolean trayicon_hide_when_iconified;
|
||||
gboolean trayicon_folder_specific;
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
gboolean trayicon_display_folder_name;
|
||||
gboolean trayicon_popup_enabled;
|
||||
gint trayicon_popup_timeout;
|
||||
#endif /* HAVE_LIBNOTIFY */
|
||||
#endif /* Trayicon */
|
||||
#ifdef NOTIFICATION_INDICATOR
|
||||
gboolean indicator_enabled;
|
||||
gboolean indicator_hide_minimized;
|
||||
#endif /* NOTIFICATION_INDICATOR */
|
||||
#ifdef NOTIFICATION_HOTKEYS
|
||||
gboolean hotkeys_enabled;
|
||||
gchar* hotkeys_toggle_mainwindow;
|
||||
#endif /* Hotkeys */
|
||||
} NotifyPrefs;
|
||||
|
||||
extern NotifyPrefs notify_config;
|
||||
extern PrefParam notify_param[];
|
||||
|
||||
void notify_gtk_init(void);
|
||||
void notify_gtk_done(void);
|
||||
void notify_save_config(void);
|
||||
|
||||
#endif /* NOTIFICATION_PREFS_H */
|
948
src/plugins/notification/notification_trayicon.c
Normal file
948
src/plugins/notification/notification_trayicon.c
Normal file
|
@ -0,0 +1,948 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt and the Claws Mail Team.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This module is of course inspired by the trayicon plugin which is
|
||||
* shipped with Claws-Mail, copyrighted by the Claws-Mail Team. */
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
|
||||
#include "notification_trayicon.h"
|
||||
#include "notification_prefs.h"
|
||||
#include "notification_core.h"
|
||||
#include "notification_hotkeys.h"
|
||||
#include "notification_pixbuf.h"
|
||||
#include "notification_foldercheck.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "account.h"
|
||||
#include "mainwindow.h"
|
||||
#include "prefs_common.h"
|
||||
#include "alertpanel.h"
|
||||
#include "gtk/menu.h"
|
||||
#ifndef USE_NEW_ADDRBOOK
|
||||
#include "addressbook.h"
|
||||
#include "addrindex.h"
|
||||
#else
|
||||
#include "addressbook-dbus.h"
|
||||
#endif
|
||||
|
||||
#include "gtk/manage_window.h"
|
||||
#include "common/utils.h"
|
||||
#include "gtk/gtkutils.h"
|
||||
|
||||
static GdkPixbuf* notification_trayicon_create(void);
|
||||
|
||||
static void notification_trayicon_on_popup_menu(GtkStatusIcon*,guint,
|
||||
guint,gpointer);
|
||||
static gboolean notification_trayicon_on_size_changed(GtkStatusIcon*,
|
||||
gint, gpointer);
|
||||
|
||||
static void trayicon_get_all_cb(GtkAction*, gpointer);
|
||||
static void trayicon_compose_cb(GtkAction*, gpointer);
|
||||
static void trayicon_compose_acc_cb(GtkMenuItem*, gpointer);
|
||||
static void trayicon_addressbook_cb(GtkAction*, gpointer);
|
||||
static void trayicon_exit_cb(GtkAction*,gpointer);
|
||||
static void trayicon_toggle_offline_cb(GtkAction*,gpointer);
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
static void trayicon_toggle_notify_cb(GtkAction*,gpointer);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
#include <libnotify/notify.h>
|
||||
|
||||
#ifndef NOTIFY_CHECK_VERSION
|
||||
# define NOTIFY_CHECK_VERSION(a,b,c) 0
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
gint count;
|
||||
gint num_mail;
|
||||
gint num_news;
|
||||
gint num_calendar;
|
||||
gint num_rss;
|
||||
gchar *msg_path;
|
||||
NotifyNotification *notification;
|
||||
GError *error;
|
||||
} NotificationTrayiconPopup;
|
||||
|
||||
static NotificationTrayiconPopup popup;
|
||||
|
||||
static gboolean notification_trayicon_popup_add_msg(MsgInfo*,
|
||||
NotificationFolderType);
|
||||
static gboolean notification_trayicon_popup_create(MsgInfo*,
|
||||
NotificationFolderType);
|
||||
static void popup_timeout_fun(NotifyNotification*, gpointer);
|
||||
static void notification_trayicon_popup_free_func(gpointer);
|
||||
static void notification_trayicon_popup_default_action_cb(NotifyNotification*,
|
||||
const char*,void*);
|
||||
static gchar* notification_trayicon_popup_assemble_summary(void);
|
||||
static gchar* notification_trayicon_popup_assemble_body(MsgInfo*);
|
||||
static void notification_trayicon_popup_count_msgs(NotificationFolderType);
|
||||
|
||||
G_LOCK_DEFINE_STATIC(trayicon_popup);
|
||||
|
||||
#endif
|
||||
|
||||
static GtkStatusIcon *trayicon;
|
||||
static gboolean updating_menu = FALSE;
|
||||
static GtkWidget *traymenu_popup;
|
||||
|
||||
static GtkActionEntry trayicon_popup_menu_entries[] = {
|
||||
{"SysTrayiconPopup", NULL, "SysTrayiconPopup" },
|
||||
{"SysTrayiconPopup/GetMail", NULL, N_("_Get Mail"), NULL, NULL, G_CALLBACK(trayicon_get_all_cb) },
|
||||
{"SysTrayiconPopup/---", NULL, "---" },
|
||||
{"SysTrayiconPopup/Email", NULL, N_("_Email"), NULL, NULL, G_CALLBACK(trayicon_compose_cb) },
|
||||
{"SysTrayiconPopup/EmailAcc", NULL, N_("E_mail from account"), NULL, NULL, NULL },
|
||||
{"SysTrayiconPopup/OpenAB", NULL, N_("Open A_ddressbook"), NULL, NULL, G_CALLBACK(trayicon_addressbook_cb) },
|
||||
{"SysTrayiconPopup/Exit", NULL, N_("E_xit Claws Mail"), NULL, NULL, G_CALLBACK(trayicon_exit_cb) },
|
||||
};
|
||||
|
||||
static GtkToggleActionEntry trayicon_popup_toggle_menu_entries[] =
|
||||
{
|
||||
{"SysTrayiconPopup/ToggleOffline", NULL, N_("_Work Offline"), NULL, NULL, G_CALLBACK(trayicon_toggle_offline_cb) },
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
{"SysTrayiconPopup/ShowBubbles", NULL, N_("Show Trayicon Notifications"), NULL, NULL, G_CALLBACK(trayicon_toggle_notify_cb) },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void notification_trayicon_msg(MsgInfo *msginfo)
|
||||
{
|
||||
#ifndef HAVE_LIBNOTIFY
|
||||
return;
|
||||
|
||||
#else
|
||||
FolderType ftype;
|
||||
NotificationFolderType nftype;
|
||||
gchar *uistr;
|
||||
|
||||
nftype = F_TYPE_MAIL;
|
||||
|
||||
if(!msginfo || !notify_config.trayicon_enabled ||
|
||||
!notify_config.trayicon_popup_enabled ||
|
||||
!MSG_IS_NEW(msginfo->flags))
|
||||
return;
|
||||
|
||||
if(notify_config.trayicon_folder_specific) {
|
||||
guint id;
|
||||
GSList *list;
|
||||
gchar *identifier;
|
||||
gboolean found = FALSE;
|
||||
|
||||
if(!(msginfo->folder))
|
||||
return;
|
||||
|
||||
identifier = folder_item_get_identifier(msginfo->folder);
|
||||
|
||||
id =
|
||||
notification_register_folder_specific_list
|
||||
(TRAYICON_SPECIFIC_FOLDER_ID_STR);
|
||||
list = notification_foldercheck_get_list(id);
|
||||
for(; (list != NULL) && !found; list = g_slist_next(list)) {
|
||||
gchar *list_identifier;
|
||||
FolderItem *list_item = (FolderItem*) list->data;
|
||||
|
||||
list_identifier = folder_item_get_identifier(list_item);
|
||||
if(!strcmp2(list_identifier, identifier))
|
||||
found = TRUE;
|
||||
|
||||
g_free(list_identifier);
|
||||
}
|
||||
g_free(identifier);
|
||||
|
||||
if(!found)
|
||||
return;
|
||||
} /* folder specific */
|
||||
|
||||
ftype = msginfo->folder->folder->klass->type;
|
||||
|
||||
G_LOCK(trayicon_popup);
|
||||
/* Check out which type to notify about */
|
||||
switch(ftype) {
|
||||
case F_MH:
|
||||
case F_MBOX:
|
||||
case F_MAILDIR:
|
||||
case F_IMAP:
|
||||
nftype = F_TYPE_MAIL;
|
||||
break;
|
||||
case F_NEWS:
|
||||
nftype = F_TYPE_NEWS;
|
||||
break;
|
||||
case F_UNKNOWN:
|
||||
if((uistr = msginfo->folder->folder->klass->uistr) == NULL) {
|
||||
G_UNLOCK(trayicon_popup);
|
||||
return;
|
||||
}
|
||||
else if(!strcmp(uistr, "vCalendar"))
|
||||
nftype = F_TYPE_CALENDAR;
|
||||
else if(!strcmp(uistr, "RSSyl"))
|
||||
nftype = F_TYPE_RSS;
|
||||
else {
|
||||
debug_print("Notification Plugin: Unknown folder type %d\n",ftype);
|
||||
G_UNLOCK(trayicon_popup);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
debug_print("Notification Plugin: Unknown folder type %d\n",ftype);
|
||||
G_UNLOCK(trayicon_popup);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
notification_trayicon_popup_add_msg(msginfo, nftype);
|
||||
|
||||
G_UNLOCK(trayicon_popup);
|
||||
|
||||
#endif /* HAVE_LIBNOTIFY */
|
||||
}
|
||||
|
||||
void notification_trayicon_destroy(void)
|
||||
{
|
||||
if(trayicon) {
|
||||
gtk_status_icon_set_visible(trayicon, FALSE);
|
||||
g_object_unref(trayicon);
|
||||
trayicon = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void notification_update_trayicon()
|
||||
{
|
||||
gchar *buf;
|
||||
static GdkPixbuf *old_icon = NULL;
|
||||
GdkPixbuf *new_icon;
|
||||
gint offset;
|
||||
NotificationMsgCount count;
|
||||
GSList *list;
|
||||
|
||||
if(!notify_config.trayicon_enabled)
|
||||
return;
|
||||
|
||||
if(notify_config.trayicon_folder_specific) {
|
||||
guint id;
|
||||
id =
|
||||
notification_register_folder_specific_list
|
||||
(TRAYICON_SPECIFIC_FOLDER_ID_STR);
|
||||
list = notification_foldercheck_get_list(id);
|
||||
}
|
||||
else
|
||||
list = NULL;
|
||||
|
||||
notification_core_get_msg_count(list, &count);
|
||||
|
||||
if(!trayicon) {
|
||||
|
||||
#ifdef NOTIFICATION_HOTKEYS
|
||||
notification_hotkeys_update_bindings();
|
||||
#endif
|
||||
|
||||
old_icon = notification_trayicon_create();
|
||||
if(!trayicon) {
|
||||
debug_print("Notification plugin: Could not create trayicon\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tooltip */
|
||||
buf = g_strdup_printf(_("New %d, Unread: %d, Total: %d"),
|
||||
count.new_msgs, count.unread_msgs,
|
||||
count.total_msgs);
|
||||
#if GTK_CHECK_VERSION(2,16,0)
|
||||
gtk_status_icon_set_tooltip_text(trayicon, buf);
|
||||
#else
|
||||
gtk_status_icon_set_tooltip(trayicon, buf);
|
||||
#endif
|
||||
g_free(buf);
|
||||
|
||||
/* Pixmap */
|
||||
(prefs_common_get_prefs()->work_offline) ? (offset = 1) : (offset = 0);
|
||||
|
||||
if((count.new_msgs > 0) && (count.unreadmarked_msgs > 0))
|
||||
new_icon =
|
||||
notification_pixbuf_get(NOTIFICATION_TRAYICON_NEWMARKEDMAIL+offset);
|
||||
else if(count.new_msgs > 0)
|
||||
new_icon =
|
||||
notification_pixbuf_get(NOTIFICATION_TRAYICON_NEWMAIL+offset);
|
||||
else if(count.unreadmarked_msgs > 0)
|
||||
new_icon =
|
||||
notification_pixbuf_get(NOTIFICATION_TRAYICON_UNREADMARKEDMAIL+offset);
|
||||
else if(count.unread_msgs > 0)
|
||||
new_icon =
|
||||
notification_pixbuf_get(NOTIFICATION_TRAYICON_UNREADMAIL+offset);
|
||||
else
|
||||
new_icon =
|
||||
notification_pixbuf_get(NOTIFICATION_TRAYICON_NOMAIL+offset);
|
||||
|
||||
if(new_icon != old_icon) {
|
||||
gtk_status_icon_set_from_pixbuf(trayicon, new_icon);
|
||||
old_icon = new_icon;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean notification_trayicon_main_window_close(gpointer source, gpointer data)
|
||||
{
|
||||
if(!notify_config.trayicon_enabled)
|
||||
return FALSE;
|
||||
|
||||
if(source) {
|
||||
gboolean *close_allowed = (gboolean*)source;
|
||||
|
||||
if(notify_config.trayicon_close_to_tray) {
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
|
||||
*close_allowed = FALSE;
|
||||
if(mainwin && gtk_widget_get_visible(GTK_WIDGET(mainwin->window)))
|
||||
main_window_hide(mainwin);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean notification_trayicon_main_window_got_iconified(gpointer source,
|
||||
gpointer data)
|
||||
{
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
|
||||
if(!notify_config.trayicon_enabled)
|
||||
return FALSE;
|
||||
|
||||
if(notify_config.trayicon_hide_when_iconified &&
|
||||
mainwin && gtk_widget_get_visible(GTK_WIDGET(mainwin->window))
|
||||
&& !gtk_window_get_skip_taskbar_hint(GTK_WINDOW(mainwin->window))) {
|
||||
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(mainwin->window), TRUE);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean notification_trayicon_account_list_changed(gpointer source,
|
||||
gpointer data)
|
||||
{
|
||||
GList *cur_ac;
|
||||
GtkWidget *menu, *submenu;
|
||||
GtkWidget *menuitem;
|
||||
PrefsAccount *ac_prefs;
|
||||
|
||||
GList *account_list = account_get_list();
|
||||
|
||||
if(!notify_config.trayicon_enabled)
|
||||
return FALSE;
|
||||
|
||||
menu = gtk_ui_manager_get_widget(gtkut_ui_manager(), "/Menus/SysTrayiconPopup/EmailAcc");
|
||||
gtk_widget_show(menu);
|
||||
|
||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu), NULL);
|
||||
submenu = gtk_menu_new();
|
||||
|
||||
for(cur_ac = account_list; cur_ac != NULL; cur_ac = cur_ac->next) {
|
||||
ac_prefs = (PrefsAccount *)cur_ac->data;
|
||||
|
||||
menuitem = gtk_menu_item_new_with_label
|
||||
(ac_prefs->account_name ? ac_prefs->account_name
|
||||
: _("Untitled"));
|
||||
gtk_widget_show(menuitem);
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
|
||||
g_signal_connect(G_OBJECT(menuitem), "activate",
|
||||
G_CALLBACK(trayicon_compose_acc_cb),
|
||||
ac_prefs);
|
||||
}
|
||||
gtk_widget_show(submenu);
|
||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu), submenu);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkPixbuf* notification_trayicon_create(void)
|
||||
{
|
||||
GdkPixbuf *trayicon_nomail;
|
||||
GtkActionGroup *action_group;
|
||||
|
||||
trayicon_nomail = notification_pixbuf_get(NOTIFICATION_TRAYICON_NOMAIL);
|
||||
|
||||
notification_trayicon_destroy();
|
||||
|
||||
trayicon = gtk_status_icon_new_from_pixbuf(trayicon_nomail);
|
||||
|
||||
g_signal_connect(G_OBJECT(trayicon), "activate",
|
||||
G_CALLBACK(notification_trayicon_on_activate), NULL);
|
||||
g_signal_connect(G_OBJECT(trayicon), "popup-menu",
|
||||
G_CALLBACK(notification_trayicon_on_popup_menu), NULL);
|
||||
g_signal_connect(G_OBJECT(trayicon), "size-changed",
|
||||
G_CALLBACK(notification_trayicon_on_size_changed), NULL);
|
||||
|
||||
/* Popup-Menu */
|
||||
action_group = cm_menu_create_action_group("SysTrayiconPopup", trayicon_popup_menu_entries,
|
||||
G_N_ELEMENTS(trayicon_popup_menu_entries), NULL);
|
||||
gtk_action_group_add_toggle_actions(action_group, trayicon_popup_toggle_menu_entries,
|
||||
G_N_ELEMENTS(trayicon_popup_toggle_menu_entries), NULL);
|
||||
|
||||
MENUITEM_ADDUI("/Menus", "SysTrayiconPopup", "SysTrayiconPopup", GTK_UI_MANAGER_MENU)
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "GetMail", "SysTrayiconPopup/GetMail", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Separator1", "SysTrayiconPopup/---", GTK_UI_MANAGER_SEPARATOR)
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Email", "SysTrayiconPopup/Email", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "EmailAcc", "SysTrayiconPopup/EmailAcc", GTK_UI_MANAGER_MENU)
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Separator2", "SysTrayiconPopup/---", GTK_UI_MANAGER_SEPARATOR)
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "OpenAB", "SysTrayiconPopup/OpenAB", GTK_UI_MANAGER_MENUITEM)
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Separator3", "SysTrayiconPopup/---", GTK_UI_MANAGER_SEPARATOR)
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "ToggleOffline", "SysTrayiconPopup/ToggleOffline", GTK_UI_MANAGER_MENUITEM)
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "ShowBubbles", "SysTrayiconPopup/ShowBubbles", GTK_UI_MANAGER_MENUITEM)
|
||||
#endif
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Separator4", "SysTrayiconPopup/---", GTK_UI_MANAGER_SEPARATOR)
|
||||
MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Exit", "SysTrayiconPopup/Exit", GTK_UI_MANAGER_MENUITEM)
|
||||
|
||||
traymenu_popup = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
|
||||
gtk_ui_manager_get_widget(gtkut_ui_manager(), "/Menus/SysTrayiconPopup")));
|
||||
|
||||
|
||||
return trayicon_nomail;
|
||||
}
|
||||
|
||||
void notification_trayicon_on_activate(GtkStatusIcon *status_icon, gpointer user_data)
|
||||
{
|
||||
notification_toggle_hide_show_window();
|
||||
}
|
||||
|
||||
static void notification_trayicon_on_popup_menu(GtkStatusIcon *status_icon,
|
||||
guint button, guint activate_time,
|
||||
gpointer user_data)
|
||||
{
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
|
||||
if(!mainwin)
|
||||
return;
|
||||
|
||||
/* tell callbacks to skip any event */
|
||||
updating_menu = TRUE;
|
||||
/* initialize checkitems according to current states */
|
||||
cm_toggle_menu_set_active("SysTrayiconPopup/ToggleOffline", prefs_common_get_prefs()->work_offline);
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
cm_toggle_menu_set_active("SysTrayiconPopup/ShowBubbles", notify_config.trayicon_popup_enabled);
|
||||
#endif
|
||||
cm_menu_set_sensitive("SysTrayiconPopup/GetMail", mainwin->lock_count == 0);
|
||||
|
||||
updating_menu = FALSE;
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
gtk_menu_popup(GTK_MENU(traymenu_popup), NULL, NULL, NULL, NULL,
|
||||
button, activate_time);
|
||||
#else
|
||||
/* http://bugzilla.gnome.org/show_bug.cgi?id=552642 */
|
||||
gtk_menu_popup(GTK_MENU(traymenu_popup), NULL, NULL, NULL, NULL,
|
||||
0, activate_time);
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean notification_trayicon_on_size_changed(GtkStatusIcon *icon,
|
||||
gint size,
|
||||
gpointer user_data)
|
||||
{
|
||||
notification_update_msg_counts(NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* popup menu callbacks */
|
||||
static void trayicon_get_all_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
inc_all_account_mail_cb(mainwin, 0, NULL);
|
||||
}
|
||||
|
||||
static void trayicon_compose_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
compose_mail_cb(mainwin, 0, NULL);
|
||||
}
|
||||
|
||||
static void trayicon_compose_acc_cb(GtkMenuItem *menuitem, gpointer data)
|
||||
{
|
||||
compose_new((PrefsAccount *)data, NULL, NULL);
|
||||
}
|
||||
|
||||
static void trayicon_addressbook_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
#ifndef USE_NEW_ADDRBOOK
|
||||
addressbook_open(NULL);
|
||||
#else
|
||||
GError* error = NULL;
|
||||
|
||||
addressbook_dbus_open(FALSE, &error);
|
||||
if (error) {
|
||||
g_warning("%s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void trayicon_toggle_offline_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
/* toggle offline mode if menu checkitem has been clicked */
|
||||
if(!updating_menu) {
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
main_window_toggle_work_offline(mainwin, !prefs_common_get_prefs()->work_offline, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
static void trayicon_toggle_notify_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
if(!updating_menu) {
|
||||
notify_config.trayicon_popup_enabled = !notify_config.trayicon_popup_enabled;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void app_exit_cb(MainWindow *mainwin, guint action, GtkWidget *widget)
|
||||
{
|
||||
if(prefs_common_get_prefs()->confirm_on_exit) {
|
||||
if(alertpanel(_("Exit"), _("Exit Claws Mail?"),
|
||||
GTK_STOCK_CANCEL, GTK_STOCK_OK,
|
||||
NULL) != G_ALERTALTERNATE) {
|
||||
return;
|
||||
}
|
||||
manage_window_focus_in(mainwin->window, NULL, NULL);
|
||||
}
|
||||
|
||||
if (prefs_common_get_prefs()->clean_on_exit) {
|
||||
if (!main_window_empty_trash(mainwin, prefs_common_get_prefs()->ask_on_clean, TRUE))
|
||||
return;
|
||||
}
|
||||
|
||||
app_will_exit(NULL, mainwin);
|
||||
}
|
||||
|
||||
static void trayicon_exit_cb(GtkAction *action, gpointer data)
|
||||
{
|
||||
MainWindow *mainwin = mainwindow_get_mainwindow();
|
||||
|
||||
if(mainwin->lock_count == 0) {
|
||||
app_exit_cb(mainwin, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBNOTIFY
|
||||
static gboolean notification_trayicon_popup_add_msg(MsgInfo *msginfo,
|
||||
NotificationFolderType nftype)
|
||||
{
|
||||
gchar *summary;
|
||||
gchar *utf8_str;
|
||||
gboolean retval;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
g_return_val_if_fail(msginfo, FALSE);
|
||||
|
||||
if(!popup.notification)
|
||||
return notification_trayicon_popup_create(msginfo,nftype);
|
||||
|
||||
/* Count messages */
|
||||
notification_trayicon_popup_count_msgs(nftype);
|
||||
|
||||
if(popup.msg_path) {
|
||||
g_free(popup.msg_path);
|
||||
popup.msg_path = NULL;
|
||||
}
|
||||
|
||||
summary = notification_trayicon_popup_assemble_summary();
|
||||
utf8_str = notification_trayicon_popup_assemble_body(msginfo);
|
||||
|
||||
/* make sure we show a logo on many msg arrival */
|
||||
pixbuf = notification_pixbuf_get(NOTIFICATION_CM_LOGO_64x64);
|
||||
if(pixbuf)
|
||||
notify_notification_set_icon_from_pixbuf(popup.notification, pixbuf);
|
||||
|
||||
retval = notify_notification_update(popup.notification, summary,
|
||||
utf8_str, NULL);
|
||||
g_free(summary);
|
||||
g_free(utf8_str);
|
||||
if(!retval) {
|
||||
debug_print("Notification Plugin: Failed to update notification.\n");
|
||||
return FALSE;
|
||||
}
|
||||
/* Show the popup */
|
||||
notify_notification_set_hint_string(popup.notification, "desktop-entry", "claws-mail");
|
||||
if(!notify_notification_show(popup.notification, &(popup.error))) {
|
||||
debug_print("Notification Plugin: Failed to send updated notification: "
|
||||
"%s\n", popup.error->message);
|
||||
g_clear_error(&(popup.error));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
debug_print("Notification Plugin: Popup successfully modified "
|
||||
"with libnotify.\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean notification_trayicon_popup_create(MsgInfo *msginfo,
|
||||
NotificationFolderType nftype)
|
||||
{
|
||||
gchar *summary = NULL;
|
||||
gchar *utf8_str = NULL;
|
||||
GdkPixbuf *pixbuf;
|
||||
GList *caps = NULL;
|
||||
gboolean support_actions = FALSE;
|
||||
|
||||
/* init libnotify if necessary */
|
||||
if(!notify_is_initted()) {
|
||||
if(!notify_init("claws-mail")) {
|
||||
debug_print("Notification Plugin: Failed to initialize libnotify. "
|
||||
"No popups will be shown.\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Count messages */
|
||||
notification_trayicon_popup_count_msgs(nftype);
|
||||
|
||||
summary = notification_trayicon_popup_assemble_summary();
|
||||
utf8_str = notification_trayicon_popup_assemble_body(msginfo);
|
||||
|
||||
#if NOTIFY_CHECK_VERSION(0, 7, 0)
|
||||
popup.notification = notify_notification_new(summary, utf8_str, NULL);
|
||||
#else
|
||||
popup.notification = notify_notification_new(summary, utf8_str, NULL, NULL);
|
||||
notify_notification_attach_to_status_icon(popup.notification, trayicon);
|
||||
#endif
|
||||
|
||||
g_free(summary);
|
||||
g_free(utf8_str);
|
||||
|
||||
caps = notify_get_server_caps();
|
||||
if(caps != NULL) {
|
||||
GList *c;
|
||||
for(c = caps; c != NULL; c = c->next) {
|
||||
if(strcmp((char*)c->data, "actions") == 0 ) {
|
||||
support_actions = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_list_foreach(caps, (GFunc)g_free, NULL);
|
||||
g_list_free(caps);
|
||||
}
|
||||
|
||||
/* Default action */
|
||||
if (support_actions)
|
||||
notify_notification_add_action(popup.notification,
|
||||
"default", "Present main window",
|
||||
(NotifyActionCallback)
|
||||
notification_trayicon_popup_default_action_cb,
|
||||
GINT_TO_POINTER(nftype),
|
||||
notification_trayicon_popup_free_func);
|
||||
|
||||
if(popup.notification == NULL) {
|
||||
debug_print("Notification Plugin: Failed to create a new notification.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Icon */
|
||||
pixbuf = NULL;
|
||||
#ifndef USE_NEW_ADDRBOOK
|
||||
if(msginfo && msginfo->from) {
|
||||
gchar *icon_path;
|
||||
icon_path = addrindex_get_picture_file(msginfo->from);
|
||||
if(is_file_exist(icon_path)) {
|
||||
GError *error = NULL;
|
||||
gint w, h;
|
||||
|
||||
gdk_pixbuf_get_file_info(icon_path, &w, &h);
|
||||
if((w > 64) || (h > 64))
|
||||
pixbuf = gdk_pixbuf_new_from_file_at_scale(icon_path,
|
||||
64, 64, TRUE, &error);
|
||||
else
|
||||
pixbuf = gdk_pixbuf_new_from_file(icon_path, &error);
|
||||
|
||||
if(!pixbuf) {
|
||||
debug_print("Could not load picture file: %s\n",
|
||||
error ? error->message : "no details");
|
||||
g_error_free(error);
|
||||
}
|
||||
}
|
||||
else
|
||||
debug_print("Picture path does not exist: %s\n",icon_path);
|
||||
g_free(icon_path);
|
||||
}
|
||||
#endif
|
||||
if(!pixbuf)
|
||||
pixbuf = g_object_ref(notification_pixbuf_get(NOTIFICATION_CM_LOGO_64x64));
|
||||
|
||||
if(pixbuf) {
|
||||
notify_notification_set_icon_from_pixbuf(popup.notification, pixbuf);
|
||||
g_object_unref(pixbuf);
|
||||
}
|
||||
else /* This is not fatal */
|
||||
debug_print("Notification plugin: Icon could not be loaded.\n");
|
||||
|
||||
/* timeout */
|
||||
notify_notification_set_timeout(popup.notification, notify_config.trayicon_popup_timeout);
|
||||
|
||||
/* Category */
|
||||
notify_notification_set_category(popup.notification, "email.arrived");
|
||||
|
||||
/* get notified on bubble close */
|
||||
g_signal_connect(G_OBJECT(popup.notification), "closed", G_CALLBACK(popup_timeout_fun), NULL);
|
||||
|
||||
/* Show the popup */
|
||||
notify_notification_set_hint_string(popup.notification, "desktop-entry", "claws-mail");
|
||||
if(!notify_notification_show(popup.notification, &(popup.error))) {
|
||||
debug_print("Notification Plugin: Failed to send notification: %s\n",
|
||||
popup.error->message);
|
||||
g_clear_error(&(popup.error));
|
||||
g_object_unref(G_OBJECT(popup.notification));
|
||||
popup.notification = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Store path to message */
|
||||
if(nftype == F_TYPE_MAIL) {
|
||||
if(msginfo->folder && msginfo->folder) {
|
||||
gchar *ident;
|
||||
ident = folder_item_get_identifier(msginfo->folder);
|
||||
popup.msg_path = g_strdup_printf("%s%s%u", ident,G_DIR_SEPARATOR_S,
|
||||
msginfo->msgnum);
|
||||
g_free(ident);
|
||||
}
|
||||
else
|
||||
popup.msg_path = NULL;
|
||||
}
|
||||
|
||||
debug_print("Notification Plugin: Popup created with libnotify.\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void popup_timeout_fun(NotifyNotification *nn, gpointer data)
|
||||
{
|
||||
G_LOCK(trayicon_popup);
|
||||
|
||||
g_object_unref(G_OBJECT(popup.notification));
|
||||
|
||||
popup.notification = NULL;
|
||||
g_clear_error(&(popup.error));
|
||||
|
||||
popup.count = 0;
|
||||
popup.num_mail = 0;
|
||||
popup.num_news = 0;
|
||||
popup.num_calendar = 0;
|
||||
popup.num_rss = 0;
|
||||
|
||||
if(popup.msg_path) {
|
||||
g_free(popup.msg_path);
|
||||
popup.msg_path = NULL;
|
||||
}
|
||||
|
||||
G_UNLOCK(trayicon_popup);
|
||||
}
|
||||
|
||||
static void notification_trayicon_popup_free_func(gpointer data)
|
||||
{
|
||||
if(popup.msg_path) {
|
||||
g_free(popup.msg_path);
|
||||
popup.msg_path = NULL;
|
||||
}
|
||||
|
||||
debug_print("Freed notification data\n");
|
||||
}
|
||||
|
||||
static void notification_trayicon_popup_default_action_cb(NotifyNotification
|
||||
*notification,
|
||||
const char *action,
|
||||
void *user_data)
|
||||
{
|
||||
if(strcmp("default", action))
|
||||
return;
|
||||
|
||||
MainWindow *mainwin;
|
||||
mainwin = mainwindow_get_mainwindow();
|
||||
if(mainwin) {
|
||||
NotificationFolderType nftype;
|
||||
|
||||
/* Let mainwindow pop up */
|
||||
notification_show_mainwindow(mainwin);
|
||||
/* If there is only one new mail message, jump to this message */
|
||||
nftype = (NotificationFolderType)GPOINTER_TO_INT(user_data);
|
||||
if((popup.count == 1) && (nftype == F_TYPE_MAIL)) {
|
||||
gchar *select_str;
|
||||
G_LOCK(trayicon_popup);
|
||||
select_str = g_strdup(popup.msg_path);
|
||||
G_UNLOCK(trayicon_popup);
|
||||
debug_print("Notification plugin: Select message %s\n", select_str);
|
||||
mainwindow_jump_to(select_str, FALSE);
|
||||
g_free(select_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void notification_trayicon_popup_count_msgs(NotificationFolderType nftype)
|
||||
{
|
||||
switch(nftype) {
|
||||
case F_TYPE_MAIL:
|
||||
popup.num_mail++;
|
||||
break;
|
||||
case F_TYPE_NEWS:
|
||||
popup.num_news++;
|
||||
break;
|
||||
case F_TYPE_CALENDAR:
|
||||
popup.num_calendar++;
|
||||
break;
|
||||
case F_TYPE_RSS:
|
||||
popup.num_rss++;
|
||||
break;
|
||||
default:
|
||||
debug_print("Notification plugin: Unknown folder type\n");
|
||||
return;
|
||||
}
|
||||
popup.count++;
|
||||
}
|
||||
|
||||
/* The returned value has to be freed by the caller */
|
||||
static gchar* notification_trayicon_popup_assemble_summary(void)
|
||||
{
|
||||
gchar *summary = NULL;
|
||||
|
||||
if(popup.count == 1) {
|
||||
if(popup.num_mail)
|
||||
summary = g_strdup(_("New mail message"));
|
||||
else if(popup.num_news)
|
||||
summary = g_strdup(_("New news post"));
|
||||
else if(popup.num_calendar)
|
||||
summary = g_strdup(_("New calendar message"));
|
||||
else
|
||||
summary = g_strdup(_("New article in RSS feed"));
|
||||
} /* One new message */
|
||||
else {
|
||||
summary = g_strdup(_("New messages arrived"));
|
||||
} /* Many new messages */
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
/* The returned value has to be freed by the caller */
|
||||
static gchar* notification_trayicon_popup_assemble_body(MsgInfo *msginfo)
|
||||
{
|
||||
gchar *utf8_str;
|
||||
|
||||
if(popup.count == 1) {
|
||||
if(popup.num_mail || popup.num_news) {
|
||||
gchar *from;
|
||||
gchar *subj;
|
||||
gchar *text;
|
||||
gchar *foldname = NULL;
|
||||
|
||||
from = notification_libnotify_sanitize_str(msginfo->from ?
|
||||
msginfo->from :
|
||||
_("(No From)"));
|
||||
subj = notification_libnotify_sanitize_str(msginfo->subject ?
|
||||
msginfo->subject :
|
||||
_("(No Subject)"));
|
||||
if (notify_config.trayicon_display_folder_name) {
|
||||
foldname = notification_libnotify_sanitize_str(msginfo->folder->path);
|
||||
text = g_strconcat(from,"\n\n", subj, "\n\n", foldname, NULL);
|
||||
}
|
||||
else
|
||||
text = g_strconcat(from, "\n\n",subj, NULL);
|
||||
|
||||
|
||||
/* Make sure text is valid UTF8 */
|
||||
utf8_str = notification_validate_utf8_str(text);
|
||||
g_free(text);
|
||||
|
||||
if(from) g_free(from);
|
||||
if(subj) g_free(subj);
|
||||
if(foldname) g_free(foldname);
|
||||
}
|
||||
else if(popup.num_calendar) {
|
||||
utf8_str = g_strdup(_("A new calendar message arrived"));
|
||||
}
|
||||
else {
|
||||
utf8_str = g_strdup(_("A new article in a RSS feed arrived"));
|
||||
}
|
||||
} /* One message */
|
||||
|
||||
else {
|
||||
gchar *msg;
|
||||
gchar *tmp;
|
||||
gboolean str_empty = TRUE;
|
||||
|
||||
utf8_str = g_strdup("");
|
||||
|
||||
if(popup.num_mail) {
|
||||
msg = g_strdup_printf(ngettext("%d new mail message arrived",
|
||||
"%d new mail messages arrived",
|
||||
popup.num_mail),
|
||||
popup.num_mail);
|
||||
tmp = g_strdup_printf("%s%s%s",utf8_str,str_empty?"":"\n",msg);
|
||||
g_free(msg);
|
||||
g_free(utf8_str);
|
||||
utf8_str = tmp;
|
||||
str_empty = FALSE;
|
||||
}
|
||||
if(popup.num_news) {
|
||||
msg = g_strdup_printf(ngettext("%d new news post arrived",
|
||||
"%d new news posts arrived",
|
||||
popup.num_news),
|
||||
popup.num_news);
|
||||
tmp = g_strdup_printf("%s%s%s",utf8_str,str_empty?"":"\n",msg);
|
||||
g_free(msg);
|
||||
g_free(utf8_str);
|
||||
utf8_str = tmp;
|
||||
str_empty = FALSE;
|
||||
}
|
||||
if(popup.num_calendar) {
|
||||
msg = g_strdup_printf(ngettext("%d new calendar message arrived",
|
||||
"%d new calendar messages arrived",
|
||||
popup.num_calendar),
|
||||
popup.num_calendar);
|
||||
tmp = g_strdup_printf("%s%s%s",utf8_str,str_empty?"":"\n",msg);
|
||||
g_free(msg);
|
||||
g_free(utf8_str);
|
||||
utf8_str = tmp;
|
||||
str_empty = FALSE;
|
||||
}
|
||||
if(popup.num_rss) {
|
||||
msg = g_strdup_printf(ngettext("%d new article in RSS feeds arrived",
|
||||
"%d new articles in RSS feeds arrived",
|
||||
popup.num_rss),
|
||||
popup.num_rss);
|
||||
tmp = g_strdup_printf("%s%s%s",utf8_str,str_empty?"":"\n",msg);
|
||||
g_free(msg);
|
||||
g_free(utf8_str);
|
||||
utf8_str = tmp;
|
||||
str_empty = FALSE;
|
||||
}
|
||||
} /* Many messages */
|
||||
|
||||
return utf8_str;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBNOTIFY */
|
||||
|
||||
gboolean notification_trayicon_is_available(void)
|
||||
{
|
||||
gboolean is_available;
|
||||
is_available = FALSE;
|
||||
|
||||
if(trayicon) {
|
||||
if(gtk_status_icon_is_embedded(trayicon) &&
|
||||
gtk_status_icon_get_visible(trayicon))
|
||||
is_available = TRUE;
|
||||
}
|
||||
|
||||
return is_available;
|
||||
}
|
||||
|
||||
#endif /* NOTIFICATION_TRAYICON */
|
47
src/plugins/notification/notification_trayicon.h
Normal file
47
src/plugins/notification/notification_trayicon.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* Notification plugin for Claws-Mail
|
||||
* Copyright (C) 2005-2007 Holger Berndt and the Claws Mail Team.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOTIFICATION_TRAYICON_H
|
||||
#define NOTIFICATION_TRAYICON_H NOTIFICATION_TRAYICON_H
|
||||
|
||||
#include "pluginconfig.h"
|
||||
|
||||
#ifdef NOTIFICATION_TRAYICON
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "procmsg.h"
|
||||
|
||||
#define TRAYICON_SPECIFIC_FOLDER_ID_STR "trayicon"
|
||||
|
||||
void notification_trayicon_msg(MsgInfo*);
|
||||
|
||||
void notification_trayicon_destroy(void);
|
||||
|
||||
/* creates it, if necessary */
|
||||
void notification_update_trayicon(void);
|
||||
|
||||
gboolean notification_trayicon_main_window_close(gpointer, gpointer);
|
||||
gboolean notification_trayicon_main_window_got_iconified(gpointer, gpointer);
|
||||
gboolean notification_trayicon_account_list_changed(gpointer, gpointer);
|
||||
|
||||
gboolean notification_trayicon_is_available(void);
|
||||
void notification_trayicon_on_activate(GtkStatusIcon*,gpointer);
|
||||
|
||||
#endif /* NOTIFICATION_TRAYICON */
|
||||
|
||||
#endif /* include guard */
|
|
@ -1 +0,0 @@
|
|||
Placeholder
|
10
src/plugins/notification/plugin.def
Normal file
10
src/plugins/notification/plugin.def
Normal file
|
@ -0,0 +1,10 @@
|
|||
EXPORTS
|
||||
plugin_desc
|
||||
plugin_done
|
||||
plugin_init
|
||||
plugin_licence
|
||||
plugin_name
|
||||
plugin_type
|
||||
plugin_provides
|
||||
plugin_version
|
||||
|
684
src/plugins/notification/raw_claws_mail_logo_64x64.h
Normal file
684
src/plugins/notification/raw_claws_mail_logo_64x64.h
Normal file
|
@ -0,0 +1,684 @@
|
|||
/* GdkPixbuf RGBA C-Source image dump */
|
||||
|
||||
#ifdef __SUNPRO_C
|
||||
#pragma align 4 (raw_claws_mail_logo_64x64)
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
static const guint8 raw_claws_mail_logo_64x64[] __attribute__ ((__aligned__ (4))) =
|
||||
#else
|
||||
static const guint8 raw_claws_mail_logo_64x64[] =
|
||||
#endif
|
||||
{ ""
|
||||
/* Pixbuf magic (0x47646b50) */
|
||||
"GdkP"
|
||||
/* length: header (24) + pixel_data (16384) */
|
||||
"\0\0@\30"
|
||||
/* pixdata_type (0x1010002) */
|
||||
"\1\1\0\2"
|
||||
/* rowstride (256) */
|
||||
"\0\0\1\0"
|
||||
/* width (64) */
|
||||
"\0\0\0@"
|
||||
/* height (64) */
|
||||
"\0\0\0@"
|
||||
/* pixel_data: */
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\1\0\0\0\1\0\0\0\3\0\0\0\5\0\0\0\7\0\0\0\10\0\0\0\10\0\0\0\7\0"
|
||||
"\0\0\6\0\0\0\4\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0"
|
||||
"\0\0\1\0\0\0\3\0\0\0\6\0\0\0\15\0\0\0\27\0\0\0(\0\0\0=\15\30\35W\"@M"
|
||||
"w-Sc\2073]n\2226`q\2250Ve\214)IW}\26&-_\4\6\7B\0\0\0+\0\0\0\31\0\0\0"
|
||||
"\16\0\0\0\6\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\1\0\0\0\2\0\0\0\4\0\0\0\14\0\0\0\31\0\0\0""0\24&.c8g{\244T\215\245"
|
||||
"\321s\257\310\362\215\304\333\375\243\321\344\377\261\327\350\377\271"
|
||||
"\333\352\377\273\335\352\377\265\331\350\377\252\323\346\377\227\311"
|
||||
"\337\376\200\267\316\366b\230\260\335Gw\213\263&@Kv\4\4\4""7\0\0\0\31"
|
||||
"\0\0\0\12\0\0\0\4\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\14\0\0"
|
||||
"\0\40\0\5\13P\25""7P\242Y\225\255\333\211\302\333\375\265\330\350\377"
|
||||
"\321\343\355\377\343\354\362\377\346\354\361\377\353\362\365\377\360"
|
||||
"\367\372\377\360\367\372\377\360\367\372\377\360\367\372\377\360\367"
|
||||
"\372\377\360\366\372\377\353\364\370\377\336\356\364\377\304\340\355"
|
||||
"\377\235\315\340\376o\246\275\351Fr\204\254\20\30\34O\0\0\0\37\0\0\0"
|
||||
"\12\0\0\0\3\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\1\0\0\0\3\0\0\0\10\0\0\0\26\0\2\4C\22""4N\250:g\212\361\236"
|
||||
"\304\327\377\311\334\346\377\331\341\350\377\336\344\352\377\336\344"
|
||||
"\352\377\336\344\352\377\337\346\353\377\346\356\363\377\345\354\361"
|
||||
"\377\344\353\357\377\344\353\357\377\346\357\363\377\352\363\370\377"
|
||||
"\353\364\370\377\351\363\367\377\346\355\363\377\352\363\366\377\352"
|
||||
"\364\370\377\334\354\364\377\265\332\350\377~\264\314\365Jv\212\263\14"
|
||||
"\21\24H\0\0\0\30\0\0\0\7\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\1\0\0\0\4\0\0\0\15\0\0\0-\22)6zCz\227\337\220\271\320\377\316"
|
||||
"\340\352\377\325\336\346\377\324\334\344\377\324\334\344\377\324\334"
|
||||
"\344\377\324\334\344\377\325\334\344\377\325\335\344\377\326\335\345"
|
||||
"\377\326\335\345\377\326\336\345\377\327\336\346\377\327\336\346\377"
|
||||
"\330\340\346\377\331\342\350\377\330\337\346\377\330\337\346\377\330"
|
||||
"\340\347\377\335\345\354\377\340\352\360\377\344\357\365\377\334\355"
|
||||
"\364\377\260\326\346\377r\251\300\3555Tb\214\0\0\0*\0\0\0\13\0\0\0\3"
|
||||
"\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\5\0\0\0\21\0\0\0""3\40G_\257i\234"
|
||||
"\272\376\242\270\313\377\306\321\334\377\312\324\336\377\312\324\336"
|
||||
"\377\312\324\336\377\312\324\336\377\312\324\336\377\313\325\336\377"
|
||||
"\314\325\337\377\314\326\337\377\315\326\337\377\315\327\340\377\316"
|
||||
"\327\340\377\316\327\340\377\317\330\341\377\317\330\341\377\317\330"
|
||||
"\341\377\320\331\341\377\320\331\342\377\320\331\342\377\320\331\342"
|
||||
"\377\320\331\342\377\320\331\342\377\326\342\351\377\334\352\361\377"
|
||||
"\313\342\354\377\220\303\330\375Q\200\223\276\6\11\12@\0\0\0\22\0\0\0"
|
||||
"\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\2\0\0\0\6\0\0\0\27\0\5\12N\13/O\303Sz\234\376\262\301\320"
|
||||
"\377\277\314\330\377\277\314\330\377\277\314\330\377\277\314\330\377"
|
||||
"\277\314\330\377\277\314\330\377\300\315\330\377\301\315\331\377\302"
|
||||
"\316\331\377\303\317\332\377\303\317\332\377\276\312\324\377\266\302"
|
||||
"\314\377\302\316\327\377\200\207\216\377\277\313\325\377\307\321\334"
|
||||
"\377\307\321\335\377\307\322\335\377\310\322\335\377\306\320\333\377"
|
||||
"\310\322\335\377\310\322\335\377\310\322\335\377\310\322\334\377\310"
|
||||
"\322\334\377\300\315\331\377\227\273\320\377T\204\235\334\25\37$`\0\0"
|
||||
"\0\36\0\0\0\6\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\2\0\0\0\6\0\0\0\27\0\7\16W\17""8`\344j\210\244\377\255\275\315"
|
||||
"\377\265\304\322\377\265\304\322\377\265\304\322\377\265\304\322\377"
|
||||
"\265\304\322\377\265\304\322\377\266\305\322\377\267\305\323\377\270"
|
||||
"\306\324\377\271\307\324\377\270\306\323\377\226\240\253\377\201\213"
|
||||
"\224\377py\200\377\267\304\320\377\40\"#\377\216\225\233\377\304\317"
|
||||
"\331\377\275\310\325\377\275\310\324\377\237\251\264\377\203\213\224"
|
||||
"\377\257\272\306\377\300\314\330\377\300\314\327\377\300\314\327\377"
|
||||
"\300\314\330\377\300\313\327\377\274\311\325\377\207\236\263\377T\200"
|
||||
"\236\372\32-=\206\0\0\0\33\0\0\0\6\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\2\0\0\0\6\0\0\0\26\0\3\10O\13""2Z\334n\213\247\377\251\272"
|
||||
"\313\377\252\274\314\377\252\274\314\377\252\274\314\377\252\274\314"
|
||||
"\377\252\273\314\377\252\273\314\377\253\275\314\377\254\275\315\377"
|
||||
"\255\276\316\377\256\277\316\377\260\300\317\377\252\271\307\377^fn\377"
|
||||
"(,/\377ox\202\377\240\256\272\377!$&\377\26\27\30\377\216\223\230\377"
|
||||
"\235\247\257\377dkq\377\32\34\36\377r{\203\377lt{\377\237\253\266\377"
|
||||
"\271\307\324\377\270\305\323\377\272\310\326\377\270\305\322\377\267"
|
||||
"\305\322\377\267\304\322\377\253\304\325\377[\212\246\362\14\26\36d\0"
|
||||
"\0\0\26\0\0\0\4\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\5\0\0\0\24\0\4\10"
|
||||
"K\12""1X\333_~\236\377\236\260\304\377\240\263\306\377\240\263\306\377"
|
||||
"\240\263\306\377\240\263\306\377\240\263\306\377\240\263\306\377\240"
|
||||
"\263\306\377\242\264\307\377\243\265\310\377\244\266\310\377\243\265"
|
||||
"\305\377\233\253\273\377\240\260\301\377x\204\220\377\24\26\30\377|\210"
|
||||
"\225\377\203\215\231\377\34\36\40\377\0\0\0\377\36\37\37\377ORU\377\3"
|
||||
"\3\3\377\16\17\21\377\26\30\31\377_in\377\265\304\323\377\277\323\337"
|
||||
"\377\267\310\326\377\304\331\344\377\261\277\316\377\262\301\317\377"
|
||||
"\300\325\341\377\311\343\355\377\260\325\344\377Q~\232\351\6\11\14J\0"
|
||||
"\0\0\17\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\15\0\0\0""1\4$D\273Tv\227"
|
||||
"\377\223\250\276\377\226\253\300\377\226\253\300\377\226\253\300\377"
|
||||
"\226\253\300\377\226\253\300\377\226\253\300\377\226\253\300\377\227"
|
||||
"\254\300\377\231\255\301\377\232\256\302\377\234\257\303\377\233\257"
|
||||
"\302\377\212\232\253\377q\177\214\3777>D\377\37\"%\377`ir\377mu}\377"
|
||||
"\27\31\33\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\21\23"
|
||||
"\24\377\207\231\241\377\276\327\342\377\311\344\357\377\311\344\357\377"
|
||||
"\260\303\321\377\252\272\312\377\260\302\321\377\310\342\355\377\306"
|
||||
"\341\355\377\305\337\353\377\241\314\340\377>f~\311\5\5\5""3\0\0\0\12"
|
||||
"\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\2\0\0\0\11\0\0\0\36\0\17\37z&Qz\374\204\234\265\377\214"
|
||||
"\242\271\377\214\242\271\377\214\242\271\377\214\242\271\377\214\242"
|
||||
"\272\377\214\242\272\377\214\242\272\377\214\242\272\377\216\244\273"
|
||||
"\377\220\245\274\377\221\246\275\377\223\250\276\377\210\235\260\377"
|
||||
"9BJ\377\2\2\2\377\0\0\0\377\20\22\24\377\40#&\377#&)\377\6\7\5\377)9"
|
||||
"\6\377*;\6\377\25\35\3\377\6\11\0\377\0\0\0\377(.1\377s\203\213\377\211"
|
||||
"\234\245\377\215\241\251\377\304\341\355\377\263\312\331\377\244\265"
|
||||
"\307\377\246\271\312\377\302\340\354\377\300\337\353\377\300\336\353"
|
||||
"\377\275\334\352\377\205\267\320\376\35""3D\220\0\0\0\34\0\0\0\5\0\0"
|
||||
"\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0"
|
||||
"\0\5\0\0\0\22\0\0\1C\12""2Z\336c\202\241\377\201\232\263\377\202\232"
|
||||
"\263\377\202\232\263\377\202\232\263\377\202\232\264\377\202\232\264"
|
||||
"\377\202\232\264\377\202\232\264\377\202\233\265\377\203\234\265\377"
|
||||
"}\230\261\377o\215\251\377[|\235\377Gj\216\3775Y}\377\34""3J\377\2\4"
|
||||
"\6\377\0\0\0\377\0\0\0\377\1\2\0\377d\207\21\377\202\262\26\377o\226"
|
||||
"\23\377`\202\21\377F`\12\377\24\35\2\377\0\0\0\377\12\14\15\377.46\377"
|
||||
"z\214\224\377\255\311\325\377\267\324\340\377\236\261\303\377\256\307"
|
||||
"\327\377\276\336\353\377\274\334\351\377\274\334\351\377\273\334\351"
|
||||
"\377\256\324\344\377V\206\242\353\7\10\11E\0\0\0\16\0\0\0\3\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\12\0\0\0#\0"
|
||||
"\27-\2224]\205\377t\220\254\377w\222\255\377w\222\255\377w\222\255\377"
|
||||
"w\222\255\377w\222\255\377w\222\256\377v\222\256\377n\213\250\377Vx\233"
|
||||
"\3777`\210\377\37Mz\377\25Ft\377\23Dr\377\27Ft\377\32Ep\377!Kw\377\37"
|
||||
"7O\377\6\12\16\377\0\0\0\377;P\16\377\207\267\34\377q\233\24\377k\222"
|
||||
"\23\377m\225\24\377k\223\23\377Hc\12\377\23\33\1\377\10\13\6\377h~\207"
|
||||
"\377\246\310\327\377\243\304\322\377\270\330\345\377\271\331\347\377"
|
||||
"\273\334\352\377\272\334\351\377\271\333\351\377\270\331\351\377\266"
|
||||
"\331\347\377\264\327\346\377\221\305\334\377>bp\236\0\0\0\37\0\0\0\6"
|
||||
"\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\5\0\0\0\21"
|
||||
"\0\0\0<\10""0W\333Xz\232\377l\212\246\377l\212\247\377l\212\247\377l"
|
||||
"\212\247\377l\212\247\377k\211\247\377[}\236\3775]\204\377\22:_\377\30"
|
||||
";L\377/PA\3776P=\377OhC\377RfA\377o\210C\377f{C\377Xk;\377Uh0\377GQ3"
|
||||
"\377La\36\377o\2114\377t\2210\377l\215\"\377h\206&\377h\211\34\377c\204"
|
||||
"\31\377Eb\11\3771F\6\377\27!\2\377\25\32\34\377L]d\377@S\\\377\222\302"
|
||||
"\327\377\237\317\343\377\257\326\347\377\265\331\350\377\264\331\350"
|
||||
"\377\263\327\347\377\261\327\346\377\260\325\345\377\246\320\342\377"
|
||||
"k\243\271\350\4\5\5B\0\0\0\15\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\2\0\0\0\11\0\0\0\34\0\15\32t\40Lx\376`\200\240\377b\202\241"
|
||||
"\377b\202\241\377b\202\241\377a\201\240\377Qt\230\377'R{\377\35>F\377"
|
||||
"6I/\377y\222C\377\200\231G\377\201\234A\377\200\2378\377}\233;\377{\232"
|
||||
"7\377o\2106\377f}3\377e\201%\377\\t&\377e\200+\377s\224'\377y\2320\377"
|
||||
"h\210\40\377b\177\33\377c\204\32\377h\210#\377f\210\33\377M_)\377FZ\33"
|
||||
"\377$/\24\377k\212\230\3775IR\377#29\377\177\264\313\377\207\303\334"
|
||||
"\377\212\303\333\377\230\312\337\377\251\323\344\377\256\325\346\377"
|
||||
"\255\324\345\377\254\323\343\377\251\321\343\377\211\301\331\3778Xe\220"
|
||||
"\0\0\0\32\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\15"
|
||||
"\0\0\0+\2#C\270:b\210\377Xz\232\377Xz\232\377Wy\232\377Nr\226\377*V\200"
|
||||
"\377\7""6c\377\20\34(\377q\204G\377\224\271=\377\205\2516\377y\241\""
|
||||
"\377y\235%\377t\223/\377k\211'\377O_(\377Ma\40\377IY(\377IZ#\377e}-\377"
|
||||
"f\204\"\377k\216\34\377k\213%\377_~\31\377Vn\36\377b\203\32\377l\222"
|
||||
"\26\377y\234*\377[o.\377d~*\377c~*\377XmT\377t\244\270\377\211\300\330"
|
||||
"\377\213\304\335\377\210\303\334\377\206\302\334\377\204\300\331\377"
|
||||
"\206\301\332\377\225\310\336\377\245\320\342\377\246\321\342\377\245"
|
||||
"\317\341\377\230\311\335\377[\216\244\324\0\0\0""0\0\0\0\12\0\0\0\2\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\6\0\0\0\23\0\0\0\77\15""8_\342Dj\216"
|
||||
"\377Nr\224\377Lp\224\3775^\206\377\16\77p\377\0""1`\377QRJ\377\306\264"
|
||||
"\223\3771*%\377Sh#\377j\217\27\377e\206\31\377f\210\30\377Pe\40\377F"
|
||||
"U&\377>L#\377N[/\377g~3\377\214\257<\377f\201'\377i\213\32\377g\203("
|
||||
"\377a|$\377Ob&\377EX\34\377[w\32\377l\221\26\377\205\2520\377o\205>\377"
|
||||
"e\200,\377z\236'\377|\2326\377Nb1\377i\222\250\377\215\306\337\377\212"
|
||||
"\304\335\377\210\303\334\377\204\300\332\377\202\277\331\377\177\276"
|
||||
"\327\377\205\300\330\377\226\310\335\377\237\314\337\377\234\313\336"
|
||||
"\377w\263\315\372\22\30\33X\0\0\0\20\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\11\0\0\0\34\1\10\17d\24Dq\374Ag\214\377>d\212\377\36Kx\377"
|
||||
"\3""6i\377\0""4g\377)9A\377\362\352\326\377\325\275\214\377pbH\377\77"
|
||||
"H/\377Vi*\377Na#\377CP%\377\40'\21\377!,\40\377\27#\35\377`u1\377\227"
|
||||
"\265N\377}\230@\377o\2121\377e\201'\377f\205\37\377K^!\377>L\34\377C"
|
||||
"T\36\377[|\22\377k\213&\377\210\250<\377u\2179\377e\203\"\377e\201&\377"
|
||||
"n\215,\377v\221:\377\\p>\377w\247\271\377\214\305\335\377\210\303\334"
|
||||
"\377\206\301\333\377\202\277\331\377\177\276\327\377}\274\326\377|\273"
|
||||
"\325\377\210\300\330\377\225\310\334\377\203\276\326\3777Vc\221\0\0\0"
|
||||
"\32\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\14\0\0\0%\0\34""6\237\40"
|
||||
"Ly\377/Y\202\377\16\77o\377\0""4g\377\0""4h\377\0""1a\377\220\205l\377"
|
||||
"\353\341\310\377\316\265\200\377H@1\377+3\36\377=K\36\3778D\33\377)4"
|
||||
"#\377\12(E\377\25*4\377i\200:\377\224\270@\377{\227;\377`s2\377Ym.\377"
|
||||
"Pd\40\377I[!\377\77G,\377,5\30\377BT\36\377Xr\36\377s\223*\377\216\256"
|
||||
"D\377at6\377Qd'\377Zv\32\377Ti$\377x\220B\377\242\303S\377cxC\377p\235"
|
||||
"\261\377\210\303\334\377\206\301\333\377\202\277\331\377\200\276\330"
|
||||
"\377}\275\326\377z\272\325\377w\270\323\377~\272\324\377\202\276\326"
|
||||
"\377O\177\222\300\0\0\0&\0\0\0\10\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\20"
|
||||
"\0\0\0/\1$H\302\30Ft\377\7""9j\377\0""4g\377\0""4g\377\0""5h\377\0/\\"
|
||||
"\377\277\260\220\377\335\312\243\377d\\G\377\0\31""2\377\26\35\34\377"
|
||||
"#+\22\377*0\35\377\14!.\377#6/\377\203\242>\377}\230@\377w\2253\377p"
|
||||
"\220(\377`y#\377Pi\35\377FV#\377*;\32\377\0\1\0\377\32\40\37\377<L\32"
|
||||
"\377Tr\22\377s\2204\377\200\231E\377Yo'\377%,\32\377IY&\377Un\37\377"
|
||||
"Zs\"\377\220\263\77\377\216\256D\377YqI\377v\252\300\377\205\301\333"
|
||||
"\377\202\277\331\377\177\276\330\377}\274\326\377z\272\325\377w\270\323"
|
||||
"\377t\266\322\377s\266\322\377[\223\253\337\0\0\0""2\0\0\0\13\0\0\0\2"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\23\0\0\0""7\0(P\327\2""5f\377\0""4f\377\0"
|
||||
"4g\377\0""4g\377\0""5h\377\0""1a\377\220\204d\377\326\300\220\377\22"
|
||||
"%4\377\0&L\377\0#G\377\7\"=\377\6\33""1\377,;&\377x\222<\377~\2348\377"
|
||||
"l\212,\377Ys\34\377]q1\3773@\27\3775>\40\377)3\34\377\16\26\34\377\31"
|
||||
"!%\377F]Y\377J]\37\377Wk*\377|\2351\377\211\245G\377r\2138\377\".3\377"
|
||||
".67\377:F#\377Nk\15\377`{#\377x\231-\377\241\310J\377Vh;\377m\236\256"
|
||||
"\377\201\277\331\377\177\276\330\377}\274\326\377z\272\325\377v\270\322"
|
||||
"\377t\266\322\377p\264\321\377d\242\274\361\3\3\3C\0\0\0\16\0\0\0\3\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\26\0\0\0>\0-V\343\0""4f\377\0""4f\377\0""4g"
|
||||
"\377\0""4h\377\0""5h\377\0""3e\3776==\377\330\276\211\377\37-7\377\0"
|
||||
"&L\377\0#F\377\25,4\377Xj6\377}\2363\377f\205!\377_|\34\377]x!\377Rf"
|
||||
"$\37719!\377\26/D\377\31""8U\377\30""1J\377$D`\377U\200\221\377\77S8"
|
||||
"\377I[!\377Ti'\377f\207\36\377\234\301H\377\232\271M\377Ool\377d\213"
|
||||
"\235\3773E:\377=H%\377Ql\24\377h\205%\377s\221.\377\206\2515\377Pd5\377"
|
||||
"q\246\275\377~\275\330\377{\274\326\377z\271\325\377v\270\322\377t\266"
|
||||
"\322\377p\264\321\377j\255\311\373\11\14\15R\0\0\0\21\0\0\0\4\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\30\0\0\0C\22Go\353\2""7i\377\0""4f\377\0""4g\377\0"
|
||||
"4h\377\0""5h\377\0""1`\377\0!B\377e^J\377\211z\\\377\3\33.\3776D*\377"
|
||||
"x\222>\377t\2158\377o\221\40\377g\206$\377a{(\377J_\37\377IT0\377\32"
|
||||
"-3\377\31:Z\377\33;[\377\36=\\\377&Ge\377Z\214\240\377AU\77\377L`!\377"
|
||||
"^z\35\377g\210\35\377\214\253C\377{\222C\377Vxy\377e\217\240\377Y\177"
|
||||
"\216\377&,$\3773B\17\377Wo#\377_x#\377k\206*\377\227\274@\377UiB\377"
|
||||
"f\230\251\377{\273\325\377x\271\325\377u\267\322\377r\265\321\377p\264"
|
||||
"\321\377k\257\314\375\25\35\"a\0\0\0\23\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\31\0\0\0D\34S{\356\30S\202\377\0""4f\377\0""4g\377\0""4g\377\0""5"
|
||||
"h\377\0/]\377\0&K\377\0\"C\377CM,\377gy:\377\214\254A\377y\233-\377c"
|
||||
"\200\"\377_u-\377Zn*\377K^\36\377'2\35\377\22'/\377\23""5U\377\27""8"
|
||||
"X\377\32:Z\377\35=\\\377Dt\223\377u\265\316\377=UE\377Re#\377`x'\377"
|
||||
"e\205\36\377\202\241;\377\211\246D\377Ruz\377c\216\240\377c\216\240\377"
|
||||
"Lkx\377484\377La\37\377_y'\377g\207#\377}\2338\377u\215<\377La<\377v"
|
||||
"\265\316\377w\270\324\377t\267\322\377r\265\321\377n\263\320\377l\261"
|
||||
"\316\376\31'-g\0\0\0\24\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\31\0\0\0E\6"
|
||||
"6c\356P\237\304\377)k\226\377\2""6i\377\0""4g\377\0""5h\377\0""1`\377"
|
||||
"\0$E\3770G)\377w\2253\377\200\237=\377f\203%\377Yq\"\377Nb#\377M`!\377"
|
||||
"Yp(\377.:!\377\15+I\377\21""3V\377\24""6W\377\27""8X\377\32<\\\377Eu"
|
||||
"\223\377z\301\337\377w\272\325\377:M#\377H\\\36\377e\205\33\377p\224"
|
||||
"\40\377\233\302C\377]l8\377a\215\232\377f\225\250\377_\213\235\377`\213"
|
||||
"\236\377A_f\377FT*\377Tj$\377b\177$\377p\223\"\377}\2372\377z\223A\377"
|
||||
"_\221\242\377v\267\324\377s\266\321\377p\264\321\377m\263\320\377i\260"
|
||||
"\315\376\26#'d\0\0\0\24\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\31\0\0\0B\1"
|
||||
".Z\350\24O~\377a\265\330\377D\217\270\377\2""7j\377\0""4h\377\0""4f\377"
|
||||
"\15';\377Xi2\377;E$\3771<\35\377Mb\35\377J_\34\377ES'\377FT(\377CU\33"
|
||||
"\377.=%\377\14""0S\377\17""2T\377\31@a\377D~\244\377h\254\316\377x\301"
|
||||
"\340\377z\303\340\377Eie\377M^)\377Vk(\377c\201\40\377j\217\32\377u\216"
|
||||
";\377z\222\77\377^tx\377\217\236\245\377lop\377[u\200\377>RV\377ET#\377"
|
||||
"Na#\377Vp\33\377g\206\"\377r\221.\377m\202=\377V\177\210\377t\267\323"
|
||||
"\377r\266\321\377n\263\320\377l\261\320\377h\254\311\374\14\23\25Z\0"
|
||||
"\0\0\24\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\30\0\0\0:\7""0X\330*l\230\377"
|
||||
"a\265\330\377a\265\331\3771v\240\377\0""4h\377\0""5h\377\2$G\377J@*\377"
|
||||
"p\\8\377TE)\377\40\34\37\377@H0\3779F\36\3774A\27\377=J\37\377\33,(\377"
|
||||
"\34Ff\377<o\211\377e\254\313\377t\300\340\377u\300\340\377v\301\337\377"
|
||||
"^\230\253\377EU&\377IZ%\377]z\34\377k\221\23\377v\231$\377\204\237H\377"
|
||||
"Ra0\377\215\215\214\377\262\262\262\377\276\276\275\377kx}\3778MQ\377"
|
||||
"4@\26\377=M\35\377JZ'\377[v\36\377r\2172\377\212\247D\377\\\204\204\377"
|
||||
"s\266\323\377p\265\321\377m\263\320\377k\261\317\377d\246\303\370\3\4"
|
||||
"\4N\0\0\0\22\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\26\0\0\0""2\20""8X\300"
|
||||
"H\224\273\377`\264\330\377a\265\330\377Z\254\321\377\2""6i\377\0""5h"
|
||||
"\377\1""5e\377\221\204a\377\376\370\356\377\312\260z\377yg>\377\14\15"
|
||||
"\21\3779D\35\3772<\33\377;E%\377\12#7\3772f\205\377c\253\312\377p\277"
|
||||
"\337\377q\274\335\377p\271\330\377u\256\306\377K^T\377=K#\377FT'\377"
|
||||
"Zv\36\377Zn0\377ay/\377w\212F\377bw0\377\263\263\262\377\263\263\262"
|
||||
"\377\375\375\373\377\234\237\240\3777NV\3779F\35\377;K\27\377AN#\377"
|
||||
"m\212)\377\201\2453\377\203\235J\377U~\177\377p\265\321\377n\263\320"
|
||||
"\377l\262\317\377i\260\316\377Y\226\260\350\0\0\0>\0\0\0\20\0\0\0\4\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\23\0\0\0+\27;S\245D\216\265\377`\264\327\377"
|
||||
"a\265\330\377a\265\331\377\32X\206\377\0""4g\377%`\211\377\214\177Z\377"
|
||||
"\370\363\347\377\306\256z\377\301\250u\377\26\24\24\3774;%\3775@\37\377"
|
||||
"\20\37\35\377\5-S\377\14>m\377]\225\262\377\201\251\271\377\230\254\265"
|
||||
"\377\257\263\265\377\300\300\300\377T]@\377IZ(\377[n+\377c}%\377b{)\377"
|
||||
"}\232<\377\217\252L\377T\\A\377\235\235\234\377\371\371\367\377\376\376"
|
||||
"\374\377\332\332\330\377Ry\213\377!*\37\377@N$\377K]$\377\40$\23\377"
|
||||
"&'\37\377OZ4\377Z\221\243\377n\264\321\377m\262\317\377j\261\317\377"
|
||||
"h\257\316\377N\205\234\320\0\0\0""2\0\0\0\16\0\0\0\3\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\20\0\0\0$\26*4wQ\236\303\377_\262\325\377_\262\325\377`\263"
|
||||
"\326\377<\204\254\377\0""4f\377\37Sw\377ohI\377\364\354\335\377\305\255"
|
||||
"{\377\311\261\177\377\21\40(\377\20\35,\377\25$.\3778I[\377it\177\377"
|
||||
"\256\261\263\377\302\302\302\377\310\310\310\377\314\314\314\377\317"
|
||||
"\317\317\377\322\322\322\377[\\W\377563\377\24\25\33\377\26\23\23\377"
|
||||
"4(\32\377\15\16\13\377h~7\377VXP\377\343\343\342\377\376\376\374\377"
|
||||
"\376\376\374\377\372\372\370\377Smy\377Aet\377+<6\377G>+\377\260\242"
|
||||
"\213\377\346\331\276\377\221~S\377V\215\244\377l\261\316\377j\260\316"
|
||||
"\377h\256\314\377e\255\313\377;ev\251\0\0\0'\0\0\0\14\0\0\0\3\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\15\0\0\0\36\1\2\2N1o\223\361\\\255\317\377\\\255\317"
|
||||
"\377]\256\320\377\\\256\317\377\34X\204\377\22Ck\377CSM\377\335\315\250"
|
||||
"\377\327\306\241\377\314\265\200\377SVR\377\200\202\204\377\214\214\214"
|
||||
"\377\217\217\217\377\264\264\264\377\317\317\317\377\322\322\322\377"
|
||||
"\326\326\326\377\331\331\331\377\334\334\334\377\337\337\337\377xxy\377"
|
||||
",-0\377>4\"\377\270\235d\377\350\327\265\377hW5\377##$\377\232\232\231"
|
||||
"\377\366\366\364\377\376\376\374\377\376\376\374\377\375\375\373\377"
|
||||
"fv{\377Q\200\225\377\77dt\377\235\210]\377\357\346\322\377\332\307\240"
|
||||
"\377\230\203T\377W\216\246\377h\254\310\377f\253\310\377d\252\306\377"
|
||||
"a\250\305\377\32-6v\0\0\0\35\0\0\0\11\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\12\0\0\0\30\0\0\0""8(Xs\306Z\250\310\377Z\251\312\377Y\247\310\377"
|
||||
"X\245\305\377f\240\272\377k\212\233\377\\in\377\213wL\377\360\346\322"
|
||||
"\377\313\264\200\377\202tV\377\202\202\202\377\226\226\226\377\233\233"
|
||||
"\233\377\322\322\322\377\334\334\334\377\332\332\332\377\340\340\340"
|
||||
"\377\217\215\207\377\334\334\334\377\352\352\352\377\264\264\264\377"
|
||||
"a[P\377\263\227\\\377\317\271\213\377\360\350\323\377m\\8\377www\377"
|
||||
"\274\274\272\377\362\362\360\377\376\376\374\377\374\374\372\377\371"
|
||||
"\370\366\377\200\203\205\377Jv\210\377NSI\377\317\271\211\377\363\355"
|
||||
"\341\377\310\257x\377a\\C\377\\\232\265\377c\247\303\377`\246\302\377"
|
||||
"_\244\301\377R\216\247\352\0\0\1F\0\0\0\26\0\0\0\7\0\0\0\1\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\7\0\0\0\23\0\0\0(\23*7\207P\230\267\377t\244\270\377"
|
||||
"\242\264\274\377\275\300\302\377\307\307\306\377\273\273\273\377\222"
|
||||
"\222\222\377ca[\377\257\234v\377\335\312\243\377\316\266\203\377~rV\377"
|
||||
"mic\377\207\206\204\377\227\224\217\377\215\204p\377i^F\377\310\310\310"
|
||||
"\377\203pE\377\253\253\251\377\362\362\362\377usp\377\226}F\377\303\252"
|
||||
"t\377\354\341\313\377\244\217f\377\\[X\377\261\261\260\377\237\237\235"
|
||||
"\377rdE\377\223\214\177\377\271\271\267\377\324\324\322\377\205\204\204"
|
||||
"\377STI\377\305\260\200\377\355\343\316\377\317\270\211\377\234\205S"
|
||||
"\3777Wc\377_\241\274\377_\241\275\377\\\240\274\377Z\236\273\3778cu\264"
|
||||
"\0\0\0-\0\0\0\20\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\17"
|
||||
"\0\0\0\37\0\0\0L7l\204\351\242\265\275\377\330\330\327\377\300\300\300"
|
||||
"\377\320\320\320\377\315\315\315\377\235\235\235\377\234\234\234\377"
|
||||
"nmj\377\207wW\377\314\264\200\377\324\273\207\377\324\274\207\377\323"
|
||||
"\272\207\377\323\271\201\377\220{N\377\255\253\247\377\340\340\340\377"
|
||||
"\230~H\377zkJ\377\203|n\377\227\200M\377\304\253u\377\337\316\254\377"
|
||||
"\264\243\202\377ROH\377\251\251\251\377\270\267\266\377\364\363\361\377"
|
||||
"\211\202u\377\250\213P\377\272\241k\377\253\230l\377\300\253{\377\323"
|
||||
"\273\210\377\330\305\233\377\310\256x\377\213uF\3775LR\377Du\211\377"
|
||||
"Z\233\267\377Z\234\267\377X\232\266\377S\223\257\372\20\35\"i\0\0\0\37"
|
||||
"\0\0\0\15\0\0\0\4\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\12\0\0\0\30"
|
||||
"\0\0\0""2\36""9E\251v\226\244\377\375\375\373\377\354\354\352\377\267"
|
||||
"\267\266\377\265\265\265\377\250\250\250\377\247\247\247\377\252\252"
|
||||
"\252\377\235\235\235\377\220\216\211\377\225\214x\377\227\213r\377\230"
|
||||
"\214u\377\225\220\205\377\326\326\326\377\376\376\376\377\365\365\365"
|
||||
"\377~mF\377\300\243f\377\307\256w\377\314\265\201\377\324\277\217\377"
|
||||
"\241\217g\377QOI\377\240\240\240\377\264\264\263\377\330\327\326\377"
|
||||
"\367\366\364\377\360\357\356\377\243\240\234\377\203uW\377\220zO\377"
|
||||
"\237\211Y\377\231\204V\377wlL\377EMC\3771S`\377<fx\377>l\177\377O\213"
|
||||
"\245\377O\213\244\377N\212\243\3775_q\313\0\0\0I\0\0\0+\0\0\0!\0\0\0"
|
||||
"\23\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\6\0\0\0\22\0\0\0$\0\2\2"
|
||||
"_Lp\200\357\356\356\354\377\376\376\374\377\376\376\374\377\334\334\332"
|
||||
"\377\216\216\215\377~~~\377\241\241\241\377\264\264\264\377\310\310\310"
|
||||
"\377\373\373\373\377\374\374\374\377\375\375\375\377\376\376\376\377"
|
||||
"\376\376\376\377\374\374\374\377\373\373\373\377\252\251\247\377\201"
|
||||
"rS\377\234\206X\377\234\207Y\377ujS\377VVU\377\234\234\232\377\263\263"
|
||||
"\261\377\304\303\302\377\363\361\357\377\354\354\352\377\356\354\353"
|
||||
"\377\356\354\352\377\350\346\345\377\331\327\325\377\316\313\312\377"
|
||||
"\202\202\201\377t{\177\377u}\200\377t|\177\377r{\177\377\205\217\223"
|
||||
"\377\236\252\256\377\234\250\255\377\234\247\253\376\236\237\237\344"
|
||||
"\245\245\244\327\244\244\244\325\243\243\242\323LLLr\0\0\0\22\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\14\0\0\0\32\0\0\0:\24$*\241\320\324"
|
||||
"\325\377\376\376\374\377\376\376\374\377\376\376\374\377\374\374\372"
|
||||
"\377\252\252\251\377oon\377www\377\230\230\230\377\304\304\304\377\337"
|
||||
"\337\337\377\344\344\344\377\333\333\333\377\310\310\310\377\310\310"
|
||||
"\310\377\353\353\353\377\271\271\271\377\362\362\362\377\344\344\344"
|
||||
"\377\264\264\264\377kkj\377\233\233\232\377\257\257\255\377\266\266\264"
|
||||
"\377\352\351\347\377\362\360\356\377\311\310\307\377\263\262\260\377"
|
||||
"\312\310\306\377\331\327\325\377\333\330\327\377\312\307\305\377\206"
|
||||
"\204\203\377\233\233\232\377\266\266\264\377\266\266\264\377\273\273"
|
||||
"\271\377\364\364\362\377\376\376\374\377\376\376\374\377\361\341\330"
|
||||
"\377\362\335\323\377\362\337\325\377\363\341\331\377\374\372\367\377"
|
||||
"kkk\246\0\0\0\34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\7\0\0\0\23"
|
||||
"\0\0\0'\0\0\0c\233\244\250\361\376\376\374\377\376\376\374\377\376\376"
|
||||
"\374\377\376\376\374\377\374\374\372\377\322\322\322\377\225\225\224"
|
||||
"\377vvu\377ssr\377\214\214\214\377\262\262\262\377\266\266\266\377\277"
|
||||
"\277\277\377\361\361\361\377\345\345\345\377\266\266\266\377\311\311"
|
||||
"\311\377\305\305\305\377jjj\377\231\231\230\377\252\252\250\377\263\263"
|
||||
"\262\377\340\337\336\377\360\356\354\377\356\353\352\377\345\343\341"
|
||||
"\377\265\262\261\377\244\242\240\377\242\240\237\377\241\236\236\377"
|
||||
"\237\234\233\377\230\225\223\377vvu\377\266\266\264\377\274\274\272\377"
|
||||
"\354\354\352\377\376\376\374\377\376\376\374\377\376\376\374\377\343"
|
||||
"yj\377\340F9\377\3325$\377\315Q=\377\365\363\356\377fff\250\0\0\0\37"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\14\0\0\0\35\0\0\0"
|
||||
"Gmmm\267\375\375\373\377\376\376\374\377\376\376\374\377\376\376\374"
|
||||
"\377\376\376\374\377\376\376\374\377\362\362\360\377\320\320\316\377"
|
||||
"\245\245\243\377\216\216\216\377\177\177\177\377\234\234\234\377\352"
|
||||
"\352\352\377\376\376\376\377\361\361\361\377\267\267\267\377\266\266"
|
||||
"\266\377nnn\377\223\223\222\377\240\240\237\377\260\257\256\377\336\335"
|
||||
"\333\377\356\354\352\377\354\352\350\377\350\346\344\377\346\344\342"
|
||||
"\377\340\334\333\377\302\277\275\377\250\246\245\377\236\233\232\377"
|
||||
"\233\230\227\377\233\230\226\377oon\377\327\327\325\377\367\367\365\377"
|
||||
"\376\376\374\377\376\376\374\377\376\376\374\377\376\376\374\377\337"
|
||||
"\236\227\377\312\277\272\377\343\240\231\377\325TD\377\365\362\352\377"
|
||||
"ccc\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\10"
|
||||
"\0\0\0\25\0\0\0""8@@@}\353\353\351\377\376\376\374\377\376\376\374\377"
|
||||
"\376\376\374\377\376\376\374\377\376\376\374\377\376\376\374\377\376"
|
||||
"\376\374\377\376\376\374\377\357\357\356\377\326\326\325\377\313\313"
|
||||
"\312\377\241\241\240\377\245\245\245\377\342\342\342\377\340\340\340"
|
||||
"\377}}|\377\215\215\214\377\240\237\236\377\274\272\271\377\334\333\332"
|
||||
"\377\344\342\340\377\344\342\340\377\346\343\342\377\344\342\340\377"
|
||||
"\342\337\335\377\340\334\332\377\334\331\330\377\331\325\323\377\322"
|
||||
"\316\315\377\316\312\310\377\315\310\307\377\211\206\205\377\373\373"
|
||||
"\371\377\376\376\374\377\376\376\374\377\376\376\374\377\376\376\374"
|
||||
"\377\371\371\367\377\312\204x\377\322\310\313\377\323\313\313\377\343"
|
||||
"ob\377\366\362\352\377```\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\1\0\0\0\5\0\0\0\17\0\0\0*\5\5\5V\316\316\315\366\376\376"
|
||||
"\374\377\376\376\374\377\376\376\374\377\376\376\374\377\376\376\374"
|
||||
"\377\376\376\374\377\376\376\374\377\376\376\374\377\376\376\374\377"
|
||||
"\374\374\372\377\350\350\346\377\332\332\331\377\330\330\330\377\251"
|
||||
"\251\250\377\220\220\220\377\265\265\263\377\326\325\324\377\340\336"
|
||||
"\335\377\344\343\341\377\342\340\336\377\340\335\334\377\334\332\331"
|
||||
"\377\332\330\326\377\333\330\326\377\334\330\326\377\334\327\326\377"
|
||||
"\330\324\322\377\326\322\320\377\324\316\315\377\320\314\312\377\316"
|
||||
"\310\307\377\233\227\226\377\332\332\330\377\376\376\374\377\376\376"
|
||||
"\374\377\376\376\374\377\376\376\374\377\356\356\354\377\314pc\377\315"
|
||||
"ZP\377\321{v\377\341RB\377\365\361\351\377\\\\\\\250\0\0\0\40\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\13\0\0\0\37\0\0\0"
|
||||
"L\250\250\250\316\376\376\374\377\376\376\374\377\376\376\374\377\376"
|
||||
"\376\374\377\376\376\374\377\376\376\374\377\376\376\374\377\376\376"
|
||||
"\374\377\376\376\374\377\370\370\366\377\365\365\363\377\361\361\357"
|
||||
"\377\346\345\344\377\337\336\334\377\336\336\334\377\336\335\334\377"
|
||||
"\342\340\337\377\344\341\337\377\340\336\334\377\336\334\332\377\334"
|
||||
"\331\330\377\331\326\324\377\326\323\322\377\324\320\317\377\322\316"
|
||||
"\314\377\320\314\313\377\322\316\314\377\322\314\313\377\320\312\310"
|
||||
"\377\314\307\306\377\312\304\302\377\277\271\270\377\237\237\236\377"
|
||||
"\376\376\374\377\376\376\374\377\376\376\374\377\376\376\374\377\375"
|
||||
"\375\373\377\306\233\220\377\317\202u\377\332\226\210\377\344\263\243"
|
||||
"\377\362\357\353\377YXX\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\2\0\0\0\11\0\0\0\30\0\0\0Bppp\245\375\375\373\377"
|
||||
"\376\376\374\377\376\376\374\377\376\376\374\377\376\376\374\377\376"
|
||||
"\376\374\377\376\376\374\377\376\376\374\377\373\373\371\377\364\364"
|
||||
"\362\377\362\361\357\377\356\356\354\377\354\353\351\377\350\347\345"
|
||||
"\377\342\340\336\377\340\336\335\377\342\337\336\377\336\334\333\377"
|
||||
"\334\332\330\377\332\330\326\377\330\324\323\377\326\322\320\377\322"
|
||||
"\317\315\377\320\314\312\377\316\311\307\377\312\306\304\377\310\303"
|
||||
"\302\377\307\302\301\377\310\303\302\377\310\302\300\377\306\277\276"
|
||||
"\377\303\274\273\377\207\205\204\377\375\375\373\377\376\376\374\377"
|
||||
"\376\376\374\377\376\375\373\377\375\374\372\377\366\365\364\377\371"
|
||||
"\370\366\377\366\366\364\377\367\366\364\377\365\364\362\377UUS\250\0"
|
||||
"\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\6\0"
|
||||
"\0\0\23\0\0\0""8<<<z\350\350\346\377\376\376\374\377\376\376\374\377"
|
||||
"\376\376\374\377\376\376\374\377\376\376\374\377\376\376\374\377\375"
|
||||
"\375\373\377\363\363\361\377\360\357\355\377\355\354\352\377\352\351"
|
||||
"\347\377\350\346\344\377\346\343\342\377\342\340\337\377\340\336\334"
|
||||
"\377\336\333\332\377\333\330\327\377\330\326\324\377\326\323\321\377"
|
||||
"\324\320\316\377\321\315\313\377\316\312\310\377\314\307\306\377\312"
|
||||
"\304\302\377\306\301\300\377\304\277\276\377\302\274\273\377\277\272"
|
||||
"\270\377\276\270\266\377\276\270\266\377\276\270\266\377xut\377\372\372"
|
||||
"\370\377\374\374\372\377\373\373\371\377\371\371\367\377\370\367\365"
|
||||
"\377\366\366\364\377\365\364\362\377\363\362\360\377\362\360\357\377"
|
||||
"\360\357\355\377PPP\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\1\0\0\0\5\0\0\0\16\0\0\0*\6\6\6V\310\310\307\367\376\376"
|
||||
"\374\377\376\376\374\377\376\376\374\377\376\376\374\377\376\376\374"
|
||||
"\377\374\374\372\377\364\364\362\377\356\356\354\377\354\352\350\377"
|
||||
"\350\350\346\377\346\344\343\377\344\342\340\377\341\337\335\377\336"
|
||||
"\334\332\377\334\332\330\377\332\327\325\377\330\324\322\377\324\321"
|
||||
"\320\377\322\316\314\377\320\313\312\377\314\310\306\377\312\306\304"
|
||||
"\377\310\302\301\377\305\300\276\377\302\276\274\377\300\273\271\377"
|
||||
"\276\270\266\377\274\264\263\377\271\262\260\377\241\233\231\377wsr\377"
|
||||
"jhg\377\362\362\360\377\370\367\365\377\366\365\363\377\365\364\362\377"
|
||||
"\363\362\360\377\362\360\356\377\360\357\355\377\357\355\353\377\355"
|
||||
"\353\351\377\354\351\350\377LLL\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\13\0\0\0\40\0\0\0L\240\240"
|
||||
"\237\321\376\376\374\377\376\376\374\377\376\376\374\377\375\375\373"
|
||||
"\377\372\372\370\377\366\365\364\377\354\354\352\377\352\350\347\377"
|
||||
"\350\346\344\377\344\343\341\377\342\340\336\377\340\335\334\377\334"
|
||||
"\332\331\377\332\330\326\377\330\325\324\377\326\322\320\377\324\317"
|
||||
"\316\377\320\314\312\377\316\312\310\377\314\306\305\377\310\304\302"
|
||||
"\377\306\300\300\377\304\276\275\377\300\274\272\377\277\271\270\377"
|
||||
"\247\241\240\377~zy\377vtt\377xwv\377\220\220\217\377\267\267\267\377"
|
||||
"\271\270\266\377\345\343\342\377\363\362\360\377\362\360\356\377\360"
|
||||
"\356\355\377\357\355\353\377\355\353\351\377\353\351\347\377\352\350"
|
||||
"\346\377\350\346\344\377\347\344\342\377GGG\250\0\0\0\40\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\11\0\0\0\30\0"
|
||||
"\0\0Cfff\247\376\376\374\377\376\376\374\377\374\374\372\377\372\371"
|
||||
"\367\377\366\366\364\377\354\353\352\377\350\347\345\377\346\344\342"
|
||||
"\377\344\341\337\377\340\336\334\377\336\334\332\377\334\331\330\377"
|
||||
"\331\326\324\377\326\323\322\377\324\320\317\377\322\316\314\377\317"
|
||||
"\313\311\377\314\310\306\377\312\304\303\377\310\302\300\377\304\277"
|
||||
"\276\377\255\250\247\377\204\200\177\377ron\377_^]\377eed\377\214\213"
|
||||
"\213\377\232\231\230\377\247\246\245\377\274\273\271\377\302\302\300"
|
||||
"\377\350\346\344\377\360\356\355\377\356\355\353\377\355\353\351\377"
|
||||
"\353\351\347\377\352\347\346\377\350\346\344\377\347\344\342\377\345"
|
||||
"\342\341\377\344\341\337\377\342\337\335\377DCC\250\0\0\0\40\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\6\0\0\0\23"
|
||||
"\0\0\0""8555}\345\345\343\377\372\372\370\377\370\367\365\377\365\364"
|
||||
"\362\377\356\355\353\377\346\345\343\377\344\342\340\377\342\337\336"
|
||||
"\377\336\334\333\377\334\332\330\377\332\330\326\377\330\324\323\377"
|
||||
"\326\322\320\377\322\317\315\377\320\314\312\377\316\311\307\377\312"
|
||||
"\306\304\377\263\257\255\377\213\210\207\377\177~}\377\202\201\200\377"
|
||||
"\230\230\230\377\277\277\275\377\313\313\311\377\302\301\300\377\272"
|
||||
"\271\270\377\300\277\275\377\320\317\315\377\332\331\327\377\333\332"
|
||||
"\330\377\353\351\347\377\355\353\351\377\353\351\347\377\352\347\345"
|
||||
"\377\350\346\344\377\347\344\342\377\345\342\341\377\344\340\337\377"
|
||||
"\342\337\335\377\340\335\333\377\337\333\332\377\335\332\330\377@\77"
|
||||
"\77\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\1\0\0\0\5\0\0\0\16\0\0\0+\7\7\7W\275\275\274\370\366\365\364\377"
|
||||
"\364\362\360\377\357\356\354\377\346\344\342\377\342\340\337\377\340"
|
||||
"\336\334\377\336\333\332\377\333\330\327\377\330\326\324\377\326\323"
|
||||
"\321\377\324\320\316\377\322\315\314\377\271\266\264\377\224\221\220"
|
||||
"\377\212\210\207\377\205\204\203\377\220\220\217\377\233\233\231\377"
|
||||
"\225\225\225\377\230\230\226\377\251\250\247\377\302\301\277\377\327"
|
||||
"\325\324\377\335\335\333\377\326\325\323\377\316\314\312\377\312\311"
|
||||
"\310\377\310\306\304\377\334\332\330\377\352\347\345\377\350\345\344"
|
||||
"\377\347\344\342\377\345\342\340\377\343\340\337\377\342\337\335\377"
|
||||
"\340\335\333\377\337\333\331\377\335\332\330\377\334\330\326\377\332"
|
||||
"\326\325\377\331\324\323\377<;;\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\13\0\0\0\40\0\0\0"
|
||||
"M\223\223\223\323\362\360\356\377\357\356\354\377\346\344\342\377\342"
|
||||
"\337\335\377\336\334\332\377\334\332\330\377\332\327\325\377\330\324"
|
||||
"\322\377\277\274\273\377\231\227\226\376\221\217\216\377\215\214\213"
|
||||
"\377\240\240\237\377\303\303\301\377\316\315\314\377\325\325\324\377"
|
||||
"\337\336\334\377\350\347\346\377\357\356\354\377\361\360\356\377\362"
|
||||
"\360\356\377\361\357\356\377\357\356\354\377\356\354\352\377\354\352"
|
||||
"\351\377\353\351\347\377\351\347\345\377\350\345\343\377\346\344\342"
|
||||
"\377\345\342\340\377\343\340\337\377\342\336\335\377\340\335\333\377"
|
||||
"\337\333\331\377\335\331\330\377\333\330\326\377\332\326\324\377\330"
|
||||
"\324\323\377\327\323\321\377\325\321\317\377\324\317\315\377866\250\0"
|
||||
"\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\2\0\0\0\11\0\0\0\31\0\0\0DYYY\253\356\354\352\377\350\345\344\377"
|
||||
"\340\335\334\377\334\332\331\377\305\303\302\377\237\235\235\372zyy\327"
|
||||
"HGG\254\35\35\35\213www\337\317\317\315\377\327\326\324\377\340\340\336"
|
||||
"\377\352\351\347\377\360\357\355\377\362\361\360\377\363\362\360\377"
|
||||
"\362\361\357\377\361\357\355\377\357\356\354\377\356\354\352\377\354"
|
||||
"\352\351\377\353\351\347\377\351\347\345\377\350\345\343\377\346\343"
|
||||
"\342\377\345\342\340\377\343\340\336\377\341\336\335\377\340\335\333"
|
||||
"\377\336\333\331\377\335\331\327\377\333\330\326\377\332\326\324\377"
|
||||
"\330\324\323\377\327\322\321\377\325\321\317\377\324\317\315\377\322"
|
||||
"\315\314\377\321\313\312\377\317\312\310\377322\250\0\0\0\40\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\6"
|
||||
"\0\0\0\23\0\0\0""8+++~\274\272\271\377\247\245\244\372\202\200\200\326"
|
||||
"NNN\254%%%\201\6\6\6X\0\0\0M\0\0\0F\0\0\0K\222\222\221\330\361\361\357"
|
||||
"\377\364\363\361\377\364\363\362\377\364\363\361\377\362\361\357\377"
|
||||
"\361\357\355\377\357\355\354\377\356\354\352\377\354\352\350\377\353"
|
||||
"\350\347\377\351\347\345\377\350\345\343\377\346\343\341\377\345\342"
|
||||
"\340\377\343\340\336\377\341\336\335\377\340\334\333\377\336\333\331"
|
||||
"\377\335\331\327\377\333\327\326\377\332\326\324\377\330\324\322\377"
|
||||
"\327\322\321\377\325\321\317\377\324\317\315\377\322\315\313\377\321"
|
||||
"\313\312\377\317\312\310\377\316\310\307\377\314\306\305\377\312\305"
|
||||
"\303\377/..\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\5\0\0\0\16\0\0\0)\0\0\0P\"\"\"v\7\7\7"
|
||||
"X\0\0\0M\0\0\0D\0\0\0""9\0\0\0-\0\0\0$\0\0\0#\0\0\0""5\227\227\226\326"
|
||||
"\364\363\361\377\362\361\357\377\361\357\355\377\357\355\354\377\356"
|
||||
"\354\352\377\354\352\350\377\353\350\347\377\351\347\345\377\347\345"
|
||||
"\343\377\346\343\341\377\344\341\340\377\343\340\336\377\341\336\334"
|
||||
"\377\340\334\333\377\336\333\331\377\335\331\327\377\333\327\325\377"
|
||||
"\332\326\324\377\330\324\322\377\327\322\321\377\325\320\317\377\323"
|
||||
"\317\315\377\322\315\313\377\320\313\312\377\317\312\310\377\315\310"
|
||||
"\306\377\314\306\305\377\312\305\303\377\311\303\301\377\307\301\277"
|
||||
"\377\306\277\276\377+**\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\12\0\0\0\30\0\0\0"
|
||||
"0\0\0\0""5\0\0\0,\0\0\0\"\0\0\0\34\0\0\0\26\0\0\0\22\0\0\0\21\0\0\0\27"
|
||||
"\0\0\0""1\223\222\222\326\357\355\353\377\355\353\352\377\354\352\350"
|
||||
"\377\352\350\346\377\351\347\345\377\347\345\343\377\346\343\341\377"
|
||||
"\344\341\340\377\343\340\336\377\341\336\334\377\340\334\333\377\336"
|
||||
"\332\331\377\335\331\327\377\333\327\325\377\331\325\324\377\330\324"
|
||||
"\322\377\326\322\320\377\325\320\317\377\323\317\315\377\322\315\313"
|
||||
"\377\320\313\311\377\317\311\310\377\315\310\306\377\314\306\305\377"
|
||||
"\312\304\303\377\311\303\301\377\307\301\277\377\306\277\276\377\304"
|
||||
"\276\274\377\302\274\272\377\301\272\271\377'&&\250\0\0\0\40\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"
|
||||
"\0\0\0\5\0\0\0\14\0\0\0\21\0\0\0\23\0\0\0\21\0\0\0\16\0\0\0\13\0\0\0"
|
||||
"\10\0\0\0\6\0\0\0\10\0\0\0\22\0\0\0/\216\215\214\325\352\350\346\377"
|
||||
"\351\346\345\377\347\345\343\377\346\343\341\377\344\341\337\377\342"
|
||||
"\337\336\377\341\336\334\377\337\334\332\377\336\332\331\377\334\331"
|
||||
"\327\377\333\327\325\377\331\325\324\377\330\324\322\377\326\322\320"
|
||||
"\377\325\320\317\377\323\316\315\377\322\315\313\377\320\313\311\377"
|
||||
"\317\311\310\377\315\310\306\377\314\306\304\377\312\304\303\377\311"
|
||||
"\303\301\377\307\301\277\377\306\277\276\377\304\275\274\377\302\274"
|
||||
"\272\377\301\272\271\377\277\270\267\377\276\267\265\377\274\265\263"
|
||||
"\377!\40\40\250\0\0\0\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\4\0\0\0\6\0\0\0\7\0\0"
|
||||
"\0\5\0\0\0\4\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\5\0\0\0\17\0\0\0'777|VUU\252"
|
||||
"TTT\252RRR\252QPP\252ONN\252MLL\252LKK\252III\252HHG\252FEE\252DCC\252"
|
||||
"CBB\252@@@\252\77>=\252=<<\252<::\252999\252776\252654\252433\252311"
|
||||
"\252100\252.--\252-,+\252+**\252*((\252(''\252%%$\252$#\"\252\"!!\252"
|
||||
"\37\36\36\251\1\1\1_\0\0\0\34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1"
|
||||
"\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\14\0\0\0\32\0"
|
||||
"\0\0&\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,"
|
||||
"\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0"
|
||||
",\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0\0,\0\0"
|
||||
"\0,\0\0\0,\0\0\0*\0\0\0\"\0\0\0\23\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\7\0\0\0"
|
||||
"\17\0\0\0\26\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0"
|
||||
"\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30"
|
||||
"\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0"
|
||||
"\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0"
|
||||
"\0\0\30\0\0\0\27\0\0\0\22\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0"};
|
||||
|
||||
|
36
src/plugins/notification/version.rc
Normal file
36
src/plugins/notification/version.rc
Normal file
|
@ -0,0 +1,36 @@
|
|||
1 VERSIONINFO
|
||||
FILEVERSION 0, 0, 0, 0
|
||||
PRODUCTVERSION 0, 0, 0, 0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "notification Plugin\0"
|
||||
VALUE "FileVersion", "0.0.0.0\0"
|
||||
VALUE "ProductVersion", "0.0.0.0 Win32\0"
|
||||
VALUE "LegalCopyright", "GPL / © 1999-2008 Hiroyuki Yamamoto & The Claws Mail Team\0"
|
||||
VALUE "CompanyName", "GNU / Free Software Foundation\0"
|
||||
VALUE "ProductName", "Claws Mail\0"
|
||||
// VALUE "Comments", "\0"
|
||||
// VALUE "InternalName", "\0"
|
||||
// VALUE "LegalTrademarks", "\0"
|
||||
// VALUE "OriginalFilename", "\0"
|
||||
// VALUE "PrivateBuild", "\0"
|
||||
// VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
26
src/plugins/pdf_viewer/Makefile.am
Normal file
26
src/plugins/pdf_viewer/Makefile.am
Normal file
|
@ -0,0 +1,26 @@
|
|||
plugindir = $(pkglibdir)/plugins
|
||||
|
||||
plugin_LTLIBRARIES = pdf_viewer.la
|
||||
|
||||
pdf_viewer_la_SOURCES = \
|
||||
poppler_viewer.c \
|
||||
poppler_viewer.h \
|
||||
gettext.h
|
||||
|
||||
pdf_viewer_la_LDFLAGS = \
|
||||
-avoid-version -module \
|
||||
$(GTK_LIBS) \
|
||||
$(POPPLER_LIBS)
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/common \
|
||||
-I$(top_srcdir)/src/gtk
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-Wall \
|
||||
$(CLAWS_MAIL_CFLAGS) \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(GTK_CFLAGS) \
|
||||
$(POPPLER_CFLAGS) \
|
||||
-DLOCALEDIR=\""$(localedir)"\"
|
21
src/plugins/pdf_viewer/doc_index.xpm
Normal file
21
src/plugins/pdf_viewer/doc_index.xpm
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* XPM */
|
||||
static char * doc_index_xpm[] = {
|
||||
"14 14 4 1",
|
||||
" c None",
|
||||
". c #1F0000",
|
||||
"+ c #4D0202",
|
||||
"@ c #000000",
|
||||
"........ ",
|
||||
".++++++. ",
|
||||
".+@@@@@@ ",
|
||||
".+@ @ ",
|
||||
".+@ @ ",
|
||||
".+@ @ ",
|
||||
"...@@@@@ ",
|
||||
" @@ @@@",
|
||||
" @@@@@@@@@@",
|
||||
" @@ @@@",
|
||||
" @@ ",
|
||||
" @@ @@@",
|
||||
" @@@@@@@@@@",
|
||||
" @@@"};
|
19
src/plugins/pdf_viewer/doc_index_close.xpm
Normal file
19
src/plugins/pdf_viewer/doc_index_close.xpm
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* XPM */
|
||||
static char * doc_index_close_xpm[] = {
|
||||
"14 14 2 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
" ",
|
||||
" ",
|
||||
" ... ... ",
|
||||
" .... .... ",
|
||||
" ... ... ",
|
||||
" ..... ",
|
||||
" ..... ",
|
||||
" ... ",
|
||||
" ..... ",
|
||||
" ..... ",
|
||||
" ... ... ",
|
||||
" ... ... ",
|
||||
" ... ... ",
|
||||
" "};
|
104
src/plugins/pdf_viewer/doc_info.xpm
Normal file
104
src/plugins/pdf_viewer/doc_info.xpm
Normal file
|
@ -0,0 +1,104 @@
|
|||
/* XPM */
|
||||
static char * doc_info_xpm[] = {
|
||||
"14 14 87 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #030303",
|
||||
"@ c #4F4F4F",
|
||||
"# c #ABABAB",
|
||||
"$ c #D3D3D3",
|
||||
"% c #ADADAD",
|
||||
"& c #515151",
|
||||
"* c #040404",
|
||||
"= c #121212",
|
||||
"- c #B1B1B1",
|
||||
"; c #EFEFEF",
|
||||
"> c #8F8F8F",
|
||||
", c #4C4C4C",
|
||||
"' c #939393",
|
||||
") c #E7E7E7",
|
||||
"! c #B4B4B4",
|
||||
"~ c #141414",
|
||||
"{ c #D4D4D4",
|
||||
"] c #373737",
|
||||
"^ c #8E8E8E",
|
||||
"/ c #929292",
|
||||
"( c #0C0C0C",
|
||||
"_ c #323232",
|
||||
": c #CECECE",
|
||||
"< c #B6B6B6",
|
||||
"[ c #505050",
|
||||
"} c #EBEBEB",
|
||||
"| c #424242",
|
||||
"1 c #010101",
|
||||
"2 c #737373",
|
||||
"3 c #747474",
|
||||
"4 c #090909",
|
||||
"5 c #0B0B0B",
|
||||
"6 c #484848",
|
||||
"7 c #F6F6F6",
|
||||
"8 c #555555",
|
||||
"9 c #919191",
|
||||
"0 c #0A0A0A",
|
||||
"a c #060606",
|
||||
"b c #2A2A2A",
|
||||
"c c #252525",
|
||||
"d c #0E0E0E",
|
||||
"e c #161616",
|
||||
"f c #B3B3B3",
|
||||
"g c #D5D5D5",
|
||||
"h c #050505",
|
||||
"i c #ACACAC",
|
||||
"j c #E0E0E0",
|
||||
"k c #080808",
|
||||
"l c #7B7B7B",
|
||||
"m c #DADADA",
|
||||
"n c #D6D6D6",
|
||||
"o c #020202",
|
||||
"p c #979797",
|
||||
"q c #070707",
|
||||
"r c #6A6A6A",
|
||||
"s c #DBDBDB",
|
||||
"t c #B0B0B0",
|
||||
"u c #898989",
|
||||
"v c #969696",
|
||||
"w c #DEDEDE",
|
||||
"x c #0F0F0F",
|
||||
"y c #B5B5B5",
|
||||
"z c #1B1B1B",
|
||||
"A c #111111",
|
||||
"B c #191919",
|
||||
"C c #E4E4E4",
|
||||
"D c #5A5A5A",
|
||||
"E c #B9B9B9",
|
||||
"F c #C0C0C0",
|
||||
"G c #262626",
|
||||
"H c #181818",
|
||||
"I c #BEBEBE",
|
||||
"J c #BDBDBD",
|
||||
"K c #BABABA",
|
||||
"L c #E8E8E8",
|
||||
"M c #A5A5A5",
|
||||
"N c #4B4B4B",
|
||||
"O c #828282",
|
||||
"P c #E3E3E3",
|
||||
"Q c #171717",
|
||||
"R c #595959",
|
||||
"S c #DCDCDC",
|
||||
"T c #DDDDDD",
|
||||
"U c #B7B7B7",
|
||||
"V c #5B5B5B",
|
||||
" .++. ",
|
||||
" +@#$$%&* ",
|
||||
" =-;>,,')!~ ",
|
||||
" +-{].^/(_:<* ",
|
||||
" [}|1.2345678.",
|
||||
".%90.abcade<f.",
|
||||
"*g8h*4ij+kdlma",
|
||||
"*n80*opj1qdrsa",
|
||||
".tuah.vw15xuy.",
|
||||
".8)zaA%$xoBCD.",
|
||||
" *EFGao..HIJh ",
|
||||
" eKLMNNOPJQ ",
|
||||
" hR<STUVa ",
|
||||
" ..qq.. "};
|
49
src/plugins/pdf_viewer/first_arrow.xpm
Normal file
49
src/plugins/pdf_viewer/first_arrow.xpm
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* XPM */
|
||||
static char * first_arrow_xpm[] = {
|
||||
"16 16 30 1",
|
||||
" c None",
|
||||
". c #1D2F3F",
|
||||
"+ c #1D2F40",
|
||||
"@ c #1C2C3C",
|
||||
"# c #3F6588",
|
||||
"$ c #000000",
|
||||
"% c #1C2E3E",
|
||||
"& c #5B88B2",
|
||||
"* c #5080AD",
|
||||
"= c #9EB8D1",
|
||||
"- c #192937",
|
||||
"; c #080D11",
|
||||
"> c #9CB7D1",
|
||||
", c #A4BDD5",
|
||||
"' c #B6CADD",
|
||||
") c #B2C7DB",
|
||||
"! c #AFC5DA",
|
||||
"~ c #B5C9DC",
|
||||
"{ c #5F8BB4",
|
||||
"] c #97B3CE",
|
||||
"^ c #A0BAD3",
|
||||
"/ c #9AB5CF",
|
||||
"( c #9BB6D0",
|
||||
"_ c #4C79A3",
|
||||
": c #95B2CE",
|
||||
"< c #91B0CC",
|
||||
"[ c #2A435B",
|
||||
"} c #49749C",
|
||||
"| c #375978",
|
||||
"1 c #456F96",
|
||||
" ",
|
||||
".+ ",
|
||||
"@# $ ",
|
||||
"%# $$ ",
|
||||
"@# $&$ ",
|
||||
"@# $*=$$$$$$$ ",
|
||||
"-# ;*>,''')!~$ ",
|
||||
"%#${]>^/(>>^($ ",
|
||||
"@$_:^>>>(//=<$ ",
|
||||
"@#$[########}$ ",
|
||||
"@# $[##|||||1$ ",
|
||||
"@# $[#$$$$$$$ ",
|
||||
"@# $[$ ",
|
||||
"%# $$ ",
|
||||
"@% $ ",
|
||||
" "};
|
49
src/plugins/pdf_viewer/last_arrow.xpm
Normal file
49
src/plugins/pdf_viewer/last_arrow.xpm
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* XPM */
|
||||
static char * last_arrow_xpm[] = {
|
||||
"16 16 30 1",
|
||||
" c None",
|
||||
". c #1D2F40",
|
||||
"+ c #1D2F3F",
|
||||
"@ c #000000",
|
||||
"# c #3F6588",
|
||||
"$ c #1C2C3C",
|
||||
"% c #1C2E3E",
|
||||
"& c #5B88B2",
|
||||
"* c #9EB8D1",
|
||||
"= c #5080AD",
|
||||
"- c #B5C9DC",
|
||||
"; c #AFC5DA",
|
||||
"> c #B2C7DB",
|
||||
", c #B6CADD",
|
||||
"' c #A4BDD5",
|
||||
") c #9CB7D1",
|
||||
"! c #080D11",
|
||||
"~ c #192937",
|
||||
"{ c #9BB6D0",
|
||||
"] c #A0BAD3",
|
||||
"^ c #9AB5CF",
|
||||
"/ c #97B3CE",
|
||||
"( c #5F8BB4",
|
||||
"_ c #91B0CC",
|
||||
": c #95B2CE",
|
||||
"< c #4C79A3",
|
||||
"[ c #49749C",
|
||||
"} c #2A435B",
|
||||
"| c #456F96",
|
||||
"1 c #375978",
|
||||
" ",
|
||||
" .+",
|
||||
" @ #$",
|
||||
" @@ #%",
|
||||
" @&@ #$",
|
||||
" @@@@@@@*=@ #$",
|
||||
" @-;>,,,')=! #~",
|
||||
" @{])){^])/(@#%",
|
||||
" @_*^^{)))]:<@$",
|
||||
" @[########}@#$",
|
||||
" @|11111##}@ #$",
|
||||
" @@@@@@@#}@ #$",
|
||||
" @}@ #$",
|
||||
" @@ #%",
|
||||
" @ %$",
|
||||
" "};
|
44
src/plugins/pdf_viewer/left_arrow.xpm
Normal file
44
src/plugins/pdf_viewer/left_arrow.xpm
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* XPM */
|
||||
static char * left_arrow_xpm[] = {
|
||||
"16 16 25 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #5B88B2",
|
||||
"@ c #5080AD",
|
||||
"# c #9EB8D1",
|
||||
"$ c #080D11",
|
||||
"% c #9CB7D1",
|
||||
"& c #A4BDD5",
|
||||
"* c #B6CADD",
|
||||
"= c #B2C7DB",
|
||||
"- c #AFC5DA",
|
||||
"; c #B5C9DC",
|
||||
"> c #5F8BB4",
|
||||
", c #97B3CE",
|
||||
"' c #A0BAD3",
|
||||
") c #9AB5CF",
|
||||
"! c #9BB6D0",
|
||||
"~ c #4C79A3",
|
||||
"{ c #95B2CE",
|
||||
"] c #91B0CC",
|
||||
"^ c #2A435B",
|
||||
"/ c #3F6588",
|
||||
"( c #49749C",
|
||||
"_ c #375978",
|
||||
": c #456F96",
|
||||
" ",
|
||||
" ",
|
||||
" . ",
|
||||
" .. ",
|
||||
" .+. ",
|
||||
" .@#....... ",
|
||||
" $@%&***=-;. ",
|
||||
" .>,%')!%%'!. ",
|
||||
" .~{'%%%!))#]. ",
|
||||
" .^////////(. ",
|
||||
" .^//_____:. ",
|
||||
" .^/....... ",
|
||||
" .^. ",
|
||||
" .. ",
|
||||
" . ",
|
||||
" "};
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue