RSSyl: Allow use of .netrc by libcurl. Bug/enhancement #3309, by Vincent Pelletier
[claws.git] / src / plugins / libravatar / libravatar_missing.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2014 Hiroyuki Yamamoto and the Claws Mail Team
4  * Copyright (C) 2014 Ricardo Mones
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdio.h>
21
22 #include "libravatar_missing.h"
23 #include "libravatar_prefs.h"
24 #include "utils.h"
25
26 /**
27  * Loads the hash table of md5sum → time from the given filename.
28  *
29  * @param filename  Name of the hash table filename.
30  *
31  * @return A hash table with the entries not expired contained in
32  *         the given filename or NULL if failed to load.
33  */
34 GHashTable *missing_load_from_file(const gchar *filename)
35 {
36         FILE *file = fopen(filename, "r");
37         time_t t;
38         long long unsigned seen;
39         gchar md5sum[33];
40         GHashTable *table;
41         int r = 0, a = 0, d = 0;
42
43         if (file == NULL) {
44                 if (!is_file_exist(filename)) { /* first run, return an empty table */
45                         return g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
46                 }
47                 g_warning("Cannot open %s for reading\n", filename);
48                 return NULL;
49         }
50         t = time(NULL);
51         if (t == (time_t)-1) {
52                 g_warning("Cannot get time!\n");
53                 return NULL;
54         }
55
56         table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
57
58         while ((r = fscanf(file, "%s %llu\n", md5sum, &seen)) != EOF) {
59                 if (t - (time_t)seen <= LIBRAVATAR_MISSING_TIME) {
60                         time_t *value = g_malloc0(sizeof(time_t));
61                         if (value == NULL) {
62                                 g_warning("Cannot allocate memory\n");
63                                 g_hash_table_destroy(table);
64                                 return NULL;
65                         }
66                         *value = (time_t)seen;
67                         g_hash_table_insert(table, g_strdup(md5sum), value);
68                 } else
69                         d++;
70                 a++;
71         }
72
73         if (fclose(file) != 0)
74                 g_warning("Error closing %s\n", filename);
75
76         debug_print("Read %d missing avatar entries, %d obsolete entries discarded\n", a, d);
77         return table;
78 }
79
80 /**
81  * Saves a hash table item.
82  *
83  * @param key    Hash table key, a md5sum string.
84  * @param vakue  Hash table value, a time_t.
85  * @param data   User data, a pointer to the open FILE being written.
86  */
87 static void missing_save_item(gpointer key, gpointer value, gpointer data)
88 {
89         FILE *file = (FILE *)data;
90         gchar *line = g_strdup_printf("%s %llu\n", (gchar *)key, *((long long unsigned *)value));
91         if (fputs(line, file) < 0)
92                 g_warning("Error saving missing item\n");
93         g_free(line);
94 }
95
96 /**
97  * Saves a hash table of md5sum → time to a given file name.
98  *
99  * @param table     The table to save.
100  * @param filename  The name of the file where table data will be saved.
101  *
102  * @return 0 on success, -1 if there was some problem saving.
103  */
104 gint missing_save_to_file(GHashTable *table, const gchar *filename)
105 {
106         FILE *file = fopen(filename, "w");
107
108         if (file == NULL) {
109                 g_warning("Cannot open %s for writing\n", filename);
110                 return -1;
111         }
112
113         g_hash_table_foreach(table, missing_save_item, (gpointer)file);
114         debug_print("Saved %u missing avatar entries\n", g_hash_table_size(table));
115
116         if (fclose(file) != 0) {
117                 g_warning("Error closing %s\n", filename);
118                 return -1;
119         }
120
121         return 0;
122 }
123
124 /**
125  * Adds a md5sum to a md5sum → time hash table.
126  * If the md5sum is already in the table its time is updated.
127  *
128  * @param table  The table to use.
129  * @param md5    The md5sum to add or update.
130  */
131 void missing_add_md5(GHashTable *table, const gchar *md5)
132 {
133         time_t t = time(NULL);
134
135         if (t == (time_t)-1) {
136                 g_warning("Cannot get time!\n");
137                 return;
138         }
139
140         time_t *seen = g_hash_table_lookup(table, md5);
141         if (seen == NULL) {
142                 seen = g_malloc0(sizeof(time_t));
143                 if (seen == NULL) {
144                         g_warning("Cannot allocate memory\n");
145                         return;
146                 }
147                 *seen = t;
148                 g_hash_table_insert(table, g_strdup(md5), seen);
149                 debug_print("New md5 %s added with time %llu\n", md5, (long long unsigned)t);
150         } else {
151                 *seen = t; /* just update */
152                 debug_print("Updated md5 %s with time %llu\n", md5, (long long unsigned)t);
153         }
154 }
155
156 /**
157  * Check if a md5sum is in hash table and not expired.
158  *
159  * @param table   The table to check against.
160  * @param md5     The md5sum to check.
161  *
162  * @return TRUE if the md5sum is in the table and is not expired,
163            FALSE otherwise.
164  */
165 gboolean is_missing_md5(GHashTable *table, const gchar *md5)
166 {
167         time_t t;
168         time_t *seen = (time_t *)g_hash_table_lookup(table, md5);
169
170         if (seen == NULL)
171                 return FALSE;
172
173         t = time(NULL);
174         if (t != (time_t)-1) {
175                 if (t - *seen <= LIBRAVATAR_MISSING_TIME) {
176                         debug_print("Found missing md5 %s\n", md5);
177                         return TRUE;
178                 }
179         }
180         return FALSE;
181 }
182