1 #include "links.h"
2
3 static struct list *block_new_item(void *ignore);
4 static void block_delete_item(struct list *data);
5 static void block_copy_item(struct list *in, struct list *out);
6 static unsigned char *block_type_item(struct terminal *term, struct list *data, int x);
7 static void block_edit_item(struct dialog_data *dlg, struct list *data, void (*ok_fn)(struct dialog_data *, struct list *, struct list *, struct list_description *), struct list *ok_arg, unsigned char dlg_title);
8 static struct list *block_find_item(struct list *start, unsigned char *str, int direction);
9
10 static struct history block_search_histroy = { 0, {&block_search_histroy.items, &block_search_histroy.items} };
11
12 struct list blocks = { init_list_1st(&blocks.list_entry) 0, -1, NULL, init_list_last(&blocks.list_entry) };
13
14 static struct list_description blocks_ld = {
15 0, /* flat */
16 &blocks, /* list head */
17 block_new_item,
18 block_edit_item,
19 NULL,
20 block_delete_item,
21 block_copy_item,
22 block_type_item,
23 block_find_item,
24 &block_search_histroy,
25 0, /* this is set in init_assoc function */
26 15, /* # of items in main window */
27 T_BLOCKED_IMAGE, /* item title */
28 T_BLOCK_LIST_IN_USE, /* Already open message */
29 T_BLOCK_LIST_MANAGER, /* Window title */
30 T_BLOCK_DELETE,
31 0, /* no button */
32 NULL, /* no button */
33 NULL, /* no save */
34
35 NULL, NULL, 0, 0, /* internal vars */
36 0, /* modified */
37 NULL,
38 NULL,
39 0,
40 };
41
42
block_new_item(void * ignore)43 static struct list *block_new_item(void *ignore)
44 {
45 /*Default constructor*/
46 struct block *neww;
47
48 neww = mem_alloc(sizeof(struct block));
49 neww->url = stracpy(cast_uchar "");
50 return &neww->head;
51 }
52
block_delete_item(struct list * data)53 static void block_delete_item(struct list *data)
54 {
55 /*Destructor */
56 struct block *del = get_struct(data, struct block, head);
57 if (del->head.list_entry.next) del_from_list(&del->head);
58 mem_free(del->url);
59 mem_free(del);
60 }
61
block_copy_item(struct list * in,struct list * out)62 static void block_copy_item(struct list *in, struct list *out)
63 {
64 /*Copy construction */
65 struct block *item_in = get_struct(in, struct block, head);
66 struct block *item_out = get_struct(out, struct block, head);
67
68 mem_free(item_out->url);
69 item_out->url = stracpy(item_in->url);
70 }
71
72 /*This is used to display the items in the menu*/
block_type_item(struct terminal * term,struct list * data,int x)73 static unsigned char *block_type_item(struct terminal *term, struct list *data, int x)
74 {
75 unsigned char *txt, *txt1;
76 struct block *item;
77
78 if (data == &blocks) return stracpy(get_text_translation(TEXT_(T_BLOCK_LIST), term));
79
80 item = get_struct(data, struct block, head);
81 txt = stracpy(item->url);
82
83 /*I have no idea what this does, but it os copied from working code in types.c*/
84 txt1 = convert(blocks_ld.codepage, term_charset(term), txt, NULL);
85 mem_free(txt);
86
87 return txt1;
88 }
89
90 struct assoc_ok_struct {
91 void (*fn)(struct dialog_data *, struct list *, struct list *, struct list_description *);
92 struct list *data;
93 struct dialog_data *dlg;
94 };
95
96 /* destroys an item, this function is called when edit window is aborted */
block_edit_abort(struct dialog_data * data)97 static void block_edit_abort(struct dialog_data *data)
98 {
99 struct block *item = (struct block *)data->dlg->udata;
100 struct dialog *dlg = data->dlg;
101
102 mem_free(dlg->udata2);
103 if (item) block_delete_item(&item->head);
104 }
105
106 /* Puts url into the block list */
block_edit_done(void * data)107 static void block_edit_done(void *data)
108 {
109 /*Copied from types.c*/
110 struct dialog *d = (struct dialog *)data;
111 struct block *item = (struct block *)d->udata;
112 struct assoc_ok_struct *s = (struct assoc_ok_struct *)d->udata2;
113 unsigned char *txt;
114 unsigned char *url;
115
116 /*See block_edit_item*/
117 url = (unsigned char *)&d->items[4];
118
119 txt = convert(term_charset(s->dlg->win->term), blocks_ld.codepage, url, NULL);
120 mem_free(item->url);
121 item->url = txt;
122
123 s->fn(s->dlg, s->data, &item->head, &blocks_ld);
124 d->udata = NULL; /* for abort function */
125 }
126
block_edit_item_fn(struct dialog_data * dlg)127 static void block_edit_item_fn(struct dialog_data *dlg)
128 {
129 /*Copied from input_field. I don't know how most of it works.*/
130 #define LL gf_val(1, G_BFU_FONT_SIZE)
131 struct terminal *term = dlg->win->term;
132 int max = 0, min = 0;
133 int w, rw;
134 int y = gf_val(-1, -G_BFU_FONT_SIZE);
135 unsigned char *text = TEXT_(T_ENTER_URL);
136
137
138 if (dlg->win->term->spec->braille) y += gf_val(1, G_BFU_FONT_SIZE);
139 max_text_width(term, text, &max, AL_LEFT);
140 min_text_width(term, text, &min, AL_LEFT);
141 max_buttons_width(term, dlg->items + 1, 2, &max);
142 min_buttons_width(term, dlg->items + 1, 2, &min);
143 if (max < dlg->dlg->items->dlen) max = dlg->dlg->items->dlen;
144 w = term->x * 9 / 10 - 2 * DIALOG_LB;
145 if (w > max) w = max;
146 if (w < min) w = min;
147 rw = w;
148 dlg_format_text_and_field(dlg, NULL, text, dlg->items, 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT);
149 y += LL;
150 dlg_format_buttons(dlg, NULL, dlg->items + 1, 2, 0, &y, w, &rw, AL_CENTER);
151 w = rw;
152 dlg->xw = rw + 2 * DIALOG_LB;
153 dlg->yw = y + 2 * DIALOG_TB;
154 center_dlg(dlg);
155 draw_dlg(dlg);
156 y = dlg->y + DIALOG_TB;
157 if (dlg->win->term->spec->braille) y += gf_val(1, G_BFU_FONT_SIZE);
158 dlg_format_text_and_field(dlg, term, text, dlg->items, dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT);
159 y += LL;
160 dlg_format_buttons(dlg, term, dlg->items + 1, 2, dlg->x + DIALOG_LB, &y, w, NULL, AL_CENTER);
161 }
162
block_edit_item(struct dialog_data * dlg,struct list * data,void (* ok_fn)(struct dialog_data *,struct list *,struct list *,struct list_description *),struct list * ok_arg,unsigned char dlg_title)163 static void block_edit_item(struct dialog_data *dlg, struct list *data, void (*ok_fn)(struct dialog_data *, struct list *, struct list *, struct list_description *), struct list *ok_arg, unsigned char dlg_title)
164 {
165 /*Copied from types.c */
166 /*Data is a new item generated by the "default" function*/
167 struct block *neww = get_struct(data, struct block, head);
168
169 struct terminal *term = dlg->win->term;
170 struct dialog *d;
171 struct assoc_ok_struct *s;
172 unsigned char *url, *txt;
173
174 /*Allocate space for dialog, 4 items followed by 1 string*/
175 d = mem_alloc(sizeof(struct dialog) + 4 * sizeof(struct dialog_item) + 1 * MAX_STR_LEN);
176 memset(d, 0, sizeof(struct dialog) + 4 * sizeof(struct dialog_item) + 1 * MAX_STR_LEN);
177
178 /*Set up this string */
179 url = (unsigned char *)&d->items[4];
180 txt = convert(blocks_ld.codepage, term_charset(dlg->win->term), neww->url, NULL);
181 safe_strncpy(url, txt, MAX_STR_LEN);
182 mem_free(txt);
183
184 /* Create the dialog */
185 s = mem_alloc(sizeof(struct assoc_ok_struct));
186
187 s->fn = ok_fn;
188 s->data = ok_arg;
189 s->dlg = dlg;
190
191 switch (dlg_title) {
192 case TITLE_EDIT:
193 d->title = TEXT_(T_BLOCK_EDIT);
194 break;
195
196 case TITLE_ADD:
197 d->title = TEXT_(T_BLOCK_ADD);
198 break;
199
200 default:
201 internal_error("Unsupported dialog title.\n");
202 }
203
204 d->udata = neww;
205 d->udata2 = s;
206 d->fn = block_edit_item_fn;
207 d->abort = block_edit_abort;
208 d->refresh = block_edit_done;
209 d->refresh_data = d;
210 d->items[0].type = D_FIELD;
211 d->items[0].dlen = MAX_STR_LEN;
212 d->items[0].data = url;
213 d->items[0].fn = check_nonempty;
214 d->items[1].type = D_BUTTON;
215 d->items[1].gid = B_ENTER;
216 d->items[1].fn = ok_dialog;
217 d->items[1].text = TEXT_(T_OK);
218 d->items[2].type = D_BUTTON;
219 d->items[2].gid = B_ESC;
220 d->items[2].text = TEXT_(T_CANCEL);
221 d->items[2].fn = cancel_dialog;
222 d->items[3].type = D_END;
223 do_dialog(term, d, getml(d, NULL));
224 }
225
test_entry(struct list * e,unsigned char * str)226 static int test_entry(struct list *e, unsigned char *str)
227 {
228 return casestrstr(get_struct(e, struct block, head)->url, str);
229 }
230
block_find_item(struct list * s,unsigned char * str,int direction)231 static struct list *block_find_item(struct list *s, unsigned char *str, int direction)
232 {
233 struct list *e;
234
235 if (direction >= 0) {
236 for (e = list_next(s); e != s; e = list_next(e)) {
237 if (e->depth >= 0 && test_entry(e, str))
238 return e;
239 }
240 } else {
241 for (e = list_prev(s); e != s; e = list_prev(e)) {
242 if (e->depth >= 0 && test_entry(e, str))
243 return e;
244 }
245 }
246
247 if (e->depth >= 0 && test_entry(e, str))
248 return e;
249
250 return NULL;
251 }
252
253
block_manager(struct terminal * term,void * fcp,void * ses_)254 void block_manager(struct terminal *term, void *fcp, void *ses_)
255 {
256 struct session *ses = (struct session *)ses_;
257 create_list_window(&blocks_ld, &blocks, term, ses);
258 }
259
260
block_url_add(void * ses_,unsigned char * url)261 void *block_url_add(void *ses_, unsigned char *url)
262 {
263 struct session *ses = (struct session *)ses_;
264 /*Callback from the dialog box created from the link menu*/
265 struct list *new_list;
266 struct block *new_b;
267 struct terminal *term = ses ? ses->term : NULL;
268
269 if (test_list_window_in_use(&blocks_ld, term))
270 return NULL;
271
272 new_list = block_new_item(0);
273 new_b = get_struct(new_list, struct block, head);
274
275 mem_free(new_b->url);
276 new_b->url = stracpy(url);
277 new_b->head.type = 0;
278
279 add_to_list(blocks.list_entry, &new_b->head);
280 return NULL;
281 }
282
block_url_query(struct session * ses,unsigned char * u)283 void block_url_query(struct session *ses, unsigned char *u)
284 {
285 if (test_list_window_in_use(&blocks_ld, ses->term))
286 return;
287
288 input_field(ses->term, NULL, TEXT_(T_BLOCK_URL), TEXT_(T_BLOCK_ADD), ses, 0, MAX_INPUT_URL_LEN, u, 0, 0, NULL, 2, TEXT_(T_OK), block_url_add, TEXT_(T_CANCEL), input_field_null);
289
290 }
291
find_first_match(unsigned char * s,unsigned char * p,unsigned * ii)292 static unsigned char *find_first_match(unsigned char *s, unsigned char *p, unsigned *ii)
293 {
294 unsigned i;
295 retry:
296 for (i = 0; s[i] && p[i] && p[i] != '*'; i++) {
297 if (s[i] != p[i] && p[i] != '?') {
298 s++;
299 goto retry;
300 }
301 }
302 *ii = i;
303 if (!p[i] || p[i] == '*') return s;
304 return NULL;
305 }
306
simple_glob_match(unsigned char * s,unsigned char * p)307 static int simple_glob_match(unsigned char *s, unsigned char *p)
308 {
309 unsigned i;
310 if (find_first_match(s, p, &i) != s) return 0;
311 if (!p[i]) return !s[i];
312 while (1) {
313 s += i;
314 p += i + 1;
315 if (!(s = find_first_match(s, p, &i))) return 0;
316 if (!p[i]) {
317 s += strlen(cast_const_char s) - i;
318 return !!find_first_match(s, p, &i);
319 }
320 }
321 }
322
323
is_url_blocked(unsigned char * url)324 int is_url_blocked(unsigned char *url)
325 {
326 struct list *b;
327 struct list_head *lb;
328
329 foreach(struct list, b, lb, blocks.list_entry) {
330 if (simple_glob_match(url, get_struct(b, struct block, head)->url))
331 return 1;
332 }
333
334 return 0;
335 }
336
init_blocks(void)337 void init_blocks(void)
338 {
339 blocks_ld.codepage = utf8_table;
340 }
341
free_blocks(void)342 void free_blocks(void)
343 {
344 /*List destructor */
345 struct list *b;
346 struct list_head *lb;
347
348 foreach(struct list, b, lb, blocks.list_entry) {
349 struct block *bm = get_struct(b, struct block, head);
350 mem_free(bm->url);
351 lb = lb->prev;
352 del_from_list(b);
353 mem_free(bm);
354 }
355
356 free_history(block_search_histroy);
357 }
358