2 * Claws-Mail-- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2004 Hiroyuki Yamamoto
4 * This file (C) 2005 Andrej Kacian <andrej@kacian.sk>
6 * - s-c folderclass callback handler functions
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <glib/gi18n.h>
30 #include <curl/curl.h>
32 /* Claws Mail includes */
35 #include <localfolder.h>
36 #include <common/utils.h>
41 #include <prefs_toolbar.h>
44 #include "libfeed/feeditem.h"
46 #include "rssyl_deleted.h"
47 #include "rssyl_gtk.h"
48 #include "rssyl_feed.h"
49 #include "rssyl_prefs.h"
50 #include "rssyl_update_feed.h"
51 #include "rssyl_update_format.h"
52 #include "opml_import.h"
53 #include "opml_export.h"
56 FolderClass rssyl_class;
58 static gint rssyl_create_tree(Folder *folder);
59 static gint rssyl_scan_tree(Folder *folder);
61 static gboolean existing_tree_found = FALSE;
63 static void rssyl_init_read_func(FolderItem *item, gpointer data)
65 RFolderItem *ritem = (RFolderItem *)item;
66 RPrefs *rsprefs = NULL;
68 if( !IS_RSSYL_FOLDER_ITEM(item) )
71 existing_tree_found = TRUE;
73 /* Don't do anything if we're on root of our folder tree or on
74 * a regular folder (no feed) */
75 if( folder_item_parent(item) == NULL || ritem->url == NULL )
78 ritem->refresh_id = 0;
80 /* Start automatic refresh timer, if necessary */
81 if( ritem->default_refresh_interval ) {
82 rsprefs = rssyl_prefs_get();
83 if( !rsprefs->refresh_enabled )
86 ritem->refresh_interval = rsprefs->refresh;
89 /* Start the timer, if determined interval is >0 */
90 if( ritem->refresh_interval > 0 )
91 rssyl_feed_start_refresh_timeout(ritem);
94 static void rssyl_make_rc_dir(void)
96 gchar *rssyl_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, RSSYL_DIR,
99 if( !is_dir_exist(rssyl_dir) ) {
100 if( make_dir(rssyl_dir) < 0 ) {
101 g_warning("couldn't create directory %s\n", rssyl_dir);
104 debug_print("RSSyl: created directory %s\n", rssyl_dir);
110 static void rssyl_create_default_mailbox(void)
116 root = folder_new(rssyl_folder_get_class(), RSSYL_DEFAULT_MAILBOX, NULL);
118 g_return_if_fail(root != NULL);
121 rssyl_scan_tree(root);
123 /* FIXME: subscribe default feed */
124 // rssyl_subscribe_new_feed(item, RSSYL_DEFAULT_FEED, TRUE);
127 static gboolean rssyl_update_all_feeds_deferred(gpointer data)
129 rssyl_update_all_feeds();
133 static void rssyl_toolbar_cb_refresh_all_feeds(gpointer parent, const gchar *item_name, gpointer data)
135 rssyl_update_all_feeds();
138 void rssyl_init(void)
140 folder_register_class(rssyl_folder_get_class());
147 folder_func_to_all_folders((FolderItemFunc)rssyl_init_read_func, NULL);
149 if( !existing_tree_found )
150 rssyl_create_default_mailbox();
152 rssyl_update_format();
154 prefs_toolbar_register_plugin_item(TOOLBAR_MAIN, "RSSyl", _("Refresh all feeds"), rssyl_toolbar_cb_refresh_all_feeds, NULL);
156 if( rssyl_prefs_get()->refresh_on_startup &&
157 claws_is_starting() )
158 g_timeout_add(2000, rssyl_update_all_feeds_deferred, NULL);
161 void rssyl_done(void)
165 prefs_toolbar_unregister_plugin_item(TOOLBAR_MAIN, "RSSyl", _("Refresh all feeds"));
170 if( !claws_is_exiting() )
171 folder_unregister_class(rssyl_folder_get_class());
173 debug_print("RSSyl is done\n");
176 static gchar *rssyl_get_new_msg_filename(FolderItem *dest)
181 destpath = folder_item_get_path(dest);
182 g_return_val_if_fail(destpath != NULL, NULL);
184 if( !is_dir_exist(destpath) )
185 make_dir_hier(destpath);
188 destfile = g_strdup_printf("%s%c%d", destpath, G_DIR_SEPARATOR,
190 if( is_file_entry_exist(destfile) ) {
202 static void rssyl_get_last_num(Folder *folder, FolderItem *item)
210 g_return_if_fail(item != NULL);
212 debug_print("rssyl_get_last_num(): Scanning %s ...\n", item->path);
213 path = folder_item_get_path(item);
214 g_return_if_fail(path != NULL);
216 if( (dp = opendir(path)) == NULL ) {
217 FILE_OP_ERROR(item->path, "opendir");
224 while( (d = readdir(dp)) != NULL ) {
225 if( (num = to_number(d->d_name)) > 0 && dirent_is_regular_file(d) ) {
232 debug_print("Last number in dir %s = %d\n", item->path, max);
233 item->last_num = max;
236 static Folder *rssyl_new_folder(const gchar *name, const gchar *path)
240 debug_print("RSSyl: new_folder: %s (%s)\n", name, path);
244 folder = g_new0(Folder, 1);
245 FOLDER(folder)->klass = &rssyl_class;
246 folder_init(FOLDER(folder), name);
248 return FOLDER(folder);
251 static void rssyl_destroy_folder(Folder *folder)
253 folder_local_folder_destroy(LOCAL_FOLDER(folder));
256 static void rssyl_item_set_xml(Folder *folder, FolderItem *item, XMLTag *tag)
259 RFolderItem *ritem = (RFolderItem *)item;
261 folder_item_set_xml(folder, item, tag);
263 for( cur = tag->attr; cur != NULL; cur = g_list_next(cur)) {
264 XMLAttr *attr = (XMLAttr *) cur->data;
266 if( !attr || !attr->name || !attr->value)
270 if( !strcmp(attr->name, "uri")) {
272 ritem->url = g_strdup(attr->value);
274 /* (str) Official title */
275 if( !strcmp(attr->name, "official_title")) {
276 g_free(ritem->official_title);
277 ritem->official_title = g_strdup(attr->value);
279 /* (bool) Keep old items */
280 if( !strcmp(attr->name, "keep_old"))
281 ritem->keep_old = (atoi(attr->value) == 0 ? FALSE : TRUE );
282 /* (bool) Use default refresh_interval */
283 if( !strcmp(attr->name, "default_refresh_interval"))
284 ritem->default_refresh_interval = (atoi(attr->value) == 0 ? FALSE : TRUE );
285 /* (int) Refresh interval */
286 if( !strcmp(attr->name, "refresh_interval"))
287 ritem->refresh_interval = atoi(attr->value);
288 /* (bool) Fetch comments */
289 if( !strcmp(attr->name, "fetch_comments"))
290 ritem->fetch_comments = (atoi(attr->value) == 0 ? FALSE : TRUE );
291 /* (int) Max age of posts to fetch comments for */
292 if( !strcmp(attr->name, "fetch_comments_max_age"))
293 ritem->fetch_comments_max_age = atoi(attr->value);
294 /* (bool) Write heading */
295 if( !strcmp(attr->name, "write_heading"))
296 ritem->write_heading = (atoi(attr->value) == 0 ? FALSE : TRUE );
297 /* (int) Silent update */
298 if( !strcmp(attr->name, "silent_update"))
299 ritem->silent_update = atoi(attr->value);
300 /* (bool) Ignore title rename */
301 if( !strcmp(attr->name, "ignore_title_rename"))
302 ritem->ignore_title_rename = (atoi(attr->value) == 0 ? FALSE : TRUE );
303 /* (bool) Verify SSL peer */
304 if( !strcmp(attr->name, "ssl_verify_peer"))
305 ritem->ssl_verify_peer = (atoi(attr->value) == 0 ? FALSE : TRUE );
309 static XMLTag *rssyl_item_get_xml(Folder *folder, FolderItem *item)
312 RFolderItem *ri = (RFolderItem *)item;
315 tag = folder_item_get_xml(folder, item);
318 if( ri->url != NULL )
319 xml_tag_add_attr(tag, xml_attr_new("uri", ri->url));
320 /* (str) Official title */
321 if( ri->official_title != NULL )
322 xml_tag_add_attr(tag, xml_attr_new("official_title", ri->official_title));
323 /* (bool) Keep old items */
324 xml_tag_add_attr(tag, xml_attr_new("keep_old",
325 (ri->keep_old ? "1" : "0")) );
326 /* (bool) Use default refresh interval */
327 xml_tag_add_attr(tag, xml_attr_new("default_refresh_interval",
328 (ri->default_refresh_interval ? "1" : "0")) );
329 /* (int) Refresh interval */
330 tmp = g_strdup_printf("%d", ri->refresh_interval);
331 xml_tag_add_attr(tag, xml_attr_new("refresh_interval", tmp));
333 /* (bool) Fetch comments */
334 xml_tag_add_attr(tag, xml_attr_new("fetch_comments",
335 (ri->fetch_comments ? "1" : "0")) );
336 /* (int) Max age of posts to fetch comments for */
337 tmp = g_strdup_printf("%d", ri->fetch_comments_max_age);
338 xml_tag_add_attr(tag, xml_attr_new("fetch_comments_max_age", tmp));
340 /* (bool) Write heading */
341 xml_tag_add_attr(tag, xml_attr_new("write_heading",
342 (ri->write_heading ? "1" : "0")) );
343 /* (int) Silent update */
344 tmp = g_strdup_printf("%d", ri->silent_update);
345 xml_tag_add_attr(tag, xml_attr_new("silent_update", tmp));
347 /* (bool) Ignore title rename */
348 xml_tag_add_attr(tag, xml_attr_new("ignore_title_rename",
349 (ri->ignore_title_rename ? "1" : "0")) );
350 /* (bool) Verify SSL peer */
351 xml_tag_add_attr(tag, xml_attr_new("ssl_verify_peer",
352 (ri->ssl_verify_peer ? "1" : "0")) );
357 static gint rssyl_scan_tree(Folder *folder)
359 g_return_val_if_fail(folder != NULL, -1);
361 folder->outbox = NULL;
362 folder->draft = NULL;
363 folder->queue = NULL;
364 folder->trash = NULL;
366 debug_print("RSSyl: scanning tree\n");
367 rssyl_create_tree(folder);
372 static gint rssyl_create_tree(Folder *folder)
374 FolderItem *rootitem;
377 g_return_val_if_fail(folder != NULL, -1);
381 if( !folder->node ) {
382 rootitem = folder_item_new(folder, folder->name, NULL);
383 rootitem->folder = folder;
384 rootnode = g_node_new(rootitem);
385 folder->node = rootnode;
386 rootitem->node = rootnode;
389 debug_print("RSSyl: created new rssyl tree\n");
393 static FolderItem *rssyl_item_new(Folder *folder)
395 RFolderItem *ritem = g_new0(RFolderItem, 1);
398 ritem->official_title = NULL;
399 ritem->source_id = NULL;
401 ritem->keep_old = FALSE;
402 ritem->default_refresh_interval = TRUE;
403 ritem->refresh_interval = atoi(PREF_DEFAULT_REFRESH);
404 ritem->fetch_comments = FALSE;
405 ritem->fetch_comments_max_age = -1;
406 ritem->write_heading = TRUE;
407 ritem->fetching_comments = FALSE;
408 ritem->silent_update = 0;
409 ritem->last_update = 0;
410 ritem->ignore_title_rename = FALSE;
412 return (FolderItem *)ritem;
415 static void rssyl_item_destroy(Folder *folder, FolderItem *item)
417 RFolderItem *ritem = (RFolderItem *)item;
419 g_return_if_fail(ritem != NULL);
422 g_free(ritem->official_title);
423 g_slist_free(ritem->items);
425 /* Remove a scheduled refresh, if any */
426 if( ritem->refresh_id != 0)
427 g_source_remove(ritem->refresh_id);
432 static FolderItem *rssyl_create_folder(Folder *folder,
433 FolderItem *parent, const gchar *name)
435 gchar *path = NULL, *basepath = NULL, *itempath = NULL;
436 FolderItem *newitem = NULL;
438 g_return_val_if_fail(folder != NULL, NULL);
439 g_return_val_if_fail(parent != NULL, NULL);
440 g_return_val_if_fail(name != NULL, NULL);
442 path = folder_item_get_path(parent);
443 if( !is_dir_exist(path) ) {
444 if( (make_dir_hier(path) != 0) ) {
445 debug_print("RSSyl: Couldn't create directory (rec) '%s'\n", path);
450 basepath = g_strdelimit(g_strdup(name), G_DIR_SEPARATOR_S, '_');
451 path = g_strconcat(path, G_DIR_SEPARATOR_S, basepath, NULL);
453 if( make_dir(path) < 0 ) {
454 debug_print("RSSyl: Couldn't create directory '%s'\n", path);
461 itempath = g_strconcat((parent->path ? parent->path : ""),
462 G_DIR_SEPARATOR_S, basepath, NULL);
463 newitem = folder_item_new(folder, name, itempath);
467 folder_item_append(parent, newitem);
472 FolderItem *rssyl_get_root_folderitem(FolderItem *item)
476 for( i = item; folder_item_parent(i) != NULL; i = folder_item_parent(i) ) { }
480 static gchar *rssyl_item_get_path(Folder *folder, FolderItem *item)
484 g_return_val_if_fail(folder != NULL, NULL);
485 g_return_val_if_fail(item != NULL, NULL);
487 debug_print("RSSyl: item_get_path\n");
489 name = folder_item_get_name(rssyl_get_root_folderitem(item));
490 path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, RSSYL_DIR,
491 G_DIR_SEPARATOR_S, name, G_DIR_SEPARATOR_S, item->path, NULL);
497 static gboolean rssyl_rename_folder_func(GNode *node, gpointer data)
499 FolderItem *item = node->data;
500 gchar **paths = data;
501 const gchar *oldpath = paths[0];
502 const gchar *newpath = paths[1];
507 oldpathlen = strlen(oldpath);
508 if (strncmp(oldpath, item->path, oldpathlen) != 0) {
509 g_warning("path doesn't match: %s, %s\n", oldpath, item->path);
513 base = item->path + oldpathlen;
514 while (*base == G_DIR_SEPARATOR) base++;
516 new_itempath = g_strdup(newpath);
518 new_itempath = g_strconcat(newpath, G_DIR_SEPARATOR_S, base,
521 item->path = new_itempath;
526 static gint rssyl_rename_folder(Folder *folder, FolderItem *item,
531 gchar *newpath, *utf8newpath;
535 g_return_val_if_fail(folder != NULL, -1);
536 g_return_val_if_fail(item != NULL, -1);
537 g_return_val_if_fail(item->path != NULL, -1);
538 g_return_val_if_fail(name != NULL, -1);
540 debug_print("RSSyl: rssyl_rename_folder '%s' -> '%s'\n",
543 if (!strcmp(item->name, name))
546 oldpath = folder_item_get_path(item);
547 if( !is_dir_exist(oldpath) )
548 make_dir_hier(oldpath);
550 dirname = g_path_get_dirname(oldpath);
551 basenewpath = g_strdelimit(g_strdup(name), G_DIR_SEPARATOR_S, '_');
552 newpath = g_strconcat(dirname, G_DIR_SEPARATOR_S, basenewpath, NULL);
555 if( g_rename(oldpath, newpath) < 0 ) {
556 FILE_OP_ERROR(oldpath, "rename");
565 if( strchr(item->path, G_DIR_SEPARATOR) != NULL ) {
566 dirname = g_path_get_dirname(item->path);
567 utf8newpath = g_strconcat(dirname, G_DIR_SEPARATOR_S, name, NULL);
570 utf8newpath = g_strdup(name);
573 item->name = g_strdup(name);
575 paths[0] = g_strdup(item->path);
576 paths[1] = utf8newpath;
577 g_node_traverse(item->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
578 rssyl_rename_folder_func, paths);
586 static gint rssyl_remove_folder(Folder *folder, FolderItem *item)
590 g_return_val_if_fail(folder != NULL, -1);
591 g_return_val_if_fail(item != NULL, -1);
592 g_return_val_if_fail(item->path != NULL, -1);
593 g_return_val_if_fail(item->stype == F_NORMAL, -1);
595 debug_print("RSSyl: removing folder item %s\n", item->path);
597 path = folder_item_get_path(item);
598 if( remove_dir_recursive(path) < 0 ) {
599 g_warning("can't remove directory '%s'\n", path);
605 folder_item_remove(item);
610 static gint rssyl_get_num_list(Folder *folder, FolderItem *item,
611 MsgNumberList **list, gboolean *old_uids_valid)
616 gint num, nummsgs = 0;
618 g_return_val_if_fail(item != NULL, -1);
620 debug_print("RSSyl: get_num_list: scanning '%s'\n", item->path);
622 *old_uids_valid = TRUE;
624 path = folder_item_get_path(item);
625 g_return_val_if_fail(path != NULL, -1);
627 if( (dp = opendir(path)) == NULL ) {
628 FILE_OP_ERROR(item->path, "opendir");
635 while( (d = readdir(dp)) != NULL ) {
636 if( (num = to_number(d->d_name)) > 0 ) {
637 *list = g_slist_prepend(*list, GINT_TO_POINTER(num));
644 debug_print("Rssyl: get_num_list: returning %d\n", nummsgs);
649 static gboolean rssyl_scan_required(Folder *folder, FolderItem *item)
654 static gchar *rssyl_fetch_msg(Folder *folder, FolderItem *item, gint num)
659 g_return_val_if_fail(item != NULL, NULL);
660 g_return_val_if_fail(num > 0, NULL);
662 path = folder_item_get_path(item);
663 file = g_strconcat(path, G_DIR_SEPARATOR_S, itos(num), NULL);
666 debug_print("RSSyl: fetch_msg '%s'\n", file);
668 if( !is_file_exist(file)) {
676 static MsgInfo *rssyl_get_msginfo(Folder *folder, FolderItem *item, gint num)
678 MsgInfo *msginfo = NULL;
682 g_return_val_if_fail(folder != NULL, NULL);
683 g_return_val_if_fail(item != NULL, NULL);
684 g_return_val_if_fail(num > 0, NULL);
686 debug_print("RSSyl: get_msginfo: %d\n", num);
688 file = rssyl_fetch_msg(folder, item, num);
689 g_return_val_if_fail(file != NULL, NULL);
691 flags.perm_flags = 0;
694 msginfo = rssyl_feed_parse_item_to_msginfo(file, flags, TRUE, TRUE, item);
698 msginfo->msgnum = num;
703 static gint rssyl_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
704 GHashTable *relation)
708 MsgFileInfo *fileinfo;
710 g_return_val_if_fail(dest != NULL, -1);
711 g_return_val_if_fail(file_list != NULL, -1);
713 if( dest->last_num < 0 ) {
714 rssyl_get_last_num(folder, dest);
715 if( dest->last_num < 0 ) return -1;
718 for( cur = file_list; cur != NULL; cur = cur->next ) {
719 fileinfo = (MsgFileInfo *)cur->data;
721 destfile = rssyl_get_new_msg_filename(dest);
722 g_return_val_if_fail(destfile != NULL, -1);
723 debug_print("RSSyl: add_msgs: new filename is '%s'\n", destfile);
725 if( link(fileinfo->file, destfile) < 0 ) {
726 if( copy_file(fileinfo->file, destfile, TRUE) < 0 ) {
727 g_warning("can't copy message %s to %s\n", fileinfo->file, destfile);
733 if( relation != NULL )
734 g_hash_table_insert(relation, fileinfo->msginfo != NULL ?
735 (gpointer) fileinfo->msginfo : (gpointer) fileinfo,
736 GINT_TO_POINTER(dest->last_num + 1));
742 return dest->last_num;
745 static gint rssyl_add_msg(Folder *folder, FolderItem *dest, const gchar *file,
749 MsgFileInfo fileinfo;
751 g_return_val_if_fail(file != NULL, -1);
753 fileinfo.msginfo = NULL;
754 fileinfo.file = (gchar *)file;
755 fileinfo.flags = flags;
756 file_list.data = &fileinfo;
757 file_list.next = NULL;
759 return rssyl_add_msgs(folder, dest, &file_list, NULL);
762 static gint rssyl_remove_msg(Folder *folder, FolderItem *item, gint num)
764 gboolean need_scan = FALSE;
767 g_return_val_if_fail(item != NULL, -1);
769 file = rssyl_fetch_msg(folder, item, num);
770 g_return_val_if_fail(file != NULL, -1);
772 need_scan = rssyl_scan_required(folder, item);
774 /* are we doing a folder move ? */
775 tmp = g_strdup_printf("%s.tmp", file);
776 if (is_file_exist(tmp)) {
784 rssyl_deleted_add((RFolderItem *)item, file);
786 if( g_unlink(file) < 0 ) {
787 FILE_OP_ERROR(file, "unlink");
793 item->mtime = time(NULL);
799 static gboolean rssyl_subscribe_uri(Folder *folder, const gchar *uri)
801 if (folder->klass != rssyl_folder_get_class())
803 return (rssyl_feed_subscribe_new(FOLDER_ITEM(folder->node->data), uri, FALSE) ?
807 static void rssyl_copy_private_data(Folder *folder, FolderItem *oldi,
810 RFolderItem *olditem = (RFolderItem *)oldi,
811 *newitem = (RFolderItem *)newi;
813 g_return_if_fail(folder != NULL);
814 g_return_if_fail(olditem != NULL);
815 g_return_if_fail(newitem != NULL);
817 if( olditem->url != NULL ) {
818 g_free(newitem->url);
819 newitem->url = g_strdup(olditem->url);
822 if( olditem->official_title != NULL ) {
823 g_free(newitem->official_title);
824 newitem->official_title = g_strdup(olditem->official_title);
828 /************************************************************************/
830 FolderClass *rssyl_folder_get_class()
832 if( rssyl_class.idstr == NULL ) {
833 rssyl_class.type = F_UNKNOWN;
834 rssyl_class.idstr = "rssyl";
835 rssyl_class.uistr = "RSSyl";
837 /* Folder functions */
838 rssyl_class.new_folder = rssyl_new_folder;
839 rssyl_class.destroy_folder = rssyl_destroy_folder;
840 rssyl_class.set_xml = folder_set_xml;
841 rssyl_class.get_xml = folder_get_xml;
842 rssyl_class.scan_tree = rssyl_scan_tree;
843 rssyl_class.create_tree = rssyl_create_tree;
845 /* FolderItem functions */
846 rssyl_class.item_new = rssyl_item_new;
847 rssyl_class.item_destroy = rssyl_item_destroy;
848 rssyl_class.item_get_path = rssyl_item_get_path;
849 rssyl_class.create_folder = rssyl_create_folder;
850 rssyl_class.rename_folder = rssyl_rename_folder;
851 rssyl_class.remove_folder = rssyl_remove_folder;
852 rssyl_class.get_num_list = rssyl_get_num_list;
853 rssyl_class.scan_required = rssyl_scan_required;
854 rssyl_class.item_set_xml = rssyl_item_set_xml;
855 rssyl_class.item_get_xml = rssyl_item_get_xml;
857 /* Message functions */
858 rssyl_class.get_msginfo = rssyl_get_msginfo;
859 rssyl_class.fetch_msg = rssyl_fetch_msg;
860 rssyl_class.copy_msg = mh_get_class()->copy_msg;
861 rssyl_class.copy_msgs = mh_get_class()->copy_msgs;
862 rssyl_class.add_msg = rssyl_add_msg;
863 rssyl_class.add_msgs = rssyl_add_msgs;
864 rssyl_class.remove_msg = rssyl_remove_msg;
865 rssyl_class.remove_msgs = NULL;
866 // rssyl_class.change_flags = rssyl_change_flags;
867 rssyl_class.change_flags = NULL;
868 rssyl_class.subscribe = rssyl_subscribe_uri;
869 rssyl_class.copy_private_data = rssyl_copy_private_data;
870 rssyl_class.search_msgs = folder_item_search_msgs_local;