sync 098claws

This commit is contained in:
Thorsten Maerz 2004-01-12 21:28:31 +00:00
parent d28c8f98ae
commit 61ee51da1d
179 changed files with 36579 additions and 49049 deletions

12
AUTHORS
View file

@ -16,7 +16,7 @@ claws-branch (http://sylpheed-claws.sourceforge.net)
Colin Leroy <colin@colino.net>
Paul Mangan <claws@thewildbeast.co.uk>
Leandro A. F. Pereira <leandro@linuxmag.com.br>
Luke Plant <lukeplant@softhome.net>
Luke Plant <L.Plant.98@cantab.net>
Martin Schaaf <mascha@ma-scha.de>
Carsten Schurig <Carsten.Schurig@web.de>
Sergey Vlasov <vsu@users.sourceforge.net>
@ -39,11 +39,12 @@ sylpheed-claws translation team
[fr] Melvin Hadasht <melvin.hadasht@free.fr>
[hr] Dragan <drleskov@inet.hr>
[it] Alessandro Maestri <maestri@cs.tin.it>
[pl] Witold Wladyslaw Wojciech Wilk
<maniack@zawilcow.tyc.katowice.supermedia.pl>
[ja] Rui Hirokawa <rui_hirokawa@ybb.ne.jp>
[pl] Emil <eminowbl@posejdon.wpk.p.lodz.pl>
[ru] Ruslan N. Balkin <baron@voices.ru>
[sk] Andrej Kacian <andrej@kacian.sk>
[sr] Urke MMI <urke@gmx.net>
[zh_CN] Hansom Young <hansom_young@yahoo.com>
sylpheed documentation (http://sylpheeddoc.sourceforge.net)
@ -194,3 +195,8 @@ contributors (beside the above; based on Changelog)
Martin Zwickel
Martin Wicke
Pawel Pêkala
Bogdan Sumanariu
David Relson
Matthias Förste
David Chalmers
Chad Robinson

284
ChangeLog
View file

@ -1,3 +1,287 @@
2003-12-15
* version 0.9.8a
2003-12-15
* src/procmsg.c: procmsg_open_data_file(): set buffer if DATA_READ
is specified and a buffer is given.
procmsg_open_cache_file_with_buffer(): new.
procmsg_read_cache(): fixed a bug that called setvbuf() after an
file I/O which caused buffer read error.
2003-12-12
* version 0.9.8
2003-12-12
* configure.in: enable IPv6 support by default.
2003-12-11
* src/inc.c: inc_mail(), inc_all_account_mail(): ask user to switch
to online when in offline mode.
* src/mainwindow.h: added main_window_toggle_online().
2003-12-11
* src/foldersel.c
src/folderview.[ch]
src/mainwindow.c
src/stock_pixmap.[ch]
src/pixmap/dir-noselect.xpm: made no-select folders display with
dim icon and string.
* src/Makefile.am: added offline.xpm, online.xpm, and
dir-noselect.xpm to EXTRA_DIST.
2003-12-11
* src/folder.h: added macro FOLDER_ITEM_CAN_ADD().
* src/folderview.c: folderview_drag_motion_cb(): code cleanup.
folderview_drag_received_cb(): don't accept at no_select folder or
from itself.
* src/foldersel.c: made folders on which no_select flag is set not
selectable.
2003-12-10
* src/imap.c: imap_do_copy_msgs(), imap_remove_msgs(): code cleanup.
set MSG_INVALID flag when messages are deleted.
* src/mh.c: mh_do_move_msgs(), mh_remove_msg(): set MSG_INVALID flag
when messages are deleted.
* src/procmsg.[ch]:
procmsg_move_messages()
procmsg_copy_messages(): return error status.
Added MSG_INVALID to MsgTmpFlags.
* src/summaryview.c: summary_execute(): detect errors and only remove
nodes that are invalidated.
summary_unthread_for_exec(): fixed a bug that didn't remove nodes
in collapsed trees.
2003-12-06
* src/mainwindow.[ch]: added online switch button to the statusbar,
and "/File/Work offline" in the menu.
* src/pixmaps/offline.xpm
src/pixmaps/online.xpm: new (borrowed from
themes/classic/communicator/icons/ in Mozilla).
* src/stock_pixmap.[ch]: added online.xpm and offline.xpm.
* src/textview.[ch]: textview_show_error(): new.
* src/summaryview.c: summary_display_msg_full(): update marks only
if messages are displayed.
* src/prefs_common.[ch]: added PrefsCommon::online_mode.
* src/news.c: news_session_get()
src/imap.c: imap_session_get(): return NULL when in offline mode.
* src/messageview.[ch]: messageview_show(): return status whether
messages are successfully displayed. Display error messages in
the view when failed.
* src/procmsg.c:
procmsg_get_message_file()
procmsg_open_message(): don't output warnings when fetch failed.
2003-12-04
* src/html.c: html_get_tag(): support attributes which don't have
values.
2003-12-04
* src/codeconv.c: conv_get_code_conv_func(): return conv_latintodisp
only if src_charset and current charset is identical or current
one is multibyte (fixes display of ISO-8859-5 on KOI8-R locale etc.).
2003-11-25
* autogen.sh: don't include m4 directory in aclocal.
* intl/libgnuintl.h: removed from cvs.
* po/.cvsignore: added stamp-po and remove-potcdate.sed.
2003-11-24
* upgraded to gettext-0.12.1.
2003-11-24 gettextize <bug-gnu-gettext@gnu.org>
* Makefile.am (SUBDIRS): Add m4.
(ACLOCAL_AMFLAGS): New variable.
(EXTRA_DIST): Add config.rpath.
* configure.in (AC_OUTPUT): Add m4/Makefile.
2003-11-21
* configure.in: added check for d_type member in struct dirent.
* src/mh.c: mh_scan_folder(): use d->d_type if available.
mh_get_uncached_msgs(): removed redundant stat().
mh_parse_msg(): return NULL if not a regular file.
mh_scan_tree_recursive(): use d->d_type if available.
* src/utils.[ch]:
dirent_is_regular_file()
dirent_is_directory(): new. Use d->d_type to determine the type
of entry if available.
remove_dir_recursive(): use dirent_is_directory().
2003-11-14
* src/folder.h: added 'updated' flag to FolderItem.
* src/folderview.[ch]: folderview_update_all_updated(): new. It
updates all updated folders.
* src/imap.c: set FolderView::update flag on changes of contents.
* src/main.c: send_queue()
src/mainwindow.c: send_queue_cb(): code cleanup.
* src/mh.c: code cleanup.
mh_scan_folder(): correctly count new messages.
* src/procmsg.[ch]: code cleanup.
procmsg_open_cache_file(): new.
procmsg_open_mark_file(): enable read/write/append.
procmsg_send_queue(): correctly choose outbox for accounts.
* src/send_message.[ch]: send_get_queue_info(): get a queue
information from queued messages.
send_queue_info_free(): free QueueInfo.
send_message_queue(): take QueueInfo as an argument instead of file.
* src/summaryview.c: summary_write_cache(): code cleanup.
2003-11-10
* src/compose.c: compose_redirect_write_headers(): correctly add
Resent-Cc: header.
2003-11-05
* src/imap.c: imap_get_msg_list(): fallback to FETCH command if SEARCH
command to get flags failed.
imap_search_flags(): returns UID array and flags hash table using
SEARCH command.
imap_fetch_flags(): returns UID array and flags hash table using
FETCH command.
2003-10-28
* src/summary_search.c: summary_search_execute(): fixed 'Select all
matched' when backward search is enabled.
Made the backward search button insensitive when 'select all
matched' is enabled.
2003-10-15
* version 0.9.7
2003-10-15
* src/imap.c: imap_scan_tree(): check the existence of root directory
with LIST instead of STATUS.
2003-10-07
* src/send_message.c: fixed format string bug (exploitable by
malicious SMTP server) when calling alertpanel_error()
(thanks to Georgi Guninski).
2003-10-03
* src/folder.[ch]
src/imap.[ch]
src/mh.[ch]
src/news.[ch]: refactoring of the folder system (based on the claws'
implementation).
* src/account.c
src/foldersel.c
src/folderview.c
src/mainwindow.c
src/messageview.c
src/procmsg.c
src/setup.c
src/summaryview.c: use FOLDER_TYPE() macro at every place.
2003-09-17
* version 0.9.6
2003-09-17
* src/addressbook.c:
addressbook_folder_load_person()
addressbook_folder_load_group(): sort the ctree after the end of
the loop (fixes performance issue when many addresses are in one
folder) (thanks to christian mock).
2003-09-16
* src/folderview.c: folder_init(): code cleanup.
* src/summaryview.c: summary_init(): check if boldfont is
successfully loaded.
* src/grouplistdialog.c: use proper callback for delete_event (thanks
to Takuro Ashie).
* src/imap.c: allow zero-length messages.
* src/recv.c: recv_bytes_write(): return immediately if size == 0.
2003-09-16
* src/folderview.c: folderview_init(): if font can't be loaded, fall
back to gtk default (fixes crashes on startup). Also removed the
redundant code.
2003-09-15
* src/compose.c: compose_insert_sig(): insert signature at the
current cursor position on manual operation.
2003-09-11
* src/summaryview.c: summary_key_pressed(): don't ignore delete key
even if the main window is locked.
2003-09-10
* src/action.c: improved synchronous action exit code (fixes long
delay after action exit on RH9) (thanks to Melvin).
* src/stringtable.[ch]: string_table_insert_string(): modified the
code to remove the warning "dereferencing type-punned pointer will
break strict-aliasing rules".
Use const gchar * instead of gchar * for arguments.
2003-09-05
* src/utils.[ch]: generate_mime_boundary(): a new function to create
MIME boundary (moved from rfc2015.c).
Removed more special characters.
Use random() instead of lrand48() which is obsolete.
Added an argument for prefix to prevent duplication.
Always add "=_" as a counter-QP sequence to simplify the code.
* src/rfc2015.c:
rfc2015_decrypt_message()
rfc2015_encrypt()
rfc2015_sign(): fixed a bug that didn't handle continuous content
lines correctly.
* src/compose.c
src/rfc2015.c: use generate_mime_boundary().
2003-09-05
* src/folderview.c:
folderview_delete_folder_cb()
folderview_remove_mailbox_cb(): close currently displayed folder
before removing FolderItem (fixes crash on deleting folder).
* src/folder.h
src/imap.[ch]: imap_scan_tree()
src/mh.[ch]: mh_scan_tree(): return -1 when scanning failed.
* src/summaryview.c: summary_clear_all(): also clear the message view.
* src/imap.c: imap_close(): fail if the specified folder is not
selected.
imap_scan_tree(): check if the specified root directory exist, and
try creating it if not.
imap_parse_list(): output warning if a server returns error.
imap_find_namespace_from_list(): support not slash-delimited path.
imap_status(): don't return values if they're not specified.
2003-09-02
* sylpheed.spec.in: fixed a typo.
2003-09-02
* version 0.9.5
2003-09-01
* src/inc.[ch]

View file

@ -1,3 +1,7 @@
2004-01-12 Thorsten Maerz <torte@netztorte.de>
* sync 098claws
2004-01-08 Thorsten Maerz <torte@netztorte.de>
* configure.ac
Makefile.am

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,287 @@
2003-12-15
* version 0.9.8a
2003-12-15
* src/procmsg.c: procmsg_open_data_file(): DATA_READ が指定されて
バッファが与えられたらバッファをセットするようにした。
procmsg_open_cache_file_with_buffer(): 新規。
procmsg_read_cache(): ファイル I/O の後に setvbuf() を呼んでいた
(バッファ読み込みエラーを起こしていた)バグを修正。
2003-12-12
* version 0.9.8
2003-12-12
* configure.in: IPv6 にデフォルトで対応するようにした。
2003-12-11
* src/inc.c: inc_mail(), inc_all_account_mail(): オフラインモードの
ときはユーザにオンラインに切り替えるように促すようにした。
* src/mainwindow.h: main_window_toggle_online() を追加。
2003-12-11
* src/foldersel.c
src/folderview.[ch]
src/mainwindow.c
src/stock_pixmap.[ch]
src/pixmap/dir-noselect.xpm: no-select フォルダを薄いアイコンと
文字列で表示。
* src/Makefile.am: offline.xpm, online.xpm, dir-noselect.xpm を
EXTRA_DIST に追加。
2003-12-11
* src/folder.h: マクロ FOLDER_ITEM_CAN_ADD() を追加。
* src/folderview.c: folderview_drag_motion_cb(): コードの整理。
folderview_drag_received_cb(): no_select フォルダで、あるいは
それ自身から受け付けないようにした。
* src/foldersel.c: no_select フラグがセットされているフォルダを選択
不可にした。
2003-12-10
* src/imap.c: imap_do_copy_msgs(), imap_remove_msgs(): コードの整理。
メッセージを削除したときに MSG_INVALID フラグをセット。
* src/mh.c: mh_do_move_msgs(), mh_remove_msg(): メッセージを削除した
ときに MSG_INVALID フラグをセット。
* src/procmsg.[ch]:
procmsg_move_messages()
procmsg_copy_messages(): エラーステータスを返すようにした。
MsgTmpFlags に MSG_INVALID を追加。
* src/summaryview.c: summary_execute(): エラーを検出し、無効になった
ノードのみを削除するようにした。
summary_unthread_for_exec(): 閉じたツリー中のノードを削除しない
バグを修正。
2003-12-06
* src/mainwindow.[ch]: ステータスバーにオンラインスイッチボタンを
追加し、メニューに「/ファイル/オフラインにする」を追加。
* src/pixmaps/offline.xpm
src/pixmaps/online.xpm: 新規(Mozilla の
themes/classic/communicator/icons/ から拝借)。
* src/stock_pixmap.[ch]: online.xpm と offline.xpm を追加。
* src/textview.[ch]: textview_show_error(): 新規。
* src/summaryview.c: summary_display_msg_full(): メッセージが表示
された場合のみマークを更新。
* src/prefs_common.[ch]: PrefsCommon::online_mode を追加。
* src/news.c: news_session_get()
src/imap.c: imap_session_get(): オフラインモードのときは NULL を
返すようにした。
* src/messageview.[ch]: messageview_show(): メッセージが表示できた
かどうかのステータスを返すようにした。失敗したときはエラー
メッセージをビューに表示するようにした。
* src/procmsg.c:
procmsg_get_message_file()
procmsg_open_message(): 取得に失敗したときに警告を表示しないように
した。
2003-12-04
* src/html.c: html_get_tag(): 値を持たない属性に対応。
2003-12-04
* src/codeconv.c: conv_get_code_conv_func(): src_charset と現在の
文字コードが同一の場合、または現在の文字コードがマルチバイトで
ある場合のみ conv_latintodisp を返す(KOI8-R locale 上での
ISO-8859-5 の表示を修正)。
2003-11-25
* autogen.sh: aclocal で m4 ディレクトリを含まないようにした。
* intl/libgnuintl.h: cvs から削除。
* po/.cvsignore: stamp-po と remove-potcdate.sed を追加。
2003-11-24
* gettext-0.12.1 に移行。
2003-11-21
* configure.in: struct dirent 中の d_type メンバのチェックを追加。
* src/mh.c: mh_scan_folder(): 利用可能な場合は d->d_type を使用。
mh_get_uncached_msgs(): 余分な stat() を削除。
mh_parse_msg(): 通常のファイルでない場合は NULL を返す。
mh_scan_tree_recursive(): 利用可能な場合は d->d_type を使用。
* src/utils.[ch]:
dirent_is_regular_file()
dirent_is_directory(): 新規。利用可能な場合はエントリのタイプを
判別するのに d->d_type を使用。
remove_dir_recursive(): dirent_is_directory() を使用。
2003-11-14
* src/folder.h: FolderItem に 'updated' フラグを追加。
* src/folderview.[ch]: folderview_update_all_updated(): 新規。全ての
更新されたフォルダを更新する。
* src/imap.c: 内容の変更時に FolderView::update フラグをセット。
* src/main.c: send_queue()
src/mainwindow.c: send_queue_cb(): コードの整理。
* src/mh.c: コードの整理。
mh_scan_folder(): 新着メッセージを正しくカウントするようにした。
* src/procmsg.[ch]: コードの整理。
procmsg_open_cache_file(): 新規。
procmsg_open_mark_file(): 読み込み/書き込み/追加書き込みができる
ようにした。
procmsg_send_queue(): アカウントに対応する送信控を正しく選択する
ようにした。
* src/send_message.[ch]: send_get_queue_info(): 送信待ちメッセージ
からキュー情報を取得。
send_queue_info_free(): QueueInfo を開放。
send_message_queue(): ファイルの代わりに QueueInfo を引数にとる
ようにした。
* src/summaryview.c: summary_write_cache(): コードの整理。
2003-11-10
* src/compose.c: compose_redirect_write_headers(): Resent-Cc: ヘッダ
を正しく付加するようにした。
2003-11-05
* src/imap.c: imap_get_msg_list(): フラグを得るための SEARCH コマンド
に失敗した場合 FETCH コマンドに fallback するようにした。
imap_search_flags(): SEARCH コマンドを使用して UID の配列とフラグの
ハッシュテーブルを返す。
imap_fetch_flags(): FETCH コマンドを使用して UID の配列とフラグの
ハッシュテーブルを返す。
2003-10-28
* src/summary_search.c: summary_search_execute(): 後方検索が有効な
ときの「一括検索」を修正。
「一括検索」が有効なときは後方検索ボタンを無効にするようにした。
2003-10-15
* version 0.9.7
2003-10-15
* src/imap.c: imap_scan_tree(): ルートディレクトリの存在を STATUS
ではなく LIST でチェックするようにした。
2003-10-07
* src/send_message.c: alertpanel_error() を呼ぶときのフォーマット
文字列のバグ(悪意のある SMTP サーバによって攻撃可能)を修正
(Georgi Guninski さん thanks)。
2003-10-03
* src/folder.[ch]
src/imap.[ch
src/mh.[ch]
src/news.[ch]: フォルダシステムのリファクタリング(claws の実装に
基づく)。
* src/account.c
src/foldersel.c
src/folderview.c
src/mainwindow.c
src/messageview.c
src/procmsg.c
src/setup.c
src/summaryview.c: 全ての場所で FOLDER_TYPE() マクロを使用。
2003-09-17
* version 0.9.6
2003-09-17
* src/addressbook.c:
addressbook_folder_load_person()
addressbook_folder_load_group(): ループの後で ctree をソートする
ようにした(一つのフォルダに多くのアドレスがある場合のパフォーマンス
の問題を解決)(christian mock さん thanks)。
2003-09-16
* src/folderview.c: folder_init(): コードを整理。
* src/summaryview.c: summary_init(): boldfont が正しくロードされたか
どうかをチェック。
* src/grouplistdialog.c: delete_event に適切なコールバックを使用する
ようにした(足永さん thanks)。
* src/imap.c: ゼロ長メッセージを許すようにした。
* src/recv.c: recv_bytes_write(): size == 0 の場合はすぐに戻るように
した。
2003-09-16
* src/folderview.c: folderview_init(): フォントが読み込めない場合は
gtk のデフォルトに fallback するようにした(起動時のクラッシュを
修正)。さらに不要なコードを除去。
2003-09-15
* src/compose.c: compose_insert_sig(): マニュアル操作のときは現在の
カーソルの位置に署名を挿入するようにした。
2003-09-11
* src/summaryview.c: summary_key_pressed(): メインウィンドウがロック
されていても delete キーを無視しないようにした。
2003-09-10
* src/action.c: action 終了のコードを改良(RH9 で action 終了時に
長時間待たされるのを修正) (Melvin さん thanks)。
* src/stringtable.[ch]: string_table_insert_string(): 警告
"dereferencing type-punned pointer will break strict-aliasing
rules" を除去するためにコードを修正。
引数に gchar * の代わりに const gchar * を使用。
2003-09-05
* src/utils.[ch]: generate_mime_boundary(): MIME boundary を作成する
新規関数(rfc2015.c から移動)。
さらに特別文字を除去。
obsolete な lrand48() のかわりに random() を使用。
重複を避けるために prefix の引数を追加。
対 QP シーケンスとして常に "=_" を追加し、コードを単純化。
* src/rfc2015.c:
rfc2015_decrypt_message()
rfc2015_encrypt()
rfc2015_sign(): 継続する content 行を正しく扱っていなかったバグを
修正。
* src/compose.c
src/rfc2015.c: generate_mime_boundary() を使用。
2003-09-05
* src/folderview.c:
folderview_delete_folder_cb()
folderview_remove_mailbox_cb(): FolderItem を削除する前に現在表示
されているフォルダを閉じるようにした(フォルダ削除時のクラッシュを
修正)。
* src/folder.h
src/imap.[ch]: imap_scan_tree()
src/mh.[ch]: mh_scan_tree(): スキャンに失敗したときは -1 を返す。
* src/summaryview.c: summary_clear_all(): メッセージビューもクリア。
* src/imap.c: imap_close(): 指定したフォルダが選択されていなければ
失敗。
imap_scan_tree(): 指定したルートディレクトリが存在するかどうかを
調べ、なければ作成するようにした。
imap_parse_list(): サーバがエラーを返したら警告を出力。
imap_find_namespace_from_list(): スラッシュで区切られていないパス
に対応。
imap_status(): 指定しなければ値を返さないようにした。
2003-09-02
* sylpheed.spec.in: typo を修正。
2003-09-02
* version 0.9.5
2003-09-01
* src/inc.[ch]

10
INSTALL
View file

@ -31,7 +31,7 @@ o RedHat Linux 5.2 (glibc 2.0.7)
o RedHat Linux 6.0
o RedHat Linux 6.1 + Helix GNOME (glibc 2.1.x)
o RedHat Linux 6.2 / 6.2J (glibc 2.1.x)
o RedHat Linux 7.0 / 7.0J / 7.1 / 7.2 / 7.3 / 8.0
o RedHat Linux 7.0 / 7.0J / 7.1 / 7.2 / 7.3 / 8.0 / 9.0
o LinuxPPC2000 + Yukikaze(Japanization kit)
o Linux2000G (Intel / PPC)
o HOLON Linux 2.0 (Intel / PPC)
@ -44,7 +44,7 @@ o Plamo Linux 2.0 / 2.1 / 2.2.x / 3.0
o Slackware 7.0 / 7.1 / 8.0 / 8.1 / 9.0
o Linux Mandrake 7.0 / 7.1 / 7.2 / 8.0 / 8.1 / 9.0 / 9.1
o SuSE Linux 6.3 (glibc 2.1.2) / 6.4
o SuSE Linux 7.0 / 7.1 / 7.2 / 7.3 / 8.0 / 8.1
o SuSE Linux 7.0 / 7.1 / 7.2 / 7.3 / 8.0 / 8.1 / 8.2
o OpenLinux 2.3 (glibc 2.1.1 -> 2.1.3)
o Caldera OpenDesktop 2.4
o Caldera Workstation 3.1
@ -74,10 +74,10 @@ Other commercial Unix
o Solaris 2.5 / 2.5.1 / 2.6
o Solaris 7 / 8 / 9
o AIX 4.3.3
o IRIX 6.3 / 6.4 / 6.5 6.5.8m
o HP-UX 10.20 / 11.0 / 11i
o Tru64 Unix 5.0 (OSF1 V5.0)
o SCO UnixWare 7
o Mac OS X 10.1.4 (Darwin 5.4) + XDarwin (without XLocale support) + libxpg4
Others
@ -126,11 +126,11 @@ Options for configure script
============================
--disable-compface disable compface (X-Face) support
--enable-openssl SSL support (requires OpenSSL)
--enable-ipv6 IPv6 support
--disable-ipv6 disable IPv6 support
--enable-gpgme GnuPG support (requires GPGME and GnuPG)
--enable-ldap LDAP support
--enable-jpilot JPilot support
--enable-openssl SSL support (requires OpenSSL)
For other options, refer to ./configure --help .

33
NEWS
View file

@ -1,5 +1,38 @@
Changes of Sylpheed
* 0.9.8a
* The bug that caused the failure of cache data read has been fixed.
* 0.9.8
* The offline mode has been implemented.
* The performance of the scanning of MH folders has been improved on
the platforms which support d_type in 'struct dirent'.
* The error checking on moving/deleting messages has become strict.
* When getting IMAP4 message list, it now fallbacks to FETCH command
if server doesn't fully support SEARCH command.
* Outbox for accounts are now correctly chosen when sending from queue.
* Gettext has been upgraded to 0.12.1.
* IPv6 support is now enabled by default.
* Other bugfixes have been made.
* 0.9.7
* The vulnerability in SMTP response handling, which is exploitable by
a malicious SMTP server, has been fixed.
* The structure of folder system has been sorted out.
* The checking of the existence of IMAP root directory has been modified.
* 0.9.6
* A crash bug when deleting currently opened folder has been fixed.
* The performance issue of the address book has been fixed.
* The behavior of manual signature insertion has been reverted.
* A crash bug on startup when a font can't be loaded has been fixed.
* The format of MIME boundary has been modified again.
* Other minor bugfixes have been made.
* 0.9.5
* The size, the position, and the visibility of separated views are now

View file

@ -17,20 +17,15 @@ win32 0.8.0claws+
[hoa]
o work on sylpheed :)
o several actions on filtering condition
o separate code of compose dialog and building of message
compose should return some kind of MIME structure so that
a message can be built.
o use libEtPan! in sylpheed
[christoph]
o Maildir support
o complete UIDPLUS IMAP support
o make summaryview display any list of messages,
fix processing rules by score
o privacy api that is independent from the crypto system
o rewrite mime message parsing (maybe required for privacy stuff)
o PEM support (S/MIME)
o add new messages to the summaryview without reloading the
whole list
@ -56,3 +51,11 @@ win32 0.8.0claws+
o Selective Download:
- pluginify selective download (separate filtering rules)
- create pop3 preview Folder as a part of the plugin
[luke]
o Content-Disposition header
- re-add parsing of Content-Disposition, to get names
for attachments (some MUAs do not set the Content-Type
'name' parameter)
o option to use KDE/GNOME for opening attachments

View file

@ -38,8 +38,6 @@ AC_DEFUN([AM_PATH_OPENSSL],
AC_ARG_WITH(openssl-libs, [ --with-openssl-libs=PREFIX Location of OpenSSL libs.],
with_openssl_libs="$withval")
if test "x${with_openssl_libs}" != "xno" -a "x${have_openssl_includes}" != "xno"; then
LIBS_save="$LIBS"
case $with_openssl_libs in
""|-L*) ;;
*) with_openssl_libs="-L$with_openssl_libs" ;;
@ -48,6 +46,7 @@ AC_DEFUN([AM_PATH_OPENSSL],
AC_CHECK_LIB(dl, dlopen, DL_LIBS="-ldl", DL_LIBS="")
AC_CACHE_CHECK([for OpenSSL libraries], openssl_libs,
[
LIBS_save="$LIBS"
LIBS="$LIBS $with_openssl_libs -lssl -lcrypto $DL_LIBS"
AC_TRY_LINK_FUNC(SSL_read, openssl_libs="yes", openssl_libs="no")
LIBS="$LIBS_save"

View file

@ -21,13 +21,6 @@ fi
dnl ----------------------------------------------------------------------
AC_CHECK_LIB(socket, socket)
AC_CHECK_LIB(crypto, CRYPTO_lock)
AC_CHECK_LIB(ssl, SSL_CTX_free,,,-lcrypto)
AC_CHECK_LIB(inet, connect)
AC_CHECK_LIB(nsl, t_accept)
AC_CHECK_LIB(dl, dlopen)
AC_CHECK_FUNCS(socket strdup strtod strtol snprintf shutdown)
dnl ----------------------------------------------------------------------

View file

@ -8,7 +8,7 @@ PACKAGE=sylpheed
dnl version number
MAJOR_VERSION=0
MINOR_VERSION=9
MICRO_VERSION=5
MICRO_VERSION=8
INTERFACE_AGE=0
BINARY_AGE=0
EXTRA_VERSION=0
@ -60,7 +60,7 @@ AC_SUBST(LT_REVISION)
AC_SUBST(LT_AGE)
dnl Specify a header configuration file
AM_CONFIG_HEADER(config.h)
AC_CONFIG_HEADERS(config.h)
AM_MAINTAINER_MODE
@ -68,7 +68,6 @@ dnl Checks for programs.
dnl AC_ARG_PROGRAM
AC_PROG_CC
AC_ISC_POSIX
AM_PROG_CC_STDC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
@ -76,7 +75,7 @@ AC_PROG_CPP
dnl AC_PROG_RANLIB
AM_PROG_LEX
AC_PROG_YACC
AM_PROG_LIBTOOL
AC_PROG_LIBTOOL
SYLPHEED_ACLOCAL_INCLUDE(ac)
@ -126,7 +125,7 @@ dnl Checks for iconv
AM_ICONV
dnl for gettext
ALL_LINGUAS="bg cs de el en_GB es fr hr hu it ja ko nl pl pt_BR ru sk sr sv zh_TW.Big5"
ALL_LINGUAS="bg cs de el en_GB es fr hr hu it ja ko nl pl pt_BR ru sk sr sv zh_CN zh_TW.Big5"
GETTEXT_PACKAGE=sylpheed
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Define text domain.])
@ -172,6 +171,19 @@ else
AC_MSG_RESULT(no)
fi
dnl Check for d_type member in struct dirent
AC_MSG_CHECKING([whether struct dirent has d_type member])
AC_CACHE_VAL(ac_cv_dirent_d_type,[
AC_TRY_COMPILE([#include <dirent.h>],
[struct dirent d; d.d_type = DT_REG;],
ac_cv_dirent_d_type=yes, ac_cv_dirent_d_type=no)
])
AC_MSG_RESULT($ac_cv_dirent_d_type)
if test $ac_cv_dirent_d_type = yes; then
AC_DEFINE(HAVE_DIRENT_D_TYPE, 1,
Define if `struct dirent' has `d_type' member.)
fi
dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
@ -239,8 +251,8 @@ LIBS=$syl_save_LIBS
dnl check for IPv6 option
AC_ARG_ENABLE(ipv6,
[ --enable-ipv6 Enable IPv6 support [default=no]],
[ac_cv_enable_ipv6=$enableval], [ac_cv_enable_ipv6=no])
[ --disable-ipv6 Disable IPv6 support],
[ac_cv_enable_ipv6=$enableval], [ac_cv_enable_ipv6=yes])
dnl automated checks for IPv6 support.
AC_MSG_CHECKING([whether to use IPv6])
@ -337,8 +349,20 @@ dnl Check for X-Face support
AC_ARG_ENABLE(compface,
[ --disable-compface Do not use compface (X-Face)],
[ac_cv_enable_compface=$enableval], [ac_cv_enable_compface=yes])
if test "$ac_cv_enable_compface" = yes; then
AC_CHECK_LIB(compface, uncompface,,[ac_cv_enable_compface=no])
AC_MSG_CHECKING([whether to use compface])
if test x"$ac_cv_enable_compface" = xyes; then
AC_MSG_RESULT(yes)
AC_CHECK_LIB(compface, uncompface,
[AC_DEFINE(HAVE_LIBCOMPFACE, 1, Define if you want compface support.)],
[ac_cv_enable_compface=no])
if test x"$ac_cv_enable_compface" = xyes; then
COMPFACE_LIBS="-lcompface"
else
COMPFACE_LIBS=""
fi
AC_SUBST(COMPFACE_LIBS)
else
AC_MSG_RESULT(no)
fi
dnl for LDAP support in addressbook
@ -401,12 +425,14 @@ if test "$ac_cv_enable_jpilot" = yes; then
[ ac_cv_enable_jpilot=yes
AC_DEFINE(USE_JPILOT, 1, Define if you want JPilot support in addressbook.) ])
fi
AC_MSG_CHECKING([whether jpilot is available])
AC_MSG_RESULT($ac_cv_enable_jpilot)
if test "$ac_cv_enable_jpilot" = yes; then
LIBS="$LIBS -lpisock"
AC_CHECK_LIB(pisock, unpack_Address, [JPILOT_LIBS="-lpisock"], [JPILOT_LIBS="" ac_cv_enable_jpilot="no"])
if test x"$ac_cv_enable_jpilot" = xyes; then
AC_DEFINE(USE_JPILOT, 1, Define if you want JPilot support in addressbook.)
else
AC_MSG_NOTICE([JPilot support not available])
fi
AC_SUBST(JPILOT_LIBS)
else
AC_MSG_RESULT(no)
fi
@ -433,7 +459,7 @@ PLUGINS=""
dnl --- Trayicon ---
AC_ARG_ENABLE(trayicon-plugin,
[ --enable-trayicon-plugin System Tray Icon [default=no]],
[ --disable-trayicon-plugin Do not build System Tray Icon plugin],
[ac_cv_enable_trayicon_plugin=$enableval], [ac_cv_enable_trayicon_plugin=yes])
if test x"$ac_cv_enable_trayicon_plugin" = xyes; then
PLUGINS="trayicon $PLUGINS"
@ -442,7 +468,7 @@ AM_CONDITIONAL(BUILD_TRAYICON_PLUGIN, test x"$ac_cv_enable_trayicon_plugin" = xy
dnl --- SpamAssassin ---
AC_ARG_ENABLE(spamassassin-plugin,
[ --enable-spamassassin-plugin Build SpamAssassin plugin [default=no]],
[ --enable-spamassassin-plugin Build SpamAssassin plugin [default=no]],
[ac_cv_enable_spamassassin_plugin=$enableval], [ac_cv_enable_spamassassin_plugin=no])
if test x"$ac_cv_enable_spamassassin_plugin" = xyes; then
AC_SPAMASSASSIN
@ -452,10 +478,10 @@ AM_CONDITIONAL(BUILD_SPAMASSASSIN_PLUGIN, test x"$ac_cv_enable_spamassassin_plug
dnl --- MathML Viewer ---
AC_ARG_ENABLE(mathml-viewer-plugin,
[ --enable-mathml-viewer-plugin Build MathML-Viewer plugin [default=no]],
[ --disable-mathml-viewer-plugin Do not build MathML-Viewer plugin],
[ac_cv_enable_mathml_viewer_plugin=$enableval], [ac_cv_enable_mathml_viewer_plugin=yes])
if test x"$ac_cv_enable_mathml_viewer_plugin" = xyes; then
PKG_CHECK_MODULES(GTK_MATH_VIEW, gtkmathview >= 0.4.2, :, ac_cv_enable_mathml_viewer_plugin=no)
PKG_CHECK_MODULES(GTK_MATH_VIEW, gtkmathview >= 0.4.2 gtkmathview < 0.5, :, ac_cv_enable_mathml_viewer_plugin=no)
if test x"$ac_cv_enable_mathml_viewer_plugin" = xyes; then
AC_SUBST(GTK_MATH_VIEW_CFLAGS)
@ -468,14 +494,14 @@ AM_CONDITIONAL(BUILD_MATHML_VIEWER_PLUGIN, test x"$ac_cv_enable_mathml_viewer_pl
dnl --- Image Viewer ---
AC_ARG_ENABLE(image-viewer-plugin,
[ --disable-image-viewer-plugin Do not build image viewer plugin],
[ --disable-image-viewer-plugin Do not build image viewer plugin],
[ac_cv_enable_image_viewer_plugin=$enableval], [ac_cv_enable_image_viewer_plugin=yes])
if test x"$ac_cv_enable_image_viewer_plugin" = xyes; then
AC_ARG_ENABLE(gdk-pixbuf,
[ --disable-gdk-pixbuf Do not use gdk-pixbuf],
[ --disable-gdk-pixbuf Do not use gdk-pixbuf],
[ac_cv_enable_gdk_pixbuf=$enableval], [ac_cv_enable_gdk_pixbuf=yes])
AC_ARG_ENABLE(imlib,
[ --disable-imlib Do not use imlib],
[ --disable-imlib Do not use imlib],
[ac_cv_enable_imlib=$enableval], [ac_cv_enable_imlib=yes])
if test "$ac_cv_enable_gdk_pixbuf" = yes; then
@ -495,7 +521,7 @@ AM_CONDITIONAL(BUILD_IMAGE_VIEWER_PLUGIN, test x"$ac_cv_enable_image_viewer_plug
dnl --- Dillo Viewer ---
AC_ARG_ENABLE(dillo-viewer-plugin,
[ --enable-dillo-viewer-plugin Build Dillo plugin for html mail rendering [default=no]],
[ --disable-dillo-viewer-plugin Do not build Dillo plugin for html mail rendering],
[ac_cv_enable_dillo_viewer_plugin=$enableval], [ac_cv_enable_dillo_viewer_plugin=yes])
if test x"$ac_cv_enable_dillo_viewer_plugin" = xyes; then
PLUGINS="dillo-viewer $PLUGINS"
@ -504,7 +530,7 @@ AM_CONDITIONAL(BUILD_DILLO_VIEWER_PLUGIN, test x"$ac_cv_enable_dillo_viewer_plug
dnl --- Demo ---
AC_ARG_ENABLE(demo-plugin,
[ --enable-demo-plugin Build demo plugin [default=no]],
[ --enable-demo-plugin Build demo plugin [default=no]],
[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"
@ -513,7 +539,7 @@ AM_CONDITIONAL(BUILD_DEMO_PLUGIN, test x"$ac_cv_enable_demo_plugin" = xyes)
dnl --- ClamAV ---
AC_ARG_ENABLE(clamav-plugin,
[ --enable-clamav-plugin Build Clam AntiVirus plugin [default=no]],
[ --disable-clamav-plugin Do not build Clam AntiVirus plugin],
[ac_cv_enable_clamav_plugin=$enableval], [ac_cv_enable_clamav_plugin=yes])
if test x"$ac_cv_enable_clamav_plugin" = xyes; then
AC_CHECK_LIB(clamav, cl_scanfile, clamav_lib=-lclamav, ac_cv_enable_clamav_plugin=no)

View file

@ -1,10 +1,10 @@
.TH "Sylpheed" "1" "" "Hiroyuki Yamamoto" ""
.TH "Sylpheed-Claws" "1" "" "Hiroyuki Yamamoto & the Sylpheed-Claws team" ""
.SH "NAME"
.LP
Sylpheed \- a GTK+ based fast e\-mail and news client
Sylpheed\-Claws \- a GTK+ based fast e\-mail and news client
.SH "DESCRIPTION"
.TP
Sylpheed is an e\-mail client (and news reader) based on GTK+, running on X Window System, and aiming for
Sylpheed\-Claws is an e\-mail client (and news reader) based on GTK+, running on X Window System, and aiming for
.br
* Quick response
.br
@ -79,6 +79,8 @@ o automake + autoconf support
o internationalization of messages by gettext
.br
o support of many code sets, including UTF\-8 (Unicode) (when using libjconv)
.br
o support for plugins
\fR
.LP
This list is not complete.
@ -109,6 +111,8 @@ This list is not complete.
\fB \-\-help\fR
.br
\fB \-\-version\fR
.br
\fB \-\-config\-dir\fR
.SH "FILES"
.LP
.TP
@ -124,8 +128,20 @@ Manual files in HTML format
$PREFIX/share/sylpheed/faq
FAQ files in HTML format
.TP
$PREFIX/share/sylpheed/themes
Global themes directory
.TP
$PREFIX/lib/sylpheed/plugins
Directory for plugins
.TP
$PREFIX/include/sylpheed
Directory for header files
.TP
$HOME/.sylpheed
User's configuration files directory
Default directory for user's configuration files directory
.TP
$HOME/.sylpheed/themes
User's themes directory
.TP
$HOME/.sylpheed/accountrc
Configuration for account(s)
@ -142,8 +158,8 @@ Configuration for custom headers for sending mail
$HOME/.sylpheed/dispheaderrc
Configuration for custom display of headers in message view
.TP
$HOME/.sylpheed/filterrc
Filter function configuration
$HOME/.sylpheed/matcherrc
Filtering and Processing function configuration
.TP
$HOME/.sylpheed/folderlist.xml
Folder hierachy listing
@ -210,11 +226,13 @@ Start sylpheed in (or switch to, if already running) online mode
Start sylpheed in (or switch to, if already running) offline mode
.TP
\fB\-\-help\fR
.br
display the help message and exit
.TP
\fB\-\-version\fR
display version number and exit
.TP
\fB\-\-config\-dir\fR
display the CONFIG\-DIR and exit
.SH "INSTALLATION"
.LP
This program requires GTK+ 1.2.6 or higher to be compiled.
@ -235,7 +253,7 @@ Password: [Enter password]
.br
# make install
.LP
See INSTALL from the source distribution package for full installation instructions.
Refer to ./configure \-\-help for further information.
.SH "AUTHORS"
.LP
.TP
@ -262,6 +280,8 @@ Thorsten Maerz <torte@netztorte.de>
.br
Paul Mangan <claws@thewildbeast.co.uk>
.br
Luke Plant <L.Plant.98@cantab.net>
.br
Martin Schaaf <mascha@ma\-scha.de>
.br
Carsten Schurig <Carsten.Schurig@web.de>
@ -270,10 +290,7 @@ Sergey Vlasov <vsu@users.sourceforge.net>
.br
Hiroyuki Yamamoto <hiro\-y@kcn.ne.jp>
.TP
sylpheed\-w32 (http://www.gnupg.org/cvs\-access.html)
Werner Koch <wk@gnupg.org>
.TP
sylpheed\-claws\-w32 (http://claws\-w32.sourceforge.net)
sylpheed\-claws\-w32
Thorsten Maerz <torte@netztorte.de>\fR
@ -284,10 +301,7 @@ Sylpheed Homepage
<http://sylpheed.good\-day.net>
.TP
Sylpheed\-Claws Homepage
<http://www.sf.net/sylpheed\-claws>
.TP
Sylpheed Win32
<http://www.gnupg.org/cvs\-access.html>
<http://sylpheed\-claws.sf.net>
.TP
Sylpheed\-Claws Win32 Homepage
<http://www.sf.net/claws\-w32>
<http://sylpheed\-claws.sf.net/win32>

View file

@ -1,23 +1,27 @@
src/account.c
src/action.c
src/addressadd.c
src/addressbook.c
src/addrgather.c
src/addrindex.c
src/alertpanel.c
src/browseldap.c
src/common/intl.h
src/common/md5.c
src/common/nntp.c
src/common/plugin.c
src/common/smtp.c
src/common/ssl.c
src/common/ssl_certificate.c
src/common/utils.c
src/compose.c
src/crash.c
src/editaddress.c
src/editbook.c
src/editgroup.c
src/editjpilot.c
src/editldap.c
src/editldap_basedn.c
src/editldap.c
src/editvcard.c
src/exphtmldlg.c
src/expldifdlg.c
@ -30,11 +34,14 @@ src/folderview.c
src/grouplistdialog.c
src/gtk/about.c
src/gtk/colorlabel.c
src/gtk/description_window.c
src/gtk/gtkaspell.c
src/gtk/gtkutils.c
src/gtk/logwindow.c
src/gtk/pluginwindow.c
src/gtk/prefswindow.c
src/gtk/progressdialog.c
src/gtk/sslcertwindow.c
src/gtk/gtkaspell.c
src/headerview.c
src/imap.c
src/import.c
@ -43,56 +50,58 @@ src/importmutt.c
src/importpine.c
src/inc.c
src/inputdialog.c
src/logwindow.c
src/ldif.c
src/main.c
src/mainwindow.c
src/matcher.c
src/message_search.c
src/messageview.c
src/mh.c
src/mimeview.c
src/news.c
src/passphrase.c
src/plugins/clamav/clamav_plugin.c
src/plugins/clamav/clamav_plugin_gtk.c
src/plugins/demo/demo.c
src/plugins/dillo_viewer/dillo_prefs.c
src/plugins/dillo_viewer/dillo_viewer.c
src/plugins/image_viewer/plugin.c
src/plugins/image_viewer/viewer.c
src/plugins/image_viewer/viewerprefs.c
src/plugins/mathml_viewer/mathml_viewer.c
src/plugins/spamassassin/libspamc.c
src/plugins/spamassassin/spamassassin.c
src/plugins/spamassassin/spamassassin_gtk.c
src/plugins/spamassassin/utils.c
src/plugins/trayicon/trayicon.c
src/pop.c
src/prefs_gtk.c
src/prefs_account.c
src/prefs_actions.c
src/prefs_common.c
src/prefs_customheader.c
src/prefs_display_header.c
src/prefs_filtering_action.c
src/prefs_filtering.c
src/prefs_folder_item.c
src/prefs_fonts.c
src/prefs_gtk.c
src/prefs_matcher.c
src/prefs_scoring.c
src/prefs_spelling.c
src/prefs_summary_column.c
src/prefs_template.c
src/prefs_toolbar.c
src/privacy.c
src/procmsg.c
src/progressdialog.c
src/quote_fmt.c
src/rfc2015.c
src/select-keys.c
src/send_message.c
src/setup.c
src/sigstatus.c
src/sgpgme.c
src/sourcewindow.c
src/ssl_manager.c
src/string_match.c
src/summary_search.c
src/summaryview.c
src/textview.c
src/toolbar.c
src/plugins/demo/demo.c
src/plugins/trayicon/trayicon.c
src/plugins/mathml_viewer/mathml_viewer.c
src/plugins/image_viewer/viewerprefs.c
src/plugins/image_viewer/viewer.c
src/plugins/image_viewer/plugin.c
src/plugins/dillo_viewer/dillo_viewer.c
src/plugins/dillo_viewer/dillo_prefs.c
src/plugins/clamav/clamav_plugin_gtk.c
src/plugins/clamav/clamav_plugin.c
src/plugins/spamassassin/spamassassin.c
src/plugins/spamassassin/libspamc.c
src/plugins/spamassassin/spamassassin_gtk.c
src/plugins/spamassassin/utils.c

4892
po/de.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

4892
po/es.po

File diff suppressed because it is too large Load diff

4992
po/fr.po

File diff suppressed because it is too large Load diff

3779
po/hr.po

File diff suppressed because it is too large Load diff

9399
po/ja.po

File diff suppressed because it is too large Load diff

5744
po/pl.po

File diff suppressed because it is too large Load diff

11126
po/sk.po

File diff suppressed because it is too large Load diff

4039
po/sr.po

File diff suppressed because it is too large Load diff

View file

@ -19,10 +19,10 @@ bin_PROGRAMS = sylpheed
sylpheed_SOURCES = \
account.c \
action.c \
addr_compl.c \
addrbook.c \
addrcache.c \
addrclip.c \
addr_compl.c \
addressadd.c \
addressbook.c \
addrgather.c \
@ -32,6 +32,7 @@ sylpheed_SOURCES = \
addrquery.c \
addrselect.c \
alertpanel.c \
browseldap.c \
codeconv.c \
compose.c \
crash.c \
@ -41,8 +42,8 @@ sylpheed_SOURCES = \
editbook.c \
editgroup.c \
editjpilot.c \
editldap.c \
editldap_basedn.c \
editldap.c \
editvcard.c \
enriched.c \
exphtmldlg.c \
@ -67,11 +68,11 @@ sylpheed_SOURCES = \
inputdialog.c \
jpilot.c \
ldapctrl.c \
ldaplocate.c \
ldapquery.c \
ldapserver.c \
ldaputil.c \
ldif.c \
logwindow.c \
main.c \
mainwindow.c \
manual.c \
@ -79,7 +80,6 @@ sylpheed_SOURCES = \
matcher_parser_lex.l \
matcher_parser_parse.y \
mbox.c \
mbox_folder.c \
message_search.c \
messageview.c \
mh.c \
@ -89,6 +89,7 @@ sylpheed_SOURCES = \
news.c \
noticeview.c \
passphrase.c \
pgpmime.c \
pine.c \
pop.c \
prefs_account.c \
@ -96,30 +97,29 @@ sylpheed_SOURCES = \
prefs_common.c \
prefs_customheader.c \
prefs_display_header.c \
prefs_filtering.c \
prefs_filtering_action.c \
prefs_filtering.c \
prefs_folder_item.c \
prefs_fonts.c \
prefs_gtk.c \
prefs_matcher.c \
prefs_scoring.c \
prefs_spelling.c \
prefs_summary_column.c \
prefs_template.c \
prefs_toolbar.c \
privacy.c \
procheader.c \
procmime.c \
procmsg.c \
progressdialog.c \
quote_fmt.c \
quote_fmt_lex.l \
quote_fmt_parse.y \
recv.c \
rfc2015.c \
scoring.c \
select-keys.c \
send_message.c \
setup.c \
sigstatus.c \
sgpgme.c \
simple-gettext.c \
sourcewindow.c \
ssl_manager.c \
@ -132,6 +132,8 @@ sylpheed_SOURCES = \
toolbar.c \
undo.c \
unmime.c \
localfolder.c \
remotefolder.c \
vcard.c
sylpheedincludedir = $(pkgincludedir)
@ -139,10 +141,11 @@ sylpheedinclude_HEADERS = \
account.h \
action.h \
adbookbase.h \
addr_compl.h \
addrbook.h \
addrcache.h \
addrclip.h \
addr_compl.h \
addrdefs.h \
addressadd.h \
addressbook.h \
addressitem.h \
@ -153,6 +156,7 @@ sylpheedinclude_HEADERS = \
addrquery.h \
addrselect.h \
alertpanel.h \
browseldap.h \
codeconv.h \
compose.h \
crash.h \
@ -162,8 +166,8 @@ sylpheedinclude_HEADERS = \
editbook.h \
editgroup.h \
editjpilot.h \
editldap.h \
editldap_basedn.h \
editldap.h \
editvcard.h \
enriched.h \
exphtmldlg.h \
@ -188,11 +192,11 @@ sylpheedinclude_HEADERS = \
inputdialog.h \
jpilot.h \
ldapctrl.h \
ldaplocate.h \
ldapquery.h \
ldapserver.h \
ldaputil.h \
ldif.h \
logwindow.h \
main.h \
mainwindow.h \
manual.h \
@ -201,7 +205,6 @@ sylpheedinclude_HEADERS = \
matcher_parser_lex.h \
matcher_parser_parse.h \
mbox.h \
mbox_folder.h \
message_search.h \
messageview.h \
mh.h \
@ -211,6 +214,7 @@ sylpheedinclude_HEADERS = \
news.h \
noticeview.h \
passphrase.h \
pgpmime.h \
pine.h \
pop.h \
prefs_account.h \
@ -218,30 +222,29 @@ sylpheedinclude_HEADERS = \
prefs_common.h \
prefs_customheader.h \
prefs_display_header.h \
prefs_filtering.h \
prefs_filtering_action.h \
prefs_filtering.h \
prefs_folder_item.h \
prefs_fonts.h \
prefs_gtk.h \
prefs_matcher.h \
prefs_scoring.h \
prefs_spelling.h \
prefs_summary_column.h \
prefs_template.h \
prefs_toolbar.h \
privacy.h \
procheader.h \
procmime.h \
procmsg.h \
progressdialog.h \
quote_fmt.h \
quote_fmt_lex.h \
quote_fmt_parse.h \
recv.h \
rfc2015.h \
scoring.h \
select-keys.h \
send_message.h \
setup.h \
sigstatus.h \
sgpgme.h \
sourcewindow.h \
ssl_manager.h \
statusbar.h \
@ -253,6 +256,8 @@ sylpheedinclude_HEADERS = \
toolbar.h \
undo.h \
unmime.h \
localfolder.h \
remotefolder.h \
vcard.h
BUILT_SOURCES = \
@ -268,6 +273,7 @@ EXTRA_DIST = \
pixmaps/category.xpm \
pixmaps/checkbox_off.xpm \
pixmaps/checkbox_on.xpm \
pixmaps/check_spelling.xpm \
pixmaps/clipkey.xpm \
pixmaps/clip.xpm \
pixmaps/close.xpm \
@ -307,16 +313,10 @@ EXTRA_DIST = \
pixmaps/mail_send.xpm \
pixmaps/mail.xpm \
pixmaps/mark.xpm \
pixmaps/messageview_text.xpm \
pixmaps/mime_application_octet_stream.xpm \
pixmaps/mime_application.xpm \
pixmaps/mime_audio.xpm \
pixmaps/mime_gpg_expired.xpm \
pixmaps/mime_gpg_failed.xpm \
pixmaps/mime_gpg_passed.xpm \
pixmaps/mime_gpg_signed.xpm \
pixmaps/mime_gpg_unknown.xpm \
pixmaps/mime_image.xpm \
pixmaps/mime_message.xpm \
pixmaps/mime_text_enriched.xpm \
pixmaps/mime_text_html.xpm \
pixmaps/mime_text_plain.xpm \
@ -326,10 +326,18 @@ EXTRA_DIST = \
pixmaps/notice_error.xpm \
pixmaps/notice_note.xpm \
pixmaps/notice_warn.xpm \
pixmaps/offline.xpm \
pixmaps/online.xpm \
pixmaps/outbox_hrm.xpm \
pixmaps/outbox.xpm \
pixmaps/paste.xpm \
pixmaps/preferences.xpm \
pixmaps/privacy_expired.xpm \
pixmaps/privacy_failed.xpm \
pixmaps/privacy_passed.xpm \
pixmaps/privacy_signed.xpm \
pixmaps/privacy_unknown.xpm \
pixmaps/privacy_warn.xpm \
pixmaps/properties.xpm \
pixmaps/quicksearch.xpm \
pixmaps/regular.xpm \
@ -341,9 +349,7 @@ EXTRA_DIST = \
pixmaps/trash.xpm \
pixmaps/unread.xpm \
pixmaps/up_arrow.xpm \
pixmaps/vcard.xpm \
pixmaps/work_offline.xpm \
pixmaps/work_online.xpm
pixmaps/vcard.xpm
INCLUDES = \
-Icommon \
@ -361,6 +367,8 @@ sylpheed_LDADD = \
$(GPGME_LIBS) \
$(LDAP_LIBS) \
$(OPENSSL_LIBS) \
$(COMPFACE_LIBS) \
$(JPILOT_LIBS) \
$(LIBICONV) \
$(SYLPHEED_RES)

View file

@ -46,6 +46,8 @@
#include "utils.h"
#include "alertpanel.h"
#include "procheader.h"
#include "customheader.h"
#include "remotefolder.h"
typedef enum
{
@ -81,6 +83,7 @@ static void account_edit_create (void);
static void account_edit_prefs (void);
static void account_delete (void);
static void account_clone (void);
static void account_up (void);
static void account_down (void);
@ -88,6 +91,10 @@ static void account_down (void);
static void account_set_default (void);
static void account_edit_close (void);
static gint account_clone_event (GtkWidget *widget,
GdkEventAny *event,
gpointer data);
static gint account_delete_event (GtkWidget *widget,
GdkEventAny *event,
gpointer data);
@ -349,7 +356,7 @@ void account_add(void)
}
folder->account = ac_prefs;
ac_prefs->folder = REMOTE_FOLDER(folder);
ac_prefs->folder = folder;
folder_add(folder);
if (ac_prefs->protocol == A_IMAP4)
folder->klass->create_tree(folder);
@ -432,7 +439,7 @@ void account_set_missing_folder(void)
}
folder->account = ap;
ap->folder = REMOTE_FOLDER(folder);
ap->folder = folder;
folder_add(folder);
if (ap->protocol == A_IMAP4)
folder->klass->create_tree(folder);
@ -539,6 +546,7 @@ static void account_edit_create(void)
GtkWidget *add_btn;
GtkWidget *edit_btn;
GtkWidget *del_btn;
GtkWidget *clone_btn;
GtkWidget *up_btn;
GtkWidget *down_btn;
@ -550,7 +558,7 @@ static void account_edit_create(void)
debug_print("Creating account edit window...\n");
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (window, 500, 320);
gtk_widget_set_usize (window, 500, 350);
gtk_container_set_border_width (GTK_CONTAINER (window), 8);
gtk_window_set_title (GTK_WINDOW (window), _("Edit accounts"));
gtk_window_set_modal (GTK_WINDOW (window), TRUE);
@ -639,6 +647,12 @@ static void account_edit_create(void)
g_signal_connect (G_OBJECT(del_btn), "clicked",
G_CALLBACK (account_delete), NULL);
clone_btn = gtk_button_new_with_label (_(" Clone "));
gtk_widget_show (clone_btn);
gtk_box_pack_start (GTK_BOX (vbox2), clone_btn, FALSE, FALSE, 4);
gtk_signal_connect (GTK_OBJECT(clone_btn), "clicked",
GTK_SIGNAL_FUNC (account_clone), NULL);
down_btn = gtk_button_new_with_label (_("Down"));
gtk_widget_show (down_btn);
gtk_box_pack_end (GTK_BOX (vbox2), down_btn, FALSE, FALSE, 4);
@ -723,6 +737,162 @@ static gboolean account_delete_references_func(GNode *node, gpointer data)
return FALSE;
}
#define ACP_FDUP(fld) ac_clon->fld = ((ac_prefs->fld) != NULL)?\
g_strdup(ac_prefs->fld): NULL
#define ACP_FASSIGN(fld) ac_clon->fld = ac_prefs->fld
static void account_clone(void)
{
GtkCList *clist = GTK_CLIST(edit_account.clist);
gint row;
PrefsAccount *ac_prefs, *ac_clon;
GSList *hdrs = NULL;
CustomHeader *cch = NULL, *ch = NULL;
if (!clist->selection) return;
row = GPOINTER_TO_INT(clist->selection->data);
ac_prefs = gtk_clist_get_row_data(clist, row);
if (ac_prefs->protocol == A_IMAP4 || ac_prefs->protocol == A_NNTP) {
alertpanel_error(_("Accounts with remote folders cannot be cloned"));
return;
}
ac_clon = prefs_account_new();
/* copy fields */
ac_clon->account_name = g_strdup_printf(_("Cloned %s"),
ac_prefs->account_name);
/* personal */
ACP_FDUP(name);
ACP_FDUP(address);
ACP_FDUP(organization);
/* server */
ACP_FASSIGN(protocol);
ACP_FDUP(recv_server);
ACP_FDUP(smtp_server);
ACP_FDUP(nntp_server);
ACP_FASSIGN(use_nntp_auth);
ACP_FASSIGN(use_nntp_auth_onconnect);
ACP_FDUP(userid);
ACP_FDUP(passwd);
ACP_FDUP(local_mbox);
ACP_FASSIGN(use_mail_command);
ACP_FDUP(mail_command);
#if USE_OPENSSL
ACP_FASSIGN(ssl_pop);
ACP_FASSIGN(ssl_imap);
ACP_FASSIGN(ssl_nntp);
ACP_FASSIGN(ssl_smtp);
ACP_FASSIGN(use_nonblocking_ssl);
#endif /* USE_OPENSSL */
ac_clon->tmp_pass = NULL;
/* receive */
ACP_FASSIGN(rmmail);
ACP_FASSIGN(msg_leave_time);
ACP_FASSIGN(getall);
ACP_FASSIGN(recv_at_getall);
ACP_FASSIGN(sd_rmmail_on_download);
ACP_FASSIGN(sd_filter_on_recv);
ACP_FASSIGN(enable_size_limit);
ACP_FASSIGN(size_limit);
ACP_FASSIGN(filter_on_recv);
ACP_FDUP(inbox);
ACP_FASSIGN(max_articles);
ACP_FASSIGN(imap_auth_type);
/* send */
ACP_FASSIGN(add_date);
ACP_FASSIGN(gen_msgid);
ACP_FASSIGN(add_customhdr);
ACP_FASSIGN(use_smtp_auth);
ACP_FASSIGN(smtp_auth_type);
ACP_FDUP(smtp_userid);
ACP_FDUP(smtp_passwd);
ac_clon->tmp_smtp_pass = NULL;
ACP_FASSIGN(pop_before_smtp);
ACP_FASSIGN(pop_before_smtp_timeout);
ACP_FASSIGN(last_pop_login_time);
ac_clon->customhdr_list = NULL;
hdrs = ac_prefs->customhdr_list;
while (hdrs != NULL) {
ch = (CustomHeader *)hdrs->data;
cch = g_new0(CustomHeader, 1);
cch->account_id = ac_clon->account_id;
cch->name = (ch->name != NULL) ? g_strdup(ch->name) : NULL;
cch->value = (ch->value != NULL) ? g_strdup(ch->value) : NULL;
ac_clon->customhdr_list = g_slist_append(ac_clon->customhdr_list, cch);
hdrs = g_slist_next(hdrs);
}
/* compose */
ACP_FASSIGN(sig_type);
ACP_FDUP(sig_path);
ACP_FASSIGN(auto_sig);
ACP_FDUP(sig_sep);
ACP_FASSIGN(set_autocc);
ACP_FDUP(auto_cc);
ACP_FASSIGN(set_autobcc);
ACP_FDUP(auto_bcc);
ACP_FASSIGN(set_autoreplyto);
ACP_FDUP(auto_replyto);
#if USE_GPGME
/* privacy */
ACP_FASSIGN(default_encrypt);
ACP_FASSIGN(default_sign);
ACP_FASSIGN(default_gnupg_mode);
ACP_FASSIGN(sign_key);
ACP_FDUP(sign_key_id);
#endif /* USE_GPGME */
/* advanced */
ACP_FASSIGN(set_smtpport);
ACP_FASSIGN(smtpport);
ACP_FASSIGN(set_popport);
ACP_FASSIGN(popport);
ACP_FASSIGN(set_imapport);
ACP_FASSIGN(imapport);
ACP_FASSIGN(set_nntpport);
ACP_FASSIGN(nntpport);
ACP_FASSIGN(set_domain);
ACP_FDUP(domain);
ACP_FASSIGN(mark_crosspost_read);
ACP_FASSIGN(crosspost_col);
ACP_FASSIGN(set_tunnelcmd);
ACP_FDUP(tunnelcmd);
ACP_FDUP(imap_dir);
ACP_FASSIGN(set_sent_folder);
ACP_FDUP(sent_folder);
ACP_FASSIGN(set_draft_folder);
ACP_FDUP(draft_folder);
ACP_FASSIGN(set_trash_folder);
ACP_FDUP(trash_folder);
/* don't want two default accounts */
ac_clon->is_default = FALSE;
ACP_FASSIGN(folder);
account_list = g_list_append(account_list, ac_clon);
account_clist_set();
}
#undef ACP_FDUP
#undef ACP_FASSIGN
static void account_delete(void)
{
GtkCList *clist = GTK_CLIST(edit_account.clist);
@ -820,6 +990,13 @@ static void account_edit_close(void)
inc_unlock();
}
static gint account_clone_event(GtkWidget *widget, GdkEventAny *event,
gpointer data)
{
account_clone();
return TRUE;
}
static gint account_delete_event(GtkWidget *widget, GdkEventAny *event,
gpointer data)
{
@ -1015,7 +1192,7 @@ PrefsAccount *account_get_reply_account(MsgInfo *msginfo, gboolean reply_autosel
}
if (!account) {
gchar cc[BUFFSIZE];
if (!get_header_from_msginfo(msginfo, cc, sizeof(cc), "CC:")) { /* Found a CC header */
if (!procheader_get_header_from_msginfo(msginfo, cc, sizeof(cc), "CC:")) { /* Found a CC header */
extract_address(cc);
account = account_find_from_address(cc);
}

View file

@ -50,6 +50,8 @@
#include "compose.h"
#include "procmsg.h"
#include "textview.h"
#include "matcher_parser.h" /* CLAWS */
#include "filtering.h"
typedef struct _Children Children;
typedef struct _ChildInfo ChildInfo;
@ -114,6 +116,9 @@ static void message_actions_execute (MessageView *msgview,
guint action_nb,
GSList *msg_list);
static gboolean execute_filtering_actions(gchar *action,
GSList *msglist);
static gboolean execute_actions (gchar *action,
GSList *msg_list,
GtkWidget *text,
@ -192,8 +197,18 @@ ActionType action_get_type(const gchar *action_str)
return ACTION_ERROR;
while (*p && action_type != ACTION_ERROR) {
if (p[0] == '%') {
if (p[0] == '%' && p[1]) {
switch (p[1]) {
case 'a':
/* CLAWS: filtering action is a mutually exclusive
* action. we can enable others if needed later. we
* add ACTION_SINGLE | ACTION_MULTIPLE so it will
* only be executed from the main window toolbar */
if (p[2] == 's') /* source messages */
action_type = ACTION_FILTERING_ACTION
| ACTION_SINGLE
| ACTION_MULTIPLE;
break;
case 'f':
action_type |= ACTION_SINGLE;
break;
@ -358,7 +373,7 @@ static gboolean parse_append_msgpart(GString *cmd, MsgInfo *msginfo,
filename = procmsg_get_message_file_path(msginfo);
part_filename = procmime_get_tmp_file_name(partinfo);
ret = procmime_get_part(part_filename, filename, partinfo);
ret = procmime_get_part(part_filename, partinfo);
if (single_part)
procmime_mimeinfo_free_all(partinfo);
@ -472,7 +487,7 @@ static void compose_actions_execute_cb(Compose *compose, guint action_nb,
if (action_type & (ACTION_SINGLE | ACTION_MULTIPLE)) {
alertpanel_warning
(_("The selected action cannot be used in the compose window\n"
"because it contains %%f, %%F or %%p."));
"because it contains %%f, %%F, %%as or %%p."));
return;
}
@ -533,7 +548,39 @@ static void message_actions_execute(MessageView *msgview, guint action_nb,
if (action_type & (ACTION_PIPE_OUT | ACTION_INSERT))
msgview->filtered = TRUE;
execute_actions(action, msg_list, text, body_pos, partinfo);
if (action_type & ACTION_FILTERING_ACTION)
/* CLAWS: most of the above code is not necessary for applying
* filtering */
execute_filtering_actions(action, msg_list);
else
execute_actions(action, msg_list, text, body_pos, partinfo);
}
static gboolean execute_filtering_actions(gchar *action, GSList *msglist)
{
GSList *action_list, *p;
const gchar *sbegin, *send;
gchar *action_string;
if (NULL == (sbegin = strstr2(action, "%as{")))
return FALSE;
sbegin += sizeof "%as{" - 1;
if (NULL == (send = strrchr(sbegin, '}')))
return FALSE;
action_string = g_strndup(sbegin, send - sbegin);
action_list = matcher_parser_get_action_list(action_string);
g_free(action_string);
if (action_list == NULL) return FALSE;
/* apply actions on each message info */
for (p = msglist; p && p->data; p = g_slist_next(p))
filteringaction_apply_action_list(action_list, (MsgInfo *) p->data);
for (p = action_list; p; p = g_slist_next(p))
if (p->data) filteringaction_free(p->data);
g_slist_free(action_list);
return TRUE;
}
static gboolean execute_actions(gchar *action, GSList *msg_list,
@ -1017,7 +1064,10 @@ static void update_io_dialog(Children *children)
ChildInfo *child_info;
GtkTextBuffer *textbuf;
GtkTextIter iter, start_iter, end_iter;
GdkFont *font;
font = gtk_object_get_data(GTK_OBJECT(children->dialog),
"s_txtfont");
gtk_widget_show(children->scrolledwin);
textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(text));
gtk_text_buffer_get_start_iter (textbuf, &start_iter);
@ -1058,6 +1108,7 @@ static void create_io_dialog(Children *children)
GtkWidget *progress_bar = NULL;
GtkWidget *abort_button;
GtkWidget *close_button;
GdkFont *output_font;
debug_print("Creating action IO dialog\n");
@ -1134,7 +1185,7 @@ static void create_io_dialog(Children *children)
children->initial_nb -children->nb,
0.0, children->initial_nb);
gtk_box_pack_start(GTK_BOX(vbox), progress_bar, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), progress_bar, FALSE, FALSE, 0);
gtk_widget_show(progress_bar);
}
@ -1160,6 +1211,13 @@ static void create_io_dialog(Children *children)
children->abort_btn = abort_button;
children->close_btn = close_button;
#warning FIXME_GTK2 convert to Pango / FontDesc?
#if 0
output_font = gtkut_font_load_from_fontset(prefs_common.textfont);
gtk_object_set_data_full(GTK_OBJECT(dialog), "s_txtfont",
output_font,
(GtkDestroyNotify)gdk_font_unref);
#endif
gtk_widget_show(dialog);
}

View file

@ -41,6 +41,7 @@ typedef enum
ACTION_USER_STR = 1 << 9,
ACTION_USER_HIDDEN_STR = 1 << 10,
ACTION_SELECTION_STR = 1 << 11,
ACTION_FILTERING_ACTION = 1 << 12,
ACTION_ERROR = 1 << 30
} ActionType;

View file

@ -40,7 +40,7 @@
# include <wctype.h>
#endif
#include "addressbook.h"
#include "addrindex.h"
#include "addr_compl.h"
#include "utils.h"
#include <pthread.h>
@ -63,11 +63,6 @@
* any of those words).
*/
/**
* Reference to address index.
*/
static AddressIndex *_addressIndex_ = NULL;
/**
* address_entry - structure which refers to the original address entry in the
* address book .
@ -210,7 +205,7 @@ static gint add_address(const gchar *name, const gchar *address, const gchar *al
* Read address book, creating all entries in the completion index.
*/
static void read_address_book(void) {
addrindex_load_completion( _addressIndex_, add_address );
addrindex_load_completion( add_address );
g_address_list = g_list_reverse(g_address_list);
g_completion_list = g_list_reverse(g_completion_list);
}
@ -594,6 +589,9 @@ static CompletionWindow *addrcompl_create_window( void ) {
* \param cw Window to destroy.
*/
static void addrcompl_destroy_window( CompletionWindow *cw ) {
/* Stop all searches currently in progress */
addrindex_stop_search( _queryID_ );
/* Remove idler function... or application may not terminate */
if( _completionIdleID_ != 0 ) {
gtk_idle_remove( _completionIdleID_ );
@ -747,17 +745,15 @@ static void addrcompl_add_entry( CompletionWindow *cw, gchar *address ) {
static gboolean addrcompl_idle( gpointer data ) {
GList *node;
gchar *address;
CompletionWindow *cw;
/* Process all entries in display queue */
pthread_mutex_lock( & _completionMutex_ );
if( _displayQueue_ ) {
cw = data;
node = _displayQueue_;
while( node ) {
address = node->data;
/* printf( "address ::: %s :::\n", address ); */
addrcompl_add_entry( cw, address );
addrcompl_add_entry( _compWindow_, address );
g_free( address );
node = g_list_next( node );
}
@ -772,35 +768,34 @@ static gboolean addrcompl_idle( gpointer data ) {
/**
* Callback entry point. The background thread (if any) appends the address
* list to the display queue.
* \param sender Sender of query.
* \param queryID Query ID of search request.
* \param listEMail List of zero of more email objects that met search
* criteria.
* \param target Target object to received data.
* \param data Query data.
*/
static gint addrcompl_callback(
gint queryID, GList *listEMail, gpointer target )
static gint addrcompl_callback_entry(
gpointer sender, gint queryID, GList *listEMail, gpointer data )
{
GList *node;
gchar *address;
/* printf( "addrcompl_callback::queryID=%d\n", queryID ); */
/* printf( "addrcompl_callback_entry::queryID=%d\n", queryID ); */
pthread_mutex_lock( & _completionMutex_ );
if( target ) {
if( queryID == _queryID_ ) {
/* Append contents to end of display queue */
node = listEMail;
while( node ) {
ItemEMail *email = node->data;
if( queryID == _queryID_ ) {
/* Append contents to end of display queue */
node = listEMail;
while( node ) {
ItemEMail *email = node->data;
address = addritem_format_email( email );
/* printf( "\temail/address ::%s::\n", address ); */
_displayQueue_ = g_list_append( _displayQueue_, address );
node = g_list_next( node );
}
address = addritem_format_email( email );
/* printf( "\temail/address ::%s::\n", address ); */
_displayQueue_ = g_list_append( _displayQueue_, address );
node = g_list_next( node );
}
}
g_list_free( listEMail );
pthread_mutex_unlock( & _completionMutex_ );
/* printf( "addrcompl_callback...done\n" ); */
return 0;
}
@ -830,9 +825,8 @@ static void addrcompl_add_queue( gchar *address ) {
/**
* Load list with entries from local completion index.
* \param cw Completion window.
*/
static void addrcompl_load_local( CompletionWindow *cw ) {
static void addrcompl_load_local( void ) {
guint count = 0;
for (count = 0; count < get_completion_count(); count++) {
@ -856,19 +850,19 @@ static void addrcompl_start_search( void ) {
/* Setup the search */
_queryID_ = addrindex_setup_search(
_addressIndex_, searchTerm, _compWindow_, addrcompl_callback );
searchTerm, NULL, addrcompl_callback_entry );
g_free( searchTerm );
/* printf( "addrcompl_start_search::queryID=%d\n", _queryID_ ); */
/* Load local stuff */
addrcompl_load_local( _compWindow_ );
addrcompl_load_local();
/* Sit back and wait until something happens */
_completionIdleID_ =
gtk_idle_add( ( GtkFunction ) addrcompl_idle, _compWindow_ );
gtk_idle_add( ( GtkFunction ) addrcompl_idle, NULL );
/* printf( "addrindex_start_search::queryID=%d\n", _queryID_ ); */
addrindex_start_search( _addressIndex_, _queryID_ );
addrindex_start_search( _queryID_ );
}
/**
@ -1374,12 +1368,8 @@ static gboolean completion_window_key_press(GtkWidget *widget,
/**
* Setup completion object.
* \param addrIndex Address index object.
*/
void addrcompl_initialize( AddressIndex *addrIndex ) {
g_return_if_fail( addrIndex != NULL );
_addressIndex_ = addrIndex;
void addrcompl_initialize( void ) {
/* printf( "addrcompl_initialize...\n" ); */
if( ! _compWindow_ ) {
_compWindow_ = addrcompl_create_window();
@ -1401,7 +1391,6 @@ void addrcompl_teardown( void ) {
}
_displayQueue_ = NULL;
_completionIdleID_ = 0;
_addressIndex_ = NULL;
/* printf( "addrcompl_teardown...done\n" ); */
}

View file

@ -23,11 +23,9 @@
#include <gtk/gtk.h>
#include "addrindex.h"
gint start_address_completion (void);
guint complete_address (const gchar *str);
gchar *get_complete_address (gint index);
gchar *get_complete_address (gint index);
gint invalidate_address_completion (void);
gint end_address_completion (void);
@ -37,7 +35,7 @@ void address_completion_register_entry (GtkEntry *entry);
void address_completion_unregister_entry(GtkEntry *entry);
void address_completion_end (GtkWidget *mainwindow);
void addrcompl_initialize ( AddressIndex *addrIndex );
void addrcompl_initialize ( void );
void addrcompl_teardown ( void );
#endif /* __ADDR_COMPL_H__ */

View file

@ -1720,6 +1720,11 @@ ItemGroup *addrbook_add_group_list(AddressBookFile *book, ItemFolder *folder,
* <code>g_free()</code> when done.
*/
ItemFolder *addrbook_add_new_folder(AddressBookFile *book, ItemFolder *parent)
{
g_return_val_if_fail(book != NULL, NULL);
return addrcache_add_new_folder( book->addressCache, parent );
}
#if 0
{
ItemFolder *folder = NULL;
ItemFolder *p = parent;
@ -1741,6 +1746,7 @@ ItemFolder *addrbook_add_new_folder(AddressBookFile *book, ItemFolder *parent)
}
return folder;
}
#endif
/**
* Update address book attribute list for specified person. Note: The existing

View file

@ -1326,17 +1326,19 @@ ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *fol
return NULL;
}
/*
* Add person and address data to cache.
* Enter: cache Cache.
* folder Folder where to add person, or NULL for root folder.
* name Common name.
* address EMail address.
* remarks Remarks.
* Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
* this will destroy the address book data.
*/
ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
/**
* Add person and address data to cache.
* \param cache Cache.
* \param folder Folder where to add person, or NULL for root folder.
* \param name Common name.
* \param address EMail address.
* \param remarks Remarks.
* \return Person added. Do not *NOT* to use the
* <code>addrbook_free_xxx()</code> functions...; this will destroy
* the address book data.
*/
ItemPerson *addrcache_add_contact(
AddressCache *cache, ItemFolder *folder, const gchar *name,
const gchar *address, const gchar *remarks )
{
ItemPerson *person = NULL;
@ -1364,6 +1366,36 @@ ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, cons
return person;
}
/**
* Create a new folder and add to address cache.
* \param cache Address cache.
* \param folder Parent folder where to add folder, or <i>NULL</i> for
* root folder.
* \return Folder that was created. This should <b>*NOT*</b> be
* <code>g_free()</code> when done.
*/
ItemFolder *addrcache_add_new_folder( AddressCache *cache, ItemFolder *parent )
{
ItemFolder *folder;
ItemFolder *p = parent;
g_return_val_if_fail( cache != NULL, NULL );
if( !p ) p = cache->rootFolder;
folder = addritem_create_item_folder();
addrcache_id_folder( cache, folder );
if( addrcache_hash_add_folder( cache, folder ) ) {
p->listFolder = g_list_append( p->listFolder, folder );
ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(p);
addrcache_set_dirty( cache, TRUE );
}
else {
addritem_free_item_folder( folder );
folder = NULL;
}
return folder;
}
/*
* End of Source.
*/

View file

@ -170,4 +170,7 @@ ItemPerson *addrcache_add_contact ( AddressCache *cache,
const gchar *address,
const gchar *remarks );
ItemFolder *addrcache_add_new_folder ( AddressCache *cache,
ItemFolder *parent );
#endif /* __ADDRCACHE_H__ */

File diff suppressed because it is too large Load diff

View file

@ -94,10 +94,17 @@
#define ATTAG_LDAP_TIMEOUT "timeout"
#define ATTAG_LDAP_MAX_AGE "max-age"
#define ATTAG_LDAP_DYN_SEARCH "dyn-search"
#define ATTAG_LDAP_MATCH_OPT "match-opt"
#define ELTAG_LDAP_ATTR_SRCH "attribute"
#define ATTAG_LDAP_ATTR_NAME "name"
/* Attribute values */
#define ATVAL_BOOLEAN_YES "yes"
#define ATVAL_BOOLEAN_NO "no"
#define ATVAL_LDAP_MATCH_BEGIN "begin-with"
#define ATVAL_LDAP_MATCH_CONTAINS "contains"
/* New attributes */
#define ATTAG_LDAP_DEFAULT "default"
@ -116,6 +123,11 @@ N_("Personal address")
#define DISP_OLD_COMMON _("Common address")
#define DISP_OLD_PERSONAL _("Personal address")
/**
* Singleton object.
*/
static AddressIndex *_addressIndex_ = NULL;
/*
* Define attribute name-value pair.
*/
@ -572,7 +584,7 @@ static void addrindex_free_cache_hash( GHashTable *table ) {
g_hash_table_destroy( table );
}
/*
/**
* Remove data source from internal hashtable.
* \param addrIndex Address index.
* \param ds Data source to remove.
@ -590,32 +602,44 @@ static void addrindex_hash_remove_cache(
}
}
/*
* Create a new address index.
/**
* Create a new address index. This is created as a singleton object.
* \return Initialized address index object.
*/
AddressIndex *addrindex_create_index( void ) {
AddressIndex *addrIndex = g_new0( AddressIndex, 1 );
AddressIndex *index;
ADDRITEM_TYPE(addrIndex) = ITEMTYPE_INDEX;
ADDRITEM_ID(addrIndex) = NULL;
ADDRITEM_NAME(addrIndex) = g_strdup( "Address Index" );
ADDRITEM_PARENT(addrIndex) = NULL;
ADDRITEM_SUBTYPE(addrIndex) = 0;
addrIndex->filePath = NULL;
addrIndex->fileName = NULL;
addrIndex->retVal = MGU_SUCCESS;
addrIndex->needsConversion = FALSE;
addrIndex->wasConverted = FALSE;
addrIndex->conversionError = FALSE;
addrIndex->interfaceList = NULL;
addrIndex->lastType = ADDR_IF_NONE;
addrIndex->dirtyFlag = FALSE;
addrIndex->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
addrIndex->loadedFlag = FALSE;
addrIndex->searchOrder = NULL;
addrindex_build_if_list( addrIndex );
return addrIndex;
if( _addressIndex_ == NULL ) {
index = g_new0( AddressIndex, 1 );
ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
ADDRITEM_ID(index) = NULL;
ADDRITEM_NAME(index) = g_strdup( "Address Index" );
ADDRITEM_PARENT(index) = NULL;
ADDRITEM_SUBTYPE(index) = 0;
index->filePath = NULL;
index->fileName = NULL;
index->retVal = MGU_SUCCESS;
index->needsConversion = FALSE;
index->wasConverted = FALSE;
index->conversionError = FALSE;
index->interfaceList = NULL;
index->lastType = ADDR_IF_NONE;
index->dirtyFlag = FALSE;
index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
index->loadedFlag = FALSE;
index->searchOrder = NULL;
addrindex_build_if_list( index );
_addressIndex_ = index;
}
return _addressIndex_;
}
/**
* Return reference to address index.
* \return Address index object.
*/
AddressIndex *addrindex_get_object( void ) {
return _addressIndex_;
}
/**
@ -671,18 +695,16 @@ GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
/**
* Perform any other initialization of address index.
* \param addrIndex Address index.
*/
void addrindex_initialize( AddressIndex *addrIndex ) {
void addrindex_initialize( void ) {
qrymgr_initialize();
addrcompl_initialize( addrIndex );
addrcompl_initialize();
}
/**
* Perform any other teardown of address index.
* \param addrIndex Address index.
*/
void addrindex_teardown( AddressIndex *addrIndex ) {
void addrindex_teardown( void ) {
addrcompl_teardown();
qrymgr_teardown();
}
@ -738,6 +760,8 @@ void addrindex_free_index( AddressIndex *addrIndex ) {
addrIndex->loadedFlag = FALSE;
g_free( addrIndex );
addrIndex = NULL;
_addressIndex_ = NULL;
}
/**
@ -1055,7 +1079,7 @@ static void addrindex_write_fragment(
}
}
/*
#if 0
static void addrindex_print_fragment_r(
const AddressIfFragment *fragment, FILE *stream, gint lvl )
{
@ -1084,7 +1108,7 @@ static void addrindex_print_fragment_r(
static void addrindex_print_fragment( const AddressIfFragment *fragment, FILE *stream ) {
addrindex_print_fragment_r( fragment, stream, 0 );
}
*/
#endif
/**
* Read/parse address index file, creating a data source for a regular
@ -1312,6 +1336,11 @@ static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
}
/**
* Parse LDAP control data from XML file.
* \param file Index file.
* \return Initialized data soruce object.
*/
static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
AddressDataSource *ds;
LdapServer *server;
@ -1319,10 +1348,13 @@ static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
GList *attr;
gchar *serverName = NULL;
gchar *criteria = NULL;
gboolean bSearch = FALSE;
gboolean cvtFlag = TRUE;
gboolean bDynSearch;
gint iMatch;
/* printf( "addrindex_parse_ldap\n" ); */
/* Set up some defaults */
bDynSearch = FALSE;
iMatch = LDAPCTL_MATCH_BEGINWITH;
ds = addrindex_create_datasource( ADDR_IF_LDAP );
ctl = ldapctl_create();
@ -1365,10 +1397,15 @@ static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
ldapctl_set_max_query_age( ctl, ivalue );
}
else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
bSearch = FALSE;
cvtFlag = FALSE;
if( strcmp( value, "yes" ) == 0 ) {
bSearch = TRUE;
bDynSearch = FALSE;
if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
bDynSearch = TRUE;
}
}
else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
iMatch = LDAPCTL_MATCH_BEGINWITH;
if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
iMatch = LDAPCTL_MATCH_CONTAINS;
}
}
attr = g_list_next( attr );
@ -1376,7 +1413,8 @@ static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
server = ldapsvr_create_noctl();
ldapsvr_set_name( server, serverName );
ldapsvr_set_search_flag( server, bSearch );
ldapsvr_set_search_flag( server, bDynSearch );
ldapctl_set_matching_option( ctl, iMatch );
g_free( serverName );
ldapsvr_set_control( server, ctl );
ds->rawDataSource = server;
@ -1393,13 +1431,6 @@ static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
}
g_free( criteria );
}
/*
* If no search flag was found, then we are converting from old format
* server data to new format.
*/
if( cvtFlag ) {
ldapsvr_set_search_flag( server, TRUE );
}
/* ldapsvr_print_data( server, stdout ); */
return ds;
@ -1436,7 +1467,12 @@ static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
server->searchFlag ? "yes" : "no" );
server->searchFlag ?
ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN );
fputs(" >\n", fp);
@ -2456,174 +2492,60 @@ GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
*/
/**
* Current query ID. This is incremented for each query created.
*/
static gint _currentQueryID_ = 0;
/*
* Variables for the search that is being performed.
*/
static gchar *_searchTerm_ = NULL;
static gpointer _searchTarget_ = NULL;
static AddrSearchCallbackFunc *_searchCallback_ = NULL;
/**
* Setup or register the search that will be performed.
* \param addrIndex Address index object.
* \param searchTerm Search term. A private copy will be made.
* \param target Target object that will receive data.
* \param callBack Callback function.
* Setup or register the dynamic search that will be performed. The search
* is registered with the query manager.
*
* \param searchTerm Search term. A private copy will be made.
* \param callBackEntry Callback function that should be called when
* each entry is received.
* \param callBackEnd Callback function that should be called when
* search has finished running.
* \return ID allocated to query that will be executed.
*/
gint addrindex_setup_search(
AddressIndex *addrIndex, const gchar *searchTerm,
const gpointer target, AddrSearchCallbackFunc callBack )
const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
{
QueryRequest *req;
gint queryID;
/* printf( "search term ::%s::\n", searchTerm ); */
g_free( _searchTerm_ );
_searchTerm_ = g_strdup( searchTerm );
/* Set up a dynamic address query */
req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
queryID = req->queryID;
qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
queryID = ++_currentQueryID_;
_searchTarget_ = target;
_searchCallback_ = callBack;
/* printf( "query ID ::%d::\n", queryID ); */
/* printf( "***> query ID ::%d::\n", queryID ); */
return queryID;
}
#ifdef USE_LDAP
/**
* LDAP callback entry point for each address entry found.
* \param qry LDAP query.
* \param listEMail List of Item EMail objects found.
*/
static void addrindex_ldap_entry_cb( LdapQuery *qry, GList *listEMail ) {
/*
GList *node;
printf( "\naddrindex::addrindex_ldap_entry_cb ::%s::\n", qry->queryName );
node = listEMail;
while( node ) {
ItemEMail *email = node->data;
printf( "\temail ::%s::\n", email->address );
node = g_list_next( node );
}
*/
if( _searchCallback_ ) {
( _searchCallback_ ) ( qry->queryID, listEMail, _searchTarget_ );
}
g_list_free( listEMail );
}
/**
* LDAP callback entry point for completion of search.
* \param qry LDAP query.
*/
static void addrindex_ldap_end_cb( LdapQuery *qry ) {
/* printf( "\naddrindex::addrindex_ldap_end_cb ::%s::\n", qry->queryName ); */
}
/**
* Return results of previous query.
* \param folder.
* \return List of ItemEMail objects.
*/
static void addrindex_ldap_use_previous(
const ItemFolder *folder, const gint queryID )
{
GList *listEMail;
GList *node;
GList *nodeEM;
listEMail = NULL;
if( _searchCallback_ ) {
node = folder->listPerson;
while( node ) {
AddrItemObject *aio = node->data;
if( aio && aio->type == ITEMTYPE_PERSON ) {
ItemPerson *person = node->data;
nodeEM = person->listEMail;
while( nodeEM ) {
ItemEMail *email = nodeEM->data;
nodeEM = g_list_next( nodeEM );
listEMail = g_list_append( listEMail, email );
}
}
node = g_list_next( node );
}
( _searchCallback_ ) ( queryID, listEMail, _searchTarget_ );
g_list_free( listEMail );
}
}
/*
* Function prototype (not in header file or circular reference encountered!)
* Function prototypes (not in header file or circular reference errors are
* encountered!)
*/
LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm );
/**
* Construct an LDAP query and initiate an LDAP dynamic search.
* \param server LDAP server object.
* \param queryID ID of search query to be executed.
*/
static void addrindex_search_ldap( LdapServer *server, const gint queryID ) {
LdapQuery *qry;
gchar *name;
if( ! server->searchFlag ) return;
/* Retire any aged queries */
ldapsvr_retire_query( server );
/* Test whether any queries for the same term exist */
qry = ldapsvr_locate_query( server, _searchTerm_ );
if( qry ) {
ItemFolder *folder = qry->folder;
/* Touch query to ensure it hangs around for a bit longer */
ldapqry_touch( qry );
if( folder ) {
addrindex_ldap_use_previous( folder, queryID );
return;
}
}
/* Construct a query */
qry = ldapqry_create();
ldapqry_set_query_id( qry, queryID );
ldapqry_set_search_value( qry, _searchTerm_ );
ldapqry_set_query_type( qry, LDAPQUERY_DYNAMIC );
ldapqry_set_callback_entry( qry, addrindex_ldap_entry_cb );
ldapqry_set_callback_end( qry, addrindex_ldap_end_cb );
/* Name the query */
name = g_strdup_printf( "Search for '%s'", _searchTerm_ );
ldapqry_set_name( qry, name );
g_free( name );
ldapsvr_add_query( server, qry );
ldapsvr_execute_query( server, qry );
}
LdapQuery *ldapsvr_new_dynamic_search(
LdapServer *server, QueryRequest *req );
LdapQuery *ldapsvr_new_explicit_search(
LdapServer *server, QueryRequest *req, ItemFolder *folder );
#endif
/**
* Perform the previously registered search.
* \param addrIndex Address index object.
* \param queryID ID of search query to be executed.
* Execute the previously registered dynamic search.
*
* \param req Address query object to execute.
* \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
* failed.
*/
gboolean addrindex_start_search( AddressIndex *addrIndex, const gint queryID ) {
static gboolean addrindex_start_dynamic( QueryRequest *req ) {
AddressInterface *iface;
AddressDataSource *ds;
GList *nodeIf;
GList *nodeDS;
gint type;
/* printf( "addrindex_start_search::%d::\n", queryID ); */
nodeIf = addrIndex->searchOrder;
/* printf( "addrindex_start_dynamic::%d::\n", req->queryID ); */
nodeIf = _addressIndex_->searchOrder;
while( nodeIf ) {
iface = nodeIf->data;
nodeIf = g_list_next( nodeIf );
@ -2631,7 +2553,6 @@ gboolean addrindex_start_search( AddressIndex *addrIndex, const gint queryID ) {
if( ! iface->useInterface ) {
continue;
}
if( ! iface->externalQuery ) {
continue;
}
@ -2643,8 +2564,22 @@ gboolean addrindex_start_search( AddressIndex *addrIndex, const gint queryID ) {
nodeDS = g_list_next( nodeDS );
#ifdef USE_LDAP
if( type == ADDR_IF_LDAP ) {
LdapServer *server = ds->rawDataSource;
addrindex_search_ldap( server, queryID );
LdapServer *server;
LdapQuery *qry;
server = ds->rawDataSource;
if( ! server->searchFlag ) {
continue;
}
if( ldapsvr_reuse_previous( server, req ) ) {
continue;
}
/* Start a new dynamic search */
qry = ldapsvr_new_dynamic_search( server, req );
if( qry ) {
ldapsvr_execute_query( server, qry );
}
}
#endif
}
@ -2654,230 +2589,193 @@ gboolean addrindex_start_search( AddressIndex *addrIndex, const gint queryID ) {
/**
* Stop the previously registered search.
* \param addrIndex Address index object.
*
* \param queryID ID of search query to stop.
*/
void addrindex_stop_search( AddressIndex *addrIndex, const gint queryID ){
#ifdef USE_LDAP
AddressInterface *iface;
AddressDataSource *ds;
GList *nodeIf;
GList *nodeDS;
gint type;
void addrindex_stop_search( const gint queryID ){
QueryRequest *req;
AddrQueryObject *aqo;
GList *node;
/* printf( "addrindex_stop_search/queryID=%d\n", queryID ); */
/* If query ID does not match, search has not been setup */
/* if( queryID != _queryID_ ) return; */
/* printf( "addrindex_stop_search::%d::\n", queryID ); */
nodeIf = addrIndex->searchOrder;
while( nodeIf ) {
iface = nodeIf->data;
nodeIf = g_list_next( nodeIf );
if( ! iface->useInterface ) {
continue;
}
type = iface->type;
nodeDS = iface->listSource;
while( nodeDS ) {
ds = nodeDS->data;
nodeDS = g_list_next( nodeDS );
if( type == ADDR_IF_LDAP ) {
LdapServer *server = ds->rawDataSource;
ldapsvr_stop_all_query( server );
}
}
}
#endif
}
#ifdef USE_LDAP
/**
* LDAP callback entry point for completion of search.
* \param qry LDAP query.
*/
static void addrindex_ldap_end_static_cb( LdapQuery *qry ) {
AddrQuery *addrQry;
gint queryID;
AddrQueryType queryType;
AddrSearchStaticFunc *callBack;
queryID = qry->queryID;
queryType = qry->queryType;
addrQry = qrymgr_find_query( queryID );
if( addrQry == NULL ) {
req = qrymgr_find_request( queryID );
if( req == NULL ) {
return;
}
callBack = addrQry->callBack;
/* Delete query */
qrymgr_delete_query( queryID );
/* Execute callback function */
callBack( queryID, queryType, qry->retVal );
}
/* Stop all queries that were associated with request */
node = req->queryList;
while( node ) {
aqo = node->data;
#ifdef USE_LDAP
if( aqo->queryType == ADDRQUERY_LDAP ) {
LdapQuery *qry = ( LdapQuery * ) aqo;
ldapqry_set_stop_flag( qry, TRUE );
}
#endif
node->data = NULL;
node = g_list_next( node );
}
/* Delete query request */
qrymgr_delete_request( queryID );
}
/**
* Setup the explicit search that will be performed. The search is registered with
* the query manager.
* Setup or register the explicit search that will be performed. The search is
* registered with the query manager.
*
* \param ds Data source to search.
* \param searchTerm Search term to locate.
* \param folder Folder to receive search results; may be NULL.
* \param callbackEnd Function to call when search has terminated.
* \param ds Data source to search.
* \param searchTerm Search term to locate.
* \param folder Folder to receive search results; may be NULL.
* \param callbackEnd Function to call when search has terminated.
* \param callbackEntry Function to called for each entry processed.
* \return ID allocated to query that will be executed.
*/
gint addrindex_setup_static_search(
gint addrindex_setup_explicit_search(
AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
void *callbackEnd )
void *callBackEnd, void *callBackEntry )
{
AddrQuery *addrQry;
QueryRequest *req;
gint queryID;
gchar *name;
queryID = ++_currentQueryID_;
/* Name the query */
name = g_strdup_printf( "Search '%s'", searchTerm );
/* Set up a generic address query */
addrQry = qrymgr_add_query( queryID, searchTerm, callbackEnd, NULL );
/* Set up query request */
req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
queryID = req->queryID;
if( ds->type == ADDR_IF_LDAP ) {
#ifdef USE_LDAP
LdapServer *server;
LdapQuery *qry;
server = ds->rawDataSource;
/* Construct a query */
qry = ldapqry_create();
ldapqry_set_query_id( qry, queryID );
ldapqry_set_name( qry, name );
ldapqry_set_search_value( qry, searchTerm );
ldapqry_set_query_type( qry, LDAPQUERY_STATIC );
ldapqry_set_callback_end( qry, addrindex_ldap_end_static_cb );
/* Specify folder type and back reference */
qry->folder = folder;
folder->folderType = ADDRFOLDER_LDAP_QUERY;
folder->folderData = ( gpointer ) qry;
/* Setup server */
ldapsvr_add_query( server, qry );
/* Set up generic query */
addrqry_set_query_type( addrQry, ADDRQUERY_LDAP );
addrqry_set_server( addrQry, server );
addrqry_set_query( addrQry, qry );
ldapsvr_new_explicit_search( server, req, folder );
#endif
}
else {
qrymgr_delete_query( queryID );
qrymgr_delete_request( queryID );
queryID = 0;
}
g_free( name );
return queryID;
}
/**
* Perform the previously registered explicit search.
* \param queryID ID of search query to be executed.
* \param idleID Idler ID.
* Execute the previously registered explicit search.
*
* \param req Address query request object to execute.
* \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
* failed.
*/
gboolean addrindex_start_static_search( const gint queryID, const guint idleID )
{
static gboolean addrindex_start_explicit( QueryRequest *req ) {
gboolean retVal;
AddrQuery *addrQry;
AddrQueryObject *aqo;
retVal = FALSE;
addrQry = qrymgr_find_query( queryID );
if( addrQry == NULL ) {
return retVal;
}
if( addrQry->queryType == ADDRQUERY_LDAP ) {
/* Note: there should only be one query in the list. */
aqo = req->queryList->data;
#ifdef USE_LDAP
if( aqo->queryType == ADDRQUERY_LDAP ) {
LdapServer *server;
LdapQuery *qry;
server = ( LdapServer * ) addrQry->serverObject;
qry = ( LdapQuery * ) addrQry->queryObject;
/* Retire any aged queries */
ldapsvr_retire_query( server );
qry = ( LdapQuery * ) aqo;
server = qry->server;
/* Start the search */
ldapsvr_execute_query( server, qry );
retVal = TRUE;
ldapsvr_execute_query( server, qry );
}
#endif
return retVal;
}
/**
* Start the previously registered search.
*
* \param queryID ID of search query to be executed.
* \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
* failed.
*/
gboolean addrindex_start_search( const gint queryID ) {
gboolean retVal;
QueryRequest *req;
AddrSearchType searchType;
retVal = FALSE;
/* printf( "addrindex_start_search/queryID=%d\n", queryID ); */
req = qrymgr_find_request( queryID );
if( req == NULL ) {
return retVal;
}
if( retVal ) {
addrqry_set_idle_id( addrQry, idleID );
searchType = req->searchType;
if( searchType == ADDRSEARCH_DYNAMIC ) {
retVal = addrindex_start_dynamic( req );
}
else if( searchType == ADDRSEARCH_EXPLICIT ) {
retVal = addrindex_start_explicit( req );
}
return retVal;
}
/**
* Read all address books that do not support dynamic queries.
* \param addrIndex Address index object.
* Remove results (folder and data) for specified data source and folder.
* \param ds Data source to process.
* \param folder Results folder to remove.
*/
void addrindex_read_all( AddressIndex *addrIndex ) {
AddressInterface *iface;
AddressDataSource *ds;
GList *nodeIf;
GList *nodeDS;
void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
AddrBookBase *adbase;
AddressCache *cache;
gint queryID = 0;
nodeIf = addrIndex->searchOrder;
while( nodeIf ) {
iface = nodeIf->data;
nodeIf = g_list_next( nodeIf );
/* Test for folder */
if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
adbase = ( AddrBookBase * ) ds->rawDataSource;
if( adbase == NULL ) return;
cache = adbase->addressCache;
if( ! iface->useInterface ) {
continue;
}
if( iface->externalQuery ) {
continue;
}
nodeDS = iface->listSource;
while( nodeDS ) {
ds = nodeDS->data;
nodeDS = g_list_next( nodeDS );
/* Hide folder to prevent re-display */
addritem_folder_set_hidden( folder, TRUE );
/* Read address book */
if( addrindex_ds_get_modify_flag( ds ) ) {
addrindex_ds_read_data( ds );
continue;
}
if( ds->type == ADDR_IF_LDAP ) {
#ifdef USE_LDAP
LdapQuery *qry;
if( ! addrindex_ds_get_read_flag( ds ) ) {
addrindex_ds_read_data( ds );
continue;
}
}
qry = ( LdapQuery * ) folder->folderData;
queryID = ADDRQUERY_ID(qry);
ldapquery_remove_results( qry );
#endif
}
/* Delete query request */
if( queryID > 0 ) {
qrymgr_delete_request( queryID );
}
addrIndex->loadedFlag = TRUE;
}
/* **********************************************************************
* Address completion stuff.
* ***********************************************************************
*/
/**
* This function is used by the address completion function to load
* addresses for all non-external address book interfaces.
*
* \param addrIndex Address index object.
* \param callBackFunc Function to be called when an address is
* to be loaded.
* \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
*/
gboolean addrindex_load_completion(
AddressIndex *addrIndex,
gint (*callBackFunc) ( const gchar *, const gchar *, const gchar * ) )
{
AddressDataSource *ds;
@ -2886,9 +2784,7 @@ gboolean addrindex_load_completion(
GList *nodeM;
gchar *sName, *sAddress, *sAlias, *sFriendly;
if( addrIndex == NULL ) return FALSE;
nodeIf = addrindex_get_interface_list( addrIndex );
nodeIf = addrindex_get_interface_list( _addressIndex_ );
while( nodeIf ) {
AddressInterface *iface = nodeIf->data;

View file

@ -99,10 +99,11 @@ struct _AddressDataSource {
gpointer rawDataSource;
};
void addrindex_initialize ( AddressIndex *addrIndex );
void addrindex_teardown ( AddressIndex *addrIndex );
void addrindex_initialize ( void );
void addrindex_teardown ( void );
AddressIndex *addrindex_create_index ( void );
AddressIndex *addrindex_get_object ( void );
void addrindex_set_file_path ( AddressIndex *addrIndex,
const gchar *value );
void addrindex_set_file_name ( AddressIndex *addrIndex,
@ -157,20 +158,27 @@ GList *addrindex_ds_get_all_persons ( AddressDataSource *ds );
GList *addrindex_ds_get_all_groups ( AddressDataSource *ds );
/* Search support */
gint addrindex_setup_search ( AddressIndex *addrIndex,
const gchar *searchTerm,
const gpointer target,
AddrSearchCallbackFunc callBack );
gboolean addrindex_start_search ( AddressIndex *addrIndex,
const gint queryID );
void addrindex_stop_search ( AddressIndex *addrIndex,
const gint queryID );
gint addrindex_setup_search ( const gchar *searchTerm,
void *callBackEnd,
void *callBackEntry );
gint addrindex_setup_static_search ( AddressDataSource *ds,
const gchar *searchTerm,
ItemFolder *folder,
void *callBackEnd,
void *callBackEntry );
gboolean addrindex_start_search ( const gint queryID );
void addrindex_stop_search ( const gint queryID );
void addrindex_remove_results ( AddressDataSource *ds,
ItemFolder *folder );
void addrindex_read_all ( AddressIndex *addrIndex );
gboolean addrindex_load_completion(
AddressIndex *addrIndex,
gint (*callBackFunc)
( const gchar *, const gchar *, const gchar * ) );
gint addrindex_setup_explicit_search(
AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
void *callBackEnd, void *callBackEntry );
#endif /* __ADDRINDEX_H__ */

View file

@ -25,6 +25,7 @@
#include <stdio.h>
#include <string.h>
#include "utils.h"
#include "addritem.h"
#include "mgutils.h"

View file

@ -50,7 +50,7 @@ typedef enum {
ADDRFOLDER_ROOT,
ADDRFOLDER_REGULAR,
ADDRFOLDER_CATEGORY,
ADDRFOLDER_LDAP_QUERY
ADDRFOLDER_QUERY_RESULTS
} AddressFolderType;
typedef struct _AddrItemObject AddrItemObject;

View file

@ -32,154 +32,152 @@
/**
* Query list for tracking current queries.
*/
static GList *_queryList_ = NULL;
static GList *_requestList_ = NULL;
/**
* Mutex to protect list from multiple threads.
*/
static pthread_mutex_t _queryListMutex_ = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _requestListMutex_ = PTHREAD_MUTEX_INITIALIZER;
/**
* Current query ID. This is incremented for each query request created.
*/
static gint _currentQueryID_ = 0;
/**
* Create new address query.
* \return Initialized address query object.
*/
AddrQuery *addrqry_create( void ) {
AddrQuery *qry;
QueryRequest *reqreq_create( void ) {
QueryRequest *req;
qry = g_new0( AddrQuery, 1 );
qry->queryType = ADDRQUERY_NONE;
qry->queryID = 0;
qry->idleID = 0;
qry->searchTerm = NULL;
qry->callBack = NULL;
qry->target = NULL;
qry->serverObject = NULL;
qry->queryObject = NULL;
return qry;
req = g_new0( QueryRequest, 1 );
req->queryID = 0;
req->searchType = ADDRSEARCH_NONE;
req->searchTerm = NULL;
req->callBackEnd = NULL;
req->callBackEntry = NULL;
req->queryList = NULL;
return req;
}
/**
* Clear the query.
* \param qry Address query object.
* \param req Request query object.
*/
void addrqry_clear( AddrQuery *qry ) {
g_return_if_fail( qry != NULL );
g_free( qry->searchTerm );
qry->queryType = ADDRQUERY_NONE;
qry->queryID = 0;
qry->idleID = 0;
qry->searchTerm = NULL;
qry->callBack = NULL;
qry->target = NULL;
qry->serverObject = NULL;
qry->queryObject = NULL;
void qryreq_clear( QueryRequest *req ) {
GList *node;
g_return_if_fail( req != NULL );
g_free( req->searchTerm );
req->queryID = 0;
req->searchType = ADDRSEARCH_NONE;
req->searchTerm = NULL;
req->callBackEnd = NULL;
req->callBackEntry = NULL;
/* Empty the list */
node = req->queryList;
while( node ) {
node->data = NULL;
node = g_list_next( node );
}
g_list_free( req->queryList );
req->queryList = NULL;
}
/**
* Free query.
* \param qry Address query object.
* \param req Request query object.
*/
void addrqry_free( AddrQuery *qry ) {
g_return_if_fail( qry != NULL );
addrqry_clear( qry );
g_free( qry );
void qryreq_free( QueryRequest *req ) {
g_return_if_fail( req != NULL );
qryreq_clear( req );
g_free( req );
}
/**
* Specify query type.
* \param qry Address query object.
* Specify search type.
* \param req Request query object.
* \param value Type.
*/
void addrqry_set_query_type( AddrQuery *qry, const AddrQueryType value ) {
g_return_if_fail( qry != NULL );
qry->queryType = value;
}
/**
* Specify idle ID.
* \param qry Address query object.
* \param value Idle ID.
*/
void addrqry_set_idle_id( AddrQuery *qry, const guint value ) {
g_return_if_fail( qry != NULL );
qry->idleID = value;
void qryreq_set_search_type( QueryRequest *req, const AddrSearchType value ) {
g_return_if_fail( req != NULL );
req->searchType = value;
}
/**
* Specify search term to be used.
* \param qry Address query object.
* \param req Request query object.
* \param value Search term.
*/
void addrqry_set_search_term( AddrQuery* qry, const gchar *value ) {
qry->searchTerm = mgu_replace_string( qry->searchTerm, value );
g_return_if_fail( qry != NULL );
g_strstrip( qry->searchTerm );
void qryreq_set_search_term( QueryRequest *req, const gchar *value ) {
req->searchTerm = mgu_replace_string( req->searchTerm, value );
g_return_if_fail( req != NULL );
g_strstrip( req->searchTerm );
}
/**
* Specify server object to be used.
* \param qry Address query object.
* \param value Server object that performs the search.
* Add address query object to request.
* \param req Request query object.
* \param aqo Address query object that performs the search.
*/
void addrqry_set_server( AddrQuery* qry, const gpointer value ) {
g_return_if_fail( qry != NULL );
qry->serverObject = value;
}
/**
* Specify query object to be used.
* \param qry Address query object.
* \param value Query object that performs the search.
*/
void addrqry_set_query( AddrQuery* qry, const gpointer value ) {
g_return_if_fail( qry != NULL );
qry->queryObject = value;
void qryreq_add_query( QueryRequest *req, AddrQueryObject *aqo ) {
g_return_if_fail( req != NULL );
g_return_if_fail( aqo != NULL );
req->queryList = g_list_append( req->queryList, aqo );
}
/**
* Display object to specified stream.
* \param qry Address query object.
* \param req Request query object.
* \param stream Output stream.
*/
void addrqry_print( const AddrQuery *qry, FILE *stream ) {
g_return_if_fail( qry != NULL );
void qryreq_print( const QueryRequest *req, FILE *stream ) {
GList *node;
g_return_if_fail( req != NULL );
fprintf( stream, "AddressQuery:\n" );
fprintf( stream, " queryID: %d\n", qry->queryID );
fprintf( stream, " idleID: %d\n", qry->idleID );
fprintf( stream, " searchTerm: '%s'\n", qry->searchTerm );
fprintf( stream, "QueryRequest:\n" );
fprintf( stream, " queryID: %d\n", req->queryID );
fprintf( stream, " searchType: %d\n", req->searchType );
fprintf( stream, " searchTerm: '%s'\n", req->searchTerm );
node = req->queryList;
while( node ) {
AddrQueryObject *aqo = node->data;
fprintf( stream, " --- type: %d\n", aqo->queryType );
node = g_list_next( node );
}
}
/**
* Add query to list.
* \param queryID ID of query being executed.
* \param searchTerm Search term. A private copy will be made.
* \param callBack Callback function.
* \param target Target object to receive data.
*
* \param searchTerm Search term. A private copy will be made.
* \param callBackEnd Callback function that will be called when query
* terminates.
* \param callBackEntry Callback function that will be called after each
* address entry has been read.
* \return Initialize query request object.
*/
AddrQuery *qrymgr_add_query(
const gint queryID, const gchar *searchTerm, void *callBack,
gpointer target )
QueryRequest *qrymgr_add_request(
const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
{
AddrQuery *qry;
QueryRequest *req;
qry = g_new0( AddrQuery, 1 );
qry->queryType = ADDRQUERY_NONE;
qry->queryID = queryID;
qry->idleID = 0;
qry->searchTerm = g_strdup( searchTerm );
qry->callBack = callBack;
qry->target = NULL;
qry->timeStart = time( NULL );
qry->serverObject = NULL;
qry->queryObject = NULL;
req = g_new0( QueryRequest, 1 );
req->searchTerm = g_strdup( searchTerm );
req->callBackEnd = callBackEnd;
req->callBackEntry = callBackEntry;
req->timeStart = time( NULL );
req->queryList = NULL;
/* Insert in head of list */
pthread_mutex_lock( & _queryListMutex_ );
_queryList_ = g_list_prepend( _queryList_, qry );
pthread_mutex_unlock( & _queryListMutex_ );
pthread_mutex_lock( & _requestListMutex_ );
req->queryID = ++_currentQueryID_;
_requestList_ = g_list_prepend( _requestList_, req );
pthread_mutex_unlock( & _requestListMutex_ );
return qry;
return req;
}
/**
@ -187,45 +185,45 @@ AddrQuery *qrymgr_add_query(
* \param queryID ID of query to find.
* \return Query object, or <i>NULL</i> if not found.
*/
AddrQuery *qrymgr_find_query( const gint queryID ) {
AddrQuery *qry;
AddrQuery *q;
QueryRequest *qrymgr_find_request( const gint queryID ) {
QueryRequest *req;
QueryRequest *q;
GList *node;
pthread_mutex_lock( & _queryListMutex_ );
qry = NULL;
node = _queryList_;
pthread_mutex_lock( & _requestListMutex_ );
req = NULL;
node = _requestList_;
while( node ) {
q = node->data;
if( q->queryID == queryID ) {
qry = q;
req = q;
break;
}
node = g_list_next( node );
}
pthread_mutex_unlock( & _queryListMutex_ );
pthread_mutex_unlock( & _requestListMutex_ );
return qry;
return req;
}
/**
* Delete specified query.
* \param queryID ID of query to retire.
*/
void qrymgr_delete_query( const gint queryID ) {
AddrQuery *qry;
void qrymgr_delete_request( const gint queryID ) {
QueryRequest *req;
GList *node, *nf;
pthread_mutex_lock( & _queryListMutex_ );
pthread_mutex_lock( & _requestListMutex_ );
/* Find node */
nf = NULL;
node = _queryList_;
node = _requestList_;
while( node ) {
qry = node->data;
if( qry->queryID == queryID ) {
req = node->data;
if( req->queryID == queryID ) {
nf = node;
addrqry_free( qry );
qryreq_free( req );
break;
}
node = g_list_next( node );
@ -233,45 +231,45 @@ void qrymgr_delete_query( const gint queryID ) {
/* Free link element and associated query */
if( nf ) {
_queryList_ = g_list_remove_link( _queryList_, nf );
_requestList_ = g_list_remove_link( _requestList_, nf );
g_list_free_1( nf );
}
pthread_mutex_unlock( & _queryListMutex_ );
pthread_mutex_unlock( & _requestListMutex_ );
}
/**
* Initialize query manager.
*/
void qrymgr_initialize( void ) {
_queryList_ = NULL;
_requestList_ = NULL;
}
/**
* Free all queries.
*/
static void qrymgr_free_all_query( void ) {
AddrQuery *qry;
static void qrymgr_free_all_request( void ) {
QueryRequest *req;
GList *node;
pthread_mutex_lock( & _queryListMutex_ );
node = _queryList_;
pthread_mutex_lock( & _requestListMutex_ );
node = _requestList_;
while( node ) {
qry = node->data;
addrqry_free( qry );
req = node->data;
qryreq_free( req );
node->data = NULL;
node = g_list_next( node );
}
g_list_free( _queryList_ );
_queryList_ = NULL;
pthread_mutex_unlock( & _queryListMutex_ );
g_list_free( _requestList_ );
_requestList_ = NULL;
pthread_mutex_unlock( & _requestListMutex_ );
}
/**
* Teardown query manager.
*/
void qrymgr_teardown( void ) {
qrymgr_free_all_query();
qrymgr_free_all_request();
}
/**
@ -279,19 +277,19 @@ void qrymgr_teardown( void ) {
* \param stream Output stream.
*/
void qrymgr_print( FILE *stream ) {
AddrQuery *qry;
QueryRequest *req;
GList *node;
pthread_mutex_lock( & _queryListMutex_ );
pthread_mutex_lock( & _requestListMutex_ );
fprintf( stream, "=== Query Manager ===\n" );
node = _queryList_;
node = _requestList_;
while( node ) {
qry = node->data;
addrqry_print( qry, stream );
req = node->data;
qryreq_print( req, stream );
fprintf( stream, "---\n" );
node = g_list_next( node );
}
pthread_mutex_unlock( & _queryListMutex_ );
pthread_mutex_unlock( & _requestListMutex_ );
}
/*

View file

@ -27,53 +27,82 @@
#include <glib.h>
#include <stdio.h>
#include <sys/time.h>
#include "addritem.h"
/* Query types */
#define ADDRQUERY_NONE 0
#define ADDRQUERY_LDAP 1
/* Search type */
typedef enum {
ADDRQUERY_NONE,
ADDRQUERY_LDAP
} AddrQueryType;
/* Address search call back function */
typedef gint ( AddrSearchCallbackFunc ) ( gint cacheID,
GList *listEMail,
gpointer target );
typedef void ( AddrSearchStaticFunc ) ( gint qid, AddrQueryType qty, gint status );
ADDRSEARCH_NONE,
ADDRSEARCH_DYNAMIC,
ADDRSEARCH_EXPLICIT,
ADDRSEARCH_LOCATE
} AddrSearchType;
/* Data structures */
typedef struct {
AddrQueryType queryType;
gint queryID;
gint idleID;
gchar *searchTerm;
time_t timeStart;
AddrSearchStaticFunc *callBack;
gpointer target;
gpointer serverObject;
gpointer queryObject;
gint queryID;
AddrSearchType searchType;
gchar *searchTerm;
time_t timeStart;
void ( *callBackEnd ) ( void * );
void ( *callBackEntry ) ( void * );
GList *queryList;
}
AddrQuery;
QueryRequest;
/* Some macros */
#define ADDRQUERY_OBJECT(obj) ((AddrQueryObject *)obj)
#define ADDRQUERY_TYPE(obj) (ADDRQUERY_OBJECT(obj)->queryType)
#define ADDRQUERY_ID(obj) (ADDRQUERY_OBJECT(obj)->queryID)
#define ADDRQUERY_SEARCHTYPE(obj) (ADDRQUERY_OBJECT(obj)->searchType)
#define ADDRQUERY_NAME(obj) (ADDRQUERY_OBJECT(obj)->queryName)
#define ADDRQUERY_RETVAL(obj) (ADDRQUERY_OBJECT(obj)->retVal)
#define ADDRQUERY_FOLDER(obj) (ADDRQUERY_OBJECT(obj)->folder)
#define ADDRQUERY_SEARCHVALUE(obj) (ADDRQUERY_OBJECT(obj)->searchValue)
/* Generic address query (base class) */
typedef struct _AddrQueryObject AddrQueryObject;
struct _AddrQueryObject {
gint queryType;
gint queryID;
AddrSearchType searchType;
gchar *queryName;
gint retVal;
ItemFolder *folder; /* Reference to folder in cache */
gchar *searchValue;
};
/* Address search call back functions */
typedef gint ( AddrSearchCallbackEntry ) ( gpointer sender,
gint queryID,
GList *listEMail,
gpointer data );
typedef void ( AddrSearchCallbackEnd ) ( gpointer sender,
gint queryID,
gint status,
gpointer data );
/* Function prototypes */
AddrQuery *addrqry_create ( void );
void addrqry_clear ( AddrQuery *qry );
void addrqry_free ( AddrQuery *qry );
void addrqry_set_query_type ( AddrQuery *qry, const AddrQueryType value );
void addrqry_set_idle_id ( AddrQuery *qry, const guint value );
void addrqry_set_search_term ( AddrQuery* qry, const gchar *value );
void addrqry_set_server ( AddrQuery* qry, const gpointer server );
void addrqry_set_query ( AddrQuery* qry, const gpointer query );
void addrqry_print ( const AddrQuery *qry, FILE *stream );
QueryRequest *qryreq_create ( void );
void qryreq_clear ( QueryRequest *req );
void qryreq_free ( QueryRequest *req );
void qryreq_set_search_type ( QueryRequest *req, const AddrSearchType value );
void qryreq_set_search_term ( QueryRequest *req, const gchar *value );
void qryreq_add_query ( QueryRequest *req, AddrQueryObject *aqo );
void qryreq_print ( const QueryRequest *req, FILE *stream );
void qrymgr_initialize ( void );
void qrymgr_teardown ( void );
AddrQuery *qrymgr_add_query(
const gint queryID, const gchar *searchTerm,
void *callBack, gpointer target );
QueryRequest *qrymgr_add_request( const gchar *searchTerm,
void *callBackEnd,
void *callBackEntry );
AddrQuery *qrymgr_find_query ( const gint queryID );
void qrymgr_delete_query ( const gint queryID );
QueryRequest *qrymgr_find_request( const gint queryID );
void qrymgr_delete_request ( const gint queryID );
void qrymgr_print ( FILE *stream );
#endif /* __ADDRQUERY_H__ */

View file

@ -21,6 +21,7 @@
# include "config.h"
#endif
#include <stddef.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
@ -31,7 +32,6 @@
#include "utils.h"
#include "gtkutils.h"
#include "inc.h"
#include "log.h"
#include "logwindow.h"
#include "prefs_common.h"

View file

@ -803,7 +803,9 @@ CodeConvFunc conv_get_code_conv_func(const gchar *src_charset_str,
case C_ISO_8859_13:
case C_ISO_8859_14:
case C_ISO_8859_15:
if (dest_charset == C_AUTO)
if (dest_charset == C_AUTO &&
(conv_get_current_charset() == src_charset ||
MB_CUR_MAX > 1))
code_conv = conv_latintodisp;
break;
case C_SHIFT_JIS:

View file

@ -201,7 +201,7 @@ void plugin_unload_all(const gchar *type)
}
g_slist_free(list);
cur = g_slist_find_custom(plugin_types, type, list_find_by_string);
cur = g_slist_find_custom(plugin_types, (gpointer) type, list_find_by_string);
if (cur) {
g_free(cur->data);
g_slist_remove(plugin_types, cur);

View file

@ -37,7 +37,6 @@ static SSL_CTX *ssl_ctx;
void ssl_init(void)
{
SSL_METHOD *meth;
FILE *cert_test;
/* Global system initialization*/
SSL_library_init();

View file

@ -68,26 +68,29 @@ StringTable *string_table_new(void)
return strtable;
}
gchar *string_table_lookup_string(StringTable *table, gchar *str)
gchar *string_table_lookup_string(StringTable *table, const gchar *str)
{
StringEntry *entry = g_hash_table_lookup(table->hash_table,
(gconstpointer)str);
if (!entry) {
return NULL;
} else {
StringEntry *entry;
entry = g_hash_table_lookup(table->hash_table, str);
if (entry) {
return entry->string;
} else {
return NULL;
}
}
gchar *string_table_insert_string(StringTable *table, gchar *str)
gchar *string_table_insert_string(StringTable *table, const gchar *str)
{
gchar *key = NULL;
StringEntry *entry = NULL;
StringEntry *entry;
if (g_hash_table_lookup_extended
(table->hash_table, str, (gpointer *)&key, (gpointer *)&entry)) {
entry = g_hash_table_lookup(table->hash_table, str);
if (entry) {
entry->ref_count++;
XXX_DEBUG ("ref++ for %s (%d)\n", entry->string, entry->ref_count);
XXX_DEBUG ("ref++ for %s (%d)\n", entry->string,
entry->ref_count);
} else {
entry = string_entry_new(str);
XXX_DEBUG ("inserting %s\n", str);
@ -99,7 +102,7 @@ gchar *string_table_insert_string(StringTable *table, gchar *str)
return entry->string;
}
void string_table_free_string(StringTable *table, gchar *str)
void string_table_free_string(StringTable *table, const gchar *str)
{
StringEntry *entry;
@ -108,11 +111,13 @@ void string_table_free_string(StringTable *table, gchar *str)
if (entry) {
entry->ref_count--;
if (entry->ref_count <= 0) {
XXX_DEBUG ("refcount of string %s dropped to zero\n", entry->string);
XXX_DEBUG ("refcount of string %s dropped to zero\n",
entry->string);
g_hash_table_remove(table->hash_table, str);
string_entry_free(entry);
} else {
XXX_DEBUG ("ref-- for %s (%d)\n", entry->string, entry->ref_count);
XXX_DEBUG ("ref-- for %s (%d)\n", entry->string,
entry->ref_count);
}
}
}

View file

@ -29,9 +29,9 @@ typedef struct {
StringTable *string_table_new (void);
void string_table_free (StringTable *table);
gchar *string_table_lookup_string (StringTable *table, gchar *str);
gchar *string_table_insert_string (StringTable *table, gchar *str);
void string_table_free_string (StringTable *table, gchar *str);
gchar *string_table_lookup_string (StringTable *table, const gchar *str);
gchar *string_table_insert_string (StringTable *table, const gchar *str);
void string_table_free_string (StringTable *table, const gchar *str);
void string_table_get_stats (StringTable *table);

View file

@ -1040,6 +1040,12 @@ void subst_for_filename(gchar *str)
subst_chars(str, " \t\r\n\"/\\", '_');
}
void subst_for_shellsafe_filename(gchar *str)
{
subst_for_filename(str);
subst_chars(str, "|&;()<>'!{}[]",'_');
}
gboolean is_header_line(const gchar *str)
{
if (str[0] == ':') return FALSE;
@ -1787,6 +1793,34 @@ gboolean is_file_entry_exist(const gchar *file)
return TRUE;
}
gboolean dirent_is_regular_file(struct dirent *d)
{
struct stat s;
#ifdef HAVE_DIRENT_D_TYPE
if (d->d_type == DT_REG)
return TRUE;
else if (d->d_type != DT_UNKNOWN)
return FALSE;
#endif
return (stat(d->d_name, &s) == 0 && S_ISREG(s.st_mode));
}
gboolean dirent_is_directory(struct dirent *d)
{
struct stat s;
#ifdef HAVE_DIRENT_D_TYPE
if (d->d_type == DT_DIR)
return TRUE;
else if (d->d_type != DT_UNKNOWN)
return FALSE;
#endif
return (stat(d->d_name, &s) == 0 && S_ISDIR(s.st_mode));
}
gint change_dir(const gchar *dir)
{
gchar *prevdir = NULL;
@ -2096,14 +2130,9 @@ gint remove_dir_recursive(const gchar *dir)
!strcmp(d->d_name, ".."))
continue;
if (stat(d->d_name, &s) < 0) {
FILE_OP_ERROR(d->d_name, "stat");
continue;
}
/* g_print("removing %s\n", d->d_name); */
if (S_ISDIR(s.st_mode)) {
if (dirent_is_directory(d)) {
if (remove_dir_recursive(d->d_name) < 0) {
g_warning("can't remove directory\n");
return -1;
@ -2707,6 +2736,55 @@ gchar *get_outgoing_rfc2822_str(FILE *fp)
return ret;
}
/*
* Create a new boundary in a way that it is very unlikely that this
* will occur in the following text. It would be easy to ensure
* uniqueness if everything is either quoted-printable or base64
* encoded (note that conversion is allowed), but because MIME bodies
* may be nested, it may happen that the same boundary has already
* been used. We avoid scanning the message for conflicts and hope the
* best.
*
* boundary := 0*69<bchars> bcharsnospace
* bchars := bcharsnospace / " "
* bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
* "+" / "_" / "," / "-" / "." /
* "/" / ":" / "=" / "?"
*
* some special characters removed because of buggy MTAs
*/
gchar *generate_mime_boundary(const gchar *prefix)
{
static gchar tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"1234567890+_./=";
gchar buf_uniq[17];
gchar buf_date[64];
gint i;
gint pid;
pid = getpid();
/* We make the boundary depend on the pid, so that all running
* processes generate different values even when they have been
* started within the same second and srandom(time(NULL)) has been
* used. I can't see whether this is really an advantage but it
* doesn't do any harm.
*/
for (i = 0; i < sizeof(buf_uniq) - 1; i++)
buf_uniq[i] = tbl[(random() ^ pid) % (sizeof(tbl) - 1)];
buf_uniq[i] = '\0';
get_rfc822_date(buf_date, sizeof(buf_date));
subst_char(buf_date, ' ', '_');
subst_char(buf_date, ',', '_');
subst_char(buf_date, ':', '_');
return g_strdup_printf("%s=_%s_%s", prefix ? prefix : "Multipart",
buf_date, buf_uniq);
}
gint change_file_mode_rw(FILE *fp, const gchar *file)
{
#if HAVE_FCHMOD
@ -2756,6 +2834,16 @@ FILE *my_tmpfile(void)
return tmpfile();
}
FILE *get_tmpfile_in_dir(const gchar *dir, gchar **filename)
{
int fd;
*filename = g_strdup_printf("%s%csylpheed.XXXXXX", dir, G_DIR_SEPARATOR);
fd = mkstemp(*filename);
return fdopen(fd, "w+");
}
FILE *str_open_as_stream(const gchar *str)
{
FILE *fp;
@ -3364,16 +3452,6 @@ int subject_get_prefix_length(const gchar *subject)
return 0;
}
FILE *get_tmpfile_in_dir(const gchar *dir, gchar **filename)
{
int fd;
*filename = g_strdup_printf("%s%csylpheed.XXXXXX", dir, G_DIR_SEPARATOR);
fd = mkstemp(*filename);
return fdopen(fd, "w+");
}
/* allow Mutt-like patterns in quick search */
gchar *expand_search_string(const gchar *search_string)
{
@ -3425,6 +3503,7 @@ gchar *expand_search_string(const gchar *search_string)
{ "T", "marked", 0, FALSE, FALSE },
{ "U", "unread", 0, FALSE, FALSE },
{ "x", "header \"References\"", 1, TRUE, TRUE },
{ "X", "test", 1, FALSE, FALSE },
{ "y", "header \"X-Label\"", 1, TRUE, TRUE },
{ "&", "&", 0, FALSE, FALSE },
{ "|", "|", 0, FALSE, FALSE },
@ -3615,64 +3694,60 @@ gchar *generate_msgid(const gchar *address, gchar *buf, gint len)
return buf;
}
/**
* Create a new boundary in a way that it is very unlikely that this
* will occur in the following text. It would be easy to ensure
* uniqueness if everything is either quoted-printable or base64
* encoded (note that conversion is allowed), but because MIME bodies
* may be nested, it may happen that the same boundary has already
* been used. We avoid scanning the message for conflicts and hope the
* best.
*
* boundary := 0*69<bchars> bcharsnospace
* bchars := bcharsnospace / " "
* bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
* "+" / "_" / "," / "-" / "." /
* "/" / ":" / "=" / "?"
*
* ":" and "," removed because of buggy MTAs
*/
gchar *generate_mime_boundary(void)
/*
quote_cmd_argument()
return a quoted string safely usable in argument of a command.
code is extracted and adapted from etPan! project -- DINH V. Hoà.
*/
gint quote_cmd_argument(gchar * result, guint size,
const gchar * path)
{
static gchar tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"1234567890'()+_./=?";
gchar bufuniq[17];
gchar bufdate[BUFFSIZE];
int i, equal;
int pid;
const gchar * p;
gchar * result_p;
guint remaining;
pid = getpid();
result_p = result;
remaining = size;
/* We make the boundary depend on the pid, so that all running
* processed generate different values even when they have been
* started within the same second and srand48(time(NULL)) has been
* used. I can't see whether this is really an advantage but it
* doesn't do any harm.
*/
equal = -1;
for (i = 0; i < sizeof(bufuniq) - 1; i++) {
bufuniq[i] = tbl[(lrand48() ^ pid) % (sizeof(tbl) - 1)]; /* fill with random */
if (bufuniq[i] == '=' && equal == -1)
equal = i;
for(p = path ; * p != '\0' ; p ++) {
if (isalnum(* p) || (* p == '/')) {
if (remaining > 0) {
* result_p = * p;
result_p ++;
remaining --;
}
else {
result[size - 1] = '\0';
return -1;
}
}
else {
if (remaining >= 2) {
* result_p = '\\';
result_p ++;
* result_p = * p;
result_p ++;
remaining -= 2;
}
else {
result[size - 1] = '\0';
return -1;
}
}
}
if (remaining > 0) {
* result_p = '\0';
}
bufuniq[i] = 0;
/* now make sure that we do have the sequence "=." in it which cannot
* be matched by quoted-printable or base64 encoding */
if (equal != -1 && (equal + 1) < i)
bufuniq[equal + 1] = '.';
else {
bufuniq[0] = '=';
bufuniq[1] = '.';
result[size - 1] = '\0';
return -1;
}
get_rfc822_date(bufdate, sizeof(bufdate));
subst_char(bufdate, ' ', '_');
subst_char(bufdate, ',', '_');
subst_char(bufdate, ':', '_');
return g_strdup_printf("Multipart_%s_%s",
bufdate, bufuniq);
return 0;
}

View file

@ -30,6 +30,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <time.h>
#if HAVE_ALLOCA_H
# include <alloca.h>
@ -279,6 +280,7 @@ void subst_chars (gchar *str,
gchar *orig,
gchar subst);
void subst_for_filename (gchar *str);
void subst_for_shellsafe_filename (gchar *str);
gboolean is_header_line (const gchar *str);
gboolean is_ascii_str (const guchar *str);
gint get_quote_level (const gchar *str,
@ -334,6 +336,8 @@ gboolean file_exist (const gchar *file,
gboolean allow_fifo);
gboolean is_dir_exist (const gchar *dir);
gboolean is_file_entry_exist (const gchar *file);
gboolean dirent_is_regular_file (struct dirent *d);
gboolean dirent_is_directory (struct dirent *d);
#define is_file_exist(file) file_exist(file, FALSE)
#define is_file_or_fifo_exist(file) file_exist(file, TRUE)
@ -380,6 +384,8 @@ gchar *get_outgoing_rfc2822_str (FILE *fp);
gint change_file_mode_rw (FILE *fp,
const gchar *file);
FILE *my_tmpfile (void);
FILE *get_tmpfile_in_dir (const gchar *dir,
gchar **filename);
FILE *str_open_as_stream (const gchar *str);
gint str_write_to_file (const gchar *str,
const gchar *file);
@ -427,6 +433,9 @@ gint g_stricase_equal (gconstpointer gptr1, gconstpointer gptr2);
gint g_int_compare (gconstpointer a, gconstpointer b);
gchar *generate_msgid (const gchar *address, gchar *buf, gint len);
gchar *generate_mime_boundary (void);
gchar *generate_mime_boundary (const gchar *prefix);
gint quote_cmd_argument(gchar * result, guint size,
const gchar * path);
#endif /* __UTILS_H__ */

View file

@ -58,7 +58,6 @@ static void xml_string_table_create(void)
#endif /* SPARSE_MEMORY */
static void xml_free_tag (XMLTag *tag);
static gint xml_get_parenthesis (XMLFile *file,
gchar *buf,
gint len);
@ -558,7 +557,7 @@ void xml_free_tree(GNode *node)
g_node_destroy(node);
}
static void xml_free_tag(XMLTag *tag)
void xml_free_tag(XMLTag *tag)
{
if (!tag) return;
@ -596,3 +595,14 @@ static gint xml_get_parenthesis(XMLFile *file, gchar *buf, gint len)
return 0;
}
void xml_tag_add_attr(XMLTag *tag, const gchar *name, gchar *value)
{
XMLAttr *attr;
attr = g_new0(XMLAttr, 1);
attr->name = XML_STRING_ADD(name);
attr->value = value;
tag->attr = g_list_append(tag->attr, attr);
}

View file

@ -91,4 +91,9 @@ gint xml_file_put_escape_str (FILE *fp,
void xml_free_node (XMLNode *node);
void xml_free_tree (GNode *node);
void xml_free_tag (XMLTag *tag);
void xml_tag_add_attr (XMLTag *tag,
const gchar *name,
gchar *value);
#endif /* __XML_H__ */

View file

@ -64,6 +64,7 @@
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <libgen.h>
#if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
# include <wchar.h>
@ -150,6 +151,14 @@ typedef enum
PRIORITY_LOWEST
} PriorityLevel;
typedef enum
{
COMPOSE_INSERT_SUCCESS,
COMPOSE_INSERT_READ_ERROR,
COMPOSE_INSERT_INVALID_CHARACTER,
COMPOSE_INSERT_NO_FILE
} ComposeInsertResult;
#define B64_LINE_SIZE 57
#define B64_BUFFSIZE 77
@ -200,7 +209,7 @@ static void compose_reedit_set_entry (Compose *compose,
static void compose_insert_sig (Compose *compose,
gboolean replace);
static gchar *compose_get_signature_str (Compose *compose);
static void compose_insert_file (Compose *compose,
static ComposeInsertResult compose_insert_file (Compose *compose,
const gchar *file);
static void compose_attach_append (Compose *compose,
const gchar *file,
@ -250,8 +259,7 @@ static void compose_convert_header (gchar *dest,
gchar *src,
gint header_len,
gboolean addr_field);
static void compose_generate_msgid (Compose *compose,
gchar *buf,
static void compose_generate_msgid (gchar *buf,
gint len);
static void compose_attach_info_free (AttachInfo *ainfo);
@ -868,7 +876,7 @@ void compose_reply_mode(ComposeMode mode, GSList *msginfo_list, gchar *body)
case COMPOSE_FORWARD_INLINE:
/* check if we reply to more than one Message */
if (list_len == 1) {
compose_forward(NULL, msginfo, FALSE, body);
compose_forward(NULL, msginfo, FALSE, body, FALSE);
break;
}
/* more messages FALL THROUGH */
@ -1007,7 +1015,8 @@ if (msginfo->var && *msginfo->var) { \
}
Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
gboolean as_attach, const gchar *body)
gboolean as_attach, const gchar *body,
gboolean no_extedit)
{
Compose *compose;
GtkTextView *textview;
@ -1030,7 +1039,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
if (!account && prefs_common.forward_account_autosel) {
gchar cc[BUFFSIZE];
if (!get_header_from_msginfo(msginfo,cc,sizeof(cc),"CC:")){ /* Found a CC header */
if (!procheader_get_header_from_msginfo(msginfo,cc,sizeof(cc),"CC:")){ /* Found a CC header */
extract_address(cc);
account = account_find_from_address(cc);
}
@ -1118,7 +1127,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
#endif
gtk_widget_grab_focus(compose->header_last->entry);
if (prefs_common.auto_exteditor)
if (!no_extedit && prefs_common.auto_exteditor)
compose_exec_ext_editor(compose);
/*save folder*/
@ -1221,22 +1230,22 @@ void compose_reedit(MsgInfo *msginfo)
gint id;
/* Select Account from queue headers */
if (!get_header_from_msginfo(msginfo, queueheader_buf,
if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
sizeof(queueheader_buf), "X-Sylpheed-Account-Id:")) {
id = atoi(&queueheader_buf[22]);
account = account_find_from_id(id);
}
if (!account && !get_header_from_msginfo(msginfo, queueheader_buf,
if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf,
sizeof(queueheader_buf), "NAID:")) {
id = atoi(&queueheader_buf[5]);
account = account_find_from_id(id);
}
if (!account && !get_header_from_msginfo(msginfo, queueheader_buf,
if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf,
sizeof(queueheader_buf), "MAID:")) {
id = atoi(&queueheader_buf[5]);
account = account_find_from_id(id);
}
if (!account && !get_header_from_msginfo(msginfo, queueheader_buf,
if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf,
sizeof(queueheader_buf), "S:")) {
account = account_find_from_address(queueheader_buf);
}
@ -1245,7 +1254,7 @@ void compose_reedit(MsgInfo *msginfo)
if (!account && prefs_common.reedit_account_autosel) {
gchar from[BUFFSIZE];
if (!get_header_from_msginfo(msginfo, from, sizeof(from), "FROM:")){
if (!procheader_get_header_from_msginfo(msginfo, from, sizeof(from), "FROM:")){
extract_address(from);
account = account_find_from_address(from);
}
@ -1261,7 +1270,7 @@ void compose_reedit(MsgInfo *msginfo)
gchar queueheader_buf[BUFFSIZE];
/* Set message save folder */
if (!get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "SCF:")) {
if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "SCF:")) {
gint startpos = 0;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), TRUE);
@ -1300,6 +1309,7 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
Compose *compose;
gchar *filename;
GtkItemFactory *ifactory;
FolderItem *item;
g_return_val_if_fail(msginfo != NULL, NULL);
@ -1324,6 +1334,17 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
compose->redirect_filename = filename;
/* Set save folder */
item = msginfo->folder;
if (item && item->prefs && item->prefs->save_copy_to_folder) {
gchar *folderidentifier;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), prefs_common.savemsg);
folderidentifier = folder_item_get_identifier(item);
gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
g_free(folderidentifier);
}
compose_attach_parts(compose, msginfo);
if (msginfo->subject)
@ -1477,6 +1498,11 @@ void compose_toolbar_cb(gint action, gpointer data)
case A_ADDRBOOK:
compose_address_cb(compose, 0, NULL);
break;
#ifdef USE_ASPELL
case A_CHECK_SPELLING:
compose_check_all(compose);
break;
#endif
default:
break;
}
@ -1850,6 +1876,10 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
if (replyto && from)
cc_list = address_list_append_with_comments(cc_list, from);
if (to_all && msginfo->folder &&
msginfo->folder->prefs->enable_default_reply_to)
cc_list = address_list_append_with_comments(cc_list,
msginfo->folder->prefs->default_reply_to);
cc_list = address_list_append_with_comments(cc_list, msginfo->to);
cc_list = address_list_append_with_comments(cc_list, compose->cc);
@ -2015,7 +2045,7 @@ static gchar *compose_get_signature_str(Compose *compose)
return sig_str;
}
static void compose_insert_file(Compose *compose, const gchar *file)
static ComposeInsertResult compose_insert_file(Compose *compose, const gchar *file)
{
GtkTextView *text;
GtkTextBuffer *buffer;
@ -2024,12 +2054,13 @@ static void compose_insert_file(Compose *compose, const gchar *file)
gchar buf[BUFFSIZE];
gint len;
FILE *fp;
gboolean badtxt = FALSE;
g_return_if_fail(file != NULL);
g_return_val_if_fail(file != NULL, COMPOSE_INSERT_NO_FILE);
if ((fp = fopen(file, "rb")) == NULL) {
FILE_OP_ERROR(file, "fopen");
return;
return COMPOSE_INSERT_READ_ERROR;
}
text = GTK_TEXT_VIEW(compose->text);
@ -2060,6 +2091,11 @@ static void compose_insert_file(Compose *compose, const gchar *file)
}
fclose(fp);
if (badtxt)
return COMPOSE_INSERT_INVALID_CHARACTER;
else
return COMPOSE_INSERT_SUCCESS;
}
static void compose_attach_append(Compose *compose, const gchar *file,
@ -2157,69 +2193,124 @@ static void compose_attach_append(Compose *compose, const gchar *file,
gtk_clist_set_row_data(GTK_CLIST(compose->attach_clist), row, ainfo);
}
#define IS_FIRST_PART_TEXT(info) \
((info->mime_type == MIME_TEXT || info->mime_type == MIME_TEXT_HTML || \
info->mime_type == MIME_TEXT_ENRICHED) || \
(info->mime_type == MIME_MULTIPART && info->content_type && \
!strcasecmp(info->content_type, "multipart/alternative") && \
(info->children && \
(info->children->mime_type == MIME_TEXT || \
info->children->mime_type == MIME_TEXT_HTML || \
info->children->mime_type == MIME_TEXT_ENRICHED))))
#ifdef USE_GPGME
static void compose_use_signing(Compose *compose, gboolean use_signing)
{
GtkItemFactory *ifactory;
GtkWidget *menuitem = NULL;
compose->use_signing = use_signing;
ifactory = gtk_item_factory_from_widget(compose->menubar);
menuitem = gtk_item_factory_get_item
(ifactory, "/Message/Sign");
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
use_signing);
compose_update_gnupg_mode_menu_item(compose);
}
#endif /* USE_GPGME */
#define NEXT_PART_NOT_CHILD(info) \
{ \
node = info->node; \
while (node->children) \
node = g_node_last_child(node); \
info = procmime_mimeinfo_next((MimeInfo *)node->data); \
}
static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
{
MimeInfo *mimeinfo;
MimeInfo *child;
gchar *infile;
MimeInfo *firsttext = NULL;
MimeInfo *encrypted = NULL;
GNode *node;
gchar *outfile;
const gchar *partname = NULL;
mimeinfo = procmime_scan_message(msginfo);
if (!mimeinfo) return;
/* skip first text (presumably message body) */
child = mimeinfo->children;
if (!child || IS_FIRST_PART_TEXT(mimeinfo)) {
if (mimeinfo->node->children == NULL) {
procmime_mimeinfo_free_all(mimeinfo);
return;
}
if (IS_FIRST_PART_TEXT(child))
child = child->next;
infile = procmsg_get_message_file_path(msginfo);
/* find first content part */
child = (MimeInfo *) mimeinfo->node->children->data;
while (child && child->node->children && (child->type == MIMETYPE_MULTIPART))
child = (MimeInfo *)child->node->children->data;
if (child->type == MIMETYPE_TEXT) {
firsttext = child;
debug_print("First text part found\n");
} else if (compose->mode == COMPOSE_REEDIT &&
child->type == MIMETYPE_APPLICATION &&
!strcasecmp(child->subtype, "pgp-encrypted")) {
AlertValue val;
val = alertpanel(_("Encrypted message"),
_("Cannot re-edit an encrypted message. \n"
"Discard encrypted part?"),
_("Yes"), _("No"), NULL);
if (val == G_ALERTDEFAULT)
encrypted = (MimeInfo *)child->node->parent->data;
}
child = (MimeInfo *) mimeinfo->node->children->data;
while (child != NULL) {
if (child->children || child->mime_type == MIME_MULTIPART) {
if (child == encrypted) {
/* skip this part of tree */
NEXT_PART_NOT_CHILD(child);
continue;
}
if (child->type == MIMETYPE_MULTIPART) {
/* get the actual content */
child = procmime_mimeinfo_next(child);
continue;
}
if (child->parent && child->parent->parent
&& !strcasecmp(child->parent->parent->content_type, "multipart/signed")
&& child->mime_type == MIME_TEXT) {
/* this is the main text part of a signed message */
if (child == firsttext) {
child = procmime_mimeinfo_next(child);
continue;
}
if ((compose->mode == COMPOSE_REEDIT ||
compose->mode == COMPOSE_FORWARD_INLINE ||
compose->mode == COMPOSE_FORWARD ) &&
(child->type == MIMETYPE_APPLICATION) &&
!strcmp(child->subtype, "pgp-signature")) {
#ifdef USE_GPGME
if (compose->mode == COMPOSE_REEDIT) {
compose->gnupg_mode = GNUPG_MODE_DETACH;
compose_use_signing(compose, TRUE);
}
#endif
child = procmime_mimeinfo_next(child);
continue;
}
outfile = procmime_get_tmp_file_name(child);
if (procmime_get_part(outfile, infile, child) < 0)
if (procmime_get_part(outfile, child) < 0)
g_warning("Can't get the part of multipart message.");
else if (compose->mode != COMPOSE_REEDIT || strcmp(child->content_type, "application/pgp-signature"))
compose_attach_append
(compose, outfile,
child->filename ? child->filename : child->name,
child->content_type);
else {
gchar *content_type;
child = child->next;
content_type = g_strdup_printf("%s/%s", procmime_get_type_str(child->type), child->subtype);
partname = procmime_mimeinfo_get_parameter(child, "name");
if (partname == NULL)
partname = "";
compose_attach_append(compose, outfile,
partname, content_type);
g_free(content_type);
}
g_free(outfile);
NEXT_PART_NOT_CHILD(child);
}
g_free(infile);
procmime_mimeinfo_free_all(mimeinfo);
}
#undef IS_FIRST_PART_TEXT
#define CHAR_BUF_SIZE 8
#undef NEXT_PART_NOT_CHILD
#define GET_CHAR(iter_p, buf, len) \
{ \
@ -3209,7 +3300,8 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
{
gchar buf[BUFFSIZE];
gchar *str;
gboolean first_address;
gboolean first_to_address;
gboolean first_cc_address;
GSList *list;
ComposeHeaderEntry *headerentry;
const gchar *headerentryname;
@ -3221,7 +3313,8 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
cc_hdr = prefs_common.trans_hdr ? _("Cc:") : "Cc:";
to_hdr = prefs_common.trans_hdr ? _("To:") : "To:";
first_address = TRUE;
first_to_address = TRUE;
first_cc_address = TRUE;
for (list = compose->header_list; list; list = list->next) {
headerentry = ((ComposeHeaderEntry *)list->data);
headerentryname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry));
@ -3235,12 +3328,24 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
compose_convert_header
(buf, sizeof(buf), str,
strlen("Resent-To") + 2, TRUE);
if (first_address) {
fprintf(fp, "Resent-To: ");
first_address = FALSE;
} else {
fprintf(fp, ",");
if (g_strcasecmp(headerentryname, to_hdr) == 0) {
if (first_to_address) {
fprintf(fp, "Resent-To: ");
first_to_address = FALSE;
} else {
fprintf(fp, ",");
}
}
if (g_strcasecmp(headerentryname, cc_hdr) == 0) {
if (first_cc_address) {
fprintf(fp, "\n");
fprintf(fp, "Resent-Cc: ");
first_cc_address = FALSE;
} else {
fprintf(fp, ",");
}
}
fprintf(fp, "%s", buf);
}
}
@ -3291,7 +3396,7 @@ static gint compose_redirect_write_headers(Compose *compose, FILE *fp)
/* Resent-Message-ID */
if (compose->account->gen_msgid) {
compose_generate_msgid(compose, buf, sizeof(buf));
compose_generate_msgid(buf, sizeof(buf));
fprintf(fp, "Resent-Message-Id: <%s>\n", buf);
compose->msgid = g_strdup(buf);
}
@ -3328,7 +3433,7 @@ static gint compose_redirect_write_to_file(Compose *compose, const gchar *file)
g_warning("can't change file mode\n");
}
while (procheader_get_unfolded_line(buf, sizeof(buf), fp)) {
while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1) {
/* should filter returnpath, delivered-to */
if (g_strncasecmp(buf, "Return-Path:",
strlen("Return-Path:")) == 0 ||
@ -3789,7 +3894,6 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
GSList *cur;
gchar buf[BUFFSIZE];
gint num;
MsgFlags flag = {0, 0};
static gboolean lock = FALSE;
PrefsAccount *mailac = NULL, *newsac = NULL;
@ -4110,14 +4214,15 @@ static void compose_write_attach(Compose *compose, FILE *fp)
static gint compose_write_headers_from_headerlist(Compose *compose,
FILE *fp,
gchar *header)
const gchar *header,
const gchar *seperator)
{
gchar buf[BUFFSIZE];
gchar *str, *header_w_colon, *trans_hdr;
gboolean first_address;
gboolean write_header = FALSE;
GSList *list;
ComposeHeaderEntry *headerentry;
const gchar * headerentryname;
GString *headerstr;
if (IS_IN_CUSTOM_HEADER(header)) {
return 0;
@ -4125,10 +4230,11 @@ static gint compose_write_headers_from_headerlist(Compose *compose,
debug_print("Writing %s-header\n", header);
headerstr = g_string_sized_new(64);
header_w_colon = g_strconcat(header, ":", NULL);
trans_hdr = (prefs_common.trans_hdr ? gettext(header_w_colon) : header_w_colon);
first_address = TRUE;
for (list = compose->header_list; list; list = list->next) {
headerentry = ((ComposeHeaderEntry *)list->data);
headerentryname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry));
@ -4138,24 +4244,26 @@ static gint compose_write_headers_from_headerlist(Compose *compose,
Xstrdup_a(str, entstr, return -1);
g_strstrip(str);
if (str[0] != '\0') {
compose_convert_header
(buf, sizeof(buf), str,
strlen(header) + 2, TRUE);
if (first_address) {
fprintf(fp, "%s: ", header);
first_address = FALSE;
} else {
fprintf(fp, ",");
}
fprintf(fp, "%s", buf);
if (write_header)
g_string_append(headerstr, seperator);
g_string_append(headerstr, str);
write_header = TRUE;
}
}
}
if (!first_address) {
fprintf(fp, "\n");
if (write_header) {
gchar *buf;
buf = g_new0(gchar, headerstr->len * 4 + 256);
compose_convert_header
(buf, headerstr->len * 4 + 256, headerstr->str,
strlen(header) + 2, TRUE);
fprintf(fp, "%s: %s\n", header, buf);
g_free(buf);
}
g_free(header_w_colon);
g_string_free(headerstr, TRUE);
return(0);
}
@ -4212,7 +4320,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
}
/* To */
compose_write_headers_from_headerlist(compose, fp, "To");
compose_write_headers_from_headerlist(compose, fp, "To", ", ");
#if 0 /* NEW COMPOSE GUI */
if (compose->use_to) {
entry_str = gtk_entry_get_text(GTK_ENTRY(compose->to_entry));
@ -4221,7 +4329,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
#endif
/* Newsgroups */
compose_write_headers_from_headerlist(compose, fp, "Newsgroups");
compose_write_headers_from_headerlist(compose, fp, "Newsgroups", ",");
#if 0 /* NEW COMPOSE GUI */
if (compose->use_newsgroups) {
entry_str = gtk_entry_get_text(GTK_ENTRY(compose->newsgroups_entry));
@ -4242,7 +4350,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
}
#endif
/* Cc */
compose_write_headers_from_headerlist(compose, fp, "Cc");
compose_write_headers_from_headerlist(compose, fp, "Cc", ", ");
#if 0 /* NEW COMPOSE GUI */
if (compose->use_cc) {
str = gtk_entry_get_text(GTK_ENTRY(compose->cc_entry));
@ -4250,7 +4358,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
}
#endif
/* Bcc */
compose_write_headers_from_headerlist(compose, fp, "Bcc");
compose_write_headers_from_headerlist(compose, fp, "Bcc", ", ");
#if 0 /* NEW COMPOSE GUI */
if (compose->use_bcc) {
str = gtk_entry_get_text(GTK_ENTRY(compose->bcc_entry));
@ -4272,7 +4380,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
/* Message-ID */
if (compose->account->gen_msgid) {
compose_generate_msgid(compose, buf, sizeof(buf));
compose_generate_msgid(buf, sizeof(buf));
fprintf(fp, "Message-Id: <%s>\n", buf);
compose->msgid = g_strdup(buf);
}
@ -4288,7 +4396,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
}
/* Followup-To */
compose_write_headers_from_headerlist(compose, fp, "Followup-To");
compose_write_headers_from_headerlist(compose, fp, "Followup-To", ",");
#if 0 /* NEW COMPOSE GUI */
if (compose->use_followupto && !IS_IN_CUSTOM_HEADER("Followup-To")) {
entry_str = gtk_entry_get_text(GTK_ENTRY(compose->followup_entry));
@ -4306,7 +4414,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
}
#endif
/* Reply-To */
compose_write_headers_from_headerlist(compose, fp, "Reply-To");
compose_write_headers_from_headerlist(compose, fp, "Reply-To", ", ");
#if 0 /* NEW COMPOSE GUI */
if (compose->use_replyto && !IS_IN_CUSTOM_HEADER("Reply-To")) {
entry_str = gtk_entry_get_text(GTK_ENTRY(compose->reply_entry));
@ -4380,7 +4488,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
/* MIME */
fprintf(fp, "Mime-Version: 1.0\n");
if (compose_use_attach(compose)) {
compose->boundary = generate_mime_boundary();
compose->boundary = generate_mime_boundary(NULL);
fprintf(fp,
"Content-Type: multipart/mixed;\n"
" boundary=\"%s\"\n", compose->boundary);
@ -4497,7 +4605,7 @@ static void compose_convert_header(gchar *dest, gint len, gchar *src,
conv_encode_header(dest, len, src, header_len, addr_field);
}
static void compose_generate_msgid(Compose *compose, gchar *buf, gint len)
static void compose_generate_msgid(gchar *buf, gint len)
{
struct tm *lt;
time_t t;
@ -4506,18 +4614,9 @@ static void compose_generate_msgid(Compose *compose, gchar *buf, gint len)
t = time(NULL);
lt = localtime(&t);
if (compose->account && compose->account->address &&
*compose->account->address) {
if (strchr(compose->account->address, '@'))
addr = g_strdup(compose->account->address);
else
addr = g_strconcat(compose->account->address, "@",
get_domain_name(), NULL);
} else
addr = g_strconcat(g_get_user_name(), "@", get_domain_name(),
NULL);
addr = g_strconcat("@", get_domain_name(), NULL);
g_snprintf(buf, len, "%04d%02d%02d%02d%02d%02d.%08x.%s",
g_snprintf(buf, len, "%04d%02d%02d%02d%02d%02d.%08x%s",
lt->tm_year + 1900, lt->tm_mon + 1,
lt->tm_mday, lt->tm_hour,
lt->tm_min, lt->tm_sec,
@ -6513,7 +6612,19 @@ static void compose_insert_file_cb(gpointer data, guint action,
for ( tmp = file_list; tmp; tmp = tmp->next) {
gchar *file = (gchar *) tmp->data;
compose_insert_file(compose, file);
gchar *filedup = g_strdup(file);
gchar *shortfile;
ComposeInsertResult res;
res = compose_insert_file(compose, file);
shortfile = g_basename(filedup);
if (res == COMPOSE_INSERT_READ_ERROR) {
alertpanel_error(_("File '%s' could not be read."), shortfile);
} else if (res == COMPOSE_INSERT_INVALID_CHARACTER) {
alertpanel_error(_("File '%s' contained invalid characters\n"
"for the current encoding, insertion may be incorrect."), shortfile);
}
g_free(filedup);
g_free(file);
}
g_list_free(file_list);

View file

@ -245,7 +245,8 @@ void compose_reply (MsgInfo *msginfo,
Compose *compose_forward (PrefsAccount *account,
MsgInfo *msginfo,
gboolean as_attach,
const gchar *body);
const gchar *body,
gboolean no_extedit);
Compose *compose_forward_multiple (PrefsAccount *account,
GSList *msginfo_list);
/* remove end */

View file

@ -502,7 +502,7 @@ static void crash_handler(int sig)
#ifdef SIGTERM
if (sig == SIGTERM)
clean_quit();
clean_quit(NULL);
#endif
/*

View file

@ -78,6 +78,7 @@ static struct _LDAPEdit {
GtkWidget *entry_criteria;
GtkWidget *spinbtn_queryage;
GtkWidget *check_dynsearch;
GtkWidget *check_matchoption;
} ldapedit;
/**
@ -372,6 +373,7 @@ static void addressbook_edit_ldap_page_basic( gint pageNum, gchar *pageLbl ) {
GtkWidget *entry_baseDN;
GtkWidget *check_btn;
GtkWidget *lookdn_btn;
GtkTooltips *toolTip;
gint top;
vbox = gtk_vbox_new( FALSE, 8 );
@ -400,6 +402,11 @@ static void addressbook_edit_ldap_page_basic( gint pageNum, gchar *pageLbl ) {
gtk_table_attach(GTK_TABLE(table), entry_name, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, entry_name, _(
"A name that you wish to call the server." ),
NULL );
/* Next row */
++top;
label = gtk_label_new(_("Hostname"));
@ -410,6 +417,15 @@ static void addressbook_edit_ldap_page_basic( gint pageNum, gchar *pageLbl ) {
gtk_table_attach(GTK_TABLE(table), entry_server, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, entry_server, _(
"This is the hostname of the server. For example, " \
"\"ldap.mydomain.com\" may be appropriate for the " \
"\"mydomain.com\" organization. An IP address may also be " \
"used. You may specify \"localhost\" if running an LDAP " \
"server on the same computer as Sylpheed." ),
NULL );
/* Next row */
++top;
label = gtk_label_new(_("Port"));
@ -425,9 +441,20 @@ static void addressbook_edit_ldap_page_basic( gint pageNum, gchar *pageLbl ) {
gtk_table_attach(GTK_TABLE(table), hbox_spin, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, spinbtn_port, _(
"The port number that the server listens on. Port 389 is " \
"the default." ),
NULL );
check_btn = gtk_button_new_with_label( _(" Check Server "));
gtk_table_attach(GTK_TABLE(table), check_btn, 2, 3, top, (top + 1), GTK_FILL, 0, 3, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, check_btn, _(
"Press this button to test the connection to the server." ),
NULL );
/* Next row */
++top;
label = gtk_label_new(_("Search Base"));
@ -438,9 +465,25 @@ static void addressbook_edit_ldap_page_basic( gint pageNum, gchar *pageLbl ) {
gtk_table_attach(GTK_TABLE(table), entry_baseDN, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, entry_baseDN, _(
"This specifies the name of the directory to be searched " \
"on the server. Examples include:\n" \
" dc=sylpheed,dc=org\n" \
" ou=people,dc=domainname,dc=com\n" \
" o=Organization Name,c=Country\n"
),
NULL );
lookdn_btn = gtk_button_new_with_label( _(" ... "));
gtk_table_attach(GTK_TABLE(table), lookdn_btn, 2, 3, top, (top + 1), GTK_FILL, 0, 3, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, lookdn_btn, _(
"Press this button to lookup the name of available " \
"directory names on the server." ),
NULL );
/* Signal handlers */
g_signal_connect(G_OBJECT(check_btn), "clicked",
G_CALLBACK(edit_ldap_server_check), NULL);
@ -465,7 +508,9 @@ static void addressbook_edit_ldap_page_search( gint pageNum, gchar *pageLbl ) {
GtkObject *spinbtn_queryage_adj;
GtkWidget *spinbtn_queryage;
GtkWidget *check_dynsearch;
GtkWidget *check_matchoption;
GtkWidget *reset_btn;
GtkTooltips *toolTip;
gint top;
vbox = gtk_vbox_new( FALSE, 8 );
@ -494,9 +539,22 @@ static void addressbook_edit_ldap_page_search( gint pageNum, gchar *pageLbl ) {
gtk_table_attach(GTK_TABLE(table), entry_criteria, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, entry_criteria, _(
"A list of LDAP attribute names that should be searched " \
"when attempting to find a name or address." ),
NULL );
reset_btn = gtk_button_new_with_label( _(" Defaults "));
gtk_table_attach(GTK_TABLE(table), reset_btn, 2, 3, top, (top + 1), GTK_FILL, 0, 3, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, reset_btn, _(
"This resets the attribute names to a default value " \
"that should find most names and addresses during a " \
"name or address search process." ),
NULL );
/* Next row */
++top;
label = gtk_label_new(_("Max Query Age (secs)"));
@ -513,6 +571,23 @@ static void addressbook_edit_ldap_page_search( gint pageNum, gchar *pageLbl ) {
gtk_table_attach(GTK_TABLE(table), hbox_spin, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, spinbtn_queryage, _(
"This defines the maximum period of time (in seconds) that " \
"an address search result is valid for address completion " \
"purposes. Search results are stored in a cache until this " \
"period of time has passed and then retired. This will " \
"improve the response time when attempting to search for " \
"the same name or address on subsequent address completion " \
"requests. The cache will be searched in preference to " \
"performing a new server search request. The default value " \
"of 600 seconds (10 minutes), should be sufficient for most " \
"servers. A larger value will reduce the search time for " \
"subsequent searches. This is useful for servers that have " \
"slow response times at the expense of more memory to cache " \
"results." ),
NULL );
/* Next row */
++top;
check_dynsearch = gtk_check_button_new_with_label(
@ -520,6 +595,31 @@ static void addressbook_edit_ldap_page_search( gint pageNum, gchar *pageLbl ) {
gtk_table_attach(GTK_TABLE(table), check_dynsearch, 1, 3, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, check_dynsearch, _(
"Check this option to include this server for dynamic " \
"searches when using address completion." ),
NULL );
/* Next row */
++top;
check_matchoption = gtk_check_button_new_with_label(
_("Match names 'containing' search term") );
gtk_table_attach(GTK_TABLE(table), check_matchoption, 1, 3, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, check_matchoption, _(
"Searches for names and addresses can be performed either " \
"using \"begins-with\" or \"contains\" search term. Check " \
"this option to perform a \"contains\" search; this type of " \
"search usually takes longer to complete. Note that for " \
"performance reasons, address completion uses " \
"\"begins-with\" for all searches against other address " \
"interfaces." \
),
NULL );
/* Signal handlers */
g_signal_connect(G_OBJECT(reset_btn), "clicked",
G_CALLBACK(edit_ldap_search_reset), NULL);
@ -527,9 +627,10 @@ static void addressbook_edit_ldap_page_search( gint pageNum, gchar *pageLbl ) {
/* Done */
gtk_widget_show_all(vbox);
ldapedit.entry_criteria = entry_criteria;
ldapedit.spinbtn_queryage = spinbtn_queryage;
ldapedit.check_dynsearch = check_dynsearch;
ldapedit.entry_criteria = entry_criteria;
ldapedit.spinbtn_queryage = spinbtn_queryage;
ldapedit.check_dynsearch = check_dynsearch;
ldapedit.check_matchoption = check_matchoption;
}
static void addressbook_edit_ldap_page_extended( gint pageNum, gchar *pageLbl ) {
@ -543,6 +644,7 @@ static void addressbook_edit_ldap_page_extended( gint pageNum, gchar *pageLbl )
GtkWidget *spinbtn_timeout;
GtkObject *spinbtn_maxentry_adj;
GtkWidget *spinbtn_maxentry;
GtkTooltips *toolTip;
gint top;
vbox = gtk_vbox_new( FALSE, 8 );
@ -571,6 +673,14 @@ static void addressbook_edit_ldap_page_extended( gint pageNum, gchar *pageLbl )
gtk_table_attach(GTK_TABLE(table), entry_bindDN, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, entry_bindDN, _(
"The LDAP user account name to be used to connect to the server. " \
"This is usually only used for protected servers. This name " \
"is typically formatted as: \"cn=user,dc=sylpheed,dc=com\". " \
"This is usually left empty when performing a search." ),
NULL );
/* Next row */
++top;
label = gtk_label_new(_("Bind Password"));
@ -581,6 +691,12 @@ static void addressbook_edit_ldap_page_extended( gint pageNum, gchar *pageLbl )
gtk_table_attach(GTK_TABLE(table), entry_bindPW, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, entry_bindPW, _(
"The password to be used when connecting as the \"Bind DN\" " \
"user." ),
NULL );
/* Next row */
++top;
label = gtk_label_new(_("Timeout (secs)"));
@ -596,6 +712,10 @@ static void addressbook_edit_ldap_page_extended( gint pageNum, gchar *pageLbl )
gtk_table_attach(GTK_TABLE(table), hbox_spin, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, spinbtn_timeout, _(
"The timeout period in seconds." ), NULL );
/* Next row */
++top;
label = gtk_label_new(_("Maximum Entries"));
@ -611,6 +731,12 @@ static void addressbook_edit_ldap_page_extended( gint pageNum, gchar *pageLbl )
gtk_table_attach(GTK_TABLE(table), hbox_spin, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
toolTip = gtk_tooltips_new();
gtk_tooltips_set_tip( toolTip, spinbtn_maxentry, _(
"The maximum number of entries that should be returned " \
"in the search result." ),
NULL );
/* Done */
gtk_widget_show_all(vbox);
@ -749,6 +875,8 @@ static void edit_ldap_clear_fields( void ) {
GTK_SPIN_BUTTON(ldapedit.spinbtn_queryage), LDAPCTL_DFL_QUERY_AGE );
gtk_toggle_button_set_active(
GTK_TOGGLE_BUTTON( ldapedit.check_dynsearch), TRUE );
gtk_toggle_button_set_active(
GTK_TOGGLE_BUTTON( ldapedit.check_matchoption), FALSE );
}
/**
@ -796,13 +924,25 @@ static void edit_ldap_set_fields( LdapServer *server ) {
GTK_SPIN_BUTTON(ldapedit.spinbtn_queryage), ctl->maxQueryAge );
gtk_toggle_button_set_active(
GTK_TOGGLE_BUTTON( ldapedit.check_dynsearch), server->searchFlag );
gtk_toggle_button_set_active(
GTK_TOGGLE_BUTTON( ldapedit.check_matchoption),
( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) );
}
AdapterDSource *addressbook_edit_ldap( AddressIndex *addrIndex, AdapterDSource *ads ) {
/**
* Edit LDAP server datasource that appears addressbook.
* \param addrIndex Address index object.
* \param ads Data source adapter.
* \return Update data source adapter, or <code>NULL</code> if user cancelled
* edit with dialog.
*/
AdapterDSource *addressbook_edit_ldap(
AddressIndex *addrIndex, AdapterDSource *ads )
{
static gboolean cancelled;
gchar *sName, *sHost, *sBase, *sBind, *sPass, *sCrit;
gint iPort, iMaxE, iTime, iAge;
gboolean bSrch;
gboolean bSrch, bMatch;
AddressDataSource *ds = NULL;
LdapServer *server = NULL;
LdapControl *ctl = NULL;
@ -834,17 +974,30 @@ AdapterDSource *addressbook_edit_ldap( AddressIndex *addrIndex, AdapterDSource *
gtk_widget_hide(ldapedit.window);
if (cancelled == TRUE) return NULL;
sName = gtk_editable_get_chars( GTK_EDITABLE(ldapedit.entry_name), 0, -1 );
sHost = gtk_editable_get_chars( GTK_EDITABLE(ldapedit.entry_server), 0, -1 );
sBase = gtk_editable_get_chars( GTK_EDITABLE(ldapedit.entry_baseDN), 0, -1 );
sCrit = gtk_editable_get_chars( GTK_EDITABLE(ldapedit.entry_criteria), 0, -1 );
sBind = gtk_editable_get_chars( GTK_EDITABLE(ldapedit.entry_bindDN), 0, -1 );
sPass = gtk_editable_get_chars( GTK_EDITABLE(ldapedit.entry_bindPW), 0, -1 );
iPort = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( ldapedit.spinbtn_port ) );
iTime = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( ldapedit.spinbtn_timeout ) );
iMaxE = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( ldapedit.spinbtn_maxentry ) );
iAge = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( ldapedit.spinbtn_queryage ) );
bSrch = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ldapedit.check_dynsearch ) );
sName = gtk_editable_get_chars(
GTK_EDITABLE(ldapedit.entry_name), 0, -1 );
sHost = gtk_editable_get_chars(
GTK_EDITABLE(ldapedit.entry_server), 0, -1 );
sBase = gtk_editable_get_chars(
GTK_EDITABLE(ldapedit.entry_baseDN), 0, -1 );
sCrit = gtk_editable_get_chars(
GTK_EDITABLE(ldapedit.entry_criteria), 0, -1 );
sBind = gtk_editable_get_chars(
GTK_EDITABLE(ldapedit.entry_bindDN), 0, -1 );
sPass = gtk_editable_get_chars(
GTK_EDITABLE(ldapedit.entry_bindPW), 0, -1 );
iPort = gtk_spin_button_get_value_as_int(
GTK_SPIN_BUTTON( ldapedit.spinbtn_port ) );
iTime = gtk_spin_button_get_value_as_int(
GTK_SPIN_BUTTON( ldapedit.spinbtn_timeout ) );
iMaxE = gtk_spin_button_get_value_as_int(
GTK_SPIN_BUTTON( ldapedit.spinbtn_maxentry ) );
iAge = gtk_spin_button_get_value_as_int(
GTK_SPIN_BUTTON( ldapedit.spinbtn_queryage ) );
bSrch = gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON( ldapedit.check_dynsearch ) );
bMatch = gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON( ldapedit.check_matchoption ) );
fin = FALSE;
if( *sName == '\0' ) fin = TRUE;
@ -855,8 +1008,10 @@ AdapterDSource *addressbook_edit_ldap( AddressIndex *addrIndex, AdapterDSource *
if( ! ads ) {
/* New server */
server = ldapsvr_create();
ds = addrindex_index_add_datasource( addrIndex, ADDR_IF_LDAP, server );
ads = addressbook_create_ds_adapter( ds, ADDR_LDAP, NULL );
ds = addrindex_index_add_datasource(
addrIndex, ADDR_IF_LDAP, server );
ads = addressbook_create_ds_adapter(
ds, ADDR_LDAP, NULL );
}
ctl = server->control;
addressbook_ads_set_name( ads, sName );
@ -870,6 +1025,9 @@ AdapterDSource *addressbook_edit_ldap( AddressIndex *addrIndex, AdapterDSource *
ldapctl_set_max_entries( ctl, iMaxE );
ldapctl_set_timeout( ctl, iTime );
ldapctl_set_max_query_age( ctl, iAge );
ldapctl_set_matching_option(
ctl, bMatch ?
LDAPCTL_MATCH_CONTAINS : LDAPCTL_MATCH_BEGINWITH );
/* Save attributes */
editldap_parse_criteria( sCrit, ctl );

View file

@ -21,13 +21,13 @@
* Export addressbook to HTML file.
*/
#ifndef __EXPORT_HTML_H__
#define __EXPORT_HTML_H__
#ifndef __EXPORT_LDIF_H__
#define __EXPORT_LDIF_H__
/* Function prototypes */
void addressbook_exp_html( AddressCache *cache );
void addressbook_exp_ldif( AddressCache *cache );
#endif /* __EXPORT_HTML_H__ */
#endif /* __EXPORT_LDIF_H__ */
/*
* End of Source.

View file

@ -81,8 +81,6 @@ ExportLdifCtl *exportldif_create( void ) {
* \return ctl Export control data.
*/
void exportldif_free( ExportLdifCtl *ctl ) {
GList *node;
g_return_if_fail( ctl != NULL );
g_free( ctl->path );

View file

@ -34,7 +34,9 @@
#define PREFSBUFSIZE 1024
GSList * global_processing = NULL;
GSList * pre_global_processing = NULL;
GSList * post_global_processing = NULL;
GSList * filtering_rules = NULL;
static gboolean filtering_is_final_action(FilteringAction *filtering_action);
@ -53,27 +55,21 @@ static inline gint strlen_with_check(const gchar *expr, gint fline, const gchar
FilteringAction * filteringaction_new(int type, int account_id,
gchar * destination,
gint labelcolor)
gint labelcolor, gint score)
{
FilteringAction * action;
action = g_new0(FilteringAction, 1);
/* NOTE:
* if type is MATCHACTION_CHANGE_SCORE, account_id = (-1, 0, 1) and
* labelcolor = the score value change
*/
action->type = type;
action->account_id = account_id;
if (destination) {
action->destination = g_strdup(destination);
action->unesc_destination = matcher_unescape_str(g_strdup(destination));
} else {
action->destination = NULL;
action->unesc_destination = NULL;
}
action->labelcolor = labelcolor;
action->score = score;
return action;
}
@ -82,8 +78,6 @@ void filteringaction_free(FilteringAction * action)
g_return_if_fail(action);
if (action->destination)
g_free(action->destination);
if (action->unesc_destination)
g_free(action->unesc_destination);
g_free(action);
}
@ -111,10 +105,6 @@ static FilteringAction * filteringaction_copy(FilteringAction * src)
new->destination = g_strdup(src->destination);
else
new->destination = NULL;
if (src->unesc_destination)
new->unesc_destination = g_strdup(src->unesc_destination);
else
new->unesc_destination = NULL;
new->labelcolor = src->labelcolor;
return new;
@ -128,10 +118,6 @@ FilteringProp * filteringprop_copy(FilteringProp *src)
new = g_new0(FilteringProp, 1);
new->matchers = g_new0(MatcherList, 1);
#if 0
new->action = g_new0(FilteringAction, 1);
#endif
for (tmp = src->matchers->matchers; tmp != NULL && tmp->data != NULL;) {
MatcherProp *matcher = (MatcherProp *)tmp->data;
@ -142,19 +128,6 @@ FilteringProp * filteringprop_copy(FilteringProp *src)
new->matchers->bool_and = src->matchers->bool_and;
#if 0
new->action->type = src->action->type;
new->action->account_id = src->action->account_id;
if (src->action->destination)
new->action->destination = g_strdup(src->action->destination);
else
new->action->destination = NULL;
if (src->action->unesc_destination)
new->action->unesc_destination = g_strdup(src->action->unesc_destination);
else
new->action->unesc_destination = NULL;
new->action->labelcolor = src->action->labelcolor;
#endif
new->action_list = NULL;
for (tmp = src->action_list ; tmp != NULL ; tmp = tmp->next) {
@ -200,8 +173,11 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info)
case MATCHACTION_MOVE:
dest_folder =
folder_find_item_from_identifier(action->destination);
if (!dest_folder)
if (!dest_folder) {
debug_print("*** folder not found '%s'\n",
action->destination ?action->destination :"");
return FALSE;
}
if (folder_item_move_msg(dest_folder, info) == -1) {
debug_print("*** could not move message\n");
@ -214,8 +190,11 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info)
dest_folder =
folder_find_item_from_identifier(action->destination);
if (!dest_folder)
if (!dest_folder) {
debug_print("*** folder not found '%s'\n",
action->destination ?action->destination :"");
return FALSE;
}
if (folder_item_copy_msg(dest_folder, info) == -1)
return FALSE;
@ -257,42 +236,20 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info)
return TRUE;
case MATCHACTION_FORWARD:
account = account_find_from_id(action->account_id);
compose = compose_forward(account, info, FALSE, NULL);
if (compose->account->protocol == A_NNTP)
compose_entry_append(compose, action->destination,
COMPOSE_NEWSGROUPS);
else
compose_entry_append(compose, action->destination,
COMPOSE_TO);
val = compose_send(compose);
if (val == 0) {
gtk_widget_destroy(compose->window);
return TRUE;
}
gtk_widget_destroy(compose->window);
return FALSE;
case MATCHACTION_FORWARD_AS_ATTACHMENT:
account = account_find_from_id(action->account_id);
compose = compose_forward(account, info, TRUE, NULL);
if (compose->account->protocol == A_NNTP)
compose_entry_append(compose, action->destination,
COMPOSE_NEWSGROUPS);
else
compose_entry_append(compose, action->destination,
COMPOSE_TO);
compose = compose_forward(account, info,
action->type == MATCHACTION_FORWARD ? FALSE : TRUE,
NULL, TRUE);
compose_entry_append(compose, action->destination,
compose->account->protocol == A_NNTP
? COMPOSE_NEWSGROUPS
: COMPOSE_TO);
val = compose_send(compose);
if (val == 0) {
gtk_widget_destroy(compose->window);
return TRUE;
}
gtk_widget_destroy(compose->window);
return FALSE;
return val == 0 ? TRUE : FALSE;
case MATCHACTION_REDIRECT:
account = account_find_from_id(action->account_id);
@ -304,16 +261,12 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info)
COMPOSE_TO);
val = compose_send(compose);
if (val == 0) {
gtk_widget_destroy(compose->window);
return TRUE;
}
gtk_widget_destroy(compose->window);
return FALSE;
return val == 0 ? TRUE : FALSE;
case MATCHACTION_EXECUTE:
cmd = matching_build_command(action->unesc_destination, info);
cmd = matching_build_command(action->destination, info);
if (cmd == NULL)
return FALSE;
else {
@ -322,23 +275,44 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info)
}
return TRUE;
case MATCHACTION_CHANGE_SCORE:
/* NOTE:
* action->account_id is 0 if just assignment, -1 if decrement
* and 1 if increment by action->labelcolor
* action->labelcolor has the score value change
*/
info->score = action->account_id == 1 ? info->score + action->labelcolor
: action->account_id == -1 ? info->score - action->labelcolor
: action->labelcolor;
case MATCHACTION_SET_SCORE:
info->score = action->score;
return TRUE;
case MATCHACTION_CHANGE_SCORE:
info->score += action->score;
return TRUE;
case MATCHACTION_STOP:
return TRUE;
case MATCHACTION_HIDE:
info->hidden = TRUE;
return TRUE;
default:
break;
}
return FALSE;
}
gboolean filteringaction_apply_action_list(GSList *action_list, MsgInfo *info)
{
GSList *p;
g_return_val_if_fail(action_list, FALSE);
g_return_val_if_fail(info, FALSE);
for (p = action_list; p && p->data; p = g_slist_next(p)) {
FilteringAction *a = (FilteringAction *) p->data;
if (filteringaction_apply(a, info)) {
if (filtering_is_final_action(a))
break;
} else
return FALSE;
}
return TRUE;
}
static gboolean filtering_match_condition(FilteringProp *filtering, MsgInfo *info)
{
return matcherlist_match(filtering->matchers, info);
@ -375,19 +349,8 @@ static gboolean filtering_is_final_action(FilteringAction *filtering_action)
switch(filtering_action->type) {
case MATCHACTION_MOVE:
case MATCHACTION_DELETE:
case MATCHACTION_STOP:
return TRUE; /* MsgInfo invalid for message */
case MATCHACTION_EXECUTE:
case MATCHACTION_COPY:
case MATCHACTION_MARK:
case MATCHACTION_UNMARK:
case MATCHACTION_LOCK:
case MATCHACTION_UNLOCK:
case MATCHACTION_MARK_AS_READ:
case MATCHACTION_MARK_AS_UNREAD:
case MATCHACTION_FORWARD:
case MATCHACTION_FORWARD_AS_ATTACHMENT:
case MATCHACTION_REDIRECT:
return FALSE; /* MsgInfo still valid for message */
default:
return FALSE;
}
@ -406,10 +369,6 @@ static gboolean filter_msginfo(GSList * filtering_list, MsgInfo * info)
if (filtering_match_condition(filtering, info)) {
applied = filtering_apply_rule(filtering, info, &final);
#if 0
if (TRUE == (final = filtering_is_final_action(filtering)))
break;
#endif
if (final)
break;
}
@ -432,7 +391,8 @@ gboolean filter_message_by_msginfo(GSList *flist, MsgInfo *info)
gchar *filteringaction_to_string(gchar *dest, gint destlen, FilteringAction *action)
{
const gchar *command_str;
gchar * quoted_dest;
command_str = get_matchparser_tab_str(action->type);
if (command_str == NULL)
@ -442,7 +402,9 @@ gchar *filteringaction_to_string(gchar *dest, gint destlen, FilteringAction *act
case MATCHACTION_MOVE:
case MATCHACTION_COPY:
case MATCHACTION_EXECUTE:
g_snprintf(dest, destlen, "%s \"%s\"", command_str, action->destination);
quoted_dest = matcher_quote_str(action->destination);
g_snprintf(dest, destlen, "%s \"%s\"", command_str, quoted_dest);
g_free(quoted_dest);
return dest;
case MATCHACTION_DELETE:
@ -452,18 +414,28 @@ gchar *filteringaction_to_string(gchar *dest, gint destlen, FilteringAction *act
case MATCHACTION_UNLOCK:
case MATCHACTION_MARK_AS_READ:
case MATCHACTION_MARK_AS_UNREAD:
case MATCHACTION_STOP:
case MATCHACTION_HIDE:
g_snprintf(dest, destlen, "%s", command_str);
return dest;
case MATCHACTION_REDIRECT:
case MATCHACTION_FORWARD:
case MATCHACTION_FORWARD_AS_ATTACHMENT:
g_snprintf(dest, destlen, "%s %d \"%s\"", command_str, action->account_id, action->destination);
quoted_dest = matcher_quote_str(action->destination);
g_snprintf(dest, destlen, "%s %d \"%s\"", command_str, action->account_id, quoted_dest);
g_free(quoted_dest);
return dest;
case MATCHACTION_COLOR:
g_snprintf(dest, destlen, "%s %d", command_str, action->labelcolor);
return dest;
case MATCHACTION_CHANGE_SCORE:
case MATCHACTION_SET_SCORE:
g_snprintf(dest, destlen, "%s %d", command_str, action->score);
return dest;
default:
return NULL;
}
@ -504,7 +476,6 @@ gchar * filteringprop_to_string(FilteringProp * prop)
gchar *list_str;
gchar *action_list_str;
gchar *filtering_str;
GSList * tmp;
action_list_str = filteringaction_list_to_string(prop->action_list);
@ -560,8 +531,12 @@ void prefs_filtering_clear(void)
prefs_filtering_free_func, NULL);
}
prefs_filtering_free(global_processing);
global_processing = NULL;
prefs_filtering_free(filtering_rules);
filtering_rules = NULL;
prefs_filtering_free(pre_global_processing);
pre_global_processing = NULL;
prefs_filtering_free(post_global_processing);
post_global_processing = NULL;
}
void prefs_filtering_clear_folder(Folder *folder)

View file

@ -29,8 +29,8 @@ struct _FilteringAction {
gint type;
gint account_id;
gchar *destination;
gchar *unesc_destination; /* for exec cmd line */
gint labelcolor;
gint score;
};
typedef struct _FilteringAction FilteringAction;
@ -46,10 +46,11 @@ typedef struct _FilteringProp FilteringProp;
FilteringAction * filteringaction_new(int type, int account_id,
gchar *destination,
gint labelcolor);
gchar * destination,
gint labelcolor, gint score);
void filteringaction_free(FilteringAction *action);
FilteringAction * filteringaction_parse(gchar **str);
gboolean filteringaction_apply_action_list (GSList *action_list, MsgInfo *info);
FilteringProp * filteringprop_new(MatcherList *matchers,
GSList *action_list);
@ -72,6 +73,8 @@ void prefs_filtering_free(GSList *prefs_filtering);
FilteringProp * filteringprop_copy(FilteringProp *src);
extern GSList * global_processing;
extern GSList * filtering_rules;
extern GSList * pre_global_processing;
extern GSList * post_global_processing;
#endif

File diff suppressed because it is too large Load diff

View file

@ -23,33 +23,22 @@
#include <glib.h>
#include <time.h>
typedef struct _Folder Folder;
typedef struct _FolderClass FolderClass;
typedef struct _LocalFolder LocalFolder;
typedef struct _RemoteFolder RemoteFolder;
#if 0
typedef struct _MaildirFolder MaildirFolder;
#endif
typedef struct _FolderItem FolderItem;
typedef struct _Folder Folder;
typedef struct _FolderClass FolderClass;
typedef struct _FolderItem FolderItem;
typedef struct _FolderUpdateData FolderUpdateData;
typedef struct _FolderItemUpdateData FolderItemUpdateData;
typedef struct _PersistPrefs PersistPrefs;
#define FOLDER(obj) ((Folder *)obj)
#define FOLDER_TYPE(obj) (FOLDER(obj)->klass->type)
#define FOLDER_CLASS(obj) (FOLDER(obj)->klass)
#define LOCAL_FOLDER(obj) ((LocalFolder *)obj)
#define REMOTE_FOLDER(obj) ((RemoteFolder *)obj)
#define FOLDER_TYPE(obj) (FOLDER(obj)->klass->type)
#define FOLDER_IS_LOCAL(obj) (FOLDER_TYPE(obj) == F_MH || \
FOLDER_TYPE(obj) == F_MBOX || \
FOLDER_TYPE(obj) == F_MAILDIR)
#if 0
#define MAILDIR_FOLDER(obj) ((MaildirFolder *)obj)
#endif
#define FOLDER_ITEM(obj) ((FolderItem *)obj)
#define FOLDER_UPDATE_HOOKLIST "folder_update"
@ -129,12 +118,13 @@ typedef void (*FolderDestroyNotify) (Folder *folder,
typedef void (*FolderItemFunc) (FolderItem *item,
gpointer data);
#include "folder_item_prefs.h"
#include "prefs_account.h"
#include "session.h"
#include "procmsg.h"
#include "msgcache.h"
#include "xml.h"
#include "prefs_account.h"
struct _Folder
{
@ -171,27 +161,35 @@ struct _FolderClass
Folder *(*new_folder) (const gchar *name,
const gchar *path);
void (*destroy_folder) (Folder *folder);
void (*scan_tree) (Folder *folder);
void (*set_xml) (Folder *folder,
XMLTag *tag);
XMLTag *(*get_xml) (Folder *folder);
gint (*scan_tree) (Folder *folder);
gint (*create_tree) (Folder *folder);
/* FolderItem functions */
FolderItem *(*item_new) (Folder *folder);
void (*item_destroy) (Folder *folder,
void (*item_destroy) (Folder *folder,
FolderItem *item);
void (*item_set_xml) (Folder *folder,
FolderItem *item,
XMLTag *tag);
XMLTag *(*item_get_xml) (Folder *folder,
FolderItem *item);
gchar *(*item_get_path) (Folder *folder,
FolderItem *item);
FolderItem *(*create_folder) (Folder *folder,
FolderItem *parent,
const gchar *name);
gint (*rename_folder) (Folder *folder,
gint (*rename_folder) (Folder *folder,
FolderItem *item,
const gchar *name);
gint (*remove_folder) (Folder *folder,
gint (*remove_folder) (Folder *folder,
FolderItem *item);
gint (*close) (Folder *folder,
gint (*close) (Folder *folder,
FolderItem *item);
gint (*get_num_list) (Folder *folder,
gint (*get_num_list) (Folder *folder,
FolderItem *item,
GSList **list,
gboolean *old_uids_valid);
@ -244,27 +242,6 @@ struct _FolderClass
MsgPermFlags newflags);
};
struct _LocalFolder
{
Folder folder;
gchar *rootpath;
};
struct _RemoteFolder
{
Folder folder;
Session *session;
};
#if 0
struct _MaildirFolder
{
LocalFolder lfolder;
};
#endif
struct _FolderItem
{
SpecialFolderItemType stype;
@ -316,7 +293,8 @@ struct _FolderItem
FolderItemPrefs * prefs;
};
typedef struct {
struct _PersistPrefs
{
FolderSortKey sort_key;
FolderSortType sort_type;
guint collapsed : 1;
@ -324,7 +302,7 @@ typedef struct {
guint threaded : 1;
guint hide_read_msgs : 1; /* CLAWS */
guint ret_rcpt : 1; /* CLAWS */
} PersistPrefs;
};
struct _FolderUpdateData
{
@ -344,16 +322,14 @@ void folder_register_class (FolderClass *klass);
Folder *folder_new (FolderClass *type,
const gchar *name,
const gchar *path);
void folder_local_folder_init (Folder *folder,
const gchar *name,
const gchar *path);
void folder_remote_folder_init (Folder *folder,
const gchar *name,
const gchar *path);
void folder_init (Folder *folder,
const gchar *name);
void folder_destroy (Folder *folder);
void folder_local_folder_destroy (LocalFolder *lfolder);
void folder_remote_folder_destroy(RemoteFolder *rfolder);
void folder_set_xml (Folder *folder,
XMLTag *tag);
XMLTag *folder_get_xml (Folder *folder);
FolderItem *folder_item_new (Folder *folder,
const gchar *name,
@ -364,6 +340,12 @@ void folder_item_remove (FolderItem *item);
void folder_item_remove_children (FolderItem *item);
void folder_item_destroy (FolderItem *item);
void folder_item_set_xml (Folder *folder,
FolderItem *item,
XMLTag *tag);
XMLTag *folder_item_get_xml (Folder *folder,
FolderItem *item);
void folder_set_ui_func (Folder *folder,
FolderUIFunc func,
gpointer data);

View file

@ -31,7 +31,6 @@
#include "utils.h"
#include "prefs_gtk.h"
#include "filtering.h"
#include "prefs_scoring.h"
#include "folder_item_prefs.h"
FolderItemPrefs tmp_prefs;
@ -53,10 +52,12 @@ static PrefParam param[] = {
NULL, NULL, NULL},
/*{"enable_thread", "TRUE", &tmp_prefs.enable_thread, P_BOOL,
NULL, NULL, NULL},*/
#if 0
{"hide_score", "-9999", &tmp_prefs.kill_score, P_INT,
NULL, NULL, NULL},
{"important_score", "1", &tmp_prefs.important_score, P_INT,
NULL, NULL, NULL},
#endif
/* MIGRATION */
{"request_return_receipt", "", &tmp_prefs.request_return_receipt, P_BOOL,
NULL, NULL, NULL},
@ -90,6 +91,10 @@ static PrefParam param[] = {
NULL, NULL, NULL},
{"folder_color", "", &tmp_prefs.color, P_INT,
NULL, NULL, NULL},
{"enable_processing", "FALSE", &tmp_prefs.enable_processing, P_BOOL,
NULL, NULL, NULL},
{"newmailcheck", "TRUE", &tmp_prefs.newmailcheck, P_BOOL,
NULL, NULL, NULL},
{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
};
@ -162,8 +167,6 @@ static FolderItemPrefs *folder_item_prefs_clear(FolderItemPrefs *prefs)
prefs->sort_by_subject = FALSE;
prefs->sort_by_score = FALSE;
prefs->sort_descending = FALSE;
prefs->kill_score = -9999;
prefs->important_score = 9999;
prefs->request_return_receipt = FALSE;
prefs->enable_default_to = FALSE;
@ -183,8 +186,11 @@ static FolderItemPrefs *folder_item_prefs_clear(FolderItemPrefs *prefs)
prefs->save_copy_to_folder = FALSE;
prefs->color = 0;
prefs->scoring = NULL;
prefs->enable_processing = TRUE;
prefs->processing = NULL;
prefs->newmailcheck = TRUE;
return prefs;
}
@ -203,8 +209,6 @@ void folder_item_prefs_free(FolderItemPrefs * prefs)
g_free(prefs->default_to);
if (prefs->default_reply_to)
g_free(prefs->default_reply_to);
if (prefs->scoring != NULL)
prefs_scoring_free(prefs->scoring);
g_free(prefs);
}
@ -239,18 +243,10 @@ void folder_item_prefs_copy_prefs(FolderItem * src, FolderItem * dest)
tmp_prefs.sort_by_score = src->prefs->sort_by_score;
tmp_prefs.sort_descending = src->prefs->sort_descending;
tmp_prefs.enable_thread = src->prefs->enable_thread;
tmp_prefs.kill_score = src->prefs->kill_score;
tmp_prefs.important_score = src->prefs->important_score;
tmp_prefs.enable_processing = src->prefs->enable_processing;
tmp_prefs.newmailcheck = src->prefs->newmailcheck;
prefs_matcher_read_config();
for (tmp = src->prefs->scoring; tmp != NULL && tmp->data != NULL;) {
ScoringProp *prop = (ScoringProp *)tmp->data;
tmp_scor_list = g_slist_append(tmp_scor_list,
scoringprop_copy(prop));
tmp = tmp->next;
}
tmp_prefs.scoring = tmp_scor_list;
for (tmp = src->prefs->processing; tmp != NULL && tmp->data != NULL;) {
FilteringProp *prop = (FilteringProp *)tmp->data;

View file

@ -41,12 +41,11 @@ struct _FolderItemPrefs {
gboolean enable_thread;
gint kill_score;
gint important_score;
GSList * scoring;
int enable_processing;
GSList * processing;
int newmailcheck;
gboolean request_return_receipt;
gboolean enable_default_to;
gchar *default_to;

View file

@ -55,7 +55,6 @@
#include "prefs_common.h"
#include "prefs_account.h"
#include "prefs_filtering.h"
#include "prefs_scoring.h"
#include "prefs_folder_item.h"
#include "account.h"
#include "folder.h"
@ -191,15 +190,19 @@ static void mark_all_read_cb (FolderView *folderview,
static void folderview_new_folder_cb (FolderView *folderview,
guint action,
GtkWidget *widget);
#if 0
static void folderview_new_mbox_folder_cb(FolderView *folderview,
guint action,
GtkWidget *widget);
#endif
static void folderview_rename_folder_cb (FolderView *folderview,
guint action,
GtkWidget *widget);
#if 0
static void folderview_rename_mbox_folder_cb(FolderView *folderview,
guint action,
GtkWidget *widget);
#endif
static void folderview_delete_folder_cb (FolderView *folderview,
guint action,
GtkWidget *widget);
@ -269,14 +272,13 @@ gboolean folderview_update_folder (gpointer source,
gboolean folderview_update_item (gpointer source,
gpointer data);
static void folderview_scoring_cb(FolderView *folderview, guint action,
GtkWidget *widget);
static void folderview_processing_cb(FolderView *folderview, guint action,
GtkWidget *widget);
static void folderview_move_to(FolderView *folderview, FolderItem *from_folder,
FolderItem *to_folder);
static void folderview_move_to_cb(FolderView *folderview);
#if 0
static GtkItemFactoryEntry folderview_mbox_popup_entries[] =
{
{N_("/Create _new folder..."), NULL, folderview_new_mbox_folder_cb, 0, NULL},
@ -290,6 +292,7 @@ static GtkItemFactoryEntry folderview_mbox_popup_entries[] =
{N_("/_Processing..."), NULL, folderview_processing_cb, 0, NULL},
{N_("/_Scoring..."), NULL, folderview_scoring_cb, 0, NULL}
};
#endif
static GtkItemFactoryEntry folderview_mail_popup_entries[] =
{
@ -309,7 +312,6 @@ static GtkItemFactoryEntry folderview_mail_popup_entries[] =
{N_("/_Search folder..."), NULL, folderview_search_cb, 0, NULL},
{N_("/_Properties..."), NULL, folderview_property_cb, 0, NULL},
{N_("/_Processing..."), NULL, folderview_processing_cb, 0, NULL},
{N_("/S_coring..."), NULL, folderview_scoring_cb, 0, NULL}
};
static GtkItemFactoryEntry folderview_imap_popup_entries[] =
@ -330,7 +332,6 @@ static GtkItemFactoryEntry folderview_imap_popup_entries[] =
{N_("/_Search folder..."), NULL, folderview_search_cb, 0, NULL},
{N_("/_Properties..."), NULL, folderview_property_cb, 0, NULL},
{N_("/_Processing..."), NULL, folderview_processing_cb, 0, NULL},
{N_("/S_coring..."), NULL, folderview_scoring_cb, 0, NULL}
};
static GtkItemFactoryEntry folderview_news_popup_entries[] =
@ -349,7 +350,6 @@ static GtkItemFactoryEntry folderview_news_popup_entries[] =
{N_("/_Search folder..."), NULL, folderview_search_cb, 0, NULL},
{N_("/_Properties..."), NULL, folderview_property_cb, 0, NULL},
{N_("/_Processing..."), NULL, folderview_processing_cb, 0, NULL},
{N_("/S_coring..."), NULL, folderview_scoring_cb, 0, NULL}
};
GtkTargetEntry folderview_drag_types[] =
@ -366,11 +366,15 @@ FolderView *folderview_create(void)
GtkWidget *mail_popup;
GtkWidget *news_popup;
GtkWidget *imap_popup;
#if 0
GtkWidget *mbox_popup;
#endif
GtkItemFactory *mail_factory;
GtkItemFactory *news_factory;
GtkItemFactory *imap_factory;
#if 0
GtkItemFactory *mbox_factory;
#endif
gint n_entries;
gint i;
@ -441,12 +445,14 @@ FolderView *folderview_create(void)
n_entries,
"<NewsFolder>", &news_factory,
folderview);
#if 0
n_entries = sizeof(folderview_mbox_popup_entries) /
sizeof(folderview_mbox_popup_entries[0]);
mbox_popup = menu_create_items(folderview_mbox_popup_entries,
n_entries,
"<MboxFolder>", &mbox_factory,
folderview);
#endif
g_signal_connect(G_OBJECT(ctree), "key_press_event",
G_CALLBACK(folderview_key_pressed),
@ -485,9 +491,11 @@ FolderView *folderview_create(void)
g_signal_connect(G_OBJECT(news_popup), "selection_done",
G_CALLBACK(folderview_popup_close),
folderview);
#if 0
g_signal_connect(G_OBJECT(mbox_popup), "selection_done",
G_CALLBACK(folderview_popup_close),
folderview);
#endif
/* drop callback */
gtk_drag_dest_set(ctree, GTK_DEST_DEFAULT_ALL & ~GTK_DEST_DEFAULT_HIGHLIGHT,
@ -514,8 +522,10 @@ FolderView *folderview_create(void)
folderview->imap_factory = imap_factory;
folderview->news_popup = news_popup;
folderview->news_factory = news_factory;
#if 0
folderview->mbox_popup = mbox_popup;
folderview->mbox_factory = mbox_factory;
#endif
folderview->folder_update_callback_id =
hooks_register_hook(FOLDER_UPDATE_HOOKLIST, folderview_update_folder, (gpointer) folderview);
@ -532,6 +542,8 @@ FolderView *folderview_create(void)
void folderview_init(FolderView *folderview)
{
static GdkFont *boldfont = NULL;
static GdkFont *normalfont = NULL;
GtkWidget *ctree = folderview->ctree;
GtkWidget *label_new;
GtkWidget *label_unread;
@ -585,46 +597,6 @@ void folderview_init(FolderView *folderview)
gtk_clist_set_column_widget(GTK_CLIST(ctree),COL_NEW,hbox_new);
gtk_clist_set_column_widget(GTK_CLIST(ctree),COL_UNREAD,hbox_unread);
#if 0
if (!normalfont) {
if (gtkut_font_load(NORMAL_FONT) == NULL) {
GtkStyle *style = gtk_style_new();
normalfont = style->font;
gdk_font_ref(normalfont);
gtk_style_unref(style);
}
else
normalfont = gtkut_font_load(NORMAL_FONT);
}
if (!boldfont) {
if (gtkut_font_load(BOLD_FONT) == NULL) {
GtkStyle *style = gtk_style_new();
boldfont = style->font;
gdk_font_ref(boldfont);
gtk_style_unref(style);
}
else
boldfont = gtkut_font_load(BOLD_FONT);
}
#endif
if (!bold_style) {
PangoFontDescription *font_desc;
bold_style = gtk_style_copy(gtk_widget_get_style(ctree));
font_desc = pango_font_description_from_string(BOLD_FONT);
if (font_desc) {
if (bold_style->font_desc)
pango_font_description_free
(bold_style->font_desc);
bold_style->font_desc = font_desc;
}
bold_color_style = gtk_style_copy(bold_style);
bold_color_style->fg[GTK_STATE_NORMAL] = folderview->color_new;
bold_tgtfold_style = gtk_style_copy(bold_style);
bold_tgtfold_style->fg[GTK_STATE_NORMAL] = folderview->color_op;
}
if (!normal_style) {
PangoFontDescription *font_desc;
normal_style = gtk_style_copy(gtk_widget_get_style(ctree));
@ -638,6 +610,23 @@ void folderview_init(FolderView *folderview)
normal_color_style = gtk_style_copy(normal_style);
normal_color_style->fg[GTK_STATE_NORMAL] = folderview->color_new;
}
if (!bold_style) {
PangoFontDescription *font_desc;
bold_style = gtk_style_copy(gtk_widget_get_style(ctree));
font_desc = pango_font_description_from_string(prefs_common.boldfont);
if (font_desc) {
if (bold_style->font_desc)
pango_font_description_free
(bold_style->font_desc);
bold_style->font_desc = font_desc;
}
bold_color_style = gtk_style_copy(bold_style);
bold_color_style->fg[GTK_STATE_NORMAL] = folderview->color_new;
bold_tgtfold_style = gtk_style_copy(bold_style);
bold_tgtfold_style->fg[GTK_STATE_NORMAL] = folderview->color_op;
}
}
void folderview_set(FolderView *folderview)
@ -895,6 +884,7 @@ gint folderview_check_new(Folder *folder)
if (item->no_select) continue;
if (folder && folder != item->folder) continue;
if (!folder && !FOLDER_IS_LOCAL(item->folder)) continue;
if (!item->prefs->newmailcheck) continue;
folderview_scan_tree_func(item->folder, item, NULL);
former_new = item->new_msgs;
@ -1367,9 +1357,11 @@ void folderview_new_folder(FolderView *folderview)
g_return_if_fail(item->folder != NULL);
switch (FOLDER_TYPE(item->folder)) {
#if 0
case F_MBOX:
folderview_new_mbox_folder_cb(folderview, 0, NULL);
break;
#endif
case F_MH:
case F_MAILDIR:
folderview_new_folder_cb(folderview, 0, NULL);
@ -1397,9 +1389,11 @@ void folderview_rename_folder(FolderView *folderview)
if (item->stype != F_NORMAL) return;
switch (FOLDER_TYPE(item->folder)) {
#if 0
case F_MBOX:
folderview_rename_mbox_folder_cb(folderview, 0, NULL);
break;
#endif
case F_MH:
case F_MAILDIR:
case F_IMAP:
@ -1426,7 +1420,9 @@ void folderview_delete_folder(FolderView *folderview)
switch (FOLDER_TYPE(item->folder)) {
case F_MH:
#if 0
case F_MBOX:
#endif
case F_MAILDIR:
case F_IMAP:
folderview_delete_folder_cb(folderview, 0, NULL);
@ -1510,7 +1506,7 @@ static gboolean folderview_button_pressed(GtkWidget *ctree, GdkEventButton *even
} else
mark_all_read = search_folder = folder_property = TRUE;
if (FOLDER_IS_LOCAL(folder) || FOLDER_TYPE(folder) == F_IMAP || FOLDER_TYPE(folder) == F_MBOX) {
if (FOLDER_IS_LOCAL(folder) || FOLDER_TYPE(folder) == F_IMAP /* || FOLDER_TYPE(folder) == F_MBOX */) {
if (item->parent == NULL)
update_tree = rescan_tree = TRUE;
else if (item->stype == F_NORMAL)
@ -1577,6 +1573,7 @@ static gboolean folderview_button_pressed(GtkWidget *ctree, GdkEventButton *even
SET_SENS(news_factory, "/Properties...", folder_property);
SET_SENS(news_factory, "/Processing...", folder_processing);
SET_SENS(news_factory, "/Scoring...", folder_scoring);
#if 0
} else if (FOLDER_TYPE(folder) == F_MBOX) {
popup = folderview->mbox_popup;
menu_set_insensitive_all(GTK_MENU_SHELL(popup));
@ -1587,6 +1584,7 @@ static gboolean folderview_button_pressed(GtkWidget *ctree, GdkEventButton *even
SET_SENS(news_factory, "/Properties...", folder_property);
SET_SENS(mbox_factory, "/Processing...", folder_processing);
SET_SENS(mbox_factory, "/Scoring...", folder_scoring);
#endif
} else
return FALSE;
@ -1942,6 +1940,7 @@ static void folderview_new_folder_cb(FolderView *folderview, guint action,
folder_write_list();
}
#if 0
static void folderview_new_mbox_folder_cb(FolderView *folderview, guint action,
GtkWidget *widget)
{
@ -1975,6 +1974,7 @@ static void folderview_new_mbox_folder_cb(FolderView *folderview, guint action,
folder_write_list();
}
#endif
static void folderview_rename_folder_cb(FolderView *folderview, guint action,
GtkWidget *widget)
@ -2059,6 +2059,7 @@ static void folderview_rename_folder_cb(FolderView *folderview, guint action,
folder_write_list();
}
#if 0
static void folderview_rename_mbox_folder_cb(FolderView *folderview,
guint action,
GtkWidget *widget)
@ -2113,6 +2114,7 @@ static void folderview_rename_mbox_folder_cb(FolderView *folderview,
folder_write_list();
}
#endif
static void folderview_delete_folder_cb(FolderView *folderview, guint action,
GtkWidget *widget)
@ -2360,8 +2362,8 @@ static void folderview_new_news_group_cb(FolderView *folderview, guint action,
folderview->opened = NULL;
}
folder_item_remove(item);
gtk_ctree_remove_node(ctree, node);
folder_item_remove(item);
gnode = next;
}
@ -2429,7 +2431,6 @@ static void folderview_rm_news_group_cb(FolderView *folderview, guint action,
}
folder_item_remove(item);
gtk_ctree_remove_node(ctree, folderview->selected);
folder_write_list();
prefs_filtering_delete_path(name);
@ -2525,18 +2526,6 @@ static void folderview_recollapse_nodes(FolderView *folderview, GtkCTreeNode *no
g_slist_free(done);
}
static void folderview_recollapse_all_nodes(FolderView *folderview)
{
GSList *list = folderview->nodes_to_recollapse;
if (!list) return;
for (; list != NULL; list = g_slist_next(list))
if (list->data)
gtk_ctree_collapse(GTK_CTREE(folderview->ctree),
GTK_CTREE_NODE(list->data));
g_slist_free(folderview->nodes_to_recollapse);
folderview->nodes_to_recollapse = NULL;
}
static void folderview_move_to_cb(FolderView *folderview)
{
FolderItem *from_folder = NULL, *to_folder = NULL;
@ -2634,21 +2623,6 @@ static gint folderview_compare_name(gconstpointer a, gconstpointer b)
return strcmp2(g_basename(item->path), name);
}
static void folderview_scoring_cb(FolderView *folderview, guint action,
GtkWidget *widget)
{
GtkCTree *ctree = GTK_CTREE(folderview->ctree);
FolderItem *item;
if (!folderview->selected) return;
item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
g_return_if_fail(item != NULL);
g_return_if_fail(item->folder != NULL);
prefs_scoring_open(item);
}
static void folderview_processing_cb(FolderView *folderview, guint action,
GtkWidget *widget)
{
@ -2661,7 +2635,8 @@ static void folderview_processing_cb(FolderView *folderview, guint action,
g_return_if_fail(item != NULL);
g_return_if_fail(item->folder != NULL);
prefs_filtering_open(item, NULL, NULL);
prefs_filtering_open(&item->prefs->processing,
_("Processing configuration"), NULL, NULL);
}
void folderview_set_target_folder_color(gint color_op)
@ -2829,7 +2804,9 @@ static gboolean folderview_drag_motion_cb(GtkWidget *widget,
src_item && src_item != item) {
switch (FOLDER_TYPE(item->folder)) {
case F_MH:
#if 0
case F_MBOX:
#endif
case F_IMAP:
acceptable = TRUE;
break;

View file

@ -26,9 +26,9 @@ typedef struct _FolderView FolderView;
#include <gtk/gtkwidget.h>
#include <gtk/gtkctree.h>
#include "folder.h"
#include "mainwindow.h"
#include "summaryview.h"
#include "folder.h"
struct _FolderView
{
@ -37,12 +37,16 @@ struct _FolderView
GtkWidget *mail_popup;
GtkWidget *imap_popup;
GtkWidget *news_popup;
#if 0
GtkWidget *mbox_popup;
#endif
GtkItemFactory *mail_factory;
GtkItemFactory *imap_factory;
GtkItemFactory *news_factory;
#if 0
GtkItemFactory *mbox_factory;
#endif
GtkCTreeNode *selected;
GtkCTreeNode *opened;

View file

@ -1,6 +1,6 @@
/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
* Copyright (C) 1999-2002 Hiroyuki Yamamoto
* 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
@ -79,6 +79,9 @@ static gboolean grouplist_recv_func (SockInfo *sock,
gint read_bytes,
gpointer data);
static gint window_deleted (GtkWidget *widget,
GdkEventAny *event,
gpointer data);
static void ok_clicked (GtkWidget *widget,
gpointer data);
static void cancel_clicked (GtkWidget *widget,
@ -172,7 +175,7 @@ static void grouplist_dialog_create(void)
gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_window_set_title(GTK_WINDOW(dialog), _("Newsgroup subscription"));
g_signal_connect(G_OBJECT(dialog), "delete_event",
G_CALLBACK(cancel_clicked), NULL);
G_CALLBACK(window_deleted), NULL);
g_signal_connect(G_OBJECT(dialog), "key_press_event",
G_CALLBACK(key_pressed), NULL);
MANAGE_WINDOW_SIGNALS_CONNECT(dialog);
@ -484,6 +487,15 @@ static gboolean grouplist_recv_func(SockInfo *sock, gint count, gint read_bytes,
return TRUE;
}
static gint window_deleted(GtkWidget *widget, GdkEventAny *event, gpointer data)
{
ack = FALSE;
if (gtk_main_level() > 1)
gtk_main_quit();
return TRUE;
}
static void ok_clicked(GtkWidget *widget, gpointer data)
{
ack = TRUE;

View file

@ -10,16 +10,19 @@ libsylpheedgtk_la_SOURCES = \
description_window.c \
filesel.c \
gtkaspell.c \
gtkutils.c \
gtksctree.c \
gtkshruler.c \
gtksctree.c \
gtkutils.c \
gtkvscrollbutton.c \
logwindow.c \
manage_window.c \
menu.c \
pluginwindow.c \
prefswindow.c \
progressdialog.c \
sslcertwindow.c \
sylpheed-marshal.c \
gtkvscrollbutton.c
sylpheed-marshal.c
sylpheedgtkincludedir = $(pkgincludedir)/gtk
sylpheedgtkinclude_HEADERS = \
@ -29,16 +32,20 @@ sylpheedgtkinclude_HEADERS = \
description_window.h \
filesel.h \
gtkaspell.h \
gtkutils.h \
gtksctree.h \
gtkshruler.h \
gtksctree.h \
gtkutils.h \
gtkvscrollbutton.h \
logwindow.h \
manage_window.h \
menu.h \
pluginwindow.h \
prefswindow.h \
gtkvscrollbutton.h \
progressdialog.h \
sslcertwindow.h \
sylpheed-marshal.h \
gtkvscrollbutton.h
sylpheed-marshal.h
AM_CPPFLAGS = \
-I../common \

View file

@ -323,8 +323,6 @@ guint colorlabel_get_color_menu_active_item(GtkWidget *menu)
GtkWidget *menuitem;
guint color;
g_return_val_if_fail
(g_object_get_data(G_OBJECT(menu), "label_color_menu"), 0);
menuitem = gtk_menu_get_active(GTK_MENU(menu));
color = GPOINTER_TO_UINT
(g_object_get_data(G_OBJECT(menuitem), "color"));

View file

@ -27,7 +27,7 @@
#include <gtk/gtkwindow.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkscrolledwindow.h>
#include <gtk/gtktext.h>
#include <gtk/gtktextview.h>
#include <gtk/gtkstyle.h>
#include "intl.h"
@ -39,7 +39,7 @@
static void hide_cb (GtkWidget *widget,
LogWindow *logwin);
static void key_pressed (GtkWidget *widget,
static gboolean key_pressed (GtkWidget *widget,
GdkEventKey *event,
LogWindow *logwin);
static gboolean log_window_append (gpointer source,
@ -53,6 +53,8 @@ LogWindow *log_window_create(void)
GtkWidget *window;
GtkWidget *scrolledwin;
GtkWidget *text;
GtkTextBuffer *buffer;
GtkTextIter iter;
debug_print("Creating log window...\n");
logwin = g_new0(LogWindow, 1);
@ -61,13 +63,13 @@ LogWindow *log_window_create(void)
gtk_window_set_title(GTK_WINDOW(window), _("Protocol log"));
gtk_window_set_wmclass(GTK_WINDOW(window), "log_window", "Sylpheed");
gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
gtk_widget_set_usize(window, 520, 400);
gtk_signal_connect(GTK_OBJECT(window), "delete_event",
GTK_SIGNAL_FUNC(gtk_widget_hide_on_delete), NULL);
gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
GTK_SIGNAL_FUNC(key_pressed), logwin);
gtk_signal_connect(GTK_OBJECT(window), "hide",
GTK_SIGNAL_FUNC(hide_cb), logwin);
gtk_widget_set_size_request(window, 520, 400);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
g_signal_connect(G_OBJECT(window), "key_press_event",
G_CALLBACK(key_pressed), logwin);
g_signal_connect(G_OBJECT(window), "hide",
G_CALLBACK(hide_cb), logwin);
gtk_widget_realize(window);
scrolledwin = gtk_scrolled_window_new(NULL, NULL);
@ -76,13 +78,14 @@ LogWindow *log_window_create(void)
gtk_container_add(GTK_CONTAINER(window), scrolledwin);
gtk_widget_show(scrolledwin);
text = gtk_text_new(gtk_scrolled_window_get_hadjustment
(GTK_SCROLLED_WINDOW(scrolledwin)),
gtk_scrolled_window_get_vadjustment
(GTK_SCROLLED_WINDOW(scrolledwin)));
text = gtk_text_view_new();
gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
gtk_text_buffer_get_start_iter(buffer, &iter);
gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
gtk_container_add(GTK_CONTAINER(scrolledwin), text);
gtk_widget_show(text);
gtk_text_freeze(GTK_TEXT(text));
logwin->window = window;
logwin->scrolledwin = scrolledwin;
@ -94,6 +97,7 @@ LogWindow *log_window_create(void)
void log_window_init(LogWindow *logwin)
{
GtkTextBuffer *buffer;
GdkColormap *colormap;
GdkColor color[3] =
{{0, 0, 0xafff, 0}, {0, 0xefff, 0, 0}, {0, 0xefff, 0, 0}};
@ -120,17 +124,27 @@ void log_window_init(LogWindow *logwin)
break;
}
}
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(logwin->text));
gtk_text_buffer_create_tag(buffer, "message",
"foreground-gdk", &logwin->msg_color,
NULL);
gtk_text_buffer_create_tag(buffer, "warn",
"foreground-gdk", &logwin->warn_color,
NULL);
gtk_text_buffer_create_tag(buffer, "error",
"foreground-gdk", &logwin->error_color,
NULL);
}
void log_window_show(LogWindow *logwin)
{
GtkText *text = GTK_TEXT(logwin->text);
GtkTextView *text = GTK_TEXT_VIEW(logwin->text);
GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
GtkTextMark *mark;
gtk_widget_hide(logwin->window);
gtk_text_thaw(text);
text->vadj->value = text->vadj->upper - text->vadj->page_size;
gtk_signal_emit_by_name(GTK_OBJECT(text->vadj), "value_changed");
mark = gtk_text_buffer_get_mark(buffer, "end");
gtk_text_view_scroll_mark_onscreen(text, mark);
gtk_widget_show(logwin->window);
}
@ -147,9 +161,12 @@ static gboolean log_window_append(gpointer source, gpointer data)
{
LogText *logtext = (LogText *) source;
LogWindow *logwindow = (LogWindow *) data;
GtkText *text;
GtkTextView *text;
GtkTextBuffer *buffer;
GtkTextIter iter;
GdkColor *color = NULL;
gchar *head = NULL;
const gchar *tag;
g_return_val_if_fail(logtext != NULL, TRUE);
g_return_val_if_fail(logtext->text != NULL, TRUE);
@ -158,27 +175,40 @@ static gboolean log_window_append(gpointer source, gpointer data)
if (logwindow->clip && !logwindow->clip_length)
return FALSE;
text = GTK_TEXT(logwindow->text);
text = GTK_TEXT_VIEW(logwindow->text);
buffer = gtk_text_view_get_buffer(text);
gtk_text_buffer_get_iter_at_offset(buffer, &iter, -1);
switch (logtext->type) {
case LOG_MSG:
color = &logwindow->msg_color;
tag = "message";
head = "* ";
break;
case LOG_WARN:
color = &logwindow->warn_color;
tag = "warn";
head = "** ";
break;
case LOG_ERROR:
color = &logwindow->error_color;
tag = "error";
head = "*** ";
break;
default:
tag = NULL;
break;
}
if (head)
gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, head, -1,
tag, NULL);
gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, logtext->text, -1,
tag, NULL);
gtk_text_buffer_get_start_iter(buffer, &iter);
gtk_text_buffer_place_cursor(buffer, &iter);
if (head) gtk_text_insert(text, NULL, color, NULL, head, -1);
gtk_text_insert(text, NULL, color, NULL, logtext->text, -1);
if (logwindow->clip)
log_window_clip (GTK_WIDGET (text), logwindow->clip_length);
@ -187,46 +217,35 @@ static gboolean log_window_append(gpointer source, gpointer data)
static void hide_cb(GtkWidget *widget, LogWindow *logwin)
{
if (GTK_TEXT(logwin->text)->freeze_count == 0)
gtk_text_freeze(GTK_TEXT(logwin->text));
}
static void key_pressed(GtkWidget *widget, GdkEventKey *event,
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
LogWindow *logwin)
{
if (event && event->keyval == GDK_Escape)
gtk_widget_hide(logwin->window);
return FALSE;
}
static void log_window_clip(GtkWidget *textw, guint clip_length)
{
guint length;
guint point;
gboolean was_frozen = FALSE;
GtkText *text = GTK_TEXT(textw);
GtkTextView *textview = GTK_TEXT_VIEW(textw);
GtkTextBuffer *textbuf = gtk_text_view_get_buffer(textview);
GtkTextIter start_iter, end_iter;
length = gtk_text_get_length (text);
length = gtk_text_buffer_get_char_count (textbuf);
debug_print("Log window length: %u\n", length);
if (length > clip_length) {
/* find the end of the first line after the cut off
* point */
point = length - clip_length;
while (point < length && GTK_TEXT_INDEX(text, point) != '\n')
point++;
/* erase the text */
if (text->freeze_count) {
was_frozen = TRUE;
gtk_text_thaw(text);
}
gtk_text_set_point (text, 0);
gtk_text_freeze(text);
if (!gtk_text_forward_delete (text, point + 1))
debug_print("Error clearing log\n");
gtk_text_thaw(text);
gtk_text_set_point(text,
gtk_text_get_length (GTK_TEXT (text)));
if (was_frozen)
gtk_text_freeze(text);
gtk_text_buffer_get_iter_at_offset(textbuf, &end_iter, point);
if (!gtk_text_iter_forward_to_line_end(&end_iter))
return;
gtk_text_buffer_get_start_iter(textbuf, &start_iter);
gtk_text_buffer_delete(textbuf, &start_iter, &end_iter);
}
}

View file

@ -83,7 +83,6 @@ static gboolean ctree_select_row(GtkCTree *ctree, GList *node, gint column, gpoi
if (!page->page_open) {
page->create_widget(page, GTK_WINDOW(prefswindow->window), prefswindow->data);
gtk_widget_show_all(page->widget);
gtk_container_add(GTK_CONTAINER(prefswindow->notebook), page->widget);
page->page_open = TRUE;
}

View file

@ -55,7 +55,7 @@ ProgressDialog *progress_dialog_create(void)
debug_print("Creating progress dialog...\n");
progress = g_new0(ProgressDialog, 1);
window = gtk_window_new(GTK_WINDOW_DIALOG);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize(window, 460, -1);
gtk_container_set_border_width(GTK_CONTAINER(window), 8);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

View file

@ -46,8 +46,6 @@
#include "gtkutils.h"
#include "utils.h"
PangoFontDescription *boldfont;
#define TR(str) (prefs_common.trans_hdr ? gettext(str) : str)
#if 0
@ -133,6 +131,8 @@ HeaderView *headerview_create(void)
void headerview_init(HeaderView *headerview)
{
static PangoFontDescription *boldfont = NULL;
if (!boldfont && BOLD_FONT)
boldfont = pango_font_description_from_string
(BOLD_FONT);

View file

@ -551,37 +551,39 @@ static HTMLTag *html_get_tag(const gchar *str)
while (isspace(*tmpp)) tmpp++;
attr_name = tmpp;
if ((p = strchr(attr_name, '=')) == NULL) {
g_warning("html_get_tag(): syntax error in tag: '%s'\n", str);
return tag;
}
tmpp = p;
*tmpp++ = '\0';
while (isspace(*tmpp)) tmpp++;
if (*tmpp == '\0') {
g_warning("html_get_tag(): syntax error in tag: '%s'\n", str);
return tag;
} else if (*tmpp == '"' || *tmpp == '\'') {
/* name="value" */
quote = *tmpp;
tmpp++;
attr_value = tmpp;
if ((p = strchr(attr_value, quote)) == NULL) {
g_warning("html_get_tag(): syntax error in tag: '%s'\n", str);
return tag;
}
tmpp = p;
while (*tmpp != '\0' && !isspace(*tmpp) && *tmpp != '=') tmpp++;
if (*tmpp != '\0' && *tmpp != '=') {
*tmpp++ = '\0';
while (isspace(*tmpp)) tmpp++;
} else {
/* name=value */
attr_value = tmpp;
while (*tmpp != '\0' && !isspace(*tmpp)) tmpp++;
if (*tmpp != '\0')
*tmpp++ = '\0';
}
if (*tmpp == '=') {
*tmpp++ = '\0';
while (isspace(*tmpp)) tmpp++;
if (*tmpp == '"' || *tmpp == '\'') {
/* name="value" */
quote = *tmpp;
tmpp++;
attr_value = tmpp;
if ((p = strchr(attr_value, quote)) == NULL) {
g_warning("html_get_tag(): syntax error in tag: '%s'\n", str);
return tag;
}
tmpp = p;
*tmpp++ = '\0';
while (isspace(*tmpp)) tmpp++;
} else {
/* name=value */
attr_value = tmpp;
while (*tmpp != '\0' && !isspace(*tmpp)) tmpp++;
if (*tmpp != '\0')
*tmpp++ = '\0';
}
} else
attr_value = "";
g_strchomp(attr_name);
g_strdown(attr_name);
attr = g_new(HTMLAttr, 1);

View file

@ -52,8 +52,11 @@
#include "md5.h"
#include "base64.h"
#include "utils.h"
#include "prefs_common.h"
#include "inputdialog.h"
#include "log.h"
#include "remotefolder.h"
#include "alertpanel.h"
typedef struct _IMAPFolder IMAPFolder;
typedef struct _IMAPSession IMAPSession;
@ -63,6 +66,7 @@ typedef struct _IMAPFolderItem IMAPFolderItem;
#include "prefs_account.h"
#define IMAP_FOLDER(obj) ((IMAPFolder *)obj)
#define IMAP_FOLDER_ITEM(obj) ((IMAPFolderItem *)obj)
#define IMAP_SESSION(obj) ((IMAPSession *)obj)
struct _IMAPFolder
@ -158,51 +162,65 @@ struct _IMAPFolderItem
GSList *uid_list;
};
static Folder *imap_folder_new(const gchar * name, const gchar * path);
static void imap_folder_destroy(Folder * folder);
static IMAPSession *imap_session_new(const PrefsAccount * account);
static void imap_session_authenticate(IMAPSession * session,
const PrefsAccount * account);
static void imap_session_destroy(Session * session);
static gchar *imap_fetch_msg(Folder * folder, FolderItem * item, gint uid);
static gint imap_add_msg(Folder * folder,
FolderItem * dest,
const gchar * file, MsgFlags * flags);
static gint imap_add_msgs(Folder * folder, FolderItem * dest,
GSList * file_list,
GRelation *relation);
static gint imap_copy_msg(Folder * folder,
FolderItem * dest, MsgInfo * msginfo);
static gint imap_copy_msgs(Folder *folder, FolderItem *dest,
MsgInfoList *msglist, GRelation *relation);
static gint imap_remove_msg(Folder * folder, FolderItem * item, gint uid);
static gint imap_remove_all_msg(Folder * folder, FolderItem * item);
static gboolean imap_is_msg_changed(Folder * folder,
FolderItem * item, MsgInfo * msginfo);
static gint imap_close(Folder * folder, FolderItem * item);
static void imap_scan_tree(Folder * folder);
static gint imap_create_tree(Folder * folder);
static FolderItem *imap_create_folder(Folder * folder,
FolderItem * parent,
const gchar * name);
static gint imap_rename_folder(Folder * folder,
FolderItem * item, const gchar * name);
static gint imap_remove_folder(Folder * folder, FolderItem * item);
static void imap_folder_init (Folder *folder,
const gchar *name,
const gchar *path);
static Folder *imap_folder_new (const gchar *name,
const gchar *path);
static void imap_folder_destroy (Folder *folder);
static IMAPSession *imap_session_new (const PrefsAccount *account);
static void imap_session_authenticate(IMAPSession *session,
const PrefsAccount *account);
static void imap_session_destroy (Session *session);
static gchar *imap_fetch_msg (Folder *folder,
FolderItem *item,
gint uid);
static gint imap_add_msg (Folder *folder,
FolderItem *dest,
const gchar *file,
MsgFlags *flags);
static gint imap_add_msgs (Folder *folder,
FolderItem *dest,
GSList *file_list,
GRelation *relation);
static gint imap_copy_msg (Folder *folder,
FolderItem *dest,
MsgInfo *msginfo);
static gint imap_copy_msgs (Folder *folder,
FolderItem *dest,
MsgInfoList *msglist,
GRelation *relation);
static gint imap_remove_msg (Folder *folder,
FolderItem *item,
gint uid);
static gint imap_remove_all_msg (Folder *folder,
FolderItem *item);
static gboolean imap_is_msg_changed (Folder *folder,
FolderItem *item,
MsgInfo *msginfo);
static gint imap_close (Folder *folder,
FolderItem *item);
static gint imap_scan_tree (Folder *folder);
static gint imap_create_tree (Folder *folder);
static FolderItem *imap_create_folder (Folder *folder,
FolderItem *parent,
const gchar *name);
static gint imap_rename_folder (Folder *folder,
FolderItem *item,
const gchar *name);
static gint imap_remove_folder (Folder *folder,
FolderItem *item);
static FolderItem *imap_folder_item_new (Folder *folder);
static void imap_folder_item_destroy (Folder *folder,
FolderItem *item);
@ -222,7 +240,7 @@ static GSList *imap_parse_list (IMAPFolder *folder,
const gchar *real_path,
gchar *separator);
static void imap_create_missing_folders (Folder *folder);
static void imap_create_missing_folders (Folder *folder);
static FolderItem *imap_create_special_folder
(Folder *folder,
SpecialFolderItemType stype,
@ -311,32 +329,32 @@ static gint imap_cmd_authenticate
const gchar *user,
const gchar *pass,
IMAPAuthType type);
static gint imap_cmd_login (IMAPSession *sock,
static gint imap_cmd_login (IMAPSession *session,
const gchar *user,
const gchar *pass);
static gint imap_cmd_logout (IMAPSession *sock);
static gint imap_cmd_noop (IMAPSession *sock);
static gint imap_cmd_starttls (IMAPSession *sock);
static gint imap_cmd_namespace (IMAPSession *sock,
static gint imap_cmd_logout (IMAPSession *session);
static gint imap_cmd_noop (IMAPSession *session);
static gint imap_cmd_starttls (IMAPSession *session);
static gint imap_cmd_namespace (IMAPSession *session,
gchar **ns_str);
static gint imap_cmd_list (IMAPSession *session,
const gchar *ref,
const gchar *mailbox,
GPtrArray *argbuf);
static gint imap_cmd_do_select (IMAPSession *sock,
static gint imap_cmd_do_select (IMAPSession *session,
const gchar *folder,
gboolean examine,
gint *exists,
gint *recent,
gint *unseen,
guint32 *uid_validity);
static gint imap_cmd_select (IMAPSession *sock,
static gint imap_cmd_select (IMAPSession *session,
const gchar *folder,
gint *exists,
gint *recent,
gint *unseen,
guint32 *uid_validity);
static gint imap_cmd_examine (IMAPSession *sock,
static gint imap_cmd_examine (IMAPSession *session,
const gchar *folder,
gint *exists,
gint *recent,
@ -347,9 +365,9 @@ static gint imap_cmd_create (IMAPSession *sock,
static gint imap_cmd_rename (IMAPSession *sock,
const gchar *oldfolder,
const gchar *newfolder);
static gint imap_cmd_delete (IMAPSession *sock,
static gint imap_cmd_delete (IMAPSession *session,
const gchar *folder);
static gint imap_cmd_envelope (IMAPSession *sock,
static gint imap_cmd_envelope (IMAPSession *session,
IMAPSet set);
static gint imap_cmd_fetch (IMAPSession *sock,
guint32 uid,
@ -363,17 +381,18 @@ static gint imap_cmd_copy (IMAPSession *session,
const gchar *seq_set,
const gchar *destfolder,
GRelation *uid_mapping);
static gint imap_cmd_store (IMAPSession *sock,
static gint imap_cmd_store (IMAPSession *session,
IMAPSet set,
gchar *sub_cmd);
static gint imap_cmd_expunge (IMAPSession *sock);
static gint imap_cmd_close (IMAPSession *session);
static gint imap_cmd_expunge (IMAPSession *session,
IMAPSet seq_set);
static gint imap_cmd_close (IMAPSession *session);
static gint imap_cmd_ok (IMAPSession *session,
GPtrArray *argbuf);
static void imap_gen_send (IMAPSession *sock,
static void imap_gen_send (IMAPSession *session,
const gchar *format, ...);
static gint imap_gen_recv (IMAPSession *sock,
static gint imap_gen_recv (IMAPSession *session,
gchar **ret);
/* misc utility functions */
@ -421,7 +440,7 @@ static gchar *imap_folder_get_path (Folder *folder);
static gchar *imap_item_get_path (Folder *folder,
FolderItem *item);
FolderClass imap_class =
static FolderClass imap_class =
{
F_IMAP,
"imap",
@ -430,12 +449,16 @@ FolderClass imap_class =
/* Folder functions */
imap_folder_new,
imap_folder_destroy,
NULL,
NULL,
imap_scan_tree,
imap_create_tree,
/* FolderItem functions */
imap_folder_item_new,
imap_folder_item_destroy,
NULL,
NULL,
imap_item_get_path,
imap_create_folder,
imap_rename_folder,
@ -466,7 +489,7 @@ FolderClass *imap_get_class(void)
return &imap_class;
}
Folder *imap_folder_new(const gchar *name, const gchar *path)
static Folder *imap_folder_new(const gchar *name, const gchar *path)
{
Folder *folder;
@ -477,7 +500,7 @@ Folder *imap_folder_new(const gchar *name, const gchar *path)
return folder;
}
void imap_folder_destroy(Folder *folder)
static void imap_folder_destroy(Folder *folder)
{
gchar *dir;
@ -595,6 +618,9 @@ static IMAPSession *imap_session_get(Folder *folder)
g_return_val_if_fail(folder != NULL, NULL);
g_return_val_if_fail(FOLDER_CLASS(folder) == &imap_class, NULL);
g_return_val_if_fail(folder->account != NULL, NULL);
if (prefs_common.work_offline)
return NULL;
/* Make sure we have a session */
if (rfolder->session != NULL) {
@ -666,7 +692,7 @@ static IMAPSession *imap_session_get(Folder *folder)
return IMAP_SESSION(session);
}
IMAPSession *imap_session_new(const PrefsAccount *account)
static IMAPSession *imap_session_new(const PrefsAccount *account)
{
IMAPSession *session;
SockInfo *imap_sock;
@ -741,7 +767,8 @@ IMAPSession *imap_session_new(const PrefsAccount *account)
session_destroy(SESSION(session));
return NULL;
}
if (!ssl_init_socket_with_method(SESSION(session)->sock, SSL_METHOD_TLSv1)) {
if (!ssl_init_socket_with_method(SESSION(session)->sock,
SSL_METHOD_TLSv1)) {
session_destroy(SESSION(session));
return NULL;
}
@ -763,7 +790,8 @@ IMAPSession *imap_session_new(const PrefsAccount *account)
return session;
}
void imap_session_authenticate(IMAPSession *session, const PrefsAccount *account)
static void imap_session_authenticate(IMAPSession *session,
const PrefsAccount *account)
{
gchar *pass;
@ -787,7 +815,7 @@ void imap_session_authenticate(IMAPSession *session, const PrefsAccount *account
session->authenticated = TRUE;
}
void imap_session_destroy(Session *session)
static void imap_session_destroy(Session *session)
{
imap_free_capabilities(IMAP_SESSION(session));
g_free(IMAP_SESSION(session)->mbox);
@ -795,7 +823,7 @@ void imap_session_destroy(Session *session)
session->sock = NULL;
}
gchar *imap_fetch_msg(Folder *folder, FolderItem *item, gint uid)
static gchar *imap_fetch_msg(Folder *folder, FolderItem *item, gint uid)
{
gchar *path, *filename;
IMAPSession *session;
@ -809,7 +837,7 @@ gchar *imap_fetch_msg(Folder *folder, FolderItem *item, gint uid)
make_dir_hier(path);
filename = g_strconcat(path, G_DIR_SEPARATOR_S, itos(uid), NULL);
g_free(path);
if (is_file_exist(filename)) {
debug_print("message %d has been already cached.\n", uid);
return filename;
@ -841,7 +869,8 @@ gchar *imap_fetch_msg(Folder *folder, FolderItem *item, gint uid)
return filename;
}
gint imap_add_msg(Folder *folder, FolderItem *dest, const gchar *file, MsgFlags *flags)
static gint imap_add_msg(Folder *folder, FolderItem *dest,
const gchar *file, MsgFlags *flags)
{
gint ret;
GSList file_list;
@ -859,7 +888,7 @@ gint imap_add_msg(Folder *folder, FolderItem *dest, const gchar *file, MsgFlags
return ret;
}
gint imap_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
static gint imap_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
GRelation *relation)
{
gchar *destdir;
@ -976,7 +1005,7 @@ static gint imap_do_copy_msgs(Folder *folder, FolderItem *dest,
for (cur = msglist; cur != NULL; cur = g_slist_next(cur)) {
MsgInfo *msginfo = (MsgInfo *)cur->data;
GTuples *tuples;
tuples = g_relation_select(uid_mapping,
GINT_TO_POINTER(msginfo->msgnum),
0);
@ -991,7 +1020,8 @@ static gint imap_do_copy_msgs(Folder *folder, FolderItem *dest,
GPOINTER_TO_INT(0));
g_tuples_destroy(tuples);
}
g_relation_destroy(uid_mapping);
imap_seq_set_free(seq_list);
g_free(destdir);
@ -1002,7 +1032,7 @@ static gint imap_do_copy_msgs(Folder *folder, FolderItem *dest,
return -1;
}
gint imap_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
static gint imap_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
{
GSList msglist;
@ -1014,7 +1044,7 @@ gint imap_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
return imap_copy_msgs(folder, dest, &msglist, NULL);
}
gint imap_copy_msgs(Folder *folder, FolderItem *dest,
static gint imap_copy_msgs(Folder *folder, FolderItem *dest,
MsgInfoList *msglist, GRelation *relation)
{
MsgInfo *msginfo;
@ -1041,7 +1071,7 @@ gint imap_copy_msgs(Folder *folder, FolderItem *dest,
return ret;
}
gint imap_remove_msg(Folder *folder, FolderItem *item, gint uid)
static gint imap_remove_msg(Folder *folder, FolderItem *item, gint uid)
{
gint ok;
IMAPSession *session;
@ -1071,12 +1101,22 @@ gint imap_remove_msg(Folder *folder, FolderItem *item, gint uid)
return ok;
}
ok = imap_cmd_expunge(session);
if (!session->uidplus) {
ok = imap_cmd_expunge(session, NULL);
} else {
gchar *uidstr;
uidstr = g_strdup_printf("%u", uid);
ok = imap_cmd_expunge(session, uidstr);
g_free(uidstr);
}
if (ok != IMAP_SUCCESS) {
log_warning(_("can't expunge\n"));
return ok;
}
IMAP_FOLDER_ITEM(item)->uid_list = g_slist_remove(
IMAP_FOLDER_ITEM(item)->uid_list, numlist.data);
dir = folder_item_get_path(item);
if (is_dir_exist(dir))
remove_numbered_files(dir, uid, uid);
@ -1085,7 +1125,7 @@ gint imap_remove_msg(Folder *folder, FolderItem *item, gint uid)
return IMAP_SUCCESS;
}
gint imap_remove_all_msg(Folder *folder, FolderItem *item)
static gint imap_remove_all_msg(Folder *folder, FolderItem *item)
{
gint ok;
IMAPSession *session;
@ -1109,7 +1149,7 @@ gint imap_remove_all_msg(Folder *folder, FolderItem *item)
return ok;
}
ok = imap_cmd_expunge(session);
ok = imap_cmd_expunge(session, NULL);
if (ok != IMAP_SUCCESS) {
log_warning(_("can't expunge\n"));
return ok;
@ -1123,13 +1163,14 @@ gint imap_remove_all_msg(Folder *folder, FolderItem *item)
return IMAP_SUCCESS;
}
gboolean imap_is_msg_changed(Folder *folder, FolderItem *item, MsgInfo *msginfo)
static gboolean imap_is_msg_changed(Folder *folder, FolderItem *item,
MsgInfo *msginfo)
{
/* TODO: properly implement this method */
return FALSE;
}
gint imap_close(Folder *folder, FolderItem *item)
static gint imap_close(Folder *folder, FolderItem *item)
{
gint ok;
IMAPSession *session;
@ -1142,8 +1183,7 @@ gint imap_close(Folder *folder, FolderItem *item)
if (!session) return -1;
if (session->mbox) {
if (strcmp(item->path, session->mbox))
return -1;
if (strcmp2(session->mbox, item->path) != 0) return -1;
ok = imap_cmd_close(session);
if (ok != IMAP_SUCCESS)
@ -1158,14 +1198,14 @@ gint imap_close(Folder *folder, FolderItem *item)
return 0;
}
void imap_scan_tree(Folder *folder)
static gint imap_scan_tree(Folder *folder)
{
FolderItem *item = NULL;
IMAPSession *session;
gchar *root_folder = NULL;
g_return_if_fail(folder != NULL);
g_return_if_fail(folder->account != NULL);
g_return_val_if_fail(folder != NULL, -1);
g_return_val_if_fail(folder->account != NULL, -1);
session = imap_session_get(folder);
if (!session) {
@ -1175,13 +1215,37 @@ void imap_scan_tree(Folder *folder)
item->folder = folder;
folder->node = item->node = g_node_new(item);
}
return;
return -1;
}
if (folder->account->imap_dir && *folder->account->imap_dir) {
Xstrdup_a(root_folder, folder->account->imap_dir, return);
gchar *real_path;
GPtrArray *argbuf;
gint ok;
Xstrdup_a(root_folder, folder->account->imap_dir, return -1);
extract_quote(root_folder, '"');
subst_char(root_folder,
imap_get_path_separator(IMAP_FOLDER(folder),
root_folder),
'/');
strtailchomp(root_folder, '/');
debug_print("IMAP root directory: %s\n", root_folder);
real_path = imap_get_real_path
(IMAP_FOLDER(folder), root_folder);
debug_print("IMAP root directory: %s\n", real_path);
/* check if root directory exist */
argbuf = g_ptr_array_new();
ok = imap_cmd_list(session, NULL, real_path, argbuf);
if (ok != IMAP_SUCCESS ||
search_array_str(argbuf, "LIST ") == NULL) {
log_warning(_("root folder %s does not exist\n"), real_path);
g_ptr_array_free(argbuf, TRUE);
g_free(real_path);
return -1;
}
g_ptr_array_free(argbuf, TRUE);
g_free(real_path);
}
if (folder->node)
@ -1196,6 +1260,8 @@ void imap_scan_tree(Folder *folder)
imap_scan_tree_recursive(session, FOLDER_ITEM(folder->node->data));
imap_create_missing_folders(folder);
return 0;
}
static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item)
@ -1352,6 +1418,10 @@ static GSList *imap_parse_list(IMAPFolder *folder, IMAPSession *session,
strretchomp(buf);
if (buf[0] != '*' || buf[1] != ' ') {
log_print("IMAP4< %s\n", buf);
if (sscanf(buf, "%*d %16s", buf) < 1 ||
strcmp(buf, "OK") != 0)
log_warning(_("error occurred while getting LIST.\n"));
break;
}
debug_print("IMAP4< %s\n", buf);
@ -1412,7 +1482,7 @@ static GSList *imap_parse_list(IMAPFolder *folder, IMAPSession *session,
return item_list;
}
gint imap_create_tree(Folder *folder)
static gint imap_create_tree(Folder *folder)
{
g_return_val_if_fail(folder != NULL, -1);
g_return_val_if_fail(folder->node != NULL, -1);
@ -1525,7 +1595,7 @@ static gchar *imap_item_get_path(Folder *folder, FolderItem *item)
return path;
}
FolderItem *imap_create_folder(Folder *folder, FolderItem *parent,
static FolderItem *imap_create_folder(Folder *folder, FolderItem *parent,
const gchar *name)
{
gchar *dirpath, *imap_path;
@ -1621,7 +1691,8 @@ FolderItem *imap_create_folder(Folder *folder, FolderItem *parent,
return new_item;
}
gint imap_rename_folder(Folder *folder, FolderItem *item, const gchar *name)
static gint imap_rename_folder(Folder *folder, FolderItem *item,
const gchar *name)
{
gchar *dirpath;
gchar *newpath;
@ -1703,7 +1774,7 @@ gint imap_rename_folder(Folder *folder, FolderItem *item, const gchar *name)
return 0;
}
gint imap_remove_folder(Folder *folder, FolderItem *item)
static gint imap_remove_folder(Folder *folder, FolderItem *item)
{
gint ok;
IMAPSession *session;
@ -2027,14 +2098,15 @@ static IMAPNameSpace *imap_find_namespace_from_list(GList *ns_list,
if (!path) path = "";
Xstrcat_a(tmp_path, path, "/", return NULL);
for (; ns_list != NULL; ns_list = ns_list->next) {
IMAPNameSpace *tmp_ns = ns_list->data;
Xstrcat_a(tmp_path, path, "/", return namespace);
Xstrdup_a(name, tmp_ns->name, return namespace);
if (tmp_ns->separator && tmp_ns->separator != '/')
if (tmp_ns->separator && tmp_ns->separator != '/') {
subst_char(tmp_path, tmp_ns->separator, '/');
subst_char(name, tmp_ns->separator, '/');
}
if (strncmp(tmp_path, name, strlen(name)) == 0)
namespace = tmp_ns;
}
@ -2124,7 +2196,7 @@ static gchar *imap_parse_atom(SockInfo *sock, gchar *src,
cur_pos = strchr_cpy(cur_pos + 1, '}', buf, sizeof(buf));
len = atoi(buf);
g_return_val_if_fail(len > 0, cur_pos);
g_return_val_if_fail(len >= 0, cur_pos);
g_string_truncate(str, 0);
cur_pos = str->str;
@ -2167,7 +2239,7 @@ static gchar *imap_get_header(SockInfo *sock, gchar *cur_pos, gchar **headers,
cur_pos = strchr_cpy(cur_pos + 1, '}', buf, sizeof(buf));
len = atoi(buf);
g_return_val_if_fail(len > 0, cur_pos);
g_return_val_if_fail(len >= 0, cur_pos);
g_string_truncate(str, 0);
cur_pos = str->str;
@ -2426,24 +2498,22 @@ static gint imap_status(IMAPSession *session, IMAPFolder *folder,
gchar *real_path;
gchar *real_path_;
gint ok;
GPtrArray *argbuf;
GPtrArray *argbuf = NULL;
gchar *str;
*messages = *recent = *uid_next = *uid_validity = *unseen = 0;
if (path == NULL)
return -1;
argbuf = g_ptr_array_new();
if (messages && recent && uid_next && uid_validity && unseen) {
*messages = *recent = *uid_next = *uid_validity = *unseen = 0;
argbuf = g_ptr_array_new();
}
real_path = imap_get_real_path(folder, path);
QUOTE_IF_REQUIRED(real_path_, real_path);
imap_gen_send(session, "STATUS %s "
"(MESSAGES RECENT UIDNEXT UIDVALIDITY UNSEEN)",
real_path_);
"(MESSAGES RECENT UIDNEXT UIDVALIDITY UNSEEN)",
real_path_);
ok = imap_cmd_ok(session, argbuf);
if (ok != IMAP_SUCCESS) THROW(ok);
if (ok != IMAP_SUCCESS || !argbuf) THROW(ok);
str = search_array_str(argbuf, "STATUS");
if (!str) THROW(IMAP_ERROR);
@ -2477,8 +2547,10 @@ static gint imap_status(IMAPSession *session, IMAPFolder *folder,
catch:
g_free(real_path);
ptr_array_free_strings(argbuf);
g_ptr_array_free(argbuf, TRUE);
if (argbuf) {
ptr_array_free_strings(argbuf);
g_ptr_array_free(argbuf, TRUE);
}
return ok;
}
@ -2497,7 +2569,7 @@ static gboolean imap_has_capability(IMAPSession *session, const gchar *cap)
return FALSE;
}
void imap_free_capabilities(IMAPSession *session)
static void imap_free_capabilities(IMAPSession *session)
{
g_strfreev(session->capability);
session->capability = NULL;
@ -2743,7 +2815,8 @@ static gint imap_cmd_delete(IMAPSession *session, const gchar *folder)
return imap_cmd_ok(session, NULL);
}
static gint imap_cmd_search(IMAPSession *session, const gchar *criteria, GSList **list)
static gint imap_cmd_search(IMAPSession *session, const gchar *criteria,
GSList **list)
{
gint ok;
gchar *uidlist;
@ -2782,7 +2855,8 @@ static gint imap_cmd_search(IMAPSession *session, const gchar *criteria, GSList
return IMAP_SUCCESS;
}
static gint imap_cmd_fetch(IMAPSession *session, guint32 uid, const gchar *filename)
static gint imap_cmd_fetch(IMAPSession *session, guint32 uid,
const gchar *filename)
{
gint ok;
gchar *buf = NULL;
@ -2818,7 +2892,7 @@ static gint imap_cmd_fetch(IMAPSession *session, guint32 uid, const gchar *filen
cur_pos = strchr_cpy(cur_pos + 1, '}', size_str, sizeof(size_str));
RETURN_ERROR_IF_FAIL(cur_pos != NULL);
size_num = atol(size_str);
RETURN_ERROR_IF_FAIL(size_num > 0);
RETURN_ERROR_IF_FAIL(size_num >= 0);
RETURN_ERROR_IF_FAIL(*cur_pos == '\0');
@ -2826,7 +2900,8 @@ static gint imap_cmd_fetch(IMAPSession *session, guint32 uid, const gchar *filen
g_free(buf);
if (recv_bytes_write_to_file(SESSION(session)->sock, size_num, filename) != 0)
if (recv_bytes_write_to_file(SESSION(session)->sock,
size_num, filename) != 0)
return IMAP_ERROR;
if (imap_gen_recv(session, &buf) != IMAP_SUCCESS) {
@ -2846,7 +2921,8 @@ static gint imap_cmd_fetch(IMAPSession *session, guint32 uid, const gchar *filen
}
static gint imap_cmd_append(IMAPSession *session, const gchar *destfolder,
const gchar *file, IMAPFlags flags, guint32 *new_uid)
const gchar *file, IMAPFlags flags,
guint32 *new_uid)
{
gint ok;
gint size;
@ -2908,10 +2984,7 @@ static gint imap_cmd_append(IMAPSession *session, const gchar *destfolder,
argbuf = g_ptr_array_new();
ok = imap_cmd_ok(session, argbuf);
if (ok != IMAP_SUCCESS)
log_warning(_("can't append message to %s\n"),
destfolder_);
else if (argbuf->len > 0) {
if ((ok == IMAP_SUCCESS) && (argbuf->len > 0)) {
resp_str = g_ptr_array_index(argbuf, argbuf->len - 1);
if (resp_str &&
sscanf(resp_str, "%*u OK [APPENDUID %*u %u]",
@ -2925,15 +2998,41 @@ static gint imap_cmd_append(IMAPSession *session, const gchar *destfolder,
} else
ok = imap_cmd_ok(session, NULL);
if (ok != IMAP_SUCCESS)
log_warning(_("can't append message to %s\n"),
destfolder_);
return ok;
}
static MsgNumberList *imapset_to_numlist(IMAPSet imapset)
{
gchar **ranges, **range;
guint32 low, high;
MsgNumberList *uids = NULL;
ranges = g_strsplit(imapset, ",", 0);
for (range = ranges; *range != NULL; range++) {
printf("%s\n", *range);
if(sscanf(*range, "%u:%u", &low, &high) == 1)
uids = g_slist_prepend(uids, GINT_TO_POINTER(low));
else {
int i;
for (i = low; i <= high; i++)
uids = g_slist_prepend(uids, GINT_TO_POINTER(i));
}
}
uids = g_slist_reverse(uids);
g_strfreev(ranges);
return uids;
}
static gint imap_cmd_copy(IMAPSession *session, const gchar *seq_set,
const gchar *destfolder, GRelation *uid_mapping)
{
gint ok;
gchar *destfolder_;
GPtrArray *reply;
g_return_val_if_fail(session != NULL, IMAP_ERROR);
g_return_val_if_fail(seq_set != NULL, IMAP_ERROR);
@ -2942,25 +3041,48 @@ static gint imap_cmd_copy(IMAPSession *session, const gchar *seq_set,
QUOTE_IF_REQUIRED(destfolder_, destfolder);
imap_gen_send(session, "UID COPY %s %s", seq_set, destfolder_);
reply = g_ptr_array_new();
if (uid_mapping != NULL && session->uidplus) {
GPtrArray *reply;
gchar *resp_str = NULL, *olduids_str, *newuids_str;
MsgNumberList *olduids, *old_cur, *newuids, *new_cur;
reply = g_ptr_array_new();
ok = imap_cmd_ok(session, reply);
if ((ok == IMAP_SUCCESS) && (reply->len > 0)) {
resp_str = g_ptr_array_index(reply, reply->len - 1);
if (resp_str) {
olduids_str = g_new0(gchar, strlen(resp_str));
newuids_str = g_new0(gchar, strlen(resp_str));
if (sscanf(resp_str, "%*s OK [COPYUID %*u %[0-9,:] %[0-9,:]]",
olduids_str, newuids_str) == 2) {
olduids = imapset_to_numlist(olduids_str);
newuids = imapset_to_numlist(newuids_str);
old_cur = olduids;
new_cur = newuids;
while(old_cur != NULL && new_cur != NULL) {
g_relation_insert(uid_mapping,
GPOINTER_TO_INT(old_cur->data),
GPOINTER_TO_INT(new_cur->data));
old_cur = g_slist_next(old_cur);
new_cur = g_slist_next(new_cur);
}
g_slist_free(olduids);
g_slist_free(newuids);
}
g_free(olduids_str);
g_free(newuids_str);
}
}
ptr_array_free_strings(reply);
g_ptr_array_free(reply, TRUE);
} else
ok = imap_cmd_ok(session, NULL);
ok = imap_cmd_ok(session, reply);
if (ok != IMAP_SUCCESS)
log_warning(_("can't copy %s to %s\n"), seq_set, destfolder_);
/*
TODO: UIDPLUS
- split IMAPSets into uids
- g_relation_insert(uid_mapping, olduid, newuid);
else if (imap_has_capability(session, "UIDPLUS") && reply->len > 0)
if ((okmsginfo = g_ptr_array_index(reply, reply->len - 1)) != NULL &&
sscanf(okmsginfo, "%*u OK [COPYUID %*u %u %u]", &olduid, &newuid) == 2 &&
olduid == msgnum)
*new_uid = newuid;
*/
ptr_array_free_strings(reply);
g_ptr_array_free(reply, TRUE);
return ok;
}
@ -3017,11 +3139,14 @@ static gint imap_cmd_store(IMAPSession *session, IMAPSet seq_set,
return IMAP_SUCCESS;
}
static gint imap_cmd_expunge(IMAPSession *session)
static gint imap_cmd_expunge(IMAPSession *session, IMAPSet seq_set)
{
gint ok;
imap_gen_send(session, "EXPUNGE");
if (seq_set && session->uidplus)
imap_gen_send(session, "UID EXPUNGE %s", seq_set);
else
imap_gen_send(session, "EXPUNGE");
if ((ok = imap_cmd_ok(session, NULL)) != IMAP_SUCCESS) {
log_warning(_("error while imap command: EXPUNGE\n"));
return ok;

View file

@ -25,7 +25,7 @@
typedef enum
{
IMAP_AUTH_LOGIN = 1 << 0,
IMAP_AUTH_CRAM_MD5 = 1 << 1,
IMAP_AUTH_CRAM_MD5 = 1 << 1
} IMAPAuthType;
FolderClass *imap_get_class (void);

View file

@ -118,7 +118,6 @@ static gint inc_dialog_delete_cb (GtkWidget *widget,
GdkEventAny *event,
gpointer data);
static gint inc_spool (void);
static gint get_spool (FolderItem *dest,
const gchar *mbox);
@ -152,6 +151,8 @@ static void inc_finished(MainWindow *mainwin, gboolean new_messages)
item = cur_account && cur_account->inbox
? folder_find_item_from_identifier(cur_account->inbox)
: folder_get_default_inbox();
folderview_unselect(mainwin->folderview);
folderview_select(mainwin->folderview, item);
}
}
@ -179,19 +180,7 @@ void inc_mail(MainWindow *mainwin, gboolean notify)
inc_autocheck_timer_set();
return;
}
if (prefs_common.inc_local) {
account_new_msgs = inc_spool();
if (account_new_msgs > 0)
new_msgs += account_new_msgs;
}
} else {
if (prefs_common.inc_local) {
account_new_msgs = inc_spool();
if (account_new_msgs > 0)
new_msgs += account_new_msgs;
}
account_new_msgs = inc_account_mail(cur_account, mainwin);
if (account_new_msgs > 0)
new_msgs += account_new_msgs;
@ -275,12 +264,6 @@ void inc_all_account_mail(MainWindow *mainwin, gboolean autocheck,
inc_autocheck_timer_remove();
main_window_lock(mainwin);
if (prefs_common.inc_local) {
account_new_msgs = inc_spool();
if (account_new_msgs > 0)
new_msgs += account_new_msgs;
}
list = account_get_list();
if (!list) {
inc_finished(mainwin, new_msgs > 0);
@ -1098,25 +1081,14 @@ static gint inc_dialog_delete_cb(GtkWidget *widget, GdkEventAny *event,
return TRUE;
}
static gint inc_spool(void)
{
gchar *mbox;
const gchar *logname;
gint msgs;
logname = g_get_user_name();
mbox = g_strconcat(prefs_common.spool_path
? prefs_common.spool_path : DEFAULT_SPOOL_PATH,
G_DIR_SEPARATOR_S, logname, NULL);
msgs = get_spool(folder_get_default_inbox(), mbox);
g_free(mbox);
return msgs;
}
static gint inc_spool_account(PrefsAccount *account)
{
FolderItem *inbox;
gchar *mbox;
const gchar *logname;
gint result;
logname = g_get_user_name();
if (account->inbox) {
inbox = folder_find_item_from_path(account->inbox);
@ -1125,7 +1097,14 @@ static gint inc_spool_account(PrefsAccount *account)
} else
inbox = folder_get_default_inbox();
return get_spool(inbox, account->local_mbox);
if (is_file_exist(account->local_mbox))
mbox = g_strdup(account->local_mbox);
else
mbox = g_strconcat(account->local_mbox,
G_DIR_SEPARATOR_S, logname, NULL);
result = get_spool(inbox, mbox);
g_free(mbox);
return result;
}
static gint inc_all_spool(void)

View file

@ -574,31 +574,6 @@ static void free_mem_rec_header(mem_rec_header **mem_rh) {
*mem_rh = NULL;
}
/* Shamelessly copied from JPilot (libplugin.c) */
static int jpilot_free_db_list( GList **br_list ) {
GList *temp_list, *first;
buf_rec *br;
/* Go to first entry in the list */
first=NULL;
for( temp_list = *br_list; temp_list; temp_list = temp_list->prev ) {
first = temp_list;
}
for (temp_list = first; temp_list; temp_list = temp_list->next) {
if (temp_list->data) {
br=temp_list->data;
if (br->buf) {
free(br->buf);
temp_list->data=NULL;
}
free(br);
}
}
g_list_free(*br_list);
*br_list=NULL;
return 0;
}
/* Shamelessly copied from JPilot (libplugin.c) */
/* Read file size */
static int jpilot_get_info_size( FILE *in, int *size ) {
@ -1658,30 +1633,6 @@ GList *jpilot_get_all_persons( JPilotFile *pilotFile ) {
return addrcache_get_all_persons( pilotFile->addressCache );
}
/**
* Check label list for specified label name.
* \param ai Address info to check.
* \param lblCheck Label name to check.
* \return Index of label in address structure. <code>-1</code> if NULL/empty
* label name, <code>-2</code> if label not found.
*/
static gint jpilot_check_label( struct AddressAppInfo *ai, gchar *lblCheck ) {
gint i;
gchar *lblName;
if( lblCheck == NULL ) return -1;
if( strlen( lblCheck ) < 1 ) return -1;
for( i = 0; i < JPILOT_NUM_LABELS; i++ ) {
lblName = ai->labels[i];
if( lblName ) {
if( strlen( lblName ) ) {
if( g_strcasecmp( lblName, lblCheck ) == 0 ) return i;
}
}
}
return -2;
}
/**
* Validate that all parameters specified.
* \param pilotFile JPilot control data.

View file

@ -55,6 +55,7 @@ LdapControl *ldapctl_create( void ) {
ctl->maxEntries = LDAPCTL_MAX_ENTRIES;
ctl->timeOut = LDAPCTL_DFL_TIMEOUT;
ctl->maxQueryAge = LDAPCTL_DFL_QUERY_AGE;
ctl->matchingOption = LDAPCTL_MATCH_BEGINWITH;
/* Mutex to protect control block */
ctl->mutexCtl = g_malloc0( sizeof( pthread_mutex_t ) );
@ -162,6 +163,27 @@ void ldapctl_set_max_query_age( LdapControl* ctl, const gint value ) {
}
}
/**
* Specify matching option to be used for searches.
* \param ctl Control object to process.
* \param value Matching option, as follows:
* <ul>
* <li><code>LDAPCTL_MATCH_BEGINWITH</code> for "begins with" search</li>
* <li><code>LDAPCTL_MATCH_CONTAINS</code> for "contains" search</li>
* </ul>
*/
void ldapctl_set_matching_option( LdapControl* ctl, const gint value ) {
if( value < LDAPCTL_MATCH_BEGINWITH ) {
ctl->matchingOption = LDAPCTL_MATCH_BEGINWITH;
}
else if( value > LDAPCTL_MATCH_CONTAINS ) {
ctl->matchingOption = LDAPCTL_MATCH_BEGINWITH;
}
else {
ctl->matchingOption = value;
}
}
/**
* Specify search criteria list to be used.
* \param ctl Control data object.
@ -259,6 +281,7 @@ void ldapctl_clear( LdapControl *ctl ) {
ctl->maxEntries = 0;
ctl->timeOut = 0;
ctl->maxQueryAge = 0;
ctl->matchingOption = LDAPCTL_MATCH_BEGINWITH;
}
/**
@ -299,6 +322,7 @@ void ldapctl_default_values( LdapControl *ctl ) {
ctl->maxEntries = LDAPCTL_MAX_ENTRIES;
ctl->timeOut = LDAPCTL_DFL_TIMEOUT;
ctl->maxQueryAge = LDAPCTL_DFL_QUERY_AGE;
ctl->matchingOption = LDAPCTL_MATCH_BEGINWITH;
ldapctl_default_attributes( ctl );
}
@ -325,6 +349,7 @@ void ldapctl_print( const LdapControl *ctl, FILE *stream ) {
fprintf( stream, "max entry: %d\n", ctl->maxEntries );
fprintf( stream, " timeout: %d\n", ctl->timeOut );
fprintf( stream, " max age: %d\n", ctl->maxQueryAge );
fprintf( stream, "match opt: %d\n", ctl->matchingOption );
fprintf( stream, "crit list:\n" );
if( ctl->listCriteria ) {
mgu_print_dlist( ctl->listCriteria, stream );
@ -377,29 +402,56 @@ void ldapctl_copy( const LdapControl *ctlFrom, LdapControl *ctlTo ) {
ctlTo->maxEntries = ctlFrom->maxEntries;
ctlTo->timeOut = ctlFrom->timeOut;
ctlTo->maxQueryAge = ctlFrom->maxQueryAge;
ctlTo->matchingOption = ctlFrom->matchingOption;
/* Unlock */
pthread_mutex_unlock( ctlTo->mutexCtl );
pthread_mutex_unlock( ctlFrom->mutexCtl );
}
/**
* Search criteria fragment - two terms - begin with (default).
*/
static gchar *_criteria2BeginWith = "(&(givenName=%s*)(sn=%s*))";
/**
* Search criteria fragment - two terms - contains.
*/
static gchar *_criteria2Contains = "(&(givenName=*%s*)(sn=*%s*))";
/**
* Create an LDAP search criteria by parsing specified search term. The search
* term may contain two names separated by the first embedded space found in
* the search term. It is assumed that the two tokens are first name and last
* name, or vice versa. An appropriate search criteria will be constructed.
*
* \param searchTerm Reference to search term to process.
* \param searchTerm Reference to search term to process.
* \param matchOption Set to the following:
* <ul>
* <li><code>LDAPCTL_MATCH_BEGINWITH</code> for "begins with" search</li>
* <li><code>LDAPCTL_MATCH_CONTAINS</code> for "contains" search</li>
* </ul>
*
* \return Formatted search criteria, or <code>NULL</code> if there is no
* embedded spaces. The search term should be g_free() when no
* longer required.
*/
static gchar *ldapctl_build_ldap_criteria( gchar *searchTerm ) {
static gchar *ldapctl_build_ldap_criteria(
const gchar *searchTerm, const gint matchOption )
{
gchar *p;
gchar *t1;
gchar *t2 = NULL;
gchar *term;
gchar *crit = NULL;
gchar *criteriaFmt;
if( matchOption == LDAPCTL_MATCH_CONTAINS ) {
criteriaFmt = _criteria2Contains;
}
else {
criteriaFmt = _criteria2BeginWith;
}
term = g_strdup( searchTerm );
g_strstrip( term );
@ -420,8 +472,8 @@ static gchar *ldapctl_build_ldap_criteria( gchar *searchTerm ) {
gchar *p1, *p2;
g_strstrip( t2 );
p1 = g_strdup_printf( "(&(givenName=%s*)(sn=%s*))", t1, t2 );
p2 = g_strdup_printf( "(&(givenName=%s*)(sn=%s*))", t2, t1 );
p1 = g_strdup_printf( criteriaFmt, t1, t2 );
p2 = g_strdup_printf( criteriaFmt, t2, t1 );
crit = g_strdup_printf( "(&(|%s%s)(mail=*))", p1, p2 );
g_free( t2 );
@ -432,6 +484,17 @@ static gchar *ldapctl_build_ldap_criteria( gchar *searchTerm ) {
return crit;
}
/**
* Search criteria fragment - single term - begin with (default).
*/
static gchar *_criteriaBeginWith = "(%s=%s*)";
/**
* Search criteria fragment - single term - contains.
*/
static gchar *_criteriaContains = "(%s=*%s*)";
/**
* Build a formatted LDAP search criteria string from criteria list.
* \param ctl Control object to process.
@ -441,14 +504,22 @@ static gchar *ldapctl_build_ldap_criteria( gchar *searchTerm ) {
gchar *ldapctl_format_criteria( LdapControl *ctl, const gchar *searchVal ) {
GList *node;
gchar *p1, *p2, *retVal;
gchar *criteriaFmt;
g_return_val_if_fail( ctl != NULL, NULL );
g_return_val_if_fail( searchVal != NULL, NULL );
/* Test whether there are more that one search terms */
retVal = ldapctl_build_ldap_criteria( searchVal );
retVal = ldapctl_build_ldap_criteria( searchVal, ctl->matchingOption );
if( retVal ) return retVal;
if( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) {
criteriaFmt = _criteriaContains;
}
else {
criteriaFmt = _criteriaBeginWith;
}
/* No - just a simple search */
/* p1 contains previous formatted criteria */
/* p2 contains next formatted criteria */
@ -468,7 +539,7 @@ gchar *ldapctl_format_criteria( LdapControl *ctl, const gchar *searchVal ) {
gchar *crit;
/* Format query criteria */
crit = g_strdup_printf( "(%s=%s*)", attr, searchVal );
crit = g_strdup_printf( criteriaFmt, attr, searchVal );
/* Append to existing criteria */
g_free( p2 );
@ -478,7 +549,7 @@ gchar *ldapctl_format_criteria( LdapControl *ctl, const gchar *searchVal ) {
}
else {
/* First time through - Format query criteria */
p2 = g_strdup_printf( "(%s=%s*)", attr, searchVal );
p2 = g_strdup_printf( criteriaFmt, attr, searchVal );
}
}

View file

@ -46,6 +46,12 @@
#define LDAPCTL_DFL_ATTR_LIST "mail, cn, givenName, sn"
/*
* Search matching options.
*/
#define LDAPCTL_MATCH_BEGINWITH 0
#define LDAPCTL_MATCH_CONTAINS 1
/*
* Data structures.
*/
@ -59,6 +65,7 @@ struct _LdapControl {
gint maxEntries;
gint timeOut;
gint maxQueryAge;
gint matchingOption;
gchar *attribEMail;
gchar *attribCName;
gchar *attribFName;
@ -77,6 +84,7 @@ void ldapctl_set_bind_password ( LdapControl* ctl, const gchar *value );
void ldapctl_set_max_entries ( LdapControl* ctl, const gint value );
void ldapctl_set_timeout ( LdapControl* ctl, const gint value );
void ldapctl_set_max_query_age ( LdapControl* ctl, const gint value );
void ldapctl_set_matching_option( LdapControl* ctl, const gint value );
void ldapctl_set_criteria_list ( LdapControl* ctl, GList *value );
GList *ldapctl_get_criteria_list( const LdapControl* ctl );
void ldapctl_criteria_list_clear( LdapControl *ctl );

View file

@ -30,7 +30,6 @@
#include <glib.h>
#include <sys/time.h>
#include <string.h>
#include <ldap.h>
#include <lber.h>
#include "ldapquery.h"
@ -40,6 +39,8 @@
#include "addritem.h"
#include "addrcache.h"
#include "ldapquery.h"
/*
* Key for thread specific data.
*/
@ -54,12 +55,15 @@ LdapQuery *ldapqry_create( void ) {
LdapQuery *qry;
qry = g_new0( LdapQuery, 1 );
ADDRQUERY_TYPE(qry) = ADDRQUERY_LDAP;
ADDRQUERY_ID(qry) = 0;
ADDRQUERY_SEARCHTYPE(qry) = ADDRSEARCH_NONE;
ADDRQUERY_NAME(qry) = NULL;
ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
ADDRQUERY_FOLDER(qry) = NULL;
ADDRQUERY_SEARCHVALUE(qry) = NULL;
qry->control = NULL;
qry->retVal = LDAPRC_SUCCESS;
qry->queryType = LDAPQUERY_NONE;
qry->queryName = NULL;
qry->searchValue = NULL;
qry->queryID = 0;
qry->server = NULL;
qry->entriesRead = 0;
qry->elapsedTime = 0;
qry->stopFlag = FALSE;
@ -67,11 +71,10 @@ LdapQuery *ldapqry_create( void ) {
qry->agedFlag = FALSE;
qry->completed = FALSE;
qry->thread = NULL;
qry->callBackStart = NULL;
qry->callBackEntry = NULL;
qry->callBackEnd = NULL;
qry->folder = NULL;
qry->server = NULL;
qry->ldap = NULL;
qry->data = NULL;
/* Mutex to protect stop and busy flags */
qry->mutexStop = g_malloc0( sizeof( pthread_mutex_t ) );
@ -103,8 +106,8 @@ void ldapqry_set_control( LdapQuery *qry, LdapControl *ctl ) {
* \param value Name.
*/
void ldapqry_set_name( LdapQuery* qry, const gchar *value ) {
qry->queryName = mgu_replace_string( qry->queryName, value );
g_strstrip( qry->queryName );
ADDRQUERY_NAME(qry) = mgu_replace_string( ADDRQUERY_NAME(qry), value );
g_strstrip( ADDRQUERY_NAME(qry) );
}
/**
@ -113,8 +116,8 @@ void ldapqry_set_name( LdapQuery* qry, const gchar *value ) {
* \param value
*/
void ldapqry_set_search_value( LdapQuery *qry, const gchar *value ) {
qry->searchValue = mgu_replace_string( qry->searchValue, value );
g_strstrip( qry->searchValue );
ADDRQUERY_SEARCHVALUE(qry) = mgu_replace_string( ADDRQUERY_SEARCHVALUE(qry), value );
g_strstrip( ADDRQUERY_SEARCHVALUE(qry) );
}
/**
@ -123,7 +126,7 @@ void ldapqry_set_search_value( LdapQuery *qry, const gchar *value ) {
* \param value Status.
*/
void ldapqry_set_error_status( LdapQuery* qry, const gint value ) {
qry->retVal = value;
ADDRQUERY_RETVAL(qry) = value;
}
/**
@ -136,8 +139,20 @@ void ldapqry_set_error_status( LdapQuery* qry, const gint value ) {
* <li><code>LDAPQUERY_DYNAMIC</code></li>
* </ul>
*/
/*
void ldapqry_set_query_type( LdapQuery* qry, const gint value ) {
qry->queryType = value;
ADDRQUERY_TYPE(qry) = value;
}
*/
/**
* Specify search type.
* \param qry Query object.
* \param value Type.
*/
void ldapqry_set_search_type( LdapQuery *qry, const AddrSearchType value ) {
g_return_if_fail( qry != NULL );
ADDRQUERY_SEARCHTYPE(qry) = value;
}
/**
@ -146,7 +161,7 @@ void ldapqry_set_query_type( LdapQuery* qry, const gint value ) {
* \param value ID for the query.
*/
void ldapqry_set_query_id( LdapQuery* qry, const gint value ) {
qry->queryID = value;
ADDRQUERY_ID(qry) = value;
}
/**
@ -163,17 +178,6 @@ void ldapqry_set_entries_read( LdapQuery* qry, const gint value ) {
}
}
/**
* Register a callback function that will be executed when the search
* starts. When called, the function will be passed this query object
* as an argument.
* \param qry Query object.
* \param func Function.
*/
void ldapqry_set_callback_start( LdapQuery *qry, void *func ) {
qry->callBackStart = func;
}
/**
* Register a callback function that will be executed when each entry
* has been read and processed. When called, the function will be passed
@ -299,6 +303,26 @@ gboolean ldapqry_get_aged_flag( LdapQuery *qry ) {
return qry->agedFlag;
}
/**
* Specify user data for query.
* \param qry Query object.
* \param value Data to set.
*/
void ldapqry_set_data( LdapQuery *qry, const gpointer value ) {
g_return_if_fail( qry != NULL );
qry->data = value;
}
/**
* Retrieve user data associated with query.
* \param qry Query object.
* \return Data.
*/
gpointer ldapqry_get_data( LdapQuery *qry ) {
g_return_if_fail( qry != NULL );
return qry->data;
}
/**
* Release the LDAP control data associated with the query.
* \param qry Query object to process.
@ -319,24 +343,25 @@ void ldapqry_clear( LdapQuery *qry ) {
g_return_if_fail( qry != NULL );
/* Free internal stuff */
g_free( qry->queryName );
g_free( qry->searchValue );
g_free( ADDRQUERY_NAME(qry) );
g_free( ADDRQUERY_SEARCHVALUE(qry) );
/* Clear pointers and value */
qry->queryName = NULL;
qry->searchValue = NULL;
qry->retVal = LDAPRC_SUCCESS;
qry->queryType = LDAPQUERY_NONE;
qry->queryID = 0;
ADDRQUERY_NAME(qry) = NULL;
ADDRQUERY_SEARCHVALUE(qry) = NULL;
ADDRQUERY_ID(qry) = 0;
ADDRQUERY_SEARCHTYPE(qry) = ADDRSEARCH_NONE;
ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
qry->entriesRead = 0;
qry->elapsedTime = 0;
qry->stopFlag = FALSE;
qry->busyFlag = FALSE;
qry->agedFlag = FALSE;
qry->completed = FALSE;
qry->callBackStart = NULL;
qry->callBackEntry = NULL;
qry->callBackEnd = NULL;
qry->ldap = NULL;
qry->data = NULL;
}
/**
@ -348,6 +373,7 @@ void ldapqry_free( LdapQuery *qry ) {
g_return_if_fail( qry != NULL );
/* Clear out internal members */
ADDRQUERY_TYPE(qry) = ADDRQUERY_NONE;
ldapqry_clear( qry );
/* Free the mutex */
@ -362,7 +388,7 @@ void ldapqry_free( LdapQuery *qry ) {
qry->mutexStop = NULL;
/* Do not free folder - parent server object should free */
qry->folder = NULL;
ADDRQUERY_FOLDER(qry) = NULL;
/* Do not free thread - thread should be terminated before freeing */
qry->thread = NULL;
@ -384,11 +410,12 @@ void ldapqry_print( const LdapQuery *qry, FILE *stream ) {
fprintf( stream, "LdapQuery:\n" );
fprintf( stream, " control?: %s\n", qry->control ? "yes" : "no" );
fprintf( stream, "err/status: %d\n", qry->retVal );
fprintf( stream, "query type: %d\n", qry->queryType );
fprintf( stream, "query name: '%s'\n", qry->queryName );
fprintf( stream, "search val: '%s'\n", qry->searchValue );
fprintf( stream, " queryID: %d\n", qry->queryID );
fprintf( stream, "err/status: %d\n", ADDRQUERY_RETVAL(qry) );
fprintf( stream, "query type: %d\n", ADDRQUERY_TYPE(qry) );
fprintf( stream, "searchType: %d\n", ADDRQUERY_SEARCHTYPE(qry) );
fprintf( stream, "query name: '%s'\n", ADDRQUERY_NAME(qry) );
fprintf( stream, "search val: '%s'\n", ADDRQUERY_SEARCHVALUE(qry) );
fprintf( stream, " queryID: %d\n", ADDRQUERY_ID(qry) );
fprintf( stream, " entries: %d\n", qry->entriesRead );
fprintf( stream, " elapsed: %d\n", qry->elapsedTime );
fprintf( stream, " stop flag: %s\n", qry->stopFlag ? "yes" : "no" );
@ -529,16 +556,16 @@ static GList *ldapqry_build_items_fl(
}
/* Create new folder for results */
if( qry->folder == NULL ) {
if( ADDRQUERY_FOLDER(qry) == NULL ) {
folder = addritem_create_item_folder();
addritem_folder_set_name( folder, qry->queryName );
addritem_folder_set_name( folder, ADDRQUERY_NAME(qry) );
addritem_folder_set_remarks( folder, "" );
addrcache_id_folder( cache, folder );
addrcache_add_folder( cache, folder );
qry->folder = folder;
ADDRQUERY_FOLDER(qry) = folder;
/* Specify folder type and back reference */
folder->folderType = ADDRFOLDER_LDAP_QUERY;
folder->folderType = ADDRFOLDER_QUERY_RESULTS;
folder->folderData = ( gpointer ) qry;
folder->isHidden = TRUE;
}
@ -550,7 +577,7 @@ static GList *ldapqry_build_items_fl(
addritem_person_set_last_name( person, lastName );
addrcache_id_person( cache, person );
addritem_person_set_external_id( person, dn );
addrcache_folder_add_person( cache, qry->folder, person );
addrcache_folder_add_person( cache, ADDRQUERY_FOLDER(qry), person );
qry->entriesRead++;
@ -644,7 +671,7 @@ static GList *ldapqry_process_single_entry(
*/
gboolean ldapqry_check_search( LdapQuery *qry ) {
LdapControl *ctl;
qry->retVal = LDAPRC_CRITERIA;
ADDRQUERY_RETVAL(qry) = LDAPRC_CRITERIA;
/* Test for control data */
ctl = qry->control;
@ -653,14 +680,13 @@ gboolean ldapqry_check_search( LdapQuery *qry ) {
}
/* Test for search value */
if( qry->searchValue == NULL ) {
if( ADDRQUERY_SEARCHVALUE(qry) == NULL ) {
return FALSE;
}
if( strlen( qry->searchValue ) < 1 ) {
if( strlen( ADDRQUERY_SEARCHVALUE(qry) ) < 1 ) {
return FALSE;
}
qry->retVal = LDAPRC_SUCCESS;
ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
return TRUE;
}
@ -674,54 +700,32 @@ void ldapqry_touch( LdapQuery *qry ) {
}
/**
* Perform the LDAP search, reading LDAP entries into cache.
* Note that one LDAP entry can have multiple values for many of its
* attributes. If these attributes are E-Mail addresses; these are
* broken out into separate address items. For any other attribute,
* only the first occurrence is read.
*
* Connect to LDAP server.
* \param qry Query object to process.
* \return Error/status code.
*/
static gint ldapqry_perform_search( LdapQuery *qry ) {
static gint ldapqry_connect( LdapQuery *qry ) {
LdapControl *ctl;
LDAP *ld;
LDAPMessage *result, *e;
char **attribs;
gchar *criteria;
gboolean entriesFound;
gboolean first;
struct timeval timeout;
gint rc;
time_t tstart, tend;
AddressCache *cache;
GList *listEMail;
/* Initialize some variables */
ctl = qry->control;
cache = qry->server->addressCache;
timeout.tv_sec = ctl->timeOut;
timeout.tv_usec = 0L;
entriesFound = FALSE;
qry->elapsedTime = -1;
qry->retVal = LDAPRC_SUCCESS;
/* Check search criteria */
if( ! ldapqry_check_search( qry ) ) {
return qry->retVal;
}
/* Initialize connection */
/* printf( "===ldapqry_connect===\n" ); */
/* ldapqry_print( qry, stdout ); */
ctl = qry->control;
/* ldapctl_print( ctl, stdout ); */
/* printf( "======\n" ); */
ldapqry_touch( qry );
tstart = qry->touchTime;
tend = tstart - 1;
qry->startTime = qry->touchTime;
qry->elapsedTime = -1;
ADDRQUERY_RETVAL(qry) = LDAPRC_INIT;
if( ( ld = ldap_init( ctl->hostName, ctl->port ) ) == NULL ) {
qry->retVal = LDAPRC_INIT;
return qry->retVal;
return ADDRQUERY_RETVAL(qry);
}
qry->ldap = ld;
ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
if( ldapqry_get_stop_flag( qry ) ) {
qry->retVal = LDAPRC_SUCCESS;
return qry->retVal;
return ADDRQUERY_RETVAL(qry);
}
ldapqry_touch( qry );
@ -730,6 +734,7 @@ static gint ldapqry_perform_search( LdapQuery *qry ) {
*/
/* Bind to the server, if required */
ADDRQUERY_RETVAL(qry) = LDAPRC_BIND;
if( ctl->bindDN ) {
if( * ctl->bindDN != '\0' ) {
/* printf( "binding...\n" ); */
@ -740,51 +745,99 @@ static gint ldapqry_perform_search( LdapQuery *qry ) {
printf( "LDAP Error: ldap_simple_bind_s: %s\n",
ldap_err2string( rc ) );
*/
ldap_unbind( ld );
qry->retVal = LDAPRC_BIND;
return qry->retVal;
return ADDRQUERY_RETVAL(qry);
}
}
}
ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
if( ldapqry_get_stop_flag( qry ) ) {
ldap_unbind( ld );
qry->retVal = LDAPRC_SUCCESS;
return qry->retVal;
return ADDRQUERY_RETVAL(qry);
}
ldapqry_touch( qry );
ADDRQUERY_RETVAL(qry) = LDAP_SUCCESS;
return ADDRQUERY_RETVAL(qry);
}
/**
* Connect to LDAP server.
* \param qry Query object to process.
* \return Error/status code.
*/
static gint ldapqry_disconnect( LdapQuery *qry ) {
/* Disconnect */
if( qry->ldap ) ldap_unbind( qry->ldap );
qry->ldap = NULL;
ldapqry_touch( qry );
qry->elapsedTime = qry->touchTime - qry->startTime;
return ADDRQUERY_RETVAL(qry);
}
/**
* Perform the LDAP search, reading LDAP entries into cache.
* Note that one LDAP entry can have multiple values for many of its
* attributes. If these attributes are E-Mail addresses; these are
* broken out into separate address items. For any other attribute,
* only the first occurrence is read.
*
* \param qry Query object to process.
* \return Error/status code.
*/
static gint ldapqry_search_retrieve( LdapQuery *qry ) {
LdapControl *ctl;
LDAP *ld;
LDAPMessage *result, *e;
char **attribs;
gchar *criteria;
gboolean entriesFound;
gboolean first;
struct timeval timeout;
gint rc;
AddressCache *cache;
GList *listEMail;
/* Initialize some variables */
ld = qry->ldap;
ctl = qry->control;
cache = qry->server->addressCache;
timeout.tv_sec = ctl->timeOut;
timeout.tv_usec = 0L;
entriesFound = FALSE;
ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
/* Define all attributes we are interested in. */
attribs = ldapctl_attribute_array( ctl );
/* Create LDAP search string */
criteria = ldapctl_format_criteria( ctl, qry->searchValue );
criteria = ldapctl_format_criteria( ctl, ADDRQUERY_SEARCHVALUE(qry) );
/* printf( "Search criteria ::%s::\n", criteria ); */
/*
* Execute the search - this step may take some time to complete
* depending on network traffic and server response time.
*/
ADDRQUERY_RETVAL(qry) = LDAPRC_TIMEOUT;
rc = ldap_search_ext_s( ld, ctl->baseDN, LDAP_SCOPE_SUBTREE, criteria,
attribs, 0, NULL, NULL, &timeout, 0, &result );
ldapctl_free_attribute_array( attribs );
g_free( criteria );
criteria = NULL;
if( rc == LDAP_TIMEOUT ) {
ldap_unbind( ld );
qry->retVal = LDAPRC_TIMEOUT;
return qry->retVal;
return ADDRQUERY_RETVAL(qry);
}
ADDRQUERY_RETVAL(qry) = LDAPRC_SEARCH;
if( rc != LDAP_SUCCESS ) {
/*
printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) );
*/
ldap_unbind( ld );
qry->retVal = LDAPRC_SEARCH;
return qry->retVal;
return ADDRQUERY_RETVAL(qry);
}
ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
if( ldapqry_get_stop_flag( qry ) ) {
qry->retVal = LDAPRC_SUCCESS;
return qry->retVal;
return ADDRQUERY_RETVAL(qry);
}
ldapqry_touch( qry );
@ -792,11 +845,6 @@ static gint ldapqry_perform_search( LdapQuery *qry ) {
printf( "Total results are: %d\n", ldap_count_entries( ld, result ) );
*/
if( ldapqry_get_stop_flag( qry ) ) {
qry->retVal = LDAPRC_SUCCESS;
return qry->retVal;
}
/* Process results */
first = TRUE;
while( TRUE ) {
@ -828,7 +876,7 @@ static gint ldapqry_perform_search( LdapQuery *qry ) {
/* Process callback */
if( qry->callBackEntry ) {
qry->callBackEntry( qry, listEMail );
qry->callBackEntry( qry, ADDRQUERY_ID(qry), listEMail, qry->data );
}
else {
g_list_free( listEMail );
@ -839,19 +887,40 @@ static gint ldapqry_perform_search( LdapQuery *qry ) {
/* Free up and disconnect */
ldap_msgfree( result );
ldap_unbind( ld );
ldapqry_touch( qry );
tend = qry->touchTime;
qry->elapsedTime = tend - tstart;
if( entriesFound ) {
qry->retVal = LDAPRC_SUCCESS;
ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
}
else {
qry->retVal = LDAPRC_NOENTRIES;
ADDRQUERY_RETVAL(qry) = LDAPRC_NOENTRIES;
}
return qry->retVal;
return ADDRQUERY_RETVAL(qry);
}
/**
* Connection, perform search and disconnect.
* \param qry Query object to process.
* \return Error/status code.
*/
static gint ldapqry_perform_search( LdapQuery *qry ) {
/* Check search criteria */
if( ! ldapqry_check_search( qry ) ) {
return ADDRQUERY_RETVAL(qry);
}
/* Connect */
qry->ldap = NULL;
ldapqry_connect( qry );
if( ADDRQUERY_RETVAL(qry) == LDAPRC_SUCCESS ) {
/* Perform search */
ldapqry_search_retrieve( qry );
}
/* Disconnect */
ldapqry_disconnect( qry );
qry->ldap = NULL;
return ADDRQUERY_RETVAL(qry);
}
/**
@ -868,11 +937,6 @@ gint ldapqry_search( LdapQuery *qry ) {
ldapqry_touch( qry );
qry->completed = FALSE;
/* Process callback */
if( qry->callBackStart ) {
qry->callBackStart( qry );
}
/* Setup pointer to thread specific area */
pthread_setspecific( _queryThreadKey_, qry );
@ -880,10 +944,15 @@ gint ldapqry_search( LdapQuery *qry ) {
/* Now perform the search */
qry->entriesRead = 0;
qry->retVal = LDAPRC_SUCCESS;
ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
ldapqry_set_busy_flag( qry, TRUE );
ldapqry_set_stop_flag( qry, FALSE );
retVal = ldapqry_perform_search( qry );
if( ADDRQUERY_SEARCHTYPE(qry) == ADDRSEARCH_LOCATE ) {
retVal = ldapqry_perform_locate( qry );
}
else {
retVal = ldapqry_perform_search( qry );
}
if( retVal == LDAPRC_SUCCESS ) {
qry->server->addressCache->dataRead = TRUE;
qry->server->addressCache->accessFlag = FALSE;
@ -905,10 +974,10 @@ gint ldapqry_search( LdapQuery *qry ) {
/* Process callback */
if( qry->callBackEnd ) {
qry->callBackEnd( qry );
qry->callBackEnd( qry, ADDRQUERY_ID(qry), ADDRQUERY_RETVAL(qry), qry->data );
}
return qry->retVal;
return ADDRQUERY_RETVAL(qry);
}
/**
@ -924,7 +993,7 @@ gint ldapqry_read_data_th( LdapQuery *qry ) {
ldapqry_set_stop_flag( qry, FALSE );
ldapqry_touch( qry );
if( ldapqry_check_search( qry ) ) {
if( qry->retVal == LDAPRC_SUCCESS ) {
if( ADDRQUERY_RETVAL(qry) == LDAPRC_SUCCESS ) {
/*
printf( "Starting LDAP search thread\n");
*/
@ -936,21 +1005,7 @@ gint ldapqry_read_data_th( LdapQuery *qry ) {
(void *) ldapqry_search, (void *) qry );
}
}
return qry->retVal;
}
/**
* Join the thread associated with the query. This should probably be removed
* to prevent joining threads.
* \param qry Query object to process.
*/
void ldapqry_join_threadX( LdapQuery *qry ) {
g_return_if_fail( qry != NULL );
/* Wait for thread */
/* printf( "ldapqry_join_thread::Joining thread...\n" ); */
pthread_join( * qry->thread, NULL );
/* printf( "ldapqry_join_thread::Thread terminated\n" ); */
return ADDRQUERY_RETVAL(qry);
}
/**
@ -963,7 +1018,7 @@ static void ldapqry_destroyer( void * ptr ) {
qry = ( LdapQuery * ) ptr;
/*
printf( "ldapqry_destroyer::%d::%s\n", (int) pthread_self(), qry->queryName );
printf( "ldapqry_destroyer::%d::%s\n", (int) pthread_self(), ADDRQUERY_NAME(qry) );
*/
/* Perform any destruction here */
@ -986,7 +1041,7 @@ void ldapqry_cancel( LdapQuery *qry ) {
g_return_if_fail( qry != NULL );
/*
printf( "cancelling::%d::%s\n", (int) pthread_self(), qry->queryName );
printf( "cancelling::%d::%s\n", (int) pthread_self(), ADDRQUERY_NAME(qry) );
*/
if( ldapqry_get_busy_flag( qry ) ) {
if( qry->thread ) {
@ -1041,14 +1096,280 @@ void ldapqry_delete_folder( LdapQuery *qry ) {
g_return_if_fail( qry != NULL );
folder = qry->folder;
folder = ADDRQUERY_FOLDER(qry);
if( folder ) {
cache = qry->server->addressCache;
folder = addrcache_remove_folder_delete( cache, folder );
if( folder ) {
addritem_free_item_folder( folder );
}
qry->folder = NULL;
ADDRQUERY_FOLDER(qry) = NULL;
}
}
/**
* Create a name/value pair object.
* \param n Name.
* \param v Value.
* \return Initialized object.
*/
static NameValuePair *ldapqry_create_name_value( const gchar *n, const gchar *v ) {
NameValuePair *nvp = g_new0( NameValuePair, 1 );
nvp->name = g_strdup( n );
nvp->value = g_strdup( v );
return nvp;
}
/**
* Free up name/value pair object.
* \param nvp Name/value object.
*/
void ldapqry_free_name_value( NameValuePair *nvp ) {
if( nvp ) {
g_free( nvp->name );
g_free( nvp->value );
nvp->name = nvp->value = NULL;
g_free( nvp );
}
}
/**
* Print name/value pair object for debug.
* \param nvp Name/value object.
* \param stream Output stream.
*/
void ldapqry_print_name_value( NameValuePair *nvp, FILE *stream ) {
if( nvp ) {
fprintf( stream, "n/v ::%s::%s::\n", nvp->name, nvp->value );
}
}
/**
* Free up a list name/value pair objects.
* \param list List of name/value objects.
*/
void ldapqry_free_list_name_value( GList *list ) {
GList *node;
node = list;
while( node ) {
NameValuePair *nvp = ( NameValuePair * ) node->data;
ldapqry_free_name_value( nvp );
node->data = NULL;
node = g_list_next( node );
}
g_list_free( list );
}
/**
* Load a list of name/value pairs from LDAP attributes.
* \param ld LDAP handle.
* \param e LDAP message.
* \param attr Attribute name.
* \param listValues List to populate.
* \return List of attribute name/value pairs.
*/
static GList *ldapqry_load_attrib_values(
LDAP *ld, LDAPMessage *entry, char *attr,
GList *listValues )
{
GList *list = NULL;
gint i;
gchar **vals;
NameValuePair *nvp;
list = listValues;
if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
for( i = 0; vals[i] != NULL; i++ ) {
nvp = ldapqry_create_name_value( attr, vals[i] );
list = g_list_append( list, nvp );
}
}
ldap_value_free( vals );
return list;
}
/**
* Fetch a list of all attributes.
* \param ld LDAP handle.
* \param e LDAP message.
* \return List of attribute name/value pairs.
*/
static GList *ldapqry_fetch_attribs( LDAP *ld, LDAPMessage *e )
{
char *attribute;
BerElement *ber;
GList *listValues = NULL;
/* Process all attributes */
for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
attribute = ldap_next_attribute( ld, e, ber ) ) {
listValues = ldapqry_load_attrib_values( ld, e, attribute, listValues );
ldap_memfree( attribute );
}
/* Free up */
if( ber != NULL ) {
ber_free( ber, 0 );
}
return listValues;
}
#define CRITERIA_SINGLE "(objectclass=*)"
/**
* Perform the data retrieval for a specific LDAP record.
*
* \param qry Query object to process.
* \return Error/status code.
*/
static gint ldapqry_locate_retrieve( LdapQuery *qry ) {
LdapControl *ctl;
LDAP *ld;
LDAPMessage *result, *e;
gboolean entriesFound;
gboolean first;
struct timeval timeout;
gint rc;
gchar *dn;
GList *listValues;
/* Initialize some variables */
ld = qry->ldap;
ctl = qry->control;
dn = ADDRQUERY_SEARCHVALUE(qry);
timeout.tv_sec = ctl->timeOut;
timeout.tv_usec = 0L;
entriesFound = FALSE;
/*
* Execute the search - this step may take some time to complete
* depending on network traffic and server response time.
*/
ADDRQUERY_RETVAL(qry) = LDAPRC_TIMEOUT;
rc = ldap_search_ext_s( ld, dn, LDAP_SCOPE_BASE, CRITERIA_SINGLE,
NULL, 0, NULL, NULL, &timeout, 0, &result );
if( rc == LDAP_TIMEOUT ) {
return ADDRQUERY_RETVAL(qry);
}
ADDRQUERY_RETVAL(qry) = LDAPRC_SEARCH;
if( rc != LDAP_SUCCESS ) {
/*
printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) );
*/
return ADDRQUERY_RETVAL(qry);
}
ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
if( ldapqry_get_stop_flag( qry ) ) {
return ADDRQUERY_RETVAL(qry);
}
ldapqry_touch( qry );
/*
printf( "Total results are: %d\n", ldap_count_entries( ld, result ) );
*/
/* Process results */
first = TRUE;
while( TRUE ) {
ldapqry_touch( qry );
if( qry->entriesRead >= ctl->maxEntries ) break;
/* Test for stop */
if( ldapqry_get_stop_flag( qry ) ) {
break;
}
/* Retrieve entry */
if( first ) {
first = FALSE;
e = ldap_first_entry( ld, result );
}
else {
e = ldap_next_entry( ld, e );
}
if( e == NULL ) break;
entriesFound = TRUE;
/* Setup a critical section here */
pthread_mutex_lock( qry->mutexEntry );
/* Process entry */
listValues = ldapqry_fetch_attribs( ld, e );
/* Process callback */
if( qry->callBackEntry ) {
qry->callBackEntry( qry, ADDRQUERY_ID(qry), listValues, qry->data );
}
ldapqry_free_list_name_value( listValues );
listValues = NULL;
pthread_mutex_unlock( qry->mutexEntry );
}
/* Free up and disconnect */
ldap_msgfree( result );
if( entriesFound ) {
ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
}
else {
ADDRQUERY_RETVAL(qry) = LDAPRC_NOENTRIES;
}
return ADDRQUERY_RETVAL(qry);
}
/**
* Perform the search to locate a specific LDAP record identified by
* distinguished name (dn).
*
* \param qry Query object to process.
* \return Error/status code.
*/
gint ldapqry_perform_locate( LdapQuery *qry ) {
/* Connect */
qry->ldap = NULL;
ldapqry_connect( qry );
if( ADDRQUERY_RETVAL(qry) == LDAPRC_SUCCESS ) {
/* Perform search */
ldapqry_locate_retrieve( qry );
}
/* Disconnect */
ldapqry_disconnect( qry );
qry->ldap = NULL;
/* Process callback */
if( qry->callBackEnd ) {
qry->callBackEnd( qry, ADDRQUERY_ID(qry), ADDRQUERY_RETVAL(qry), qry->data );
}
return ADDRQUERY_RETVAL(qry);
}
/**
* Remove results (folder and data) for specified LDAP query.
* \param qry Query object to process.
*/
void ldapquery_remove_results( LdapQuery *qry ) {
/* Set query as aged - will be retired on a later call */
ldapqry_set_aged_flag( qry, TRUE );
/*
printf( "ldapquery_remove_results...\n" );
printf( "testing busy flag...\n" );
*/
if( ldapqry_get_busy_flag( qry ) ) {
/* Query is still busy - cancel query */
/* printf( "\tquery is still busy running...\n" ); */
ldapqry_set_stop_flag( qry, TRUE );
ldapqry_cancel( qry );
}
else {
/* Delete folder */
/* printf( "\tquery can be deleted!\n" ); */
ldapqry_delete_folder( qry );
}
}

View file

@ -30,53 +30,41 @@
#include <stdio.h>
#include <sys/time.h>
#include <pthread.h>
#include <ldap.h>
#include "addrquery.h"
#include "ldapctrl.h"
#include "ldapserver.h"
#include "addritem.h"
#include "addrcache.h"
/*
* Constants.
*/
#define LDAPQUERY_NONE 0
#define LDAPQUERY_STATIC 1
#define LDAPQUERY_DYNAMIC 2
/* Error codes */
#define LDAPRC_SUCCESS 0
#define LDAPRC_CONNECT -1
#define LDAPRC_INIT -2
#define LDAPRC_BIND -3
#define LDAPRC_SEARCH -4
#define LDAPRC_TIMEOUT -5
#define LDAPRC_CRITERIA -6
#define LDAPRC_NOENTRIES -7
typedef struct _LdapQuery LdapQuery;
struct _LdapQuery {
LdapControl *control;
gint retVal;
gint queryType;
gchar *queryName;
gchar *searchValue;
gint queryID;
gint entriesRead;
gint elapsedTime;
gboolean stopFlag;
gboolean busyFlag;
gboolean agedFlag;
gboolean completed;
time_t touchTime;
pthread_t *thread;
AddrQueryObject obj;
LdapControl *control;
LdapServer *server; /* Reference to (parent) LDAP server */
gint entriesRead;
gint elapsedTime;
gboolean stopFlag;
gboolean busyFlag;
gboolean agedFlag;
gboolean completed;
time_t startTime;
time_t touchTime;
pthread_t *thread;
pthread_mutex_t *mutexStop;
pthread_mutex_t *mutexBusy;
pthread_mutex_t *mutexEntry;
void (*callBackStart)( void * );
void (*callBackEntry)( void *, void * );
void (*callBackEnd)( void * );
ItemFolder *folder; /* Reference to folder in cache */
LdapServer *server; /* Reference to (parent) LDAP server */
void (*callBackEntry)( void *, gint, void *, void * );
void (*callBackEnd)( void *, gint, gint, void * );
LDAP *ldap;
gpointer data;
};
typedef struct _NameValuePair NameValuePair;
struct _NameValuePair {
gchar *name;
gchar *value;
};
/* Function prototypes */
@ -86,7 +74,7 @@ void ldapqry_set_control ( LdapQuery *qry, LdapControl *ctl );
void ldapqry_set_name ( LdapQuery* qry, const gchar *value );
void ldapqry_set_search_value ( LdapQuery *qry, const gchar *value );
void ldapqry_set_error_status ( LdapQuery* qry, const gint value );
void ldapqry_set_query_type ( LdapQuery* qry, const gint value );
void ldapqry_set_search_type ( LdapQuery *qry, const AddrSearchType value );
void ldapqry_set_query_id ( LdapQuery* qry, const gint value );
void ldapqry_set_entries_read ( LdapQuery* qry, const gint value );
void ldapqry_set_callback_start ( LdapQuery *qry, void *func );
@ -101,15 +89,17 @@ void ldapqry_set_busy_flag ( LdapQuery *qry, const gboolean value );
gboolean ldapqry_get_busy_flag ( LdapQuery *qry );
void ldapqry_set_aged_flag ( LdapQuery *qry, const gboolean value );
gboolean ldapqry_get_aged_flag ( LdapQuery *qry );
void ldapqry_set_data ( LdapQuery *qry, const gpointer value );
gpointer ldapqry_get_data ( LdapQuery *qry );
gboolean ldapqry_check_search ( LdapQuery *qry );
void ldapqry_touch ( LdapQuery *qry );
gint ldapqry_search ( LdapQuery *qry );
gint ldapqry_read_data_th ( LdapQuery *qry );
void ldapqry_join_thread ( LdapQuery *qry );
void ldapqry_cancel ( LdapQuery *qry );
void ldapqry_age ( LdapQuery *qry, gint maxAge );
void ldapqry_delete_folder ( LdapQuery *qry );
void ldapquery_remove_results ( LdapQuery *qry );
#endif /* USE_LDAP */

View file

@ -310,7 +310,7 @@ void ldapsvr_print_data( LdapServer *server, FILE *stream ) {
node = server->listQuery;
while( node ) {
LdapQuery *qry = node->data;
fprintf( stream, " query: %2d : %s\n", i, qry->queryName );
fprintf( stream, " query: %2d : %s\n", i, ADDRQUERY_NAME(qry) );
i++;
node = g_list_next( node );
}
@ -356,8 +356,9 @@ void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry ) {
ldapqry_initialize();
/* Perform query */
/* printf( "ldapsvr_execute_query::reading with thread...\n" ); */
/* printf( "ldapsvr_execute_query::checking query...\n" ); */
if( ldapqry_check_search( qry ) ) {
/* printf( "ldapsvr_execute_query::reading with thread...\n" ); */
ldapqry_read_data_th( qry );
/*
if( qry->retVal == LDAPRC_SUCCESS ) {
@ -380,7 +381,7 @@ void ldapsvr_stop_query_id( LdapServer *server, const gint queryID ) {
node = server->listQuery;
while( node ) {
LdapQuery *qry = node->data;
if( qry->queryID == queryID ) {
if( ADDRQUERY_ID(qry) == queryID ) {
/* Notify thread to stop */
ldapqry_set_stop_flag( qry, TRUE );
}
@ -431,7 +432,8 @@ void ldapsvr_cancel_all_query( LdapServer *server ) {
* \param searchTerm Search term to locate.
* \return Query object, or <i>NULL</i> if none found.
*/
LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm )
static LdapQuery *ldapsvr_locate_query(
const LdapServer *server, const gchar *searchTerm )
{
LdapQuery *incomplete = NULL;
GList *node;
@ -442,7 +444,7 @@ LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm )
/* Search backwards for query */
while( node ) {
LdapQuery *qry = node->data;
if( g_strcasecmp( qry->searchValue, searchTerm ) == 0 ) {
if( g_strcasecmp( ADDRQUERY_SEARCHVALUE(qry), searchTerm ) == 0 ) {
if( qry->agedFlag ) continue;
if( qry->completed ) {
/* Found */
@ -458,7 +460,12 @@ LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm )
}
/**
* Retire aged queries. Only dynamic queries are retired.
* Retire aged queries. Only the following queries are retired:
*
* a) Dynamic queries.
* b) Explicit searches that have a hidden folders.
* c) Locate searches that have a hidden folder.
*
* \param server LdapServer.
*/
void ldapsvr_retire_query( LdapServer *server ) {
@ -467,6 +474,7 @@ void ldapsvr_retire_query( LdapServer *server ) {
GList *listQuery;
gint maxAge;
LdapControl *ctl;
ItemFolder *folder;
/* printf( "ldapsvr_retire_query\n" ); */
g_return_if_fail( server != NULL );
@ -480,14 +488,18 @@ void ldapsvr_retire_query( LdapServer *server ) {
LdapQuery *qry = node->data;
node = g_list_next( node );
if( qry->queryType == LDAPQUERY_STATIC ) continue;
folder = ADDRQUERY_FOLDER(qry);
if( folder == NULL ) continue;
if( ! folder->isHidden ) {
if( ADDRQUERY_SEARCHTYPE(qry) == ADDRSEARCH_EXPLICIT ) continue;
if( ADDRQUERY_SEARCHTYPE(qry) == ADDRSEARCH_LOCATE ) continue;
}
/* Only dynamic queries are retired */
ldapqry_age( qry, maxAge );
if( qry->agedFlag ) {
/* Delete folder associated with query */
/*
printf( "deleting folder... ::%s::\n", qry->queryName );
printf( "deleting folder... ::%s::\n", ADDRQUERY_NAME(qry) );
*/
ldapqry_delete_folder( qry );
listDelete = g_list_append( listDelete, qry );
@ -511,6 +523,176 @@ void ldapsvr_retire_query( LdapServer *server ) {
g_list_free( listDelete );
}
/**
* Return results of a previous query by executing callback for each address
* contained in specified folder.
*
* \param folder Address book folder to process.
* \param req Address query request object.
*/
static void ldapsvr_previous_query(
const ItemFolder *folder, const QueryRequest *req, AddrQueryObject *aqo )
{
AddrSearchCallbackEntry *callBack;
GList *listEMail;
GList *node;
GList *nodeEM;
gpointer sender;
sender = aqo;
callBack = ( AddrSearchCallbackEntry * ) req->callBackEntry;
if( callBack ) {
listEMail = NULL;
node = folder->listPerson;
while( node ) {
AddrItemObject *aio = node->data;
if( aio && aio->type == ITEMTYPE_PERSON ) {
ItemPerson *person = node->data;
nodeEM = person->listEMail;
while( nodeEM ) {
ItemEMail *email = nodeEM->data;
nodeEM = g_list_next( nodeEM );
listEMail = g_list_append( listEMail, email );
}
}
node = g_list_next( node );
}
( callBack ) ( sender, req->queryID, listEMail, NULL );
/* // g_list_free( listEMail ); */
}
}
/**
* Reuse search results from a previous LDAP query. If there is a query that
* has the same search term as specified in the query request, then the query
* will be reused.
*
* \param server LDAP server object.
* \param req Address query object.
* \return <i>TRUE</i> if previous query was used.
*/
gboolean ldapsvr_reuse_previous( const LdapServer *server, const QueryRequest *req ) {
LdapQuery *qry;
gchar *searchTerm;
ItemFolder *folder;
g_return_val_if_fail( server != NULL, FALSE );
g_return_val_if_fail( req != NULL, FALSE );
searchTerm = req->searchTerm;
/* Test whether any queries for the same term exist */
qry = ldapsvr_locate_query( server, searchTerm );
if( qry ) {
/* Touch query to ensure it hangs around for a bit longer */
ldapqry_touch( qry );
folder = ADDRQUERY_FOLDER(qry);
if( folder ) {
ldapsvr_previous_query( folder, req, ADDRQUERY_OBJECT(qry) );
return TRUE;
}
}
return FALSE;
}
/**
* Construct a new LdapQuery object that will be used to perform an dynamic
* search request.
*
* \param server LdapServer.
* \param req Query request.
* \return LdapQuery object, or <i>NULL</i> if none created.
*/
LdapQuery *ldapsvr_new_dynamic_search( LdapServer *server, QueryRequest *req )
{
LdapQuery *qry;
gchar *name;
gchar *searchTerm;
g_return_val_if_fail( server != NULL, NULL );
g_return_val_if_fail( req != NULL, NULL );
/* Retire any aged queries */
/* // ldapsvr_retire_query( server ); */
searchTerm = req->searchTerm;
/* Construct a query */
qry = ldapqry_create();
ldapqry_set_query_id( qry, req->queryID );
ldapqry_set_search_value( qry, searchTerm );
ldapqry_set_search_type( qry, ADDRSEARCH_DYNAMIC );
ldapqry_set_callback_entry( qry, req->callBackEntry );
ldapqry_set_callback_end( qry, req->callBackEnd );
/* Name the query */
name = g_strdup_printf( "Search for '%s'", searchTerm );
ldapqry_set_name( qry, name );
g_free( name );
/* Add query to request */
qryreq_add_query( req, ADDRQUERY_OBJECT(qry) );
/* Now start the search */
ldapsvr_add_query( server, qry );
return qry;
}
/**
* Construct a new LdapQuery object that will be used to perform an explicit
* search request.
*
* \param server LdapServer.
* \param req Query request.
* \param folder Folder that will be used to contain search results; may be NULL.
* \return LdapQuery object, or <i>NULL</i> if none created.
*/
LdapQuery *ldapsvr_new_explicit_search(
LdapServer *server, QueryRequest *req, ItemFolder *folder )
{
LdapQuery *qry;
gchar *searchTerm;
gchar *name;
g_return_val_if_fail( server != NULL, NULL );
g_return_val_if_fail( req != NULL, NULL );
searchTerm = req->searchTerm;
/* Retire any aged queries */
/* // ldapsvr_retire_query( server ); */
/* Name the query */
name = g_strdup_printf( "Explicit search for '%s'", searchTerm );
/* Construct a query */
qry = ldapqry_create();
ldapqry_set_query_id( qry, req->queryID );
ldapqry_set_name( qry, name );
ldapqry_set_search_value( qry, searchTerm );
ldapqry_set_search_type( qry, ADDRSEARCH_EXPLICIT );
ldapqry_set_callback_end( qry, req->callBackEnd );
ldapqry_set_callback_entry( qry, req->callBackEntry );
if( folder ) {
/* Specify folder type and back reference */
ADDRQUERY_FOLDER(qry) = folder;
folder->folderType = ADDRFOLDER_QUERY_RESULTS;
folder->folderData = ( gpointer ) qry;
}
/* Setup server */
ldapsvr_add_query( server, qry );
/* Set up query request */
qryreq_add_query( req, ADDRQUERY_OBJECT(qry) );
g_free( name );
return qry;
}
#endif /* USE_LDAP */
/*

View file

@ -32,14 +32,18 @@
#include "addritem.h"
#include "addrcache.h"
#include "adbookbase.h"
#include "addrquery.h"
#define MGU_LDAP_CONNECT -51
#define MGU_LDAP_INIT -52
#define MGU_LDAP_BIND -53
#define MGU_LDAP_SEARCH -54
#define MGU_LDAP_TIMEOUT -55
#define MGU_LDAP_CRITERIA -56
#define MGU_LDAP_NOENTRIES -57
/* Error codes */
#define LDAPRC_SUCCESS 0
#define LDAPRC_CONNECT -1
#define LDAPRC_INIT -2
#define LDAPRC_BIND -3
#define LDAPRC_SEARCH -4
#define LDAPRC_TIMEOUT -5
#define LDAPRC_CRITERIA -6
#define LDAPRC_NOENTRIES -7
#define LDAPRC_STOP_FLAG -8
typedef struct _LdapServer LdapServer;
struct _LdapServer {
@ -80,6 +84,9 @@ void ldapsvr_stop_all_query ( LdapServer *server );
void ldapsvr_cancel_all_query ( LdapServer *server );
void ldapsvr_retire_query ( LdapServer *server );
gboolean ldapsvr_reuse_previous ( const LdapServer *server,
const QueryRequest *req );
#endif /* USE_LDAP */
#endif /* __LDAPSERVER_H__ */

View file

@ -1,245 +0,0 @@
/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
* Copyright (C) 1999-2002 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 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtkwidget.h>
#include <gtk/gtkwindow.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkscrolledwindow.h>
#include <gtk/gtktextview.h>
#include <gtk/gtkstyle.h>
#include "intl.h"
#include "logwindow.h"
#include "utils.h"
#include "gtkutils.h"
#include "prefs_common.h"
#include "log.h"
#include "hooks.h"
static void hide_cb (GtkWidget *widget,
LogWindow *logwin);
static gboolean key_pressed (GtkWidget *widget,
GdkEventKey *event,
LogWindow *logwin);
static gboolean log_window_append (gpointer source,
gpointer data);
void log_window_clear (GtkWidget *text);
LogWindow *log_window_create(void)
{
LogWindow *logwin;
GtkWidget *window;
GtkWidget *scrolledwin;
GtkWidget *text;
GtkTextBuffer *buffer;
GtkTextIter iter;
debug_print("Creating log window...\n");
logwin = g_new0(LogWindow, 1);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), _("Protocol log"));
gtk_window_set_wmclass(GTK_WINDOW(window), "log_window", "Sylpheed");
gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
gtk_widget_set_size_request(window, 520, 400);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
g_signal_connect(G_OBJECT(window), "key_press_event",
G_CALLBACK(key_pressed), logwin);
g_signal_connect(G_OBJECT(window), "hide",
G_CALLBACK(hide_cb), logwin);
gtk_widget_realize(window);
scrolledwin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
gtk_container_add(GTK_CONTAINER(window), scrolledwin);
gtk_widget_show(scrolledwin);
text = gtk_text_view_new();
gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
gtk_text_buffer_get_start_iter(buffer, &iter);
gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
gtk_container_add(GTK_CONTAINER(scrolledwin), text);
gtk_widget_show(text);
logwin->window = window;
logwin->scrolledwin = scrolledwin;
logwin->text = text;
logwin->hook_id = hooks_register_hook(LOG_APPEND_TEXT_HOOKLIST, log_window_append, logwin);
return logwin;
}
void log_window_init(LogWindow *logwin)
{
GtkTextBuffer *buffer;
GdkColormap *colormap;
GdkColor color[3] =
{{0, 0, 0xafff, 0}, {0, 0xefff, 0, 0}, {0, 0xefff, 0, 0}};
gboolean success[3];
gint i;
gtkut_widget_disable_theme_engine(logwin->text);
logwin->msg_color = color[0];
logwin->warn_color = color[1];
logwin->error_color = color[2];
colormap = gdk_window_get_colormap(logwin->window->window);
gdk_colormap_alloc_colors(colormap, color, 3, FALSE, TRUE, success);
for (i = 0; i < 3; i++) {
if (success[i] == FALSE) {
GtkStyle *style;
g_warning("LogWindow: color allocation failed\n");
style = gtk_widget_get_style(logwin->window);
logwin->msg_color = logwin->warn_color =
logwin->error_color = style->black;
break;
}
}
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(logwin->text));
gtk_text_buffer_create_tag(buffer, "message",
"foreground-gdk", &logwin->msg_color,
NULL);
gtk_text_buffer_create_tag(buffer, "warn",
"foreground-gdk", &logwin->warn_color,
NULL);
gtk_text_buffer_create_tag(buffer, "error",
"foreground-gdk", &logwin->error_color,
NULL);
}
void log_window_show(LogWindow *logwin)
{
GtkTextView *text = GTK_TEXT_VIEW(logwin->text);
GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
GtkTextMark *mark;
mark = gtk_text_buffer_get_mark(buffer, "end");
gtk_text_view_scroll_mark_onscreen(text, mark);
gtk_widget_show(logwin->window);
}
static gboolean log_window_append(gpointer source, gpointer data)
{
LogText *logtext = (LogText *) source;
LogWindow *logwindow = (LogWindow *) data;
GtkTextView *text;
GtkTextBuffer *buffer;
GtkTextIter iter;
GdkColor *color = NULL;
gchar *head = NULL;
const gchar *tag;
g_return_val_if_fail(logtext != NULL, TRUE);
g_return_val_if_fail(logtext->text != NULL, TRUE);
g_return_val_if_fail(logwindow != NULL, FALSE);
if (prefs_common.cliplog && !prefs_common.loglength)
return FALSE;
text = GTK_TEXT_VIEW(logwindow->text);
buffer = gtk_text_view_get_buffer(text);
gtk_text_buffer_get_iter_at_offset(buffer, &iter, -1);
switch (logtext->type) {
case LOG_MSG:
color = &logwindow->msg_color;
tag = "message";
head = "* ";
break;
case LOG_WARN:
color = &logwindow->warn_color;
tag = "warn";
head = "** ";
break;
case LOG_ERROR:
color = &logwindow->error_color;
tag = "error";
head = "*** ";
break;
default:
tag = NULL;
break;
}
if (head)
gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, head, -1,
tag, NULL);
gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, logtext->text, -1,
tag, NULL);
gtk_text_buffer_get_start_iter(buffer, &iter);
gtk_text_buffer_place_cursor(buffer, &iter);
if (prefs_common.cliplog)
log_window_clear (GTK_WIDGET (text));
return FALSE;
}
static void hide_cb(GtkWidget *widget, LogWindow *logwin)
{
}
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
LogWindow *logwin)
{
if (event && event->keyval == GDK_Escape)
gtk_widget_hide(logwin->window);
return FALSE;
}
void log_window_clear(GtkWidget *textw)
{
guint length;
guint point;
GtkTextView *textview = GTK_TEXT_VIEW(textw);
GtkTextBuffer *textbuf = gtk_text_view_get_buffer(textview);
GtkTextIter start_iter, end_iter;
length = gtk_text_buffer_get_char_count (textbuf);
debug_print("Log window length: %u\n", length);
if (length > prefs_common.loglength) {
/* find the end of the first line after the cut off
* point */
point = length - prefs_common.loglength;
gtk_text_buffer_get_iter_at_offset(textbuf, &end_iter, point);
if (!gtk_text_iter_forward_to_line_end(&end_iter))
return;
gtk_text_buffer_get_start_iter(textbuf, &start_iter);
gtk_text_buffer_delete(textbuf, &start_iter, &end_iter);
}
}

View file

@ -1,45 +0,0 @@
/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
* Copyright (C) 1999,2000 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 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __LOGWINDOW_H__
#define __LOGWINDOW_H__
#include <glib.h>
#include <gtk/gtkwidget.h>
typedef struct _LogWindow LogWindow;
struct _LogWindow
{
GtkWidget *window;
GtkWidget *scrolledwin;
GtkWidget *text;
GdkColor msg_color;
GdkColor warn_color;
GdkColor error_color;
guint hook_id;
};
LogWindow *log_window_create(void);
void log_window_init(LogWindow *logwin);
void log_window_show(LogWindow *logwin);
#endif /* __LOGWINDOW_H__ */

View file

@ -51,8 +51,8 @@
#include "prefs_common.h"
#include "prefs_account.h"
#include "prefs_actions.h"
#include "prefs_fonts.h"
#include "prefs_spelling.h"
#include "scoring.h"
#include "prefs_display_header.h"
#include "account.h"
#include "procmsg.h"
@ -73,7 +73,8 @@
#include "plugin.h"
#if USE_GPGME
# include "rfc2015.h"
# include "sgpgme.h"
# include "pgpmime.h"
#endif
#if USE_OPENSSL
# include "ssl.h"
@ -116,10 +117,6 @@ static struct RemoteCmd {
static void parse_cmd_opt(int argc, char *argv[]);
#if USE_GPGME
static void idle_function_for_gpgme(void);
#endif /* USE_GPGME */
static gint prohibit_duplicate_launch (void);
static gchar * get_crashfile_name (void);
static gint lock_socket_remove (void);
@ -139,6 +136,7 @@ static void send_queue (void);
static void initial_processing (FolderItem *item, gpointer data);
static void quit_signal_handler (int sig);
static void install_basic_sighandlers (void);
static void exit_sylpheed (MainWindow *mainwin);
#if 0
/* for gettext */
@ -249,29 +247,11 @@ int main(int argc, char *argv[])
prefs_common_read_config();
#if USE_GPGME
gpg_started = FALSE;
if (gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP) !=
GPGME_No_Error) { /* Also does some gpgme init */
rfc2015_disable_all();
debug_print("gpgme_engine_version:\n%s\n",
gpgme_get_engine_info());
if (prefs_common.gpg_warning) {
AlertValue val;
val = alertpanel_message_with_disable
(_("Warning"),
_("GnuPG is not installed properly, or needs to be upgraded.\n"
"OpenPGP support disabled."));
if (val & G_ALERTDISABLE)
prefs_common.gpg_warning = FALSE;
}
} else
gpg_started = TRUE;
gpgme_register_idle(idle_function_for_gpgme);
sgpgme_init();
pgpmime_init();
#endif
prefs_fonts_init();
#ifdef USE_ASPELL
gtkaspell_checkers_init();
prefs_spelling_init();
@ -312,7 +292,6 @@ int main(int argc, char *argv[])
folder_set_missing_folders();
folderview_set(folderview);
/* prefs_scoring_read_config(); */
prefs_matcher_read_config();
/* make one all-folder processing before using sylpheed */
@ -333,6 +312,11 @@ int main(int argc, char *argv[])
/* ignore SIGPIPE signal for preventing sudden death of program */
signal(SIGPIPE, SIG_IGN);
if (cmd.online_mode == ONLINE_MODE_OFFLINE)
main_window_toggle_work_offline(mainwin, TRUE);
if (cmd.online_mode == ONLINE_MODE_ONLINE)
main_window_toggle_work_offline(mainwin, FALSE);
if (cmd.receive_all)
inc_all_account_mail(mainwin, FALSE,
prefs_common.newmail_notify_manu);
@ -362,11 +346,6 @@ int main(int argc, char *argv[])
cmd.status_full_folders = NULL;
}
if (cmd.online_mode == ONLINE_MODE_OFFLINE)
main_window_toggle_work_offline(mainwin, TRUE);
if (cmd.online_mode == ONLINE_MODE_ONLINE)
main_window_toggle_work_offline(mainwin, FALSE);
prefs_toolbar_init();
plugin_load_all("GTK");
@ -374,19 +353,93 @@ int main(int argc, char *argv[])
static_mainwindow = mainwin;
gtk_main();
exit_sylpheed(mainwin);
return 0;
}
static void save_all_caches(FolderItem *item, gpointer data)
{
if (!item->cache)
return;
folder_item_write_cache(item);
}
static void exit_sylpheed(MainWindow *mainwin)
{
gchar *filename;
GList *list;
debug_print("shutting down\n");
inc_autocheck_timer_remove();
if (prefs_common.clean_on_exit)
main_window_empty_trash(mainwin, prefs_common.ask_on_clean);
/* save prefs for opened folder */
if(mainwin->folderview->opened)
{
FolderItem *item;
item = gtk_ctree_node_get_row_data(GTK_CTREE(mainwin->folderview->ctree), mainwin->folderview->opened);
summary_save_prefs_to_folderitem(mainwin->folderview->summaryview, item);
}
/* save all state before exiting */
folder_write_list();
folder_func_to_all_folders(save_all_caches, NULL);
for (list = folder_get_list(); list != NULL; list = g_list_next(list)) {
Folder *folder = FOLDER(list->data);
folder_tree_destroy(folder);
}
main_window_get_size(mainwin);
main_window_get_position(mainwin);
prefs_common_save_config();
account_save_config_all();
addressbook_export_to_file();
filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
#warning FIXME_GTK2 gtk_item_factory_dump_rc() not existing
#if 0
gtk_item_factory_dump_rc(filename, NULL, TRUE);
#endif
gtk_accel_map_save(filename);
g_free(filename);
/* delete temporary files */
remove_all_files(get_mime_tmp_dir());
close_log_file();
/* delete crashfile */
if (!cmd.crash)
unlink(get_crashfile_name());
lock_socket_remove();
main_window_destroy(mainwin);
plugin_unload_all("GTK");
prefs_toolbar_done();
addressbook_destroy();
#ifdef USE_GPGME
pgpmime_done();
sgpgme_done();
#endif
prefs_fonts_done();
#ifdef USE_ASPELL
prefs_spelling_done();
gtkaspell_checkers_quit();
#endif
sylpheed_done();
return 0;
}
static void parse_cmd_opt(int argc, char *argv[])
@ -511,13 +564,6 @@ static gint get_queued_message_num(void)
return queue->total_msgs;
}
static void save_all_caches(FolderItem *item, gpointer data)
{
if (!item->cache)
return;
folder_item_write_cache(item);
}
static void initial_processing(FolderItem *item, gpointer data)
{
MainWindow *mainwin = (MainWindow *)data;
@ -533,7 +579,8 @@ static void initial_processing(FolderItem *item, gpointer data)
main_window_cursor_wait(mainwin);
folder_item_apply_processing(item);
if (item->prefs->enable_processing)
folder_item_apply_processing(item);
debug_print("done.\n");
STATUSBAR_POP(mainwin);
@ -554,8 +601,14 @@ static void draft_all_messages(void)
}
}
void clean_quit(void)
gboolean clean_quit(gpointer data)
{
static gboolean firstrun = TRUE;
if (!firstrun)
return FALSE;
firstrun = FALSE;
/*!< Good idea to have the main window stored in a
* static variable so we can check that variable
* to see if we're really allowed to do things
@ -569,27 +622,19 @@ void clean_quit(void)
* in the original spawner, and not in a spawned
* child. */
if (!static_mainwindow)
return;
return FALSE;
draft_all_messages();
if (prefs_common.warn_queued_on_exit) {
/* disable the popup */
prefs_common.warn_queued_on_exit = FALSE;
app_will_exit(NULL, static_mainwindow);
prefs_common.warn_queued_on_exit = TRUE;
prefs_common_save_config();
} else {
app_will_exit(NULL, static_mainwindow);
}
exit_sylpheed(static_mainwindow);
exit(0);
return FALSE;
}
void app_will_exit(GtkWidget *widget, gpointer data)
{
MainWindow *mainwin = data;
gchar *filename;
GList *list;
if (compose_get_compose_list()) {
gint val = alertpanel(_("Notice"),
@ -614,66 +659,9 @@ void app_will_exit(GtkWidget *widget, gpointer data)
return;
manage_window_focus_in(mainwin->window, NULL, NULL);
}
inc_autocheck_timer_remove();
#if USE_GPGME
gpgmegtk_free_passphrase();
#endif
if (prefs_common.clean_on_exit)
main_window_empty_trash(mainwin, prefs_common.ask_on_clean);
/* save prefs for opened folder */
if(mainwin->folderview->opened)
{
FolderItem *item;
item = gtk_ctree_node_get_row_data(GTK_CTREE(mainwin->folderview->ctree), mainwin->folderview->opened);
summary_save_prefs_to_folderitem(mainwin->folderview->summaryview, item);
}
/* save all state before exiting */
folder_write_list();
folder_func_to_all_folders(save_all_caches, NULL);
for (list = folder_get_list(); list != NULL; list = g_list_next(list)) {
Folder *folder = FOLDER(list->data);
folder_tree_destroy(folder);
}
main_window_get_size(mainwin);
main_window_get_position(mainwin);
prefs_common_save_config();
account_save_config_all();
addressbook_export_to_file();
filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
gtk_accel_map_save (filename);
g_free(filename);
/* delete temporary files */
remove_all_files(get_mime_tmp_dir());
close_log_file();
/* delete crashfile */
if (!cmd.crash)
unlink(get_crashfile_name());
lock_socket_remove();
gtk_main_quit();
}
#if USE_GPGME
static void idle_function_for_gpgme(void)
{
while (gtk_events_pending())
gtk_main_iteration();
}
#endif /* USE_GPGME */
/*
* CLAWS: want this public so crash dialog can delete the
* lock file too
@ -902,9 +890,6 @@ static void open_compose_new(const gchar *address, GPtrArray *attach_files)
static void send_queue(void)
{
GList *list;
FolderItem *def_outbox;
def_outbox = folder_get_default_outbox();
for (list = folder_get_list(); list != NULL; list = list->next) {
Folder *folder = list->data;
@ -917,10 +902,6 @@ static void send_queue(void)
alertpanel_error(_("Some errors occurred while sending queued messages."));
if (res)
folder_item_scan(folder->queue);
if (prefs_common.savemsg && folder->outbox) {
if (folder->outbox == def_outbox)
def_outbox = NULL;
}
}
}
}
@ -928,7 +909,8 @@ static void send_queue(void)
static void quit_signal_handler(int sig)
{
debug_print("Quitting on signal %d\n", sig);
clean_quit();
g_timeout_add(0, clean_quit, NULL);
}
static void install_basic_sighandlers()

View file

@ -27,6 +27,6 @@ extern gchar *prog_version;
extern gboolean debug_mode;
void app_will_exit (GtkWidget *widget, gpointer data);
void clean_quit (void);
gboolean clean_quit (gpointer data);
#endif /* __MAIN_H__ */

View file

@ -39,6 +39,7 @@
#include <gtk/gtkhandlebox.h>
#include <gtk/gtktoolbar.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtktooltips.h>
#include <string.h>
#include "intl.h"
@ -62,7 +63,6 @@
#include "prefs_common.h"
#include "prefs_actions.h"
#include "prefs_filtering.h"
#include "prefs_scoring.h"
#include "prefs_account.h"
#include "prefs_summary_column.h"
#include "prefs_template.h"
@ -86,6 +86,8 @@
#include "pluginwindow.h"
#include "hooks.h"
#include "progressindicator.h"
#include "localfolder.h"
#include "filtering.h"
#define AC_LABEL_WIDTH 240
@ -136,9 +138,6 @@ static void message_window_size_allocate_cb (GtkWidget *widget,
static void new_folder_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
static void add_mbox_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
static void rename_folder_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
@ -345,6 +344,9 @@ static void select_thread_cb (MainWindow *mainwin,
static void create_filter_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
static void create_processing_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
static void prefs_common_open_cb (MainWindow *mainwin,
guint action,
@ -358,9 +360,15 @@ static void prefs_actions_open_cb (MainWindow *mainwin,
static void prefs_account_open_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
static void prefs_scoring_open_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
static void prefs_pre_processing_open_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
static void prefs_post_processing_open_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
static void prefs_filtering_open_cb (MainWindow *mainwin,
guint action,
GtkWidget *widget);
@ -425,15 +433,15 @@ static GtkItemFactoryEntry mainwin_entries[] =
NULL, update_folderview_cb, 0, NULL},
{N_("/_File/_Add mailbox"), NULL, NULL, 0, "<Branch>"},
{N_("/_File/_Add mailbox/MH..."), NULL, add_mailbox_cb, 0, NULL},
{N_("/_File/_Add mailbox/mbox..."), NULL, add_mbox_cb, 0, NULL},
{N_("/_File/_Import mbox file..."), NULL, import_mbox_cb, 0, NULL},
{N_("/_File/_Export to mbox file..."), NULL, export_mbox_cb, 0, NULL},
{N_("/_File/Empty _trash"), "<shift>D", empty_trash_cb, 0, NULL},
{N_("/_File/_Work offline"), "<control>W", toggle_work_offline_cb, 0, "<ToggleItem>"},
{N_("/_File/---"), NULL, NULL, 0, "<Separator>"},
{N_("/_File/_Save as..."), "<control>S", save_as_cb, 0, NULL},
{N_("/_File/_Print..."), NULL, print_cb, 0, NULL},
{N_("/_File/---"), NULL, NULL, 0, "<Separator>"},
{N_("/_File/_Work offline"), "<control>W", toggle_work_offline_cb, 0, "<ToggleItem>"},
{N_("/_File/---"), NULL, NULL, 0, "<Separator>"},
/* {N_("/_File/_Close"), "<alt>W", app_exit_cb, 0, NULL}, */
{N_("/_File/E_xit"), "<control>Q", app_exit_cb, 0, NULL},
@ -665,6 +673,15 @@ static GtkItemFactoryEntry mainwin_entries[] =
NULL, create_filter_cb, FILTER_BY_TO, NULL},
{N_("/_Tools/_Create filter rule/by _Subject"),
NULL, create_filter_cb, FILTER_BY_SUBJECT, NULL},
{N_("/_Tools/_Create processing rule"), NULL, NULL, 0, "<Branch>"},
{N_("/_Tools/_Create processing rule/_Automatically"),
NULL, create_processing_cb, FILTER_BY_AUTO, NULL},
{N_("/_Tools/_Create processing rule/by _From"),
NULL, create_processing_cb, FILTER_BY_FROM, NULL},
{N_("/_Tools/_Create processing rule/by _To"),
NULL, create_processing_cb, FILTER_BY_TO, NULL},
{N_("/_Tools/_Create processing rule/by _Subject"),
NULL, create_processing_cb, FILTER_BY_SUBJECT, NULL},
{N_("/_Tools/---"), NULL, NULL, 0, "<Separator>"},
{N_("/_Tools/Actio_ns"), NULL, NULL, 0, "<Branch>"},
{N_("/_Tools/---"), NULL, NULL, 0, "<Separator>"},
@ -692,8 +709,10 @@ static GtkItemFactoryEntry mainwin_entries[] =
{N_("/_Configuration/---"), NULL, NULL, 0, "<Separator>"},
{N_("/_Configuration/_Common preferences..."),
NULL, prefs_common_open_cb, 0, NULL},
{N_("/_Configuration/_Scoring..."),
NULL, prefs_scoring_open_cb, 0, NULL},
{N_("/_Configuration/Pre-processing..."),
NULL, prefs_pre_processing_open_cb, 0, NULL},
{N_("/_Configuration/Post-processing..."),
NULL, prefs_post_processing_open_cb, 0, NULL},
{N_("/_Configuration/_Filtering..."),
NULL, prefs_filtering_open_cb, 0, NULL},
{N_("/_Configuration/_Templates..."), NULL, prefs_template_open_cb, 0, NULL},
@ -824,16 +843,17 @@ MainWindow *main_window_create(SeparateType type)
gtk_widget_set_size_request(progressbar, 120, 1);
gtk_box_pack_start(GTK_BOX(hbox_stat), progressbar, FALSE, FALSE, 0);
online_pixmap = stock_pixmap_widget(hbox_stat, STOCK_PIXMAP_WORK_ONLINE);
offline_pixmap = stock_pixmap_widget(hbox_stat, STOCK_PIXMAP_WORK_OFFLINE);
online_pixmap = stock_pixmap_widget(hbox_stat, STOCK_PIXMAP_ONLINE);
offline_pixmap = stock_pixmap_widget(hbox_stat, STOCK_PIXMAP_OFFLINE);
online_tip = gtk_tooltips_new();
online_switch = gtk_button_new ();
gtk_tooltips_set_tip(GTK_TOOLTIPS(online_tip),
online_switch, _("Go offline"), NULL);
gtk_tooltips_set_tip(GTK_TOOLTIPS(online_tip),online_switch,
_("You are online. Click the icon to go offline"), NULL);
offline_tip = gtk_tooltips_new();
offline_switch = gtk_button_new ();
gtk_tooltips_set_tip(GTK_TOOLTIPS(offline_tip),
offline_switch, _("Go online"), NULL);
gtk_tooltips_set_tip(GTK_TOOLTIPS(offline_tip),offline_switch,
_("You are offline. Click the icon to go online"),
NULL);
gtk_container_add (GTK_CONTAINER(online_switch), online_pixmap);
gtk_button_set_relief (GTK_BUTTON(online_switch), GTK_RELIEF_NONE);
g_signal_connect (G_OBJECT(online_switch), "clicked", G_CALLBACK(online_switch_clicked), mainwin);
@ -1013,6 +1033,8 @@ MainWindow *main_window_create(SeparateType type)
summary_init(summaryview);
messageview_init(messageview);
log_window_init(mainwin->logwin);
log_window_set_clipping(mainwin->logwin, prefs_common.cliplog,
prefs_common.loglength);
#ifdef USE_OPENSSL
sslcertwindow_register_hook();
#endif
@ -1035,6 +1057,12 @@ MainWindow *main_window_create(SeparateType type)
return mainwin;
}
void main_window_destroy(MainWindow *mainwin)
{
/* TODO : destroy other component */
messageview_destroy(mainwin->messageview);
}
void main_window_cursor_wait(MainWindow *mainwin)
{
@ -1118,13 +1146,13 @@ void main_window_reflect_prefs_all_real(gboolean pixmap_theme_changed)
folderview_reflect_prefs_pixmap_theme(mainwin->folderview);
summary_reflect_prefs_pixmap_theme(mainwin->summaryview);
pixmap = stock_pixmap_widget(mainwin->hbox_stat, STOCK_PIXMAP_WORK_ONLINE);
pixmap = stock_pixmap_widget(mainwin->hbox_stat, STOCK_PIXMAP_ONLINE);
gtk_container_remove(GTK_CONTAINER(mainwin->online_switch),
mainwin->online_pixmap);
gtk_container_add (GTK_CONTAINER(mainwin->online_switch), pixmap);
gtk_widget_show(pixmap);
mainwin->online_pixmap = pixmap;
pixmap = stock_pixmap_widget(mainwin->hbox_stat, STOCK_PIXMAP_WORK_OFFLINE);
pixmap = stock_pixmap_widget(mainwin->hbox_stat, STOCK_PIXMAP_OFFLINE);
gtk_container_remove(GTK_CONTAINER(mainwin->offline_switch),
mainwin->offline_pixmap);
gtk_container_add (GTK_CONTAINER(mainwin->offline_switch), pixmap);
@ -1482,39 +1510,6 @@ void main_window_add_mailbox(MainWindow *mainwin)
folderview_set(mainwin->folderview);
}
void main_window_add_mbox(MainWindow *mainwin)
{
gchar *path;
Folder *folder;
FolderItem * item;
path = input_dialog(_("Add mbox mailbox"),
_("Input the location of mailbox."),
"mail");
if (!path) return;
if (folder_find_from_path(path)) {
alertpanel_error(_("The mailbox `%s' already exists."), path);
g_free(path);
return;
}
folder = folder_new(folder_get_class_from_string("mbox"),
g_basename(path), path);
g_free(path);
if (folder->klass->create_tree(folder) < 0) {
alertpanel_error(_("Creation of the mailbox failed."));
folder_destroy(folder);
return;
}
folder_add(folder);
folderview_set(mainwin->folderview);
}
SensitiveCond main_window_get_current_state(MainWindow *mainwin)
{
SensitiveCond state = 0;
@ -1596,7 +1591,6 @@ void main_window_set_menu_sensitive(MainWindow *mainwin)
{"/File/Add mailbox" , M_UNLOCKED},
{"/File/Add mailbox/MH..." , M_UNLOCKED},
{"/File/Add mailbox/mbox..." , M_UNLOCKED},
{"/File/Export to mbox file..." , M_UNLOCKED},
{"/File/Empty trash" , M_UNLOCKED},
{"/File/Work offline" , M_UNLOCKED},
@ -1721,7 +1715,7 @@ void main_window_set_menu_sensitive(MainWindow *mainwin)
}
SET_CHECK_MENU_ACTIVE("/View/Show all headers",
mainwin->messageview->textview->show_all_headers);
mainwin->messageview->mimeview->textview->show_all_headers);
SET_CHECK_MENU_ACTIVE("/View/Thread view", (state & M_THREADED) != 0);
#undef SET_CHECK_MENU_ACTIVE
@ -1854,9 +1848,6 @@ static void main_window_set_widgets(MainWindow *mainwin, SeparateType type)
g_signal_connect(G_OBJECT(messagewin), "delete_event",
G_CALLBACK(message_window_close_cb),
mainwin);
gtk_container_add(GTK_CONTAINER(messagewin),
GTK_WIDGET_PTR(mainwin->messageview));
gtk_widget_realize(messagewin);
if (messageview_is_visible(mainwin->messageview))
gtk_widget_show(messagewin);
}
@ -1944,14 +1935,32 @@ static void main_window_set_widgets(MainWindow *mainwin, SeparateType type)
mainwin->win.sep_message.messagewin = messagewin;
mainwin->win.sep_message.hpaned = hpaned;
gtk_widget_realize(messagewin);
gtk_widget_show_all(GTK_WIDGET_PTR(mainwin->messageview));
gtk_widget_show_all(messagewin);
toolbar_set_style(mainwin->messageview->toolbar->toolbar,
mainwin->messageview->handlebox,
prefs_common.toolbar_style);
break;
case SEPARATE_BOTH:
messageview_add_toolbar(mainwin->messageview, messagewin);
msgview_ifactory = gtk_item_factory_from_widget(mainwin->messageview->menubar);
menu_set_sensitive(msgview_ifactory, "/File/Close", FALSE);
gtk_box_pack_start(GTK_BOX(vbox_body),
GTK_WIDGET_PTR(mainwin->summaryview),
TRUE, TRUE, 0);
mainwin->win.sep_both.folderwin = folderwin;
mainwin->win.sep_both.messagewin = messagewin;
gtk_widget_realize(messagewin);
gtk_widget_show_all(GTK_WIDGET_PTR(mainwin->messageview));
gtk_widget_show_all(messagewin);
toolbar_set_style(mainwin->messageview->toolbar->toolbar,
mainwin->messageview->handlebox,
prefs_common.toolbar_style);
break;
}
@ -1967,6 +1976,8 @@ static void main_window_set_widgets(MainWindow *mainwin, SeparateType type)
* and mimeview icon list/ctree lose track of their visibility states */
if (!noticeview_is_visible(mainwin->messageview->noticeview))
gtk_widget_hide(GTK_WIDGET_PTR(mainwin->messageview->noticeview));
if (!noticeview_is_visible(mainwin->messageview->mimeview->siginfoview))
gtk_widget_hide(GTK_WIDGET_PTR(mainwin->messageview->mimeview->siginfoview));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mainwin->messageview->mimeview->mime_toggle)))
gtk_widget_hide(mainwin->messageview->mimeview->icon_mainbox);
else
@ -2157,12 +2168,6 @@ static void add_mailbox_cb(MainWindow *mainwin, guint action,
main_window_add_mailbox(mainwin);
}
static void add_mbox_cb(MainWindow *mainwin, guint action,
GtkWidget *widget)
{
main_window_add_mbox(mainwin);
}
static void update_folderview_cb(MainWindow *mainwin, guint action,
GtkWidget *widget)
{
@ -2681,8 +2686,7 @@ static void allsel_cb(MainWindow *mainwin, guint action, GtkWidget *widget)
if (GTK_WIDGET_HAS_FOCUS(mainwin->summaryview->ctree))
summary_select_all(mainwin->summaryview);
else if (messageview_is_visible(msgview) &&
(GTK_WIDGET_HAS_FOCUS(msgview->textview->text) ||
GTK_WIDGET_HAS_FOCUS(msgview->mimeview->textview->text)))
(GTK_WIDGET_HAS_FOCUS(msgview->mimeview->textview->text)))
messageview_select_all(mainwin->messageview);
}
@ -2695,7 +2699,13 @@ static void select_thread_cb(MainWindow *mainwin, guint action,
static void create_filter_cb(MainWindow *mainwin, guint action,
GtkWidget *widget)
{
summary_filter_open(mainwin->summaryview, (PrefsFilterType)action);
summary_filter_open(mainwin->summaryview, (PrefsFilterType)action, 0);
}
static void create_processing_cb(MainWindow *mainwin, guint action,
GtkWidget *widget)
{
summary_filter_open(mainwin->summaryview, (PrefsFilterType)action, 1);
}
static void prefs_common_open_cb(MainWindow *mainwin, guint action,
@ -2704,16 +2714,28 @@ static void prefs_common_open_cb(MainWindow *mainwin, guint action,
prefs_common_open();
}
static void prefs_scoring_open_cb(MainWindow *mainwin, guint action,
GtkWidget *widget)
static void prefs_pre_processing_open_cb(MainWindow *mainwin, guint action,
GtkWidget *widget)
{
prefs_scoring_open(NULL);
prefs_filtering_open(&pre_global_processing,
_("Processing rules to apply before folder rules"),
NULL, NULL);
}
static void prefs_post_processing_open_cb(MainWindow *mainwin, guint action,
GtkWidget *widget)
{
prefs_filtering_open(&post_global_processing,
_("Processing rules to apply after folder rules"),
NULL, NULL);
}
static void prefs_filtering_open_cb(MainWindow *mainwin, guint action,
GtkWidget *widget)
{
prefs_filtering_open(NULL, NULL, NULL);
prefs_filtering_open(&filtering_rules,
_("Filtering configuration"),
NULL, NULL);
}
static void prefs_template_open_cb(MainWindow *mainwin, guint action,
@ -2800,6 +2822,11 @@ static gboolean mainwindow_focus_in_event(GtkWidget *widget, GdkEventFocus *focu
g_return_val_if_fail(data, FALSE);
summary = ((MainWindow *)data)->summaryview;
g_return_val_if_fail(summary, FALSE);
if (GTK_CLIST(summary->ctree)->selection &&
g_list_length(GTK_CLIST(summary->ctree)->selection) > 1)
return FALSE;
if (summary->selected != summary->displayed)
summary_select_node(summary, summary->displayed, FALSE, TRUE);
return FALSE;

View file

@ -136,6 +136,8 @@ struct _MainWindow
MainWindow *main_window_create (SeparateType type);
void main_window_destroy (MainWindow *mainwin);
void main_window_cursor_wait (MainWindow *mainwin);
void main_window_cursor_normal (MainWindow *mainwin);

View file

@ -28,6 +28,7 @@
#include "intl.h"
#include "matcher_parser.h"
#include "prefs_gtk.h"
#include <ctype.h>
/*!
*\brief Keyword lookup element
@ -100,8 +101,8 @@ static const MatchParser matchparser_tab[] = {
{MATCHCRITERIA_NOT_MESSAGE, "~message"},
{MATCHCRITERIA_BODY_PART, "body_part"},
{MATCHCRITERIA_NOT_BODY_PART, "~body_part"},
{MATCHCRITERIA_EXECUTE, "execute"},
{MATCHCRITERIA_NOT_EXECUTE, "~execute"},
{MATCHCRITERIA_TEST, "test"},
{MATCHCRITERIA_NOT_TEST, "~test"},
/* match type */
{MATCHTYPE_MATCHCASE, "matchcase"},
@ -110,7 +111,7 @@ static const MatchParser matchparser_tab[] = {
{MATCHTYPE_REGEXP, "regexp"},
/* actions */
{MATCHACTION_SCORE, "score"},
{MATCHACTION_SCORE, "score"}, /* for backward compatibility */
{MATCHACTION_MOVE, "move"},
{MATCHACTION_COPY, "copy"},
{MATCHACTION_DELETE, "delete"},
@ -125,7 +126,10 @@ static const MatchParser matchparser_tab[] = {
{MATCHACTION_EXECUTE, "execute"},
{MATCHACTION_COLOR, "color"},
{MATCHACTION_REDIRECT, "redirect"},
{MATCHACTION_CHANGE_SCORE, "change_score"}
{MATCHACTION_CHANGE_SCORE, "change_score"},
{MATCHACTION_SET_SCORE, "set_score"},
{MATCHACTION_STOP, "stop"},
{MATCHACTION_HIDE, "hide"},
};
/*!
@ -183,92 +187,6 @@ gint get_matchparser_tab_id(const gchar *str)
return -1;
}
/*!
*\brief Escape characters in a string by inserting '\' characters
*
*\param str String with characters to be escaped
*
*\return gchar * Newly allocated string with escaped characters
*/
gchar *matcher_escape_str(const gchar *str)
{
register const gchar *walk;
register int escape;
gchar *res;
register char *reswalk;
if (str == NULL)
return NULL;
for (escape = 0, walk = str; *walk; walk++)
if (*walk == '\\' || *walk == '\'' || *walk == '\"')
escape++;
if (!escape)
return g_strdup(str);
reswalk = res = g_new0(gchar, (walk - str) + escape + 1);
for (walk = str; *walk; walk++, reswalk++) {
if (*walk == '\\' || *walk == '\'' || *walk == '\"')
*reswalk++ = '\\';
*reswalk = *walk;
}
*reswalk = 0;
return res;
}
/*!
*\brief Unescape string by replacing escaped char sequences
* (\b, \n, etc) by their actual char. Note that this
* function changes the contents of the buffer pointed
* to by \a str.
*
*\param str Buffer containing string that needs to be escaped.
* Note that this function changes the contents of the
* buffer
*
*\return gchar * Pointer to changed buffer
*/
gchar *matcher_unescape_str(gchar *str)
{
gchar *tmp = alloca(strlen(str) + 1);
register gchar *src = tmp;
register gchar *dst = str;
strcpy(tmp, str);
for ( ; *src; src++) {
if (*src != '\\')
*dst++ = *src;
else {
src++;
if (*src == 'n') /* insert control characters */
*dst++ = '\n';
else if (*src == 'r')
*dst++ = '\r';
else if (*src == 't')
*dst++ = '\t';
else if (*src == 'r')
*dst++ = '\r';
else if (*src == 'b')
*dst++ = '\b';
else if (*src == 'f')
*dst++ = '\f';
else if (*src == '\\' || *src == '\'' || *src == '\"')
/* insert \\, \' or \" */
*dst++ = *src;
else {
/* FIXME: should perhaps escape character... */
src--;
*dst++ = *src;
}
}
}
*dst = 0;
return str;
}
/* **************** data structure allocation **************** */
/*!
@ -342,42 +260,6 @@ MatcherProp *matcherprop_copy(const MatcherProp *src)
return prop;
}
/* ****************** wrapper for file reading ************** */
/*!
*\brief Allocate a matcher structure where all strings
* are unescaped ("unquoted")
*
*\param criteria One of the MATCHCRITERIA_XXX constants
*\param header A header string
*\param matchtype Type of matcher (MATCHTYPE_XXX)
*\param expr Matcher string expression
*\param value Matcher integer value
*
*\return MatcherProp * Pointer to newly allocated matcher
* structure
*/
MatcherProp *matcherprop_unquote_new(gint criteria, const gchar *header,
gint matchtype, const gchar *expr,
int value)
{
MatcherProp *prop;
if (expr != NULL)
expr = matcher_unescape_str(g_strdup(expr));
if (header != NULL)
header = matcher_unescape_str(g_strdup(header));
prop = matcherprop_new(criteria, header, matchtype, expr, value);
g_free((gpointer) header);
g_free((gpointer) expr);
return prop;
}
/* ************** match ******************************/
/*!
@ -446,7 +328,7 @@ static gboolean matcherprop_string_match(MatcherProp *prop, const gchar *str)
*
*\return gboolean TRUE if command was executed succesfully
*/
static gboolean matcherprop_match_execute(const MatcherProp *prop,
static gboolean matcherprop_match_test(const MatcherProp *prop,
MsgInfo *info)
{
gchar *file;
@ -577,10 +459,10 @@ gboolean matcherprop_match(MatcherProp *prop,
return matcherprop_string_match(prop, info->references);
case MATCHCRITERIA_NOT_REFERENCES:
return !matcherprop_string_match(prop, info->references);
case MATCHCRITERIA_EXECUTE:
return matcherprop_match_execute(prop, info);
case MATCHCRITERIA_NOT_EXECUTE:
return !matcherprop_match_execute(prop, info);
case MATCHCRITERIA_TEST:
return matcherprop_match_test(prop, info);
case MATCHCRITERIA_NOT_TEST:
return !matcherprop_match_test(prop, info);
default:
return 0;
}
@ -1028,8 +910,8 @@ gboolean matcherlist_match(MatcherList *matchers, MsgInfo *info)
case MATCHCRITERIA_SIZE_GREATER:
case MATCHCRITERIA_SIZE_SMALLER:
case MATCHCRITERIA_SIZE_EQUAL:
case MATCHCRITERIA_EXECUTE:
case MATCHCRITERIA_NOT_EXECUTE:
case MATCHCRITERIA_TEST:
case MATCHCRITERIA_NOT_TEST:
if (matcherprop_match(matcher, info)) {
if (!matchers->bool_and) {
return TRUE;
@ -1057,6 +939,68 @@ gboolean matcherlist_match(MatcherList *matchers, MsgInfo *info)
return result;
}
static gint quote_filter_str(gchar * result, guint size,
const gchar * path)
{
const gchar * p;
gchar * result_p;
guint remaining;
result_p = result;
remaining = size;
for(p = path ; * p != '\0' ; p ++) {
if ((* p != '\"') && (* p != '\\')) {
if (remaining > 0) {
* result_p = * p;
result_p ++;
remaining --;
}
else {
result[size - 1] = '\0';
return -1;
}
}
else {
if (remaining >= 2) {
* result_p = '\\';
result_p ++;
* result_p = * p;
result_p ++;
remaining -= 2;
}
else {
result[size - 1] = '\0';
return -1;
}
}
}
if (remaining > 0) {
* result_p = '\0';
}
else {
result[size - 1] = '\0';
return -1;
}
return 0;
}
gchar * matcher_quote_str(const gchar * src)
{
gchar * res;
gint len;
len = strlen(src) * 2 + 1;
res = g_malloc(len);
quote_filter_str(res, len, src);
return res;
}
/*!
*\brief Convert a matcher structure to a string
*
@ -1070,8 +1014,8 @@ gchar *matcherprop_to_string(MatcherProp *matcher)
const gchar *criteria_str;
const gchar *matchtype_str;
int i;
gchar *expr;
gchar * quoted_expr;
criteria_str = NULL;
for (i = 0; i < (int) (sizeof(matchparser_tab) / sizeof(MatchParser)); i++) {
if (matchparser_tab[i].id == matcher->criteria)
@ -1110,11 +1054,12 @@ gchar *matcherprop_to_string(MatcherProp *matcher)
case MATCHCRITERIA_IGNORE_THREAD:
case MATCHCRITERIA_NOT_IGNORE_THREAD:
return g_strdup(criteria_str);
case MATCHCRITERIA_EXECUTE:
case MATCHCRITERIA_NOT_EXECUTE:
expr = matcher_escape_str(matcher->expr);
matcher_str = g_strdup_printf("%s \"%s\"", criteria_str, expr);
g_free((gpointer) expr);
case MATCHCRITERIA_TEST:
case MATCHCRITERIA_NOT_TEST:
quoted_expr = matcher_quote_str(matcher->expr);
matcher_str = g_strdup_printf("%s \"%s\"",
criteria_str, quoted_expr);
g_free(quoted_expr);
return matcher_str;
}
@ -1132,17 +1077,22 @@ gchar *matcherprop_to_string(MatcherProp *matcher)
case MATCHTYPE_MATCHCASE:
case MATCHTYPE_REGEXP:
case MATCHTYPE_REGEXPCASE:
expr = matcher_escape_str(matcher->expr);
if (matcher->header)
quoted_expr = matcher_quote_str(matcher->expr);
if (matcher->header) {
gchar * quoted_header;
quoted_header = matcher_quote_str(matcher->header);
matcher_str = g_strdup_printf
("%s \"%s\" %s \"%s\"",
criteria_str, matcher->header,
matchtype_str, expr);
criteria_str, quoted_header,
matchtype_str, quoted_expr);
g_free(quoted_header);
}
else
matcher_str = g_strdup_printf
("%s %s \"%s\"", criteria_str,
matchtype_str, expr);
g_free((gpointer) expr);
matchtype_str, quoted_expr);
g_free(quoted_expr);
break;
}
@ -1187,8 +1137,27 @@ gchar *matcherlist_to_string(const MatcherList *matchers)
return result;
}
#define STRLEN_ZERO(s) ((s) ? strlen(s) : 0)
#define STRLEN_DEFAULT(s,d) ((s) ? strlen(s) : STRLEN_ZERO(d))
static void add_str_default(gchar ** dest,
const gchar * s, const gchar * d)
{
gchar quoted_str[4096];
const gchar * str;
if (s != NULL)
str = s;
else
str = d;
quote_cmd_argument(quoted_str, sizeof(quoted_str), str);
strcpy(* dest, quoted_str);
(* dest) += strlen(* dest);
}
/* matching_build_command() - preferably cmd should be unescaped */
/*!
*\brief Build the command line to execute
@ -1197,9 +1166,6 @@ gchar *matcherlist_to_string(const MatcherList *matchers)
*\param info Message info to use for command
*
*\return gchar * Newly allocated string
*
*\warning The \a cmd string should have been unescaped using
* #matcher_unescape_str.
*/
gchar *matching_build_command(const gchar *cmd, MsgInfo *info)
{
@ -1251,21 +1217,25 @@ gchar *matching_build_command(const gchar *cmd, MsgInfo *info)
size += STRLEN_DEFAULT(info->references, no_references) - 2;
break;
case 'F': /* file */
filename = folder_item_fetch_msg(info->folder,
info->msgnum);
if (filename == NULL)
filename = folder_item_fetch_msg(info->folder, info->msgnum);
if (filename == NULL) {
g_warning("filename is not set");
return NULL;
}
else
else {
size += strlen(filename) - 2;
}
break;
}
s++;
}
else s++;
}
/* as the string can be quoted, we double the result */
size *= 2;
processed_cmd = g_new0(gchar, size);
s = cmd;
@ -1280,65 +1250,40 @@ gchar *matching_build_command(const gchar *cmd, MsgInfo *info)
p++;
break;
case 's': /* subject */
if (info->subject != NULL)
strcpy(p, info->subject);
else
strcpy(p, no_subject);
p += strlen(p);
add_str_default(&p, info->subject,
no_subject);
break;
case 'f': /* from */
if (info->from != NULL)
strcpy(p, info->from);
else
strcpy(p, no_from);
p += strlen(p);
add_str_default(&p, info->from,
no_from);
break;
case 't': /* to */
if (info->to != NULL)
strcpy(p, info->to);
else
strcpy(p, no_to);
p += strlen(p);
add_str_default(&p, info->to,
no_to);
break;
case 'c': /* cc */
if (info->cc != NULL)
strcpy(p, info->cc);
else
strcpy(p, no_cc);
p += strlen(p);
add_str_default(&p, info->cc,
no_cc);
break;
case 'd': /* date */
if (info->date != NULL)
strcpy(p, info->date);
else
strcpy(p, no_date);
p += strlen(p);
add_str_default(&p, info->date,
no_date);
break;
case 'i': /* message-id */
if (info->msgid != NULL)
strcpy(p, info->msgid);
else
strcpy(p, no_msgid);
p += strlen(p);
add_str_default(&p, info->msgid,
no_msgid);
break;
case 'n': /* newsgroups */
if (info->newsgroups != NULL)
strcpy(p, info->newsgroups);
else
strcpy(p, no_newsgroups);
p += strlen(p);
add_str_default(&p, info->newsgroups,
no_newsgroups);
break;
case 'r': /* references */
if (info->references != NULL)
strcpy(p, info->references);
else
strcpy(p, no_references);
p += strlen(p);
add_str_default(&p, info->references,
no_references);
break;
case 'F': /* file */
strcpy(p, filename);
p += strlen(p);
g_free(filename);
if (filename != NULL)
add_str_default(&p, filename, NULL);
break;
default:
*p = '%';
@ -1355,7 +1300,8 @@ gchar *matching_build_command(const gchar *cmd, MsgInfo *info)
s++;
}
}
g_free(filename);
return processed_cmd;
}
#undef STRLEN_DEFAULT
@ -1363,31 +1309,6 @@ gchar *matching_build_command(const gchar *cmd, MsgInfo *info)
/* ************************************************************ */
/*!
*\brief Write scoring list to file
*
*\param fp File
*\param prefs_scoring List of scoring conditions
*/
static void prefs_scoring_write(FILE *fp, GSList *prefs_scoring)
{
GSList *cur;
for (cur = prefs_scoring; cur != NULL; cur = cur->next) {
gchar *scoring_str;
ScoringProp *prop;
prop = (ScoringProp *) cur->data;
scoring_str = scoringprop_to_string(prop);
if (fputs(scoring_str, fp) == EOF ||
fputc('\n', fp) == EOF) {
FILE_OP_ERROR("scoring config", "fputs || fputc");
g_free(scoring_str);
return;
}
g_free(scoring_str);
}
}
/*!
*\brief Write filtering list to file
@ -1432,33 +1353,20 @@ static gboolean prefs_matcher_write_func(GNode *node, gpointer data)
FolderItem *item;
FILE *fp = data;
gchar *id;
GSList *prefs_scoring;
GSList *prefs_filtering;
if (node != NULL) {
item = node->data;
/* prevent warning */
if (item->path == NULL)
return FALSE;
id = folder_item_get_identifier(item);
if (id == NULL)
return FALSE;
prefs_scoring = item->prefs->scoring;
prefs_filtering = item->prefs->processing;
}
else {
item = NULL;
id = g_strdup("global"); /* because it is g_freed */
prefs_scoring = global_scoring;
prefs_filtering = global_processing;
}
item = node->data;
/* prevent warning */
if (item->path == NULL)
return FALSE;
id = folder_item_get_identifier(item);
if (id == NULL)
return FALSE;
prefs_filtering = item->prefs->processing;
if (prefs_filtering != NULL || prefs_scoring != NULL) {
if (prefs_filtering != NULL) {
fprintf(fp, "[%s]\n", id);
prefs_filtering_write(fp, prefs_filtering);
prefs_scoring_write(fp, prefs_scoring);
fputc('\n', fp);
}
@ -1483,7 +1391,21 @@ static void prefs_matcher_save(FILE *fp)
g_node_traverse(folder->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
prefs_matcher_write_func, fp);
}
prefs_matcher_write_func(NULL, fp);
/* pre global rules */
fprintf(fp, "[preglobal]\n");
prefs_filtering_write(fp, pre_global_processing);
fputc('\n', fp);
/* post global rules */
fprintf(fp, "[postglobal]\n");
prefs_filtering_write(fp, post_global_processing);
fputc('\n', fp);
/* filtering rules */
fprintf(fp, "[filtering]\n");
prefs_filtering_write(fp, filtering_rules);
fputc('\n', fp);
}
/*!
@ -1527,7 +1449,6 @@ void prefs_matcher_read_config(void)
FILE *f;
create_matchparser_hashtab();
prefs_scoring_clear();
prefs_filtering_clear();
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MATCHER_RC, NULL);

View file

@ -27,6 +27,7 @@
/* constants generated by yacc */
#if !defined(YYBISON) && !defined(MATCHER_ALL)
# include "matcher_parser_lex.h"
# include "matcher_parser_parse.h"
#endif
@ -93,7 +94,7 @@ enum {
MC_(HEADERS_PART), MC_(NOT_HEADERS_PART),
MC_(MESSAGE), MC_(NOT_MESSAGE),
MC_(BODY_PART), MC_(NOT_BODY_PART),
MC_(EXECUTE), MC_(NOT_EXECUTE),
MC_(TEST), MC_(NOT_TEST),
MC_(SCORE_EQUAL),
MC_(SIZE_GREATER),
MC_(SIZE_SMALLER),
@ -120,6 +121,9 @@ enum {
MA_(COLOR),
MA_(REDIRECT),
MA_(CHANGE_SCORE),
MA_(SET_SCORE),
MA_(STOP),
MA_(HIDE),
/* boolean operations */
MB_(OR),
MB_(AND)
@ -133,11 +137,6 @@ MatcherProp *matcherprop_new (gint criteria,
gint matchtype,
const gchar *expr,
int value);
MatcherProp *matcherprop_unquote_new (gint criteria,
const gchar *header,
gint matchtype,
const gchar *expr,
int value);
void matcherprop_free (MatcherProp *prop);
MatcherProp *matcherprop_parse (gchar **str);
@ -161,8 +160,6 @@ gint matcher_parse_number (gchar **str);
gboolean matcher_parse_boolean_op (gchar **str);
gchar *matcher_parse_regexp (gchar **str);
gchar *matcher_parse_str (gchar **str);
gchar *matcher_escape_str (const gchar *str);
gchar *matcher_unescape_str (gchar *str);
gchar *matcherprop_to_string (MatcherProp *matcher);
gchar *matcherlist_to_string (const MatcherList *matchers);
gchar *matching_build_command (const gchar *cmd,
@ -170,6 +167,7 @@ gchar *matching_build_command (const gchar *cmd,
void prefs_matcher_read_config (void);
void prefs_matcher_write_config (void);
void *matcher_parser_scan_string (const gchar *str);
gchar * matcher_quote_str(const gchar * src);
#endif

View file

@ -21,7 +21,6 @@
#define MATCHER_PARSER_H
#include "filtering.h"
#include "scoring.h"
#include <glib.h>
extern FILE *matcher_parserin;
@ -34,7 +33,6 @@ int matcher_parserparse (void);
MatcherList *matcher_parser_get_cond (const gchar *str);
MatcherProp *matcher_parser_get_prop (const gchar *str);
FilteringProp *matcher_parser_get_filtering (const gchar *str);
ScoringProp *matcher_parser_get_scoring (const gchar *str);
GSList *matcher_parser_get_action_list(const gchar *str);
#endif

View file

@ -21,6 +21,7 @@
#include <string.h>
#include <glib.h>
#include "matcher.h"
#include "matcher_parser_lex.h"
#include "matcher_parser_parse.h"
@ -75,15 +76,6 @@ void matcher_parser_init(void)
BEGIN(string);
string_buf_ptr = string_buf;
}
/* alfons - OK, the new attempt is to just swallow
* *EVERYTHING* and make sure everything is escaped
* when actually performing things. */
<string>\\\" {
/* take care of escaped \" because this means the
* quote char should be skipped */
add_char('\\');
add_char('\"');
}
<string>\" {
/* get out of the state: string ends. */
BEGIN(0);
@ -91,11 +83,15 @@ void matcher_parser_init(void)
yylval.str = string_buf;
return MATCHER_STRING;
}
/* put everything else in the output. */
<string>\\. {
/* take care of quoted characters */
add_char(yytext[1]);
}
<string>. {
add_char(yytext[0]);
}
\[[^\[\]]*\] {
/* for section name in configuration file */
BEGIN(0);
yylval.str = yytext + 1;
yytext[strlen(yytext) - 1] = '\0';

View file

@ -27,7 +27,6 @@
#include "intl.h"
#include "utils.h"
#include "filtering.h"
#include "scoring.h"
#include "matcher.h"
#include "matcher_parser.h"
#include "matcher_parser_lex.h"
@ -50,23 +49,18 @@ static GSList *action_list = NULL;
static FilteringAction *action = NULL;
static FilteringProp *filtering;
static ScoringProp *scoring = NULL;
static GSList **prefs_scoring = NULL;
static GSList **prefs_filtering = NULL;
#if 0
static int matcher_parser_dialog = 0;
#endif
static int enable_compatibility = 0;
enum {
MATCHER_PARSE_NONE,
MATCHER_PARSE_FILE,
MATCHER_PARSE_NO_EOL,
MATCHER_PARSE_CONDITION,
MATCHER_PARSE_FILTERING_OR_SCORING,
MATCHER_PARSE_FILTERING_ACTION,
};
static int matcher_parse_op = MATCHER_PARSE_NONE;
static int matcher_parse_op = MATCHER_PARSE_FILE;
/* ******************************************************************** */
@ -76,6 +70,9 @@ void matcher_parser_start_parsing(FILE *f)
matcher_parserrestart(f);
matcher_parserparse();
}
void * matcher_parser_scan_string(const char * str);
FilteringProp *matcher_parser_get_filtering(const gchar *str)
{
@ -87,34 +84,15 @@ FilteringProp *matcher_parser_get_filtering(const gchar *str)
matcher_parse_op = MATCHER_PARSE_NO_EOL;
matcher_parserrestart(NULL);
matcher_parser_init();
bufstate = matcher_parser_scan_string(str);
bufstate = matcher_parser_scan_string((const char *) str);
matcher_parser_switch_to_buffer(bufstate);
if (matcher_parserparse() != 0)
filtering = NULL;
matcher_parse_op = MATCHER_PARSE_NONE;
matcher_parse_op = MATCHER_PARSE_FILE;
matcher_parser_delete_buffer(bufstate);
return filtering;
}
ScoringProp *matcher_parser_get_scoring(const gchar *str)
{
void *bufstate;
/* bad coding to enable the sub-grammar matching
in yacc */
matcher_parserlineno = 1;
matcher_parse_op = MATCHER_PARSE_NO_EOL;
matcher_parserrestart(NULL);
matcher_parser_init();
bufstate = matcher_parser_scan_string(str);
matcher_parser_switch_to_buffer(bufstate);
if (matcher_parserparse() != 0)
scoring = NULL;
matcher_parse_op = MATCHER_PARSE_NONE;
matcher_parser_delete_buffer(bufstate);
return scoring;
}
static gboolean check_quote_symetry(gchar *str)
{
const gchar *walk;
@ -151,7 +129,7 @@ MatcherList *matcher_parser_get_cond(const gchar *str)
matcher_parser_init();
bufstate = matcher_parser_scan_string(str);
matcher_parserparse();
matcher_parse_op = MATCHER_PARSE_NONE;
matcher_parse_op = MATCHER_PARSE_FILE;
matcher_parser_delete_buffer(bufstate);
return cond;
}
@ -168,12 +146,12 @@ GSList *matcher_parser_get_action_list(const gchar *str)
/* bad coding to enable the sub-grammar matching
in yacc */
matcher_parserlineno = 1;
matcher_parse_op = MATCHER_PARSE_FILTERING_OR_SCORING;
matcher_parse_op = MATCHER_PARSE_FILTERING_ACTION;
matcher_parserrestart(NULL);
matcher_parser_init();
bufstate = matcher_parser_scan_string(str);
matcher_parserparse();
matcher_parse_op = MATCHER_PARSE_NONE;
matcher_parse_op = MATCHER_PARSE_FILE;
matcher_parser_delete_buffer(bufstate);
return action_list;
}
@ -216,7 +194,7 @@ void matcher_parsererror(char *str)
matchers_list = NULL;
}
cond = NULL;
g_warning("scoring / filtering parsing: %i: %s\n",
g_warning("filtering parsing: %i: %s\n",
matcher_parserlineno, str);
error = 1;
}
@ -245,9 +223,11 @@ int matcher_parserwrap(void)
%token MATCHER_SCORE_LOWER MATCHER_HEADER MATCHER_NOT_HEADER
%token MATCHER_HEADERS_PART MATCHER_NOT_HEADERS_PART MATCHER_MESSAGE
%token MATCHER_NOT_MESSAGE MATCHER_BODY_PART MATCHER_NOT_BODY_PART
%token MATCHER_EXECUTE MATCHER_NOT_EXECUTE MATCHER_MATCHCASE MATCHER_MATCH
%token MATCHER_TEST MATCHER_NOT_TEST MATCHER_MATCHCASE MATCHER_MATCH
%token MATCHER_REGEXPCASE MATCHER_REGEXP MATCHER_SCORE MATCHER_MOVE
%token MATCHER_COPY MATCHER_DELETE MATCHER_MARK MATCHER_UNMARK MATCHER_LOCK MATCHER_UNLOCK
%token MATCHER_COPY MATCHER_DELETE MATCHER_MARK MATCHER_UNMARK
%token MATCHER_LOCK MATCHER_UNLOCK
%token MATCHER_EXECUTE
%token MATCHER_MARK_AS_READ MATCHER_MARK_AS_UNREAD MATCHER_FORWARD
%token MATCHER_FORWARD_AS_ATTACHMENT MATCHER_EOL MATCHER_STRING
%token MATCHER_OR MATCHER_AND
@ -256,7 +236,8 @@ int matcher_parserwrap(void)
%token MATCHER_LOCKED MATCHER_NOT_LOCKED
%token MATCHER_COLORLABEL MATCHER_NOT_COLORLABEL
%token MATCHER_IGNORE_THREAD MATCHER_NOT_IGNORE_THREAD
%token MATCHER_CHANGE_SCORE
%token MATCHER_CHANGE_SCORE MATCHER_SET_SCORE
%token MATCHER_STOP MATCHER_HIDE
%start file
@ -268,9 +249,8 @@ int matcher_parserwrap(void)
file:
{
if (matcher_parse_op == MATCHER_PARSE_NONE) {
prefs_scoring = &global_scoring;
prefs_filtering = &global_processing;
if (matcher_parse_op == MATCHER_PARSE_FILE) {
prefs_filtering = &pre_global_processing;
}
}
file_line_list;
@ -297,17 +277,26 @@ MATCHER_SECTION MATCHER_EOL
gchar *folder = $1;
FolderItem *item = NULL;
if (matcher_parse_op == MATCHER_PARSE_NONE) {
if (matcher_parse_op == MATCHER_PARSE_FILE) {
enable_compatibility = 0;
if (!strcmp(folder, "global")) {
prefs_scoring = &global_scoring;
prefs_filtering = &global_processing;
} else {
/* backward compatibility */
enable_compatibility = 1;
}
else if (!strcmp(folder, "preglobal")) {
prefs_filtering = &pre_global_processing;
}
else if (!strcmp(folder, "postglobal")) {
prefs_filtering = &post_global_processing;
}
else if (!strcmp(folder, "filtering")) {
prefs_filtering = &filtering_rules;
}
else {
item = folder_find_item_from_identifier(folder);
if (item != NULL) {
prefs_scoring = &item->prefs->scoring;
prefs_filtering = &item->prefs->processing;
} else {
prefs_scoring = NULL;
prefs_filtering = NULL;
}
}
@ -316,8 +305,8 @@ MATCHER_SECTION MATCHER_EOL
;
instruction:
condition filtering_or_scoring MATCHER_EOL
| condition filtering_or_scoring
condition filtering MATCHER_EOL
| condition filtering
{
if (matcher_parse_op == MATCHER_PARSE_NO_EOL)
YYACCEPT;
@ -337,7 +326,7 @@ condition filtering_or_scoring MATCHER_EOL
}
| filtering_action_list
{
if (matcher_parse_op == MATCHER_PARSE_FILTERING_OR_SCORING)
if (matcher_parse_op == MATCHER_PARSE_FILTERING_ACTION)
YYACCEPT;
else {
matcher_parsererror("parse error");
@ -347,29 +336,33 @@ condition filtering_or_scoring MATCHER_EOL
| MATCHER_EOL
;
filtering_or_scoring:
filtering:
filtering_action_list
{
filtering = filteringprop_new(cond, action_list);
if (enable_compatibility) {
prefs_filtering = &filtering_rules;
if (action_list != NULL) {
FilteringAction * first_action;
first_action = action_list->data;
if (first_action->type == MATCHACTION_CHANGE_SCORE)
prefs_filtering = &pre_global_processing;
}
}
cond = NULL;
action_list = NULL;
if ((matcher_parse_op == MATCHER_PARSE_NONE) && (prefs_filtering != NULL)) {
if ((matcher_parse_op == MATCHER_PARSE_FILE) &&
(prefs_filtering != NULL)) {
*prefs_filtering = g_slist_append(*prefs_filtering,
filtering);
filtering = NULL;
}
}
| scoring_rule
{
scoring = scoringprop_new(cond, score);
cond = NULL;
score = 0;
if ((matcher_parse_op == MATCHER_PARSE_NONE)
&& (prefs_scoring != NULL)) {
*prefs_scoring = g_slist_append(*prefs_scoring, scoring);
scoring = NULL;
}
}
;
filtering_action_list:
@ -441,105 +434,105 @@ MATCHER_ALL
gint criteria = 0;
criteria = MATCHCRITERIA_ALL;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_UNREAD
{
gint criteria = 0;
criteria = MATCHCRITERIA_UNREAD;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_NOT_UNREAD
{
gint criteria = 0;
criteria = MATCHCRITERIA_NOT_UNREAD;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_NEW
{
gint criteria = 0;
criteria = MATCHCRITERIA_NEW;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_NOT_NEW
{
gint criteria = 0;
criteria = MATCHCRITERIA_NOT_NEW;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_MARKED
{
gint criteria = 0;
criteria = MATCHCRITERIA_MARKED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_NOT_MARKED
{
gint criteria = 0;
criteria = MATCHCRITERIA_NOT_MARKED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_DELETED
{
gint criteria = 0;
criteria = MATCHCRITERIA_DELETED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_NOT_DELETED
{
gint criteria = 0;
criteria = MATCHCRITERIA_NOT_DELETED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_REPLIED
{
gint criteria = 0;
criteria = MATCHCRITERIA_REPLIED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_NOT_REPLIED
{
gint criteria = 0;
criteria = MATCHCRITERIA_NOT_REPLIED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_FORWARDED
{
gint criteria = 0;
criteria = MATCHCRITERIA_FORWARDED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_NOT_FORWARDED
{
gint criteria = 0;
criteria = MATCHCRITERIA_NOT_FORWARDED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_LOCKED
{
gint criteria = 0;
criteria = MATCHCRITERIA_LOCKED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_NOT_LOCKED
{
gint criteria = 0;
criteria = MATCHCRITERIA_NOT_LOCKED;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_COLORLABEL MATCHER_INTEGER
{
@ -547,10 +540,10 @@ MATCHER_ALL
gint value = 0;
criteria = MATCHCRITERIA_COLORLABEL;
value = atoi($2);
if (value < 1) value = 1;
value = strtol($2, NULL, 10);
if (value < 0) value = 0;
else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_NOT_COLORLABEL MATCHER_INTEGER
{
@ -558,24 +551,24 @@ MATCHER_ALL
gint value = 0;
criteria = MATCHCRITERIA_NOT_COLORLABEL;
value = atoi($2);
if (value < 1) value = 1;
value = strtol($2, NULL, 0);
if (value < 0) value = 0;
else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_IGNORE_THREAD
{
gint criteria = 0;
criteria = MATCHCRITERIA_IGNORE_THREAD;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_NOT_IGNORE_THREAD
{
gint criteria = 0;
criteria = MATCHCRITERIA_NOT_IGNORE_THREAD;
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
}
| MATCHER_SUBJECT match_type MATCHER_STRING
{
@ -584,7 +577,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_SUBJECT;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_SUBJECT match_type MATCHER_STRING
{
@ -593,7 +586,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_SUBJECT;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_FROM match_type MATCHER_STRING
{
@ -602,7 +595,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_FROM;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_FROM match_type MATCHER_STRING
{
@ -611,7 +604,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_FROM;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_TO match_type MATCHER_STRING
{
@ -620,7 +613,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_TO;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_TO match_type MATCHER_STRING
{
@ -629,7 +622,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_TO;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_CC match_type MATCHER_STRING
{
@ -638,7 +631,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_CC;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_CC match_type MATCHER_STRING
{
@ -647,7 +640,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_CC;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_TO_OR_CC match_type MATCHER_STRING
{
@ -656,7 +649,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_TO_OR_CC;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_TO_AND_NOT_CC match_type MATCHER_STRING
{
@ -665,7 +658,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_TO_AND_NOT_CC;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_AGE_GREATER MATCHER_INTEGER
{
@ -673,8 +666,8 @@ MATCHER_ALL
gint value = 0;
criteria = MATCHCRITERIA_AGE_GREATER;
value = atoi($2);
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
value = strtol($2, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_AGE_LOWER MATCHER_INTEGER
{
@ -682,8 +675,8 @@ MATCHER_ALL
gint value = 0;
criteria = MATCHCRITERIA_AGE_LOWER;
value = atoi($2);
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
value = strtol($2, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_NEWSGROUPS match_type MATCHER_STRING
{
@ -692,7 +685,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NEWSGROUPS;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_NEWSGROUPS match_type MATCHER_STRING
{
@ -701,7 +694,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_NEWSGROUPS;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_INREPLYTO match_type MATCHER_STRING
{
@ -710,7 +703,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_INREPLYTO;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_INREPLYTO match_type MATCHER_STRING
{
@ -719,7 +712,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_INREPLYTO;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_REFERENCES match_type MATCHER_STRING
{
@ -728,7 +721,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_REFERENCES;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_REFERENCES match_type MATCHER_STRING
{
@ -737,7 +730,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_REFERENCES;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_SCORE_GREATER MATCHER_INTEGER
{
@ -745,8 +738,8 @@ MATCHER_ALL
gint value = 0;
criteria = MATCHCRITERIA_SCORE_GREATER;
value = atoi($2);
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
value = strtol($2, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_SCORE_LOWER MATCHER_INTEGER
{
@ -754,8 +747,8 @@ MATCHER_ALL
gint value = 0;
criteria = MATCHCRITERIA_SCORE_LOWER;
value = atoi($2);
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
value = strtol($2, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_SCORE_EQUAL MATCHER_INTEGER
{
@ -763,32 +756,32 @@ MATCHER_ALL
gint value = 0;
criteria = MATCHCRITERIA_SCORE_EQUAL;
value = atoi($2);
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
value = strtol($2, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_SIZE_GREATER MATCHER_INTEGER
{
gint criteria = 0;
gint value = 0;
criteria = MATCHCRITERIA_SIZE_GREATER;
value = atoi($2);
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
value = strtol($2, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_SIZE_SMALLER MATCHER_INTEGER
{
gint criteria = 0;
gint value = 0;
criteria = MATCHCRITERIA_SIZE_SMALLER;
value = atoi($2);
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
value = strtol($2, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_SIZE_EQUAL MATCHER_INTEGER
{
gint criteria = 0;
gint value = 0;
criteria = MATCHCRITERIA_SIZE_EQUAL;
value = atoi($2);
prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
value = strtol($2, NULL, 0);
prop = matcherprop_new(criteria, NULL, 0, NULL, value);
}
| MATCHER_HEADER MATCHER_STRING
{
@ -800,7 +793,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_HEADER;
expr = $2;
prop = matcherprop_unquote_new(criteria, header, match_type, expr, 0);
prop = matcherprop_new(criteria, header, match_type, expr, 0);
g_free(header);
}
| MATCHER_NOT_HEADER MATCHER_STRING
@ -813,7 +806,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_HEADER;
expr = $2;
prop = matcherprop_unquote_new(criteria, header, match_type, expr, 0);
prop = matcherprop_new(criteria, header, match_type, expr, 0);
g_free(header);
}
| MATCHER_HEADERS_PART match_type MATCHER_STRING
@ -823,7 +816,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_HEADERS_PART;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_HEADERS_PART match_type MATCHER_STRING
{
@ -832,7 +825,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_HEADERS_PART;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_MESSAGE match_type MATCHER_STRING
{
@ -841,7 +834,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_MESSAGE;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_MESSAGE match_type MATCHER_STRING
{
@ -850,7 +843,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_MESSAGE;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_BODY_PART match_type MATCHER_STRING
{
@ -859,7 +852,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_BODY_PART;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_NOT_BODY_PART match_type MATCHER_STRING
{
@ -868,25 +861,25 @@ MATCHER_ALL
criteria = MATCHCRITERIA_NOT_BODY_PART;
expr = $3;
prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
}
| MATCHER_EXECUTE MATCHER_STRING
| MATCHER_TEST MATCHER_STRING
{
gint criteria = 0;
gchar *expr = NULL;
criteria = MATCHCRITERIA_EXECUTE;
criteria = MATCHCRITERIA_TEST;
expr = $2;
prop = matcherprop_unquote_new(criteria, NULL, 0, expr, 0);
prop = matcherprop_new(criteria, NULL, 0, expr, 0);
}
| MATCHER_NOT_EXECUTE MATCHER_STRING
| MATCHER_NOT_TEST MATCHER_STRING
{
gint criteria = 0;
gchar *expr = NULL;
criteria = MATCHCRITERIA_NOT_EXECUTE;
criteria = MATCHCRITERIA_NOT_TEST;
expr = $2;
prop = matcherprop_unquote_new(criteria, NULL, 0, expr, 0);
prop = matcherprop_new(criteria, NULL, 0, expr, 0);
}
;
@ -898,7 +891,7 @@ MATCHER_EXECUTE MATCHER_STRING
action_type = MATCHACTION_EXECUTE;
cmd = $2;
action = filteringaction_new(action_type, 0, cmd, 0);
action = filteringaction_new(action_type, 0, cmd, 0, 0);
}
| MATCHER_MOVE MATCHER_STRING
{
@ -907,7 +900,7 @@ MATCHER_EXECUTE MATCHER_STRING
action_type = MATCHACTION_MOVE;
destination = $2;
action = filteringaction_new(action_type, 0, destination, 0);
action = filteringaction_new(action_type, 0, destination, 0, 0);
}
| MATCHER_COPY MATCHER_STRING
{
@ -916,56 +909,56 @@ MATCHER_EXECUTE MATCHER_STRING
action_type = MATCHACTION_COPY;
destination = $2;
action = filteringaction_new(action_type, 0, destination, 0);
action = filteringaction_new(action_type, 0, destination, 0, 0);
}
| MATCHER_DELETE
{
gint action_type = 0;
action_type = MATCHACTION_DELETE;
action = filteringaction_new(action_type, 0, NULL, 0);
action = filteringaction_new(action_type, 0, NULL, 0, 0);
}
| MATCHER_MARK
{
gint action_type = 0;
action_type = MATCHACTION_MARK;
action = filteringaction_new(action_type, 0, NULL, 0);
action = filteringaction_new(action_type, 0, NULL, 0, 0);
}
| MATCHER_UNMARK
{
gint action_type = 0;
action_type = MATCHACTION_UNMARK;
action = filteringaction_new(action_type, 0, NULL, 0);
action = filteringaction_new(action_type, 0, NULL, 0, 0);
}
| MATCHER_LOCK
{
gint action_type = 0;
action_type = MATCHACTION_LOCK;
action = filteringaction_new(action_type, 0, NULL, 0);
action = filteringaction_new(action_type, 0, NULL, 0, 0);
}
| MATCHER_UNLOCK
{
gint action_type = 0;
action_type = MATCHACTION_UNLOCK;
action = filteringaction_new(action_type, 0, NULL, 0);
action = filteringaction_new(action_type, 0, NULL, 0, 0);
}
| MATCHER_MARK_AS_READ
{
gint action_type = 0;
action_type = MATCHACTION_MARK_AS_READ;
action = filteringaction_new(action_type, 0, NULL, 0);
action = filteringaction_new(action_type, 0, NULL, 0, 0);
}
| MATCHER_MARK_AS_UNREAD
{
gint action_type = 0;
action_type = MATCHACTION_MARK_AS_UNREAD;
action = filteringaction_new(action_type, 0, NULL, 0);
action = filteringaction_new(action_type, 0, NULL, 0, 0);
}
| MATCHER_FORWARD MATCHER_INTEGER MATCHER_STRING
{
@ -974,9 +967,10 @@ MATCHER_EXECUTE MATCHER_STRING
gint account_id = 0;
action_type = MATCHACTION_FORWARD;
account_id = atoi($2);
account_id = strtol($2, NULL, 10);
destination = $3;
action = filteringaction_new(action_type, account_id, destination, 0);
action = filteringaction_new(action_type,
account_id, destination, 0, 0);
}
| MATCHER_FORWARD_AS_ATTACHMENT MATCHER_INTEGER MATCHER_STRING
{
@ -985,9 +979,10 @@ MATCHER_EXECUTE MATCHER_STRING
gint account_id = 0;
action_type = MATCHACTION_FORWARD_AS_ATTACHMENT;
account_id = atoi($2);
account_id = strtol($2, NULL, 10);
destination = $3;
action = filteringaction_new(action_type, account_id, destination, 0);
action = filteringaction_new(action_type,
account_id, destination, 0, 0);
}
| MATCHER_REDIRECT MATCHER_INTEGER MATCHER_STRING
{
@ -996,9 +991,10 @@ MATCHER_EXECUTE MATCHER_STRING
gint account_id = 0;
action_type = MATCHACTION_REDIRECT;
account_id = atoi($2);
account_id = strtol($2, NULL, 10);
destination = $3;
action = filteringaction_new(action_type, account_id, destination, 0);
action = filteringaction_new(action_type,
account_id, destination, 0, 0);
}
| MATCHER_COLOR MATCHER_INTEGER
{
@ -1006,35 +1002,40 @@ MATCHER_EXECUTE MATCHER_STRING
gint color = 0;
action_type = MATCHACTION_COLOR;
color = atoi($2);
action = filteringaction_new(action_type, 0, NULL, color);
color = strtol($2, NULL, 10);
action = filteringaction_new(action_type, 0, NULL, color, 0);
}
| MATCHER_CHANGE_SCORE MATCHER_STRING
| MATCHER_CHANGE_SCORE MATCHER_INTEGER
{
gint action_type = MATCHACTION_CHANGE_SCORE;
char *last_tok = NULL;
const gchar *first_tok;
long int chscore;
int change_type; /* -1 == decrement, 0 == assign, 1 == increment */
#define is_number(x) ( ((x) == '+') || ((x) == '-') || (isdigit((x))) )
/* find start */
for (first_tok = $2; *first_tok && !is_number(*first_tok); first_tok++)
;
#undef is_number
chscore = strtol(first_tok, &last_tok, 10);
if (last_tok == first_tok || *last_tok == 0)
chscore = 0;
change_type = *first_tok == '+' ? 1 : *first_tok == '-' ? -1 : 0;
action = filteringaction_new(MATCHACTION_CHANGE_SCORE, change_type,
NULL, chscore);
}
;
scoring_rule:
MATCHER_SCORE MATCHER_INTEGER
{
score = atoi($2);
gint score = 0;
score = strtol($2, NULL, 10);
action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
NULL, 0, score);
}
/* backward compatibility */
| MATCHER_SCORE MATCHER_INTEGER
{
gint score = 0;
score = strtol($2, NULL, 10);
action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
NULL, 0, score);
}
| MATCHER_SET_SCORE MATCHER_INTEGER
{
gint score = 0;
score = strtol($2, NULL, 10);
action = filteringaction_new(MATCHACTION_SET_SCORE, 0,
NULL, 0, score);
}
| MATCHER_HIDE
{
action = filteringaction_new(MATCHACTION_HIDE, 0, NULL, 0, 0);
}
| MATCHER_STOP
{
action = filteringaction_new(MATCHACTION_STOP, 0, NULL, 0, 0);
}
;

File diff suppressed because it is too large Load diff

View file

@ -1,46 +0,0 @@
/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
* Copyright (C) 1999-2001 Hiroyuki Yamamoto & The Sylpheed Claws 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 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef MBOX_FOLDER_H
#define MBOX_FOLDER_H
#include <glib.h>
#include "folder.h"
/*
mailfile mailfile_init(char * filename);
char * mailfile_readmsg(mailfile f, int index);
char * mailfile_readheader(mailfile f, int index);
void mailfile_done(mailfile f);
int mailfile_count(mailfile f);
*/
typedef struct _MBOXFolder MBOXFolder;
#define MBOX_FOLDER(obj) ((MBOXFolder *)obj)
struct _MBOXFolder
{
LocalFolder lfolder;
};
FolderClass *mbox_get_class (void);
gchar * mbox_get_virtual_path(FolderItem * item);
#endif

View file

@ -61,11 +61,10 @@
#include "send_message.h"
#include "stock_pixmap.h"
#include "hooks.h"
#include "filtering.h"
static GList *messageview_list = NULL;
static void messageview_change_view_type(MessageView *messageview,
MessageType type);
static void messageview_destroy_cb (GtkWidget *widget,
MessageView *messageview);
static void messageview_size_allocate_cb(GtkWidget *widget,
@ -128,6 +127,9 @@ static void add_address_cb (gpointer data,
static void create_filter_cb (gpointer data,
guint action,
GtkWidget *widget);
static void create_processing_cb (gpointer data,
guint action,
GtkWidget *widget);
static void about_cb (gpointer data,
guint action,
@ -271,6 +273,14 @@ static GtkItemFactoryEntry msgview_entries[] =
NULL, create_filter_cb, FILTER_BY_TO, NULL},
{N_("/_Tools/_Create filter rule/by _Subject"),
NULL, create_filter_cb, FILTER_BY_SUBJECT, NULL},
{N_("/_Tools/Create processing rule/_Automatically"),
NULL, create_processing_cb, FILTER_BY_AUTO, NULL},
{N_("/_Tools/Create processing rule/by _From"),
NULL, create_processing_cb, FILTER_BY_FROM, NULL},
{N_("/_Tools/Create processing rule/by _To"),
NULL, create_processing_cb, FILTER_BY_TO, NULL},
{N_("/_Tools/Create processing rule/by _Subject"),
NULL, create_processing_cb, FILTER_BY_SUBJECT, NULL},
{N_("/_Tools/---"), NULL, NULL, 0, "<Separator>"},
{N_("/_Tools/Actio_ns"), NULL, NULL, 0, "<Branch>"},
@ -283,22 +293,16 @@ MessageView *messageview_create(MainWindow *mainwin)
MessageView *messageview;
GtkWidget *vbox;
HeaderView *headerview;
TextView *textview;
MimeView *mimeview;
NoticeView *noticeview;
debug_print("Creating message view...\n");
messageview = g_new0(MessageView, 1);
messageview->type = MVIEW_TEXT;
headerview = headerview_create();
noticeview = noticeview_create(mainwin);
textview = textview_create();
textview->messageview = messageview;
mimeview = mimeview_create(mainwin);
mimeview->textview = textview_create();
mimeview->textview->messageview = messageview;
@ -309,20 +313,14 @@ MessageView *messageview_create(MainWindow *mainwin)
FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(noticeview),
FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(textview),
TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox),
GTK_WIDGET_PTR(mimeview), TRUE, TRUE, 0);
gtk_widget_show(vbox);
/* to remove without destroyed */
gtk_widget_ref(GTK_WIDGET_PTR(textview));
gtk_widget_ref(GTK_WIDGET_PTR(mimeview));
gtk_widget_ref(GTK_WIDGET_PTR(mimeview->textview));
messageview->vbox = vbox;
messageview->new_window = FALSE;
messageview->window = NULL;
messageview->headerview = headerview;
messageview->textview = textview;
messageview->mimeview = mimeview;
messageview->noticeview = noticeview;
messageview->mainwin = mainwin;
@ -395,8 +393,8 @@ MessageView *messageview_create_with_new_window(MainWindow *mainwin)
messageview_add_toolbar(msgview, window);
gtk_widget_grab_focus(msgview->textview->text);
gtk_widget_show_all(window);
gtk_widget_grab_focus(msgview->mimeview->textview->text);
gtk_widget_show(window);
msgview->new_window = TRUE;
msgview->window = window;
@ -412,7 +410,6 @@ MessageView *messageview_create_with_new_window(MainWindow *mainwin)
void messageview_init(MessageView *messageview)
{
headerview_init(messageview->headerview);
textview_init(messageview->textview);
mimeview_init(messageview->mimeview);
/*messageview_set_font(messageview);*/
@ -454,6 +451,8 @@ static gint disposition_notification_send(MsgInfo *msginfo)
FolderItem *queue, *outbox;
gint num;
gchar *path;
gchar *addr;
gchar *addrp;
if ((!msginfo->returnreceiptto) &&
(!msginfo->dispositionnotificationto))
@ -465,7 +464,7 @@ static gint disposition_notification_send(MsgInfo *msginfo)
else
to = msginfo->returnreceiptto;
ok = get_header_from_msginfo(msginfo, buf, sizeof(buf),
ok = procheader_get_header_from_msginfo(msginfo, buf, sizeof(buf),
"Return-Path:");
if (ok == 0) {
gchar *to_addr = g_strdup(to);
@ -532,7 +531,12 @@ static gint disposition_notification_send(MsgInfo *msginfo)
FILE_OP_ERROR(tmp, "chmod");
g_warning("can't change file mode\n");
}
addr = g_strdup(to);
extract_address(addr);
addrp = addr;
/* write queue headers */
fprintf(fp, "AF:\n");
fprintf(fp, "NF:0\n");
@ -550,7 +554,9 @@ static gint disposition_notification_send(MsgInfo *msginfo)
else
fprintf(fp, "SSV:\n");
fprintf(fp, "SSH:\n");
fprintf(fp, "R:<%s>\n", to);
fprintf(fp, "R:<%s>\n", addrp);
g_free(addrp);
/* check whether we need to save the message */
outbox = account_get_special_folder(account, F_OUTBOX);
@ -623,22 +629,55 @@ GList *messageview_get_window_list(void)
return messageview_list;
}
void messageview_show(MessageView *messageview, MsgInfo *msginfo,
static gboolean find_encrypted_func(GNode *node, gpointer data)
{
MimeInfo *mimeinfo = (MimeInfo *) node->data;
MimeInfo **encinfo = (MimeInfo **) data;
if (privacy_mimeinfo_is_encrypted(mimeinfo)) {
*encinfo = mimeinfo;
return TRUE;
}
return FALSE;
}
static MimeInfo *find_encrypted_part(MimeInfo *rootinfo)
{
MimeInfo *encinfo = NULL;
g_node_traverse(rootinfo->node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
find_encrypted_func, &encinfo);
return encinfo;
}
gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
gboolean all_headers)
{
gchar *file;
MimeInfo *mimeinfo;
MimeInfo *mimeinfo, *encinfo;
g_return_if_fail(msginfo != NULL);
g_return_val_if_fail(msginfo != NULL, -1);
mimeinfo = procmime_scan_message(msginfo);
g_return_if_fail(mimeinfo != NULL);
if (!mimeinfo) {
textview_show_error(messageview->mimeview->textview);
return -1;
}
while ((encinfo = find_encrypted_part(mimeinfo)) != NULL) {
debug_print("decrypting message part\n");
if (privacy_mimeinfo_decrypt(encinfo) < 0)
break;
}
file = procmsg_get_message_file_path(msginfo);
if (!file) {
g_warning("can't get message file path.\n");
procmime_mimeinfo_free_all(mimeinfo);
return;
textview_show_error(messageview->mimeview->textview);
return -1;
}
if (messageview->msginfo != msginfo) {
@ -648,17 +687,9 @@ void messageview_show(MessageView *messageview, MsgInfo *msginfo,
headerview_show(messageview->headerview, messageview->msginfo);
messageview->all_headers = all_headers;
textview_set_all_headers(messageview->textview, all_headers);
textview_set_all_headers(messageview->mimeview->textview, all_headers);
if (mimeinfo->mime_type != MIME_TEXT) {
messageview_change_view_type(messageview, MVIEW_MIME);
mimeview_show_message(messageview->mimeview, mimeinfo, file);
} else {
messageview_change_view_type(messageview, MVIEW_TEXT);
textview_show_message(messageview->textview, mimeinfo, file);
procmime_mimeinfo_free_all(mimeinfo);
}
mimeview_show_message(messageview->mimeview, mimeinfo, file);
if ((messageview->msginfo->dispositionnotificationto ||
messageview->msginfo->returnreceiptto) &&
@ -668,41 +699,8 @@ void messageview_show(MessageView *messageview, MsgInfo *msginfo,
noticeview_hide(messageview->noticeview);
g_free(file);
}
static void messageview_change_view_type(MessageView *messageview,
MessageType type)
{
TextView *textview = messageview->textview;
MimeView *mimeview = messageview->mimeview;
gboolean hadfocus = GTK_WIDGET_HAS_FOCUS(textview->text);
if (messageview->type == type) return;
if (type == MVIEW_MIME) {
gtkut_container_remove
(GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
GTK_WIDGET_PTR(textview));
gtk_box_pack_start(GTK_BOX(messageview->vbox),
GTK_WIDGET_PTR(mimeview), TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(mimeview->vbox),
GTK_WIDGET_PTR(textview));
} else if (type == MVIEW_TEXT) {
gtkut_container_remove
(GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
GTK_WIDGET_PTR(mimeview));
if (mimeview->vbox == GTK_WIDGET_PTR(textview)->parent)
gtkut_container_remove(GTK_CONTAINER(mimeview->vbox),
GTK_WIDGET_PTR(textview));
gtk_box_pack_start(GTK_BOX(messageview->vbox),
GTK_WIDGET_PTR(textview), TRUE, TRUE, 0);
} else
return;
if (hadfocus) gtk_widget_grab_focus(textview->text);
messageview->type = type;
return 0;
}
void messageview_reflect_prefs_pixmap_theme(void)
@ -721,16 +719,14 @@ void messageview_clear(MessageView *messageview)
{
procmsg_msginfo_free(messageview->msginfo);
messageview->msginfo = NULL;
messageview_change_view_type(messageview, MVIEW_TEXT);
messageview->filtered = FALSE;
mimeview_clear(messageview->mimeview);
headerview_clear(messageview->headerview);
textview_clear(messageview->textview);
noticeview_hide(messageview->noticeview);
}
void messageview_destroy(MessageView *messageview)
{
GtkWidget *textview = GTK_WIDGET_PTR(messageview->textview);
GtkWidget *mimeview = GTK_WIDGET_PTR(messageview->mimeview);
debug_print("destroy messageview\n");
@ -740,7 +736,6 @@ void messageview_destroy(MessageView *messageview)
messageview->msginfo_update_callback_id);
headerview_destroy(messageview->headerview);
textview_destroy(messageview->textview);
mimeview_destroy(messageview->mimeview);
noticeview_destroy(messageview->noticeview);
@ -755,16 +750,30 @@ void messageview_destroy(MessageView *messageview)
g_free(messageview);
gtk_widget_unref(textview);
gtk_widget_unref(mimeview);
}
void messageview_delete(MessageView *msgview)
{
MsgInfo *msginfo = (MsgInfo *) msgview->msginfo;
FolderItem *trash = folder_get_default_trash();
FolderItem *trash = NULL;
PrefsAccount *ac = NULL;
g_return_if_fail(msginfo != NULL);
/* to get the trash folder, we have to choose either
* the folder's or account's trash default - we prefer
* the one in the account prefs */
if (msginfo->folder) {
if (NULL != (ac = account_find_from_item(msginfo->folder)))
trash = account_get_special_folder(ac, F_TRASH);
if (!trash && msginfo->folder->folder)
trash = msginfo->folder->folder->trash;
/* if still not found, use the default */
if (!trash)
trash = folder_get_default_trash();
}
g_return_if_fail(trash != NULL);
if (prefs_common.immediate_exec)
@ -805,32 +814,20 @@ void messageview_quote_color_set(void)
void messageview_set_font(MessageView *messageview)
{
textview_set_font(messageview->textview, NULL);
}
TextView *messageview_get_current_textview(MessageView *messageview)
{
TextView *text = NULL;
if (messageview->type == MVIEW_TEXT)
text = messageview->textview;
else if (messageview->type == MVIEW_MIME) {
if (gtk_notebook_get_current_page
(GTK_NOTEBOOK(messageview->mimeview->notebook)) == 0)
text = messageview->textview;
else if (messageview->mimeview->type == MIMEVIEW_TEXT)
text = messageview->mimeview->textview;
}
text = messageview->mimeview->textview;
return text;
}
MimeInfo *messageview_get_selected_mime_part(MessageView *messageview)
{
if (messageview->type == MVIEW_MIME)
return mimeview_get_selected_part(messageview->mimeview);
return NULL;
return mimeview_get_selected_part(messageview->mimeview);
}
void messageview_copy_clipboard(MessageView *messageview)
@ -859,13 +856,21 @@ void messageview_select_all(MessageView *messageview)
void messageview_set_position(MessageView *messageview, gint pos)
{
textview_set_position(messageview->textview, pos);
TextView *text;
text = messageview_get_current_textview(messageview);
if (text)
textview_set_position(text, pos);
}
gboolean messageview_search_string(MessageView *messageview, const gchar *str,
gboolean case_sens)
{
return textview_search_string(messageview->textview, str, case_sens);
TextView *text;
text = messageview_get_current_textview(messageview);
if (text)
return textview_search_string(text, str, case_sens);
return FALSE;
}
@ -873,8 +878,11 @@ gboolean messageview_search_string_backward(MessageView *messageview,
const gchar *str,
gboolean case_sens)
{
return textview_search_string_backward(messageview->textview,
str, case_sens);
TextView *text;
text = messageview_get_current_textview(messageview);
return textview_search_string_backward(text,
str, case_sens);
return FALSE;
}
@ -964,7 +972,6 @@ void messageview_toggle_view_real(MessageView *messageview)
gtkut_container_remove(GTK_CONTAINER(container), vpaned);
gtk_widget_reparent(GTK_WIDGET_PTR(messageview), container);
menu_set_sensitive(ifactory, "/View/Expand Summary View", FALSE);
gtk_widget_grab_focus(GTK_WIDGET(messageview->textview->text));
} else {
gtk_widget_reparent(GTK_WIDGET_PTR(messageview), vpaned);
gtk_container_add(GTK_CONTAINER(container), vpaned);
@ -1060,15 +1067,11 @@ gchar *messageview_get_selection(MessageView *msgview)
g_return_val_if_fail(msgview != NULL, NULL);
textview = messageview_get_current_textview(msgview);
if (textview) {
edit = GTK_TEXT_VIEW(textview->text);
body_pos = textview->body_pos;
} else {
edit = GTK_TEXT_VIEW(msgview->mimeview->textview->text);
body_pos = msgview->mimeview->textview->body_pos;
}
g_return_val_if_fail(textview != NULL, NULL);
edit = GTK_EDITABLE(textview->text);
g_return_val_if_fail(edit != NULL, NULL);
body_pos = textview->body_pos;
textbuf = gtk_text_view_get_buffer(edit);
@ -1205,12 +1208,14 @@ static void reply_cb(gpointer data, guint action, GtkWidget *widget)
MsgInfo *msginfo;
gchar *text = NULL;
ComposeMode mode = (ComposeMode)action;
TextView *textview;
msginfo = messageview->msginfo;
mlist = g_slist_append(NULL, msginfo);
textview = messageview_get_current_textview(messageview);
text = gtkut_editable_get_selection
(GTK_EDITABLE(messageview->textview->text));
(GTK_EDITABLE(textview->text));
if (text && *text == '\0') {
g_free(text);
text = NULL;
@ -1272,7 +1277,7 @@ static void reply_cb(gpointer data, guint action, GtkWidget *widget)
}
break;
case COMPOSE_FORWARD_INLINE:
compose_forward(NULL, msginfo, FALSE, text);
compose_forward(NULL, msginfo, FALSE, text, FALSE);
break;
case COMPOSE_FORWARD_AS_ATTACH:
compose_forward_multiple(NULL, mlist);
@ -1326,17 +1331,26 @@ static void add_address_cb(gpointer data, guint action, GtkWidget *widget)
static void create_filter_cb(gpointer data, guint action, GtkWidget *widget)
{
MessageView *messageview = (MessageView *)data;
gchar *header = NULL;
gchar *key = NULL;
FolderItem * item;
if (!messageview->msginfo) return;
item = messageview->msginfo->folder;
summary_msginfo_filter_open(item, messageview->msginfo,
(PrefsFilterType)action, 0);
}
procmsg_get_filter_keyword(messageview->msginfo, &header, &key,
(PrefsFilterType)action);
prefs_filtering_open(NULL, header, key);
g_free(header);
g_free(key);
static void create_processing_cb(gpointer data, guint action,
GtkWidget *widget)
{
MessageView *messageview = (MessageView *)data;
FolderItem * item;
if (!messageview->msginfo) return;
item = messageview->msginfo->folder;
summary_msginfo_filter_open(item, messageview->msginfo,
(PrefsFilterType)action, 1);
}
static void about_cb(gpointer data, guint action, GtkWidget *widget)

View file

@ -23,7 +23,7 @@
#include <glib.h>
#include <gtk/gtkwidget.h>
typedef struct _MessageView MessageView;
typedef struct _MessageView MessageView;
#include "mainwindow.h"
#include "headerview.h"
@ -34,17 +34,10 @@ typedef struct _MessageView MessageView;
#include "procmime.h"
#include "toolbar.h"
typedef enum
{
MVIEW_TEXT,
MVIEW_MIME
} MessageType;
struct _MessageView
{
GtkWidget *vbox;
MessageType type;
gboolean new_window;
GtkWidget *window;
@ -54,7 +47,6 @@ struct _MessageView
GtkWidget *menubar;
HeaderView *headerview;
TextView *textview;
MimeView *mimeview;
NoticeView *noticeview;
@ -79,7 +71,7 @@ MessageView *messageview_create (MainWindow *mainwin);
MessageView *messageview_create_with_new_window (MainWindow *mainwin);
void messageview_init (MessageView *messageview);
void messageview_show (MessageView *messageview,
gint messageview_show (MessageView *messageview,
MsgInfo *msginfo,
gboolean all_headers);
void messageview_clear (MessageView *messageview);

189
src/mh.c
View file

@ -44,51 +44,70 @@
#include "utils.h"
#include "codeconv.h"
static void mh_folder_init(Folder * folder,
const gchar * name, const gchar * path);
static void mh_folder_init (Folder *folder,
const gchar *name,
const gchar *path);
static Folder *mh_folder_new(const gchar * name, const gchar * path);
static void mh_folder_destroy(Folder * folder);
static gchar *mh_fetch_msg(Folder * folder, FolderItem * item, gint num);
static MsgInfo *mh_get_msginfo(Folder * folder,
FolderItem * item, gint num);
static gint mh_add_msg(Folder * folder,
FolderItem * dest,
const gchar * file,
MsgFlags * flags);
static gint mh_add_msgs(Folder * folder,
FolderItem * dest, GSList * file_list, GRelation *relation);
static gint mh_copy_msg(Folder * folder,
FolderItem * dest, MsgInfo * msginfo);
static gint mh_remove_msg(Folder * folder, FolderItem * item, gint num);
static gint mh_remove_all_msg(Folder * folder, FolderItem * item);
static gboolean mh_is_msg_changed(Folder * folder,
FolderItem * item, MsgInfo * msginfo);
static Folder *mh_folder_new (const gchar *name,
const gchar *path);
static void mh_folder_destroy (Folder *folder);
static gchar *mh_fetch_msg (Folder *folder,
FolderItem *item,
gint num);
static MsgInfo *mh_get_msginfo (Folder *folder,
FolderItem *item,
gint num);
static gint mh_add_msg (Folder *folder,
FolderItem *dest,
const gchar *file,
MsgFlags *flags);
static gint mh_add_msgs (Folder *folder,
FolderItem *dest,
GSList *file_list,
GRelation *relation);
static gint mh_copy_msg (Folder *folder,
FolderItem *dest,
MsgInfo *msginfo);
static gint mh_remove_msg (Folder *folder,
FolderItem *item,
gint num);
static gint mh_remove_all_msg (Folder *folder,
FolderItem *item);
static gboolean mh_is_msg_changed (Folder *folder,
FolderItem *item,
MsgInfo *msginfo);
static gint mh_get_num_list(Folder * folder,
FolderItem * item, GSList ** list, gboolean *old_uids_valid);
static void mh_scan_tree(Folder * folder);
static gint mh_get_num_list (Folder *folder,
FolderItem *item,
GSList **list,
gboolean *old_uids_valid);
static gint mh_scan_tree (Folder *folder);
static gint mh_create_tree(Folder * folder);
static FolderItem *mh_create_folder(Folder * folder,
FolderItem * parent,
const gchar * name);
static gint mh_rename_folder(Folder * folder,
FolderItem * item, const gchar * name);
static gint mh_remove_folder(Folder * folder, FolderItem * item);
static gint mh_create_tree (Folder *folder);
static FolderItem *mh_create_folder (Folder *folder,
FolderItem *parent,
const gchar *name);
static gint mh_rename_folder (Folder *folder,
FolderItem *item,
const gchar *name);
static gint mh_remove_folder (Folder *folder,
FolderItem *item);
static gchar *mh_get_new_msg_filename(FolderItem * dest);
static gchar *mh_get_new_msg_filename (FolderItem *dest);
static MsgInfo *mh_parse_msg(const gchar * file, FolderItem * item);
static MsgInfo *mh_parse_msg (const gchar *file,
FolderItem *item);
static void mh_remove_missing_folder_items (Folder *folder);
static void mh_scan_tree_recursive(FolderItem * item);
static gchar *mh_filename_from_utf8 (const gchar *path);
static gchar *mh_filename_to_utf8 (const gchar *path);
static void mh_scan_tree_recursive (FolderItem *item);
static gboolean mh_rename_folder_func(GNode * node, gpointer data);
static gchar *mh_item_get_path(Folder *folder, FolderItem *item);
static gboolean mh_rename_folder_func (GNode *node,
gpointer data);
static gchar *mh_item_get_path (Folder *folder,
FolderItem *item);
FolderClass mh_class =
static FolderClass mh_class =
{
F_MH,
"mh",
@ -97,12 +116,16 @@ FolderClass mh_class =
/* Folder functions */
mh_folder_new,
mh_folder_destroy,
folder_local_set_xml,
folder_local_get_xml,
mh_scan_tree,
mh_create_tree,
/* FolderItem functions */
NULL,
NULL,
NULL,
NULL,
mh_item_get_path,
mh_create_folder,
mh_rename_folder,
@ -133,7 +156,7 @@ FolderClass *mh_get_class(void)
return &mh_class;
}
Folder *mh_folder_new(const gchar *name, const gchar *path)
static Folder *mh_folder_new(const gchar *name, const gchar *path)
{
Folder *folder;
@ -160,7 +183,6 @@ void mh_get_last_num(Folder *folder, FolderItem *item)
gchar *path;
DIR *dp;
struct dirent *d;
struct stat s;
gint max = 0;
gint num;
@ -183,8 +205,7 @@ void mh_get_last_num(Folder *folder, FolderItem *item)
while ((d = readdir(dp)) != NULL) {
if ((num = to_number(d->d_name)) >= 0 &&
stat(d->d_name, &s) == 0 &&
S_ISREG(s.st_mode)) {
dirent_is_regular_file(d)) {
if (max < num)
max = num;
}
@ -201,7 +222,6 @@ gint mh_get_num_list(Folder *folder, FolderItem *item, GSList **list, gboolean *
gchar *path;
DIR *dp;
struct dirent *d;
struct stat s;
gint num, nummsgs = 0;
g_return_val_if_fail(item != NULL, -1);
@ -224,11 +244,9 @@ gint mh_get_num_list(Folder *folder, FolderItem *item, GSList **list, gboolean *
}
while ((d = readdir(dp)) != NULL) {
if ((num = to_number(d->d_name)) >= 0 &&
stat(d->d_name, &s) == 0 &&
S_ISREG(s.st_mode)) {
if ((num = to_number(d->d_name)) >= 0) {
*list = g_slist_prepend(*list, GINT_TO_POINTER(num));
nummsgs++;
nummsgs++;
}
}
closedir(dp);
@ -236,7 +254,7 @@ gint mh_get_num_list(Folder *folder, FolderItem *item, GSList **list, gboolean *
return nummsgs;
}
gchar *mh_fetch_msg(Folder *folder, FolderItem *item, gint num)
static gchar *mh_fetch_msg(Folder *folder, FolderItem *item, gint num)
{
gchar *path;
gchar *file;
@ -255,7 +273,7 @@ gchar *mh_fetch_msg(Folder *folder, FolderItem *item, gint num)
return file;
}
MsgInfo *mh_get_msginfo(Folder *folder, FolderItem *item, gint num)
static MsgInfo *mh_get_msginfo(Folder *folder, FolderItem *item, gint num)
{
MsgInfo *msginfo;
gchar *file;
@ -275,7 +293,7 @@ MsgInfo *mh_get_msginfo(Folder *folder, FolderItem *item, gint num)
return msginfo;
}
gchar *mh_get_new_msg_filename(FolderItem *dest)
static gchar *mh_get_new_msg_filename(FolderItem *dest)
{
gchar *destfile;
gchar *destpath;
@ -301,7 +319,7 @@ gchar *mh_get_new_msg_filename(FolderItem *dest)
return destfile;
}
gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file, MsgFlags *flags)
static gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file, MsgFlags *flags)
{
gint ret;
GSList file_list;
@ -319,7 +337,7 @@ gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file, MsgFlags *f
return ret;
}
gint mh_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
static gint mh_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
GRelation *relation)
{
gchar *destfile;
@ -357,7 +375,7 @@ gint mh_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
return dest->last_num;
}
gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
static gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
{
gchar *srcfile;
gchar *destfile;
@ -423,7 +441,7 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
return dest->last_num;
}
gint mh_remove_msg(Folder *folder, FolderItem *item, gint num)
static gint mh_remove_msg(Folder *folder, FolderItem *item, gint num)
{
gchar *file;
@ -442,7 +460,7 @@ gint mh_remove_msg(Folder *folder, FolderItem *item, gint num)
return 0;
}
gint mh_remove_all_msg(Folder *folder, FolderItem *item)
static gint mh_remove_all_msg(Folder *folder, FolderItem *item)
{
gchar *path;
gint val;
@ -457,7 +475,8 @@ gint mh_remove_all_msg(Folder *folder, FolderItem *item)
return val;
}
gboolean mh_is_msg_changed(Folder *folder, FolderItem *item, MsgInfo *msginfo)
static gboolean mh_is_msg_changed(Folder *folder, FolderItem *item,
MsgInfo *msginfo)
{
struct stat s;
@ -469,12 +488,12 @@ gboolean mh_is_msg_changed(Folder *folder, FolderItem *item, MsgInfo *msginfo)
return FALSE;
}
void mh_scan_tree(Folder *folder)
static gint mh_scan_tree(Folder *folder)
{
FolderItem *item;
gchar *rootpath;
g_return_if_fail(folder != NULL);
g_return_val_if_fail(folder != NULL, -1);
if (!folder->node) {
item = folder_item_new(folder, folder->name, NULL);
@ -486,13 +505,15 @@ void mh_scan_tree(Folder *folder)
rootpath = folder_item_get_path(item);
if (change_dir(rootpath) < 0) {
g_free(rootpath);
return;
return -1;
}
g_free(rootpath);
mh_create_tree(folder);
mh_remove_missing_folder_items(folder);
mh_scan_tree_recursive(item);
return 0;
}
#define MAKE_DIR_IF_NOT_EXIST(dir) \
@ -508,7 +529,7 @@ void mh_scan_tree(Folder *folder)
} \
}
gint mh_create_tree(Folder *folder)
static gint mh_create_tree(Folder *folder)
{
gchar *rootpath;
@ -529,7 +550,7 @@ gint mh_create_tree(Folder *folder)
#undef MAKE_DIR_IF_NOT_EXIST
gchar *mh_item_get_path(Folder *folder, FolderItem *item)
static gchar *mh_item_get_path(Folder *folder, FolderItem *item)
{
gchar *folder_path, *path;
@ -559,8 +580,8 @@ gchar *mh_item_get_path(Folder *folder, FolderItem *item)
return path;
}
FolderItem *mh_create_folder(Folder *folder, FolderItem *parent,
const gchar *name)
static FolderItem *mh_create_folder(Folder *folder, FolderItem *parent,
const gchar *name)
{
gchar *path, *real_name;
gchar *fullpath;
@ -611,7 +632,8 @@ FolderItem *mh_create_folder(Folder *folder, FolderItem *parent,
return new_item;
}
gint mh_rename_folder(Folder *folder, FolderItem *item, const gchar *name)
static gint mh_rename_folder(Folder *folder, FolderItem *item,
const gchar *name)
{
gchar *real_name;
gchar *oldpath;
@ -664,7 +686,7 @@ gint mh_rename_folder(Folder *folder, FolderItem *item, const gchar *name)
return 0;
}
gint mh_remove_folder(Folder *folder, FolderItem *item)
static gint mh_remove_folder(Folder *folder, FolderItem *item)
{
gchar *path;
@ -690,32 +712,32 @@ static MsgInfo *mh_parse_msg(const gchar *file, FolderItem *item)
MsgInfo *msginfo;
MsgFlags flags;
flags.perm_flags = MSG_NEW|MSG_UNREAD;
flags.tmp_flags = 0;
g_return_val_if_fail(item != NULL, NULL);
g_return_val_if_fail(file != NULL, NULL);
flags.perm_flags = MSG_NEW|MSG_UNREAD;
flags.tmp_flags = 0;
if (item->stype == F_QUEUE) {
MSG_SET_TMP_FLAGS(flags, MSG_QUEUED);
} else if (item->stype == F_DRAFT) {
MSG_SET_TMP_FLAGS(flags, MSG_DRAFT);
}
if (stat(file, &s) < 0) {
FILE_OP_ERROR(file, "stat");
return NULL;
}
if (!S_ISREG(s.st_mode))
return NULL;
msginfo = procheader_parse_file(file, flags, FALSE, FALSE);
if (!msginfo) return NULL;
msginfo->msgnum = atoi(file);
msginfo->folder = item;
if (stat(file, &s) < 0) {
FILE_OP_ERROR(file, "stat");
msginfo->size = 0;
msginfo->mtime = 0;
} else {
msginfo->size = s.st_size;
msginfo->mtime = s.st_mtime;
}
msginfo->size = s.st_size;
msginfo->mtime = s.st_mtime;
return msginfo;
}
@ -817,15 +839,16 @@ static void mh_scan_tree_recursive(FolderItem *item)
utf8entry = g_strdup(utf8name);
entry = mh_filename_from_utf8(utf8entry);
if (stat(entry, &s) < 0) {
FILE_OP_ERROR(entry, "stat");
g_free(entry);
g_free(utf8entry);
g_free(utf8name);
continue;
}
if (S_ISDIR(s.st_mode)) {
if (
#ifdef HAVE_DIRENT_D_TYPE
d->d_type == DT_DIR ||
(d->d_type == DT_UNKNOWN &&
#endif
stat(entry, &s) == 0 && S_ISDIR(s.st_mode)
#ifdef HAVE_DIRENT_D_TYPE
)
#endif
) {
FolderItem *new_item = NULL;
GNode *node;

View file

@ -1,6 +1,6 @@
/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
* Copyright (C) 1999-2002 Hiroyuki Yamamoto
* 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
@ -23,7 +23,7 @@
#include <glib.h>
#include "folder.h"
#include "procmsg.h"
#include "localfolder.h"
typedef struct _MHFolder MHFolder;

File diff suppressed because it is too large Load diff

View file

@ -37,6 +37,7 @@ typedef struct _MimeViewer MimeViewer;
#include "textview.h"
#include "messageview.h"
#include "procmime.h"
#include "noticeview.h"
typedef enum
{
@ -48,8 +49,6 @@ struct _MimeView
{
GtkWidget *hbox;
GtkWidget *paned;
GtkWidget *notebook;
GtkWidget *vbox;
GtkWidget *scrolledwin;
GtkWidget *ctree;
GtkWidget *mime_notebook;
@ -83,6 +82,9 @@ struct _MimeView
MainWindow *mainwin;
GtkTooltips *tooltips;
gint oldsize;
NoticeView *siginfoview;
MimeInfo *siginfo;
};
struct _MimeViewerFactory
@ -114,12 +116,11 @@ void mimeview_show_message (MimeView *mimeview,
const gchar *file);
void mimeview_destroy (MimeView *mimeview);
void mimeview_update (MimeView *mimeview);
void mimeview_clear (MimeView *mimeview);
MimeInfo *mimeview_get_selected_part (MimeView *mimeview);
#if USE_GPGME
void mimeview_check_signature (MimeView *mimeview);
#endif
void mimeview_check_signature (MimeView *mimeview);
void mimeview_pass_key_press_event (MimeView *mimeview,
GdkEventKey *event);

View file

@ -434,6 +434,7 @@ MsgInfo *msgcache_get_msg_by_id(MsgCache *cache, const gchar *msgid)
MsgInfo *msginfo;
g_return_val_if_fail(cache != NULL, NULL);
g_return_val_if_fail(msgid != NULL, NULL);
msginfo = g_hash_table_lookup(cache->msgid_table, msgid);
if(!msginfo)

Some files were not shown because too many files have changed in this diff Show more