1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2001-2003 Ximian Inc.
5 * Authors: Michael Zucchi <notzed@ximian.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
33 #include <sys/types.h>
36 #include <glib/gstdio.h>
38 #include <libedataserver/e-memory.h>
39 #include <libedataserver/md5-utils.h>
41 #include "camel-file-utils.h"
42 #include "camel-private.h"
43 #include "camel-store-summary.h"
44 #include "camel-url.h"
47 #define io(x) /* io debug */
49 /* possible versions, for versioning changes */
50 #define CAMEL_STORE_SUMMARY_VERSION_0 (1)
51 #define CAMEL_STORE_SUMMARY_VERSION_2 (2)
54 #define CAMEL_STORE_SUMMARY_VERSION (2)
56 #define _PRIVATE(o) (((CamelStoreSummary *)(o))->priv)
58 static int summary_header_load(CamelStoreSummary *, FILE *);
59 static int summary_header_save(CamelStoreSummary *, FILE *);
61 static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);
62 static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *);
63 static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *);
64 static void store_info_free(CamelStoreSummary *, CamelStoreInfo *);
66 static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int);
67 static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *);
69 static void camel_store_summary_class_init (CamelStoreSummaryClass *klass);
70 static void camel_store_summary_init (CamelStoreSummary *obj);
71 static void camel_store_summary_finalise (CamelObject *obj);
73 static CamelObjectClass *camel_store_summary_parent;
76 camel_store_summary_class_init (CamelStoreSummaryClass *klass)
78 camel_store_summary_parent = camel_type_get_global_classfuncs (camel_object_get_type ());
80 klass->summary_header_load = summary_header_load;
81 klass->summary_header_save = summary_header_save;
83 klass->store_info_new = store_info_new;
84 klass->store_info_load = store_info_load;
85 klass->store_info_save = store_info_save;
86 klass->store_info_free = store_info_free;
88 klass->store_info_string = store_info_string;
89 klass->store_info_set_string = store_info_set_string;
93 camel_store_summary_init (CamelStoreSummary *s)
95 struct _CamelStoreSummaryPrivate *p;
97 p = _PRIVATE(s) = g_malloc0(sizeof(*p));
99 s->store_info_size = sizeof(CamelStoreInfo);
101 s->store_info_chunks = NULL;
103 s->version = CAMEL_STORE_SUMMARY_VERSION;
108 s->folders = g_ptr_array_new();
109 s->folders_path = g_hash_table_new(g_str_hash, g_str_equal);
111 p->summary_lock = g_mutex_new();
112 p->io_lock = g_mutex_new();
113 p->alloc_lock = g_mutex_new();
114 p->ref_lock = g_mutex_new();
118 camel_store_summary_finalise (CamelObject *obj)
120 struct _CamelStoreSummaryPrivate *p;
121 CamelStoreSummary *s = (CamelStoreSummary *)obj;
125 camel_store_summary_clear(s);
126 g_ptr_array_free(s->folders, TRUE);
127 g_hash_table_destroy(s->folders_path);
129 g_free(s->summary_path);
131 if (s->store_info_chunks)
132 e_memchunk_destroy(s->store_info_chunks);
134 g_mutex_free(p->summary_lock);
135 g_mutex_free(p->io_lock);
136 g_mutex_free(p->alloc_lock);
137 g_mutex_free(p->ref_lock);
143 camel_store_summary_get_type (void)
145 static CamelType type = CAMEL_INVALID_TYPE;
147 if (type == CAMEL_INVALID_TYPE) {
148 type = camel_type_register (camel_object_get_type (), "CamelStoreSummary",
149 sizeof (CamelStoreSummary),
150 sizeof (CamelStoreSummaryClass),
151 (CamelObjectClassInitFunc) camel_store_summary_class_init,
153 (CamelObjectInitFunc) camel_store_summary_init,
154 (CamelObjectFinalizeFunc) camel_store_summary_finalise);
162 * camel_store_summary_new:
164 * Create a new #CamelStoreSummary object.
166 * Returns a new #CamelStoreSummary object
169 camel_store_summary_new (void)
171 CamelStoreSummary *new = CAMEL_STORE_SUMMARY ( camel_object_new (camel_store_summary_get_type ())); return new;
176 * camel_store_summary_set_filename:
177 * @summary: a #CamelStoreSummary
178 * @filename: a filename
180 * Set the filename where the summary will be loaded to/saved from.
183 camel_store_summary_set_filename(CamelStoreSummary *s, const char *name)
185 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
187 g_free(s->summary_path);
188 s->summary_path = g_strdup(name);
190 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
195 * camel_store_summary_set_uri_base:
196 * @summary: a #CamelStoreSummary object
199 * Sets the base URI for the summary.
202 camel_store_summary_set_uri_base(CamelStoreSummary *s, CamelURL *base)
204 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
207 camel_url_free(s->uri_base);
208 s->uri_base = camel_url_new_with_base(base, "");
210 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
215 * camel_store_summary_count:
216 * @summary: a #CamelStoreSummary object
218 * Get the number of summary items stored in this summary.
220 * Returns the number of items int he summary.
223 camel_store_summary_count(CamelStoreSummary *s)
225 return s->folders->len;
230 * camel_store_summary_index:
231 * @summary: a #CamelStoreSummary object
232 * @index: record index
234 * Retrieve a summary item by index number.
236 * A referenced to the summary item is returned, which may be ref'd or
237 * free'd as appropriate.
239 * It must be freed using #camel_store_summary_info_free.
241 * Returns the summary item, or %NULL if @index is out of range
244 camel_store_summary_index(CamelStoreSummary *s, int i)
246 CamelStoreInfo *info = NULL;
248 CAMEL_STORE_SUMMARY_LOCK(s, ref_lock);
249 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
251 if (i<s->folders->len)
252 info = g_ptr_array_index(s->folders, i);
254 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
259 CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock);
266 * camel_store_summary_array:
267 * @summary: a #CamelStoreSummary object
269 * Obtain a copy of the summary array. This is done atomically,
270 * so cannot contain empty entries.
272 * It must be freed using #camel_store_summary_array_free.
274 * Returns the summary array
277 camel_store_summary_array(CamelStoreSummary *s)
279 CamelStoreInfo *info;
280 GPtrArray *res = g_ptr_array_new();
283 CAMEL_STORE_SUMMARY_LOCK(s, ref_lock);
284 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
286 g_ptr_array_set_size(res, s->folders->len);
287 for (i=0;i<s->folders->len;i++) {
288 info = res->pdata[i] = g_ptr_array_index(s->folders, i);
292 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
293 CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock);
300 * camel_store_summary_array_free:
301 * @summary: a #CamelStoreSummary object
302 * @array: the summary array as gotten from #camel_store_summary_array
304 * Free the folder summary array.
307 camel_store_summary_array_free(CamelStoreSummary *s, GPtrArray *array)
311 for (i=0;i<array->len;i++)
312 camel_store_summary_info_free(s, array->pdata[i]);
314 g_ptr_array_free(array, TRUE);
319 * camel_store_summary_path:
320 * @summary: a #CamelStoreSummary object
321 * @path: path to the item
323 * Retrieve a summary item by path name.
325 * A referenced to the summary item is returned, which may be ref'd or
326 * free'd as appropriate.
328 * It must be freed using #camel_store_summary_info_free.
330 * Returns the summary item, or %NULL if the @path name is not
334 camel_store_summary_path(CamelStoreSummary *s, const char *path)
336 CamelStoreInfo *info;
338 CAMEL_STORE_SUMMARY_LOCK(s, ref_lock);
339 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
341 info = g_hash_table_lookup(s->folders_path, path);
343 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
348 CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock);
354 * camel_store_summary_load:
355 * @summary: a #CamelStoreSummary object
357 * Load the summary off disk.
359 * Returns %0 on success or %-1 on fail
362 camel_store_summary_load(CamelStoreSummary *s)
366 CamelStoreInfo *info;
368 g_assert(s->summary_path);
370 in = g_fopen(s->summary_path, "rb");
374 CAMEL_STORE_SUMMARY_LOCK(s, io_lock);
375 if ( ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in) == -1)
378 /* now read in each message ... */
379 for (i=0;i<s->count;i++) {
380 info = ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_load(s, in);
385 camel_store_summary_add(s, info);
388 CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock);
390 if (fclose (in) != 0)
393 s->flags &= ~CAMEL_STORE_SUMMARY_DIRTY;
399 g_warning ("Cannot load summary file: %s", strerror (ferror (in)));
400 CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock);
402 s->flags |= ~CAMEL_STORE_SUMMARY_DIRTY;
410 * camel_store_summary_save:
411 * @summary: a #CamelStoreSummary object
413 * Writes the summary to disk. The summary is only written if changes
416 * Returns %0 on succes or %-1 on fail
419 camel_store_summary_save(CamelStoreSummary *s)
425 CamelStoreInfo *info;
427 g_assert(s->summary_path);
429 io(printf("** saving summary\n"));
431 if ((s->flags & CAMEL_STORE_SUMMARY_DIRTY) == 0) {
432 io(printf("** summary clean no save\n"));
436 fd = g_open(s->summary_path, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600);
438 io(printf("** open error: %s\n", strerror (errno)));
441 out = fdopen(fd, "wb");
444 printf("** fdopen error: %s\n", strerror (errno));
450 io(printf("saving header\n"));
452 CAMEL_STORE_SUMMARY_LOCK(s, io_lock);
454 if ( ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_save(s, out) == -1) {
457 CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock);
462 /* now write out each message ... */
464 /* FIXME: Locking? */
466 count = s->folders->len;
467 for (i=0;i<count;i++) {
468 info = s->folders->pdata[i];
469 ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_save(s, out, info);
472 CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock);
474 if (fflush (out) != 0 || fsync (fileno (out)) == -1) {
481 if (fclose (out) != 0)
484 s->flags &= ~CAMEL_STORE_SUMMARY_DIRTY;
490 * camel_store_summary_header_load:
491 * @summary: a #CamelStoreSummary object
493 * Only load the header information from the summary,
494 * keep the rest on disk. This should only be done on
495 * a fresh summary object.
497 * Returns %0 on success or %-1 on fail
500 camel_store_summary_header_load(CamelStoreSummary *s)
505 g_assert(s->summary_path);
507 in = g_fopen(s->summary_path, "rb");
511 CAMEL_STORE_SUMMARY_LOCK(s, io_lock);
512 ret = ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in);
513 CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock);
516 s->flags &= ~CAMEL_STORE_SUMMARY_DIRTY;
522 * camel_store_summary_add:
523 * @summary: a #CamelStoreSummary object
524 * @info: a #CamelStoreInfo
526 * Adds a new @info record to the summary. If @info->uid is %NULL,
527 * then a new uid is automatically re-assigned by calling
528 * #camel_store_summary_next_uid_string.
530 * The @info record should have been generated by calling one of the
531 * info_new_*() functions, as it will be free'd based on the summary
532 * class. And MUST NOT be allocated directly using malloc.
535 camel_store_summary_add(CamelStoreSummary *s, CamelStoreInfo *info)
540 if (camel_store_info_path(s, info) == NULL) {
541 g_warning("Trying to add a folder info with missing required path name\n");
545 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
547 g_ptr_array_add(s->folders, info);
548 g_hash_table_insert(s->folders_path, (char *)camel_store_info_path(s, info), info);
549 s->flags |= CAMEL_STORE_SUMMARY_DIRTY;
551 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
556 * camel_store_summary_add_from_path:
557 * @summary: a #CamelStoreSummary object
560 * Build a new info record based on the name, and add it to the summary.
562 * Returns the newly added record
565 camel_store_summary_add_from_path(CamelStoreSummary *s, const char *path)
567 CamelStoreInfo *info;
569 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
571 info = g_hash_table_lookup(s->folders_path, path);
573 g_warning("Trying to add folder '%s' to summary that already has it", path);
576 info = camel_store_summary_info_new_from_path(s, path);
577 g_ptr_array_add(s->folders, info);
578 g_hash_table_insert(s->folders_path, (char *)camel_store_info_path(s, info), info);
579 s->flags |= CAMEL_STORE_SUMMARY_DIRTY;
582 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
589 * camel_store_summary_info_new_from_path:
590 * @summary: a #CamelStoreSummary object
593 * Create a new info record from a name.
595 * This info record MUST be freed using
596 * #camel_store_summary_info_free, #camel_store_info_free will not
599 * Returns the #CamelStoreInfo associated with @path
602 camel_store_summary_info_new_from_path(CamelStoreSummary *s, const char *path)
604 return ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_new(s, path);
609 * camel_store_summary_info_free:
610 * @summary: a #CamelStoreSummary object
611 * @info: a #CamelStoreInfo
613 * Unref and potentially free @info, and all associated memory.
616 camel_store_summary_info_free(CamelStoreSummary *s, CamelStoreInfo *info)
621 CAMEL_STORE_SUMMARY_LOCK(s, ref_lock);
623 g_assert(info->refcount >= 1);
626 if (info->refcount > 0) {
627 CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock);
631 CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock);
633 ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_free(s, info);
638 * camel_store_summary_info_ref:
639 * @summary: a #CamelStoreSummary object
640 * @info: a #CamelStoreInfo
642 * Add an extra reference to @info.
645 camel_store_summary_info_ref(CamelStoreSummary *s, CamelStoreInfo *info)
650 CAMEL_STORE_SUMMARY_LOCK(s, ref_lock);
651 g_assert(info->refcount >= 1);
653 CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock);
658 * camel_store_summary_touch:
659 * @summary: a #CamelStoreSummary object
661 * Mark the summary as changed, so that a save will force it to be
662 * written back to disk.
665 camel_store_summary_touch(CamelStoreSummary *s)
667 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
668 s->flags |= CAMEL_STORE_SUMMARY_DIRTY;
669 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
674 * camel_store_summary_clear:
675 * @summary: a #CamelStoreSummary object
677 * Empty the summary contents.
680 camel_store_summary_clear(CamelStoreSummary *s)
684 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
685 if (camel_store_summary_count(s) == 0) {
686 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
690 for (i=0;i<s->folders->len;i++)
691 camel_store_summary_info_free(s, s->folders->pdata[i]);
693 g_ptr_array_set_size(s->folders, 0);
694 g_hash_table_destroy(s->folders_path);
695 s->folders_path = g_hash_table_new(g_str_hash, g_str_equal);
696 s->flags |= CAMEL_STORE_SUMMARY_DIRTY;
697 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
702 * camel_store_summary_remove:
703 * @summary: a #CamelStoreSummary object
704 * @info: a #CamelStoreInfo
706 * Remove a specific @info record from the summary.
709 camel_store_summary_remove(CamelStoreSummary *s, CamelStoreInfo *info)
711 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
712 g_hash_table_remove(s->folders_path, camel_store_info_path(s, info));
713 g_ptr_array_remove(s->folders, info);
714 s->flags |= CAMEL_STORE_SUMMARY_DIRTY;
715 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
717 camel_store_summary_info_free(s, info);
722 * camel_store_summary_remove_path:
723 * @summary: a #CamelStoreSummary object
726 * Remove a specific info record from the summary, by @path.
729 camel_store_summary_remove_path(CamelStoreSummary *s, const char *path)
731 CamelStoreInfo *oldinfo;
734 CAMEL_STORE_SUMMARY_LOCK(s, ref_lock);
735 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
736 if (g_hash_table_lookup_extended(s->folders_path, path, (void *)&oldpath, (void *)&oldinfo)) {
737 /* make sure it doesn't vanish while we're removing it */
739 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
740 CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock);
741 camel_store_summary_remove(s, oldinfo);
742 camel_store_summary_info_free(s, oldinfo);
744 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
745 CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock);
751 * camel_store_summary_remove_index:
752 * @summary: a #CamelStoreSummary object
755 * Remove a specific info record from the summary, by index.
758 camel_store_summary_remove_index(CamelStoreSummary *s, int index)
760 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
761 if (index < s->folders->len) {
762 CamelStoreInfo *info = s->folders->pdata[index];
764 g_hash_table_remove(s->folders_path, camel_store_info_path(s, info));
765 g_ptr_array_remove_index(s->folders, index);
766 s->flags |= CAMEL_STORE_SUMMARY_DIRTY;
768 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
769 camel_store_summary_info_free(s, info);
771 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
776 summary_header_load(CamelStoreSummary *s, FILE *in)
778 gint32 version, flags, count;
781 fseek(in, 0, SEEK_SET);
783 io(printf("Loading header\n"));
785 if (camel_file_util_decode_fixed_int32(in, &version) == -1
786 || camel_file_util_decode_fixed_int32(in, &flags) == -1
787 || camel_file_util_decode_time_t(in, &time) == -1
788 || camel_file_util_decode_fixed_int32(in, &count) == -1) {
795 s->version = version;
797 if (version < CAMEL_STORE_SUMMARY_VERSION_0) {
798 g_warning("Store summary header version too low");
806 summary_header_save(CamelStoreSummary *s, FILE *out)
808 fseek(out, 0, SEEK_SET);
810 io(printf("Savining header\n"));
812 /* always write latest version */
813 camel_file_util_encode_fixed_int32(out, CAMEL_STORE_SUMMARY_VERSION);
814 camel_file_util_encode_fixed_int32(out, s->flags);
815 camel_file_util_encode_time_t(out, s->time);
816 return camel_file_util_encode_fixed_int32(out, camel_store_summary_count(s));
821 * camel_store_summary_info_new:
822 * @summary: a #CamelStoreSummary object
824 * Allocate a new #CamelStoreInfo, suitable for adding to this
827 * Returns the newly allocated #CamelStoreInfo
830 camel_store_summary_info_new(CamelStoreSummary *s)
832 CamelStoreInfo *info;
834 CAMEL_STORE_SUMMARY_LOCK(s, alloc_lock);
835 if (s->store_info_chunks == NULL)
836 s->store_info_chunks = e_memchunk_new(32, s->store_info_size);
837 info = e_memchunk_alloc0(s->store_info_chunks);
838 CAMEL_STORE_SUMMARY_UNLOCK(s, alloc_lock);
845 * camel_store_info_string:
846 * @summary: a #CamelStoreSummary object
847 * @info: a #CamelStoreInfo
848 * @type: specific string being requested
850 * Get a specific string from the @info.
852 * Returns the string value
855 camel_store_info_string(CamelStoreSummary *s, const CamelStoreInfo *info, int type)
857 return ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_string(s, info, type);
862 * camel_store_info_set_string:
863 * @summary: a #CamelStoreSummary object
864 * @info: a #CamelStoreInfo
865 * @type: specific string being set
866 * @value: string value to set
868 * Set a specific string on the @info.
871 camel_store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *info, int type, const char *value)
873 ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_set_string(s, info, type, value);
876 static CamelStoreInfo *
877 store_info_new(CamelStoreSummary *s, const char *f)
879 CamelStoreInfo *info;
881 info = camel_store_summary_info_new(s);
883 info->path = g_strdup(f);
884 info->unread = CAMEL_STORE_INFO_FOLDER_UNKNOWN;
885 info->total = CAMEL_STORE_INFO_FOLDER_UNKNOWN;
890 static CamelStoreInfo *
891 store_info_load(CamelStoreSummary *s, FILE *in)
893 CamelStoreInfo *info;
895 info = camel_store_summary_info_new(s);
897 io(printf("Loading folder info\n"));
899 camel_file_util_decode_string(in, &info->path);
900 camel_file_util_decode_uint32(in, &info->flags);
901 camel_file_util_decode_uint32(in, &info->unread);
902 camel_file_util_decode_uint32(in, &info->total);
904 /* Ok, brown paper bag bug - prior to version 2 of the file, flags are
905 stored using the bit number, not the bit. Try to recover as best we can */
906 if (s->version < CAMEL_STORE_SUMMARY_VERSION_2) {
910 flags |= CAMEL_STORE_INFO_FOLDER_NOSELECT;
912 flags |= CAMEL_STORE_INFO_FOLDER_READONLY;
914 flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED;
916 flags |= CAMEL_STORE_INFO_FOLDER_FLAGGED;
924 camel_store_summary_info_free(s, info);
930 store_info_save(CamelStoreSummary *s, FILE *out, CamelStoreInfo *info)
932 io(printf("Saving folder info\n"));
934 camel_file_util_encode_string(out, camel_store_info_path(s, info));
935 camel_file_util_encode_uint32(out, info->flags);
936 camel_file_util_encode_uint32(out, info->unread);
937 camel_file_util_encode_uint32(out, info->total);
943 store_info_free(CamelStoreSummary *s, CamelStoreInfo *info)
947 e_memchunk_free(s->store_info_chunks, info);
951 store_info_string(CamelStoreSummary *s, const CamelStoreInfo *info, int type)
957 g_assert (info != NULL);
960 case CAMEL_STORE_INFO_PATH:
962 case CAMEL_STORE_INFO_NAME:
963 p = strrchr(info->path, '/');
968 case CAMEL_STORE_INFO_URI:
969 if (info->uri == NULL) {
972 uri = camel_url_new_with_base(s->uri_base, info->path);
973 ((CamelStoreInfo *)info)->uri = camel_url_to_string(uri, 0);
983 store_info_set_string (CamelStoreSummary *s, CamelStoreInfo *info, int type, const char *str)
989 g_assert (info != NULL);
992 case CAMEL_STORE_INFO_PATH:
993 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
994 g_hash_table_remove(s->folders_path, (char *)camel_store_info_path(s, info));
997 info->path = g_strdup(str);
998 g_hash_table_insert(s->folders_path, (char *)camel_store_info_path(s, info), info);
999 s->flags |= CAMEL_STORE_SUMMARY_DIRTY;
1000 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
1002 case CAMEL_STORE_INFO_NAME:
1003 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
1004 g_hash_table_remove(s->folders_path, (char *)camel_store_info_path(s, info));
1005 p = strrchr(info->path, '/');
1007 len = p-info->path+1;
1008 v = g_malloc(len+strlen(str)+1);
1009 memcpy(v, info->path, len);
1016 g_hash_table_insert(s->folders_path, (char *)camel_store_info_path(s, info), info);
1017 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
1019 case CAMEL_STORE_INFO_URI:
1020 g_warning("Cannot set store info uri, aborting");