1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2002 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.
32 #include <libedataserver/md5-utils.h>
33 #include <libedataserver/e-memory.h>
35 #include "camel-file-utils.h"
36 #include "camel-private.h"
37 #include "camel-utf8.h"
39 #include "camel-nntp-store-summary.h"
42 #define io(x) /* io debug */
44 #define CAMEL_NNTP_STORE_SUMMARY_VERSION_0 (0)
45 #define CAMEL_NNTP_STORE_SUMMARY_VERSION_1 (1)
47 #define CAMEL_NNTP_STORE_SUMMARY_VERSION (1)
49 #define _PRIVATE(o) (((CamelNNTPStoreSummary *)(o))->priv)
51 static int summary_header_load(CamelStoreSummary *, FILE *);
52 static int summary_header_save(CamelStoreSummary *, FILE *);
54 /*static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);*/
55 static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *);
56 static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *);
57 static void store_info_free(CamelStoreSummary *, CamelStoreInfo *);
59 static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int);
60 static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *);
62 static void camel_nntp_store_summary_class_init (CamelNNTPStoreSummaryClass *klass);
63 static void camel_nntp_store_summary_init (CamelNNTPStoreSummary *obj);
64 static void camel_nntp_store_summary_finalise (CamelObject *obj);
66 static CamelStoreSummaryClass *camel_nntp_store_summary_parent;
69 camel_nntp_store_summary_class_init (CamelNNTPStoreSummaryClass *klass)
71 CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *)klass;
73 ssklass->summary_header_load = summary_header_load;
74 ssklass->summary_header_save = summary_header_save;
76 /*ssklass->store_info_new = store_info_new;*/
77 ssklass->store_info_load = store_info_load;
78 ssklass->store_info_save = store_info_save;
79 ssklass->store_info_free = store_info_free;
81 ssklass->store_info_string = store_info_string;
82 ssklass->store_info_set_string = store_info_set_string;
86 camel_nntp_store_summary_init (CamelNNTPStoreSummary *s)
88 /*struct _CamelNNTPStoreSummaryPrivate *p;
90 p = _PRIVATE(s) = g_malloc0(sizeof(*p));*/
92 ((CamelStoreSummary *) s)->store_info_size = sizeof (CamelNNTPStoreInfo);
93 s->version = CAMEL_NNTP_STORE_SUMMARY_VERSION;
94 memset (&s->last_newslist, 0, sizeof (s->last_newslist));
98 camel_nntp_store_summary_finalise (CamelObject *obj)
100 /*struct _CamelNNTPStoreSummaryPrivate *p;*/
101 /*CamelNNTPStoreSummary *s = (CamelNNTPStoreSummary *)obj;*/
108 camel_nntp_store_summary_get_type (void)
110 static CamelType type = CAMEL_INVALID_TYPE;
112 if (type == CAMEL_INVALID_TYPE) {
113 camel_nntp_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type();
114 type = camel_type_register((CamelType)camel_nntp_store_summary_parent, "CamelNNTPStoreSummary",
115 sizeof (CamelNNTPStoreSummary),
116 sizeof (CamelNNTPStoreSummaryClass),
117 (CamelObjectClassInitFunc) camel_nntp_store_summary_class_init,
119 (CamelObjectInitFunc) camel_nntp_store_summary_init,
120 (CamelObjectFinalizeFunc) camel_nntp_store_summary_finalise);
127 * camel_nntp_store_summary_new:
129 * Create a new CamelNNTPStoreSummary object.
131 * Return value: A new CamelNNTPStoreSummary widget.
133 CamelNNTPStoreSummary *
134 camel_nntp_store_summary_new (void)
136 return (CamelNNTPStoreSummary *) camel_object_new (camel_nntp_store_summary_get_type ());
140 * camel_nntp_store_summary_full_name:
144 * Retrieve a summary item by full name.
146 * A referenced to the summary item is returned, which may be
147 * ref'd or free'd as appropriate.
149 * Return value: The summary item, or NULL if the @full_name name
151 * It must be freed using camel_store_summary_info_free().
154 camel_nntp_store_summary_full_name(CamelNNTPStoreSummary *s, const char *full_name)
157 CamelNNTPStoreInfo *info;
159 count = camel_store_summary_count ((CamelStoreSummary *) s);
160 for (i = 0; i < count; i++) {
161 info = (CamelNNTPStoreInfo *)camel_store_summary_index ((CamelStoreSummary *) s, i);
163 if (strcmp (info->full_name, full_name) == 0)
165 camel_store_summary_info_free ((CamelStoreSummary *) s, (CamelStoreInfo *)info);
173 camel_nntp_store_summary_full_to_path (CamelNNTPStoreSummary *s, const char *full_name, char dir_sep)
179 if (dir_sep != '/') {
180 p = path = g_alloca (strlen (full_name) * 3 + 1);
182 while ((c = *f++ & 0xff)) {
185 else if (c == '/' || c == '%')
186 p += sprintf (p, "%%%02X", c);
192 path = (char *) full_name;
194 return camel_utf7_utf8 (path);
200 if (c >= '0' && c <= '9')
202 else if (c >= 'A' && c <= 'Z')
209 camel_nntp_store_summary_path_to_full (CamelNNTPStoreSummary *s, const char *path, char dir_sep)
215 char *subpath, *last = NULL;
218 /* check to see if we have a subpath of path already defined */
219 subpath = g_alloca (strlen (path) + 1);
220 strcpy (subpath, path);
222 si = camel_store_summary_path ((CamelStoreSummary *) s, subpath);
224 last = strrchr (subpath, '/');
228 } while (si == NULL && last);
230 /* path is already present, use the raw version we have */
231 if (si && strlen (subpath) == strlen (path)) {
232 f = g_strdup (camel_nntp_store_info_full_name (s, si));
233 camel_store_summary_info_free ((CamelStoreSummary *) s, si);
237 f = full = g_alloca (strlen (path)*2+1);
239 p = path + strlen (subpath);
243 while ((c = camel_utf8_getc ((const unsigned char **) &p))) {
251 camel_utf8_putc((unsigned char **) &f, c);
261 camel_utf8_putc ((unsigned char **) &f, v);
265 camel_utf8_putc ((unsigned char **) &f, c);
267 /* merge old path part if required */
268 f = camel_utf8_utf7 (full);
270 full = g_strdup_printf ("%s%s", camel_nntp_store_info_full_name (s, si), f);
272 camel_store_summary_info_free ((CamelStoreSummary *) s, si);
280 camel_nntp_store_summary_add_from_full (CamelNNTPStoreSummary *s, const char *full, char dir_sep)
282 CamelNNTPStoreInfo *info;
287 d(printf("adding full name '%s' '%c'\n", full, dir_sep));
290 full_name = g_alloca (len+1);
291 strcpy(full_name, full);
292 if (full_name[len-1] == dir_sep)
293 full_name[len-1] = 0;
295 info = camel_nntp_store_summary_full_name (s, full_name);
297 camel_store_summary_info_free ((CamelStoreSummary *) s, (CamelStoreInfo *) info);
298 d(printf(" already there\n"));
302 pathu8 = camel_nntp_store_summary_full_to_path (s, full_name, dir_sep);
304 info = (CamelNNTPStoreInfo *) camel_store_summary_add_from_path ((CamelStoreSummary *) s, pathu8);
306 d(printf(" '%s' -> '%s'\n", pathu8, full_name));
307 camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_NNTP_STORE_INFO_FULL_NAME, full_name);
309 d(printf(" failed\n"));
315 summary_header_load (CamelStoreSummary *s, FILE *in)
317 CamelNNTPStoreSummary *is = (CamelNNTPStoreSummary *) s;
320 if (camel_nntp_store_summary_parent->summary_header_load ((CamelStoreSummary *) s, in) == -1
321 || camel_file_util_decode_fixed_int32 (in, &version) == -1)
324 is->version = version;
326 if (version < CAMEL_NNTP_STORE_SUMMARY_VERSION_0) {
327 g_warning("Store summary header version too low");
331 if (fread (is->last_newslist, 1, NNTP_DATE_SIZE, in) < NNTP_DATE_SIZE)
334 camel_file_util_decode_fixed_int32 (in, &nil);
340 summary_header_save (CamelStoreSummary *s, FILE *out)
342 CamelNNTPStoreSummary *is = (CamelNNTPStoreSummary *) s;
344 /* always write as latest version */
345 if (camel_nntp_store_summary_parent->summary_header_save ((CamelStoreSummary *) s, out) == -1
346 || camel_file_util_encode_fixed_int32 (out, CAMEL_NNTP_STORE_SUMMARY_VERSION) == -1
347 || fwrite (is->last_newslist, 1, NNTP_DATE_SIZE, out) < NNTP_DATE_SIZE
348 || camel_file_util_encode_fixed_int32 (out, 0) == -1)
354 static CamelStoreInfo *
355 store_info_load (CamelStoreSummary *s, FILE *in)
357 CamelNNTPStoreInfo *ni;
359 ni = (CamelNNTPStoreInfo *) camel_nntp_store_summary_parent->store_info_load (s, in);
361 if (camel_file_util_decode_string (in, &ni->full_name) == -1) {
362 camel_store_summary_info_free (s, (CamelStoreInfo *) ni);
365 if (((CamelNNTPStoreSummary *)s)->version >= CAMEL_NNTP_STORE_SUMMARY_VERSION_1) {
366 if (camel_file_util_decode_uint32(in, &ni->first) == -1
367 || camel_file_util_decode_uint32(in, &ni->last) == -1) {
368 camel_store_summary_info_free (s, (CamelStoreInfo *) ni);
375 return (CamelStoreInfo *) ni;
379 store_info_save (CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi)
381 CamelNNTPStoreInfo *isi = (CamelNNTPStoreInfo *)mi;
383 if (camel_nntp_store_summary_parent->store_info_save (s, out, mi) == -1
384 || camel_file_util_encode_string (out, isi->full_name) == -1
385 || camel_file_util_encode_uint32(out, isi->first) == -1
386 || camel_file_util_encode_uint32(out, isi->last) == -1)
393 store_info_free (CamelStoreSummary *s, CamelStoreInfo *mi)
395 CamelNNTPStoreInfo *nsi = (CamelNNTPStoreInfo *) mi;
397 g_free (nsi->full_name);
398 camel_nntp_store_summary_parent->store_info_free (s, mi);
402 store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type)
404 CamelNNTPStoreInfo *nsi = (CamelNNTPStoreInfo *)mi;
408 g_assert (mi != NULL);
411 case CAMEL_NNTP_STORE_INFO_FULL_NAME:
412 return nsi->full_name;
414 return camel_nntp_store_summary_parent->store_info_string(s, mi, type);
419 store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str)
421 CamelNNTPStoreInfo *nsi = (CamelNNTPStoreInfo *)mi;
423 g_assert(mi != NULL);
426 case CAMEL_NNTP_STORE_INFO_FULL_NAME:
427 d(printf("Set full name %s -> %s\n", nsi->full_name, str));
428 CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
429 g_free (nsi->full_name);
430 nsi->full_name = g_strdup (str);
431 CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
434 camel_nntp_store_summary_parent->store_info_set_string (s, mi, type, str);