iconv: Bail out of the loop when an illegal sequence of bytes occurs.
[elinks/elinks-j605.git] / src / cache / dialogs.c
blobec2533083c8e958e14819c322cde156410536102
1 /* Cache-related dialogs */
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE /* XXX: we _WANT_ strcasestr() ! */
5 #endif
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
11 #include <string.h>
13 #include "elinks.h"
15 #include "bfu/dialog.h"
16 #include "cache/cache.h"
17 #include "cache/dialogs.h"
18 #include "dialogs/edit.h"
19 #include "intl/gettext/libintl.h"
20 #include "main/object.h"
21 #include "protocol/uri.h"
22 #include "session/session.h"
23 #include "terminal/draw.h"
24 #include "terminal/terminal.h"
25 #include "util/conv.h"
26 #include "util/memory.h"
27 #include "util/string.h"
30 static void
31 lock_cache_entry(struct listbox_item *item)
33 object_lock((struct cache_entry *) item->udata);
36 static void
37 unlock_cache_entry(struct listbox_item *item)
39 object_unlock((struct cache_entry *) item->udata);
42 static int
43 is_cache_entry_used(struct listbox_item *item)
45 return is_object_used((struct cache_entry *) item->udata);
48 static unsigned char *
49 get_cache_entry_text(struct listbox_item *item, struct terminal *term)
51 struct cache_entry *cached = item->udata;
53 return get_uri_string(cached->uri, URI_PUBLIC);
56 static unsigned char *
57 get_cache_entry_info(struct listbox_item *item, struct terminal *term)
59 struct cache_entry *cached = item->udata;
60 struct string msg;
62 if (item->type == BI_FOLDER) return NULL;
63 if (!init_string(&msg)) return NULL;
65 add_to_string(&msg, _("URL", term));
66 add_to_string(&msg, ": ");
67 add_uri_to_string(&msg, cached->uri, URI_PUBLIC);
69 /* No need to use compare_uri() here we only want to check whether they
70 * point to the same URI. */
71 if (cached->proxy_uri != cached->uri) {
72 add_format_to_string(&msg, "\n%s: ", _("Proxy URL", term));
73 add_uri_to_string(&msg, cached->proxy_uri, URI_PUBLIC);
76 if (cached->redirect) {
77 add_format_to_string(&msg, "\n%s: ", _("Redirect", term));
78 add_uri_to_string(&msg, cached->redirect, URI_PUBLIC);
80 if (cached->redirect_get) {
81 add_to_string(&msg, " (GET)");
85 add_format_to_string(&msg, "\n%s: %" OFF_PRINT_FORMAT, _("Size", term),
86 (off_print_T) cached->length);
87 add_format_to_string(&msg, "\n%s: %" OFF_PRINT_FORMAT, _("Loaded size", term),
88 (off_print_T) cached->data_size);
89 if (cached->content_type) {
90 add_format_to_string(&msg, "\n%s: %s", _("Content type", term),
91 cached->content_type);
93 if (cached->last_modified) {
94 add_format_to_string(&msg, "\n%s: %s", _("Last modified", term),
95 cached->last_modified);
97 if (cached->etag) {
98 add_format_to_string(&msg, "\n%s: %s", "ETag",
99 cached->etag);
101 if (cached->ssl_info) {
102 add_format_to_string(&msg, "\n%s: %s", _("SSL Cipher", term),
103 cached->ssl_info);
105 if (cached->encoding_info) {
106 add_format_to_string(&msg, "\n%s: %s", _("Encoding", term),
107 cached->encoding_info);
110 if (cached->incomplete || !cached->valid) {
111 add_char_to_string(&msg, '\n');
112 add_to_string(&msg, _("Flags", term));
113 add_to_string(&msg, ": ");
114 if (cached->incomplete) {
115 add_to_string(&msg, _("incomplete", term));
116 add_char_to_string(&msg, ' ');
118 if (!cached->valid) add_to_string(&msg, _("invalid", term));
121 #ifdef HAVE_STRFTIME
122 if (cached->expire) {
123 time_t expires = timeval_to_seconds(&cached->max_age);
125 add_format_to_string(&msg, "\n%s: ", _("Expires", term));
126 add_date_to_string(&msg, get_opt_str("ui.date_format", NULL), &expires);
128 #endif
130 add_format_to_string(&msg, "\n%s: ", _("Cache mode", term));
131 switch (cached->cache_mode) {
132 case CACHE_MODE_NEVER:
133 add_to_string(&msg, _("never use cache entry", term));
134 break;
135 case CACHE_MODE_ALWAYS:
136 add_to_string(&msg, _("always use cache entry", term));
137 break;
138 case CACHE_MODE_INCREMENT:
139 case CACHE_MODE_NORMAL:
140 case CACHE_MODE_CHECK_IF_MODIFIED:
141 case CACHE_MODE_FORCE_RELOAD:
142 /* Cache entries only use two values of enum cache_mode. */
143 INTERNAL("cached->cache_mode = %d", cached->cache_mode);
144 break;
147 #ifdef CONFIG_DEBUG
148 add_format_to_string(&msg, "\n%s: %d", "Refcount", get_object_refcount(cached));
149 add_format_to_string(&msg, "\n%s: %u", _("ID", term), cached->cache_id);
151 if (cached->head && *cached->head) {
152 add_format_to_string(&msg, "\n%s:\n\n%s", _("Header", term),
153 cached->head);
155 #endif
157 return msg.source;
160 static struct uri *
161 get_cache_entry_uri(struct listbox_item *item)
163 struct cache_entry *cached = item->udata;
165 return get_uri_reference(cached->uri);
168 static struct listbox_item *
169 get_cache_entry_root(struct listbox_item *item)
171 return NULL;
174 static int
175 can_delete_cache_entry(struct listbox_item *item)
177 return 1;
180 static void
181 delete_cache_entry_item(struct listbox_item *item, int last)
183 struct cache_entry *cached = item->udata;
185 assert(!is_object_used(cached));
187 delete_cache_entry(cached);
190 static enum listbox_match
191 match_cache_entry(struct listbox_item *item, struct terminal *term,
192 unsigned char *text)
194 struct cache_entry *cached = item->udata;
196 if (c_strcasestr(struri(cached->uri), text)
197 || (cached->head && c_strcasestr(cached->head, text)))
198 return LISTBOX_MATCH_OK;
200 return LISTBOX_MATCH_NO;
203 static enum listbox_match
204 match_cache_entry_contents(struct listbox_item *item, struct terminal *term,
205 unsigned char *text)
207 struct cache_entry *cached = item->udata;
208 struct fragment *fragment = get_cache_fragment(cached);
210 if (fragment && strlcasestr(fragment->data, fragment->length, text, -1))
211 return LISTBOX_MATCH_OK;
213 return LISTBOX_MATCH_NO;
216 const static struct listbox_ops cache_entry_listbox_ops;
218 static widget_handler_status_T
219 push_cache_hierbox_search_button(struct dialog_data *dlg_data, struct widget_data *button)
221 struct listbox_data *box = get_dlg_listbox_data(dlg_data);
223 box->ops = &cache_entry_listbox_ops;
225 return push_hierbox_search_button(dlg_data, button);
228 const static struct listbox_ops cache_entry_listbox_ops_match_contents;
230 static widget_handler_status_T
231 push_cache_hierbox_search_contents_button(struct dialog_data *dlg_data, struct widget_data *button)
233 struct listbox_data *box = get_dlg_listbox_data(dlg_data);
235 box->ops = &cache_entry_listbox_ops_match_contents;
237 return push_hierbox_search_button(dlg_data, button);
240 static struct listbox_ops_messages cache_messages = {
241 /* cant_delete_item */
242 N_("Sorry, but cache entry \"%s\" cannot be deleted."),
243 /* cant_delete_used_item */
244 N_("Sorry, but cache entry \"%s\" is being used by something else."),
245 /* cant_delete_folder */
246 NULL,
247 /* cant_delete_used_folder */
248 NULL,
249 /* delete_marked_items_title */
250 N_("Delete marked cache entries"),
251 /* delete_marked_items */
252 N_("Delete marked cache entries?"),
253 /* delete_folder_title */
254 NULL,
255 /* delete_folder */
256 NULL,
257 /* delete_item_title */
258 N_("Delete cache entry"),
259 /* delete_item; xgettext:c-format */
260 N_("Delete this cache entry?"),
261 /* clear_all_items_title */
262 NULL,
263 /* clear_all_items_title */
264 NULL,
267 #define ops(matchfn) \
268 lock_cache_entry, \
269 unlock_cache_entry, \
270 is_cache_entry_used, \
271 get_cache_entry_text, \
272 get_cache_entry_info, \
273 get_cache_entry_uri, \
274 get_cache_entry_root, \
275 matchfn, \
276 can_delete_cache_entry, \
277 delete_cache_entry_item, \
278 NULL, \
279 &cache_messages,
281 /* Each hierbox window is represented by an instance of struct hierbox,
282 * which has a corresponding instance of struct listbox_data. That
283 * instance of struct listbox_data will point one of the following two
284 * struct listbox_ops instances depending on which type of search the
285 * user is performing in that hierbox. The two struct listbox_ops
286 * instances differ only in the match callback. */
288 const static struct listbox_ops cache_entry_listbox_ops_match_contents = {
289 ops(match_cache_entry_contents)
292 const static struct listbox_ops cache_entry_listbox_ops = {
293 ops(match_cache_entry)
296 #undef ops
298 static widget_handler_status_T
299 push_invalidate_button(struct dialog_data *dlg_data, struct widget_data *button)
301 struct terminal *term = dlg_data->win->term;
302 struct listbox_data *box = get_dlg_listbox_data(dlg_data);
303 struct cache_entry *cached = box->sel->udata;
305 if (!box->sel || !box->sel->udata) return EVENT_PROCESSED;
307 assert(box->sel->type == BI_LEAF);
309 cached->valid = 0;
311 info_box(term, 0, N_("Cache entry invalidated"), ALIGN_CENTER,
312 N_("Cache entry invalidated."));
314 return EVENT_PROCESSED;
317 static const struct hierbox_browser_button cache_buttons[] = {
318 /* [gettext_accelerator_context(.cache_buttons)] */
319 { N_("~Info"), push_hierbox_info_button, 1 },
320 { N_("~Goto"), push_hierbox_goto_button, 1 },
321 { N_("~Delete"), push_hierbox_delete_button, 1 },
322 { N_("~Search"), push_cache_hierbox_search_button, 1 },
323 { N_("Search c~ontents"), push_cache_hierbox_search_contents_button, 1 },
324 { N_("In~validate"), push_invalidate_button, 1 },
327 struct_hierbox_browser(
328 cache_browser,
329 N_("Cache manager"),
330 cache_buttons,
331 &cache_entry_listbox_ops
334 void
335 cache_manager(struct session *ses)
337 hierbox_browser(&cache_browser, ses);