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