~ubuntu-branches/ubuntu/feisty/elinks/feisty-updates

« back to all changes in this revision

Viewing changes to src/sched/task.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-06-30 08:57:43 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060630085743-l81fgbw9dehvl1ds
Tags: 0.11.1-1ubuntu1
* Merge to Debian unstable.
* Removed gnutls12 porting, this is upstream now.
* Only Ubuntu changes left:
  - Killed type-handling.
  - Add X-Ubuntu-Gettext-Domain to .desktop files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Sessions task management */
2
 
/* $Id: task.c,v 1.146.2.8 2005/09/14 13:19:10 jonas Exp $ */
3
 
 
4
 
#ifdef HAVE_CONFIG_H
5
 
#include "config.h"
6
 
#endif
7
 
 
8
 
#include <stdio.h>
9
 
#include <stdlib.h>
10
 
#include <string.h>
11
 
 
12
 
#include "elinks.h"
13
 
 
14
 
#include "bfu/menu.h"
15
 
#include "bfu/dialog.h"
16
 
#include "cache/cache.h"
17
 
#include "dialogs/status.h"
18
 
#include "document/document.h"
19
 
#include "document/html/parser.h"
20
 
#include "document/refresh.h"
21
 
#include "document/view.h"
22
 
#include "intl/gettext/libintl.h"
23
 
#include "lowlevel/select.h"
24
 
#include "protocol/protocol.h"
25
 
#include "protocol/uri.h"
26
 
#include "terminal/terminal.h"
27
 
#include "terminal/window.h"
28
 
#include "sched/download.h"
29
 
#include "sched/event.h"
30
 
#include "sched/session.h"
31
 
#include "sched/task.h"
32
 
#include "viewer/text/view.h"
33
 
 
34
 
 
35
 
static void
36
 
free_task(struct session *ses)
37
 
{
38
 
        assertm(ses->task.type, "Session has no task");
39
 
        if_assert_failed return;
40
 
 
41
 
        if (ses->loading_uri) {
42
 
                done_uri(ses->loading_uri);
43
 
                ses->loading_uri = NULL;
44
 
        }
45
 
        ses->task.type = TASK_NONE;
46
 
}
47
 
 
48
 
void
49
 
abort_preloading(struct session *ses, int interrupt)
50
 
{
51
 
        if (!ses->task.type) return;
52
 
 
53
 
        change_connection(&ses->loading, NULL, PRI_CANCEL, interrupt);
54
 
        free_task(ses);
55
 
}
56
 
 
57
 
 
58
 
struct task {
59
 
        struct session *ses;
60
 
        struct uri *uri;
61
 
        enum cache_mode cache_mode;
62
 
        enum task_type type;
63
 
        unsigned char *target_frame;
64
 
        struct location *target_location;
65
 
};
66
 
 
67
 
static void
68
 
post_yes(struct task *task)
69
 
{
70
 
        struct session *ses = task->ses;
71
 
 
72
 
        abort_preloading(task->ses, 0);
73
 
 
74
 
        ses->loading.callback = (void (*)(struct download *, void *)) loading_callback;
75
 
        ses->loading.data = task->ses;
76
 
        ses->loading_uri = task->uri; /* XXX: Make the session inherit the URI. */
77
 
 
78
 
        ses->task.type = task->type;
79
 
        ses->task.target_frame = task->target_frame;
80
 
        ses->task.target_location = task->target_location;
81
 
 
82
 
        load_uri(ses->loading_uri, ses->referrer, &ses->loading,
83
 
                 PRI_MAIN, task->cache_mode, -1);
84
 
}
85
 
 
86
 
static void
87
 
post_no(struct task *task)
88
 
{
89
 
        reload(task->ses, CACHE_MODE_NORMAL);
90
 
        done_uri(task->uri);
91
 
}
92
 
 
93
 
/* Check if the URI is obfuscated (bug 382). The problem is said to occur when
94
 
 * a URI designed to pass access a specific location with a supplied username,
95
 
 * contains misleading chars prior to the @ symbol.
96
 
 *
97
 
 * An attacker can exploit this issue by supplying a malicious URI pointing to
98
 
 * a page designed to mimic that of a trusted site, and tricking a victim who
99
 
 * follows a link into believing they are actually at the trusted location.
100
 
 *
101
 
 * Only the user ID (and not also the password) is checked because only the
102
 
 * user ID is displayed in the status bar. */
103
 
static int
104
 
check_malicious_uri(struct uri *uri)
105
 
{
106
 
        unsigned char *user, *pos;
107
 
        int warn = 0;
108
 
 
109
 
        assert(uri->user && uri->userlen);
110
 
 
111
 
        user = pos = memacpy(uri->user, uri->userlen);
112
 
        if (!user) return 0;
113
 
 
114
 
        decode_uri_for_display(user);
115
 
 
116
 
        while (*pos) {
117
 
                int length, trailing_dots;
118
 
 
119
 
                for (length = 0; pos[length] != '\0'; length++)
120
 
                        if (!(isalnum(pos[length]) || pos[length] == '.'))
121
 
                                break;
122
 
 
123
 
                /* Wind back so that the TLD part is checked correctly. */
124
 
                for (trailing_dots = 0; trailing_dots < length; trailing_dots++)
125
 
                        if (!length || pos[length - trailing_dots - 1] != '.')
126
 
                                break;
127
 
 
128
 
                /* Not perfect, but I am clueless as how to do better. Besides
129
 
                 * I don't really think it is an issue for ELinks. --jonas */
130
 
                if (end_with_known_tld(pos, length - trailing_dots) != -1) {
131
 
                        warn = 1;
132
 
                        break;
133
 
                }
134
 
 
135
 
                pos += length;
136
 
 
137
 
                while (*pos && (!isalnum(*pos) || *pos == '.'))
138
 
                        pos++;
139
 
        }
140
 
 
141
 
        mem_free(user);
142
 
 
143
 
        return warn;
144
 
}
145
 
 
146
 
void
147
 
ses_goto(struct session *ses, struct uri *uri, unsigned char *target_frame,
148
 
         struct location *target_location, enum cache_mode cache_mode,
149
 
         enum task_type task_type, int redir)
150
 
{
151
 
        struct task *task = NULL;
152
 
        int referrer_incomplete = 0;
153
 
        int malicious_uri = 0;
154
 
        int confirm_submit = uri->form;
155
 
        unsigned char *m1 = NULL, *message = NULL;
156
 
 
157
 
        if (ses->doc_view
158
 
            && ses->doc_view->document
159
 
            && ses->doc_view->document->refresh) {
160
 
                kill_document_refresh(ses->doc_view->document->refresh);
161
 
        }
162
 
 
163
 
        assertm(!ses->loading_uri, "Buggy URI reference counting");
164
 
 
165
 
        /* Reset the redirect counter if this is not a redirect. */
166
 
        if (!redir) {
167
 
                ses->redirect_cnt = 0;
168
 
        }
169
 
 
170
 
        /* Figure out whether to confirm submit or not */
171
 
 
172
 
        /* Only confirm submit if we are posting form data or a misleading URI
173
 
         * was detected. */
174
 
        /* Note uri->post might be empty here but we are still supposely
175
 
         * posting form data so this should be more correct. */
176
 
 
177
 
        if (uri->user && uri->userlen
178
 
            && get_opt_bool("document.browse.links.warn_malicious")
179
 
            && check_malicious_uri(uri)) {
180
 
                malicious_uri = 1;
181
 
                confirm_submit = 1;
182
 
 
183
 
        } else if (!uri->form) {
184
 
                confirm_submit = 0;
185
 
 
186
 
        } else {
187
 
                struct cache_entry *cached;
188
 
 
189
 
                /* First check if the referring URI was incomplete. It
190
 
                 * indicates that the posted form data might be incomplete too.
191
 
                 * See bug 460. */
192
 
                if (ses->referrer) {
193
 
                        cached = find_in_cache(ses->referrer);
194
 
                        referrer_incomplete = (cached && cached->incomplete);
195
 
                }
196
 
 
197
 
                if (!get_opt_bool("document.browse.forms.confirm_submit")
198
 
                    && !referrer_incomplete) {
199
 
                        confirm_submit = 0;
200
 
 
201
 
                } else if (get_validated_cache_entry(uri, cache_mode)) {
202
 
                        confirm_submit = 0;
203
 
                }
204
 
        }
205
 
 
206
 
        if (!confirm_submit) {
207
 
                ses->loading.callback = (void (*)(struct download *, void *)) loading_callback;
208
 
                ses->loading.data = ses;
209
 
                ses->loading_uri = get_uri_reference(uri);
210
 
 
211
 
                ses->task.type = task_type;
212
 
                ses->task.target_frame = target_frame;
213
 
                ses->task.target_location = target_location;
214
 
 
215
 
                load_uri(ses->loading_uri, ses->referrer, &ses->loading,
216
 
                         PRI_MAIN, cache_mode, -1);
217
 
 
218
 
                return;
219
 
        }
220
 
 
221
 
        task = mem_alloc(sizeof(*task));
222
 
        if (!task) return;
223
 
 
224
 
        task->ses = ses;
225
 
        task->uri = get_uri_reference(uri);
226
 
        task->cache_mode = cache_mode;
227
 
        task->type = task_type;
228
 
        task->target_frame = target_frame;
229
 
        task->target_location = target_location;
230
 
 
231
 
        if (malicious_uri) {
232
 
                unsigned char *host = memacpy(uri->host, uri->hostlen);
233
 
                unsigned char *user = memacpy(uri->user, uri->userlen);
234
 
                unsigned char *uristring = get_uri_string(uri, URI_PUBLIC);
235
 
 
236
 
                message = msg_text(ses->tab->term,
237
 
                        N_("The URL you are about to follow might be maliciously "
238
 
                        "crafted in order to confuse you. By following the URL "
239
 
                        "you will be connecting to host \"%s\" as user \"%s\".\n\n"
240
 
                        "Do you want to go to URL %s?"), host, user, uristring);
241
 
 
242
 
                mem_free_if(host);
243
 
                mem_free_if(user);
244
 
                mem_free_if(uristring);
245
 
 
246
 
        } else if (redir) {
247
 
                m1 = N_("Do you want to follow the redirect and post form data "
248
 
                        "to URL %s?");
249
 
 
250
 
        } else if (referrer_incomplete) {
251
 
                m1 = N_("The form data you are about to post might be incomplete.\n"
252
 
                        "Do you want to post to URL %s?");
253
 
 
254
 
        } else if (task_type == TASK_FORWARD) {
255
 
                m1 = N_("Do you want to post form data to URL %s?");
256
 
 
257
 
        } else {
258
 
                m1 = N_("Do you want to repost form data to URL %s?");
259
 
        }
260
 
 
261
 
        if (!message && m1) {
262
 
                unsigned char *uristring = get_uri_string(uri, URI_PUBLIC);
263
 
 
264
 
                message = msg_text(ses->tab->term, m1, uristring);
265
 
                mem_free_if(uristring);
266
 
        }
267
 
 
268
 
        msg_box(ses->tab->term, getml(task, NULL), MSGBOX_FREE_TEXT,
269
 
                N_("Warning"), ALIGN_CENTER,
270
 
                message,
271
 
                task, 2,
272
 
                N_("~Yes"), post_yes, B_ENTER,
273
 
                N_("~No"), post_no, B_ESC);
274
 
}
275
 
 
276
 
 
277
 
/* If @loaded_in_frame is set, this was called just to indicate a move inside a
278
 
 * frameset, and we basically just reset the appropriate frame's view_state in
279
 
 * that case. When clicking on a link inside a frame, the frame URI is somehow
280
 
 * updated and added to the files-to-load queue, then ses_forward() is called
281
 
 * with @loaded_in_frame unset, duplicating the whole frameset's location, then
282
 
 * later the file-to-load callback calls it for the particular frame with
283
 
 * @loaded_in_frame set. */
284
 
struct view_state *
285
 
ses_forward(struct session *ses, int loaded_in_frame)
286
 
{
287
 
        struct location *loc = NULL;
288
 
        struct view_state *vs;
289
 
 
290
 
        if (!loaded_in_frame) {
291
 
                free_files(ses);
292
 
                mem_free_set(&ses->search_word, NULL);
293
 
        }
294
 
 
295
 
x:
296
 
        if (!loaded_in_frame) {
297
 
                loc = mem_calloc(1, sizeof(*loc));
298
 
                if (!loc) return NULL;
299
 
                copy_struct(&loc->download, &ses->loading);
300
 
        }
301
 
 
302
 
        if (ses->task.target_frame && *ses->task.target_frame) {
303
 
                struct frame *frame;
304
 
 
305
 
                assertm(have_location(ses), "no location yet");
306
 
                if_assert_failed return NULL;
307
 
 
308
 
                if (!loaded_in_frame) {
309
 
                        copy_location(loc, cur_loc(ses));
310
 
                        add_to_history(&ses->history, loc);
311
 
                }
312
 
 
313
 
                frame = ses_find_frame(ses, ses->task.target_frame);
314
 
                if (!frame) {
315
 
                        if (!loaded_in_frame) {
316
 
                                del_from_history(&ses->history, loc);
317
 
                                destroy_location(loc);
318
 
                        }
319
 
                        ses->task.target_frame = NULL;
320
 
                        goto x;
321
 
                }
322
 
 
323
 
                vs = &frame->vs;
324
 
                if (!loaded_in_frame) {
325
 
                        destroy_vs(vs, 1);
326
 
                        init_vs(vs, ses->loading_uri, vs->plain);
327
 
                } else {
328
 
                        done_uri(vs->uri);
329
 
                        vs->uri = get_uri_reference(ses->loading_uri);
330
 
                        if (vs->doc_view) {
331
 
                                /* vs->doc_view itself will get detached in
332
 
                                 * render_document_frames(), but that's too
333
 
                                 * late for us. */
334
 
                                vs->doc_view->vs = NULL;
335
 
                                vs->doc_view = NULL;
336
 
                        }
337
 
#ifdef CONFIG_ECMASCRIPT
338
 
                        vs->ecmascript_fragile = 1;
339
 
#endif
340
 
                }
341
 
 
342
 
        } else {
343
 
                assert(loc);
344
 
                if_assert_failed return NULL;
345
 
 
346
 
                init_list(loc->frames);
347
 
                vs = &loc->vs;
348
 
                init_vs(vs, ses->loading_uri, vs->plain);
349
 
                add_to_history(&ses->history, loc);
350
 
        }
351
 
 
352
 
        ses->status.visited = 0;
353
 
 
354
 
        /* This is another "branch" in the browsing, so throw away the current
355
 
         * unhistory, we are venturing in another direction! */
356
 
        if (ses->task.type == TASK_FORWARD)
357
 
                clean_unhistory(&ses->history);
358
 
        return vs;
359
 
}
360
 
 
361
 
static void
362
 
ses_imgmap(struct session *ses)
363
 
{
364
 
        struct cache_entry *cached = find_in_cache(ses->loading_uri);
365
 
        struct document_view *doc_view = current_frame(ses);
366
 
        struct fragment *fragment;
367
 
        struct memory_list *ml;
368
 
        struct menu_item *menu;
369
 
 
370
 
        if (!cached) {
371
 
                INTERNAL("can't find cache entry");
372
 
                return;
373
 
        }
374
 
 
375
 
        fragment = get_cache_fragment(cached);
376
 
        if (!fragment) return;
377
 
 
378
 
        if (!doc_view || !doc_view->document) return;
379
 
        global_doc_opts = &doc_view->document->options;
380
 
 
381
 
        if (get_image_map(cached->head, fragment->data,
382
 
                          fragment->data + fragment->length,
383
 
                          &menu, &ml, ses->loading_uri, ses->task.target_frame,
384
 
                          get_opt_codepage_tree(ses->tab->term->spec, "charset"),
385
 
                          get_opt_codepage("document.codepage.assume"),
386
 
                          get_opt_bool("document.codepage.force_assumed")))
387
 
                return;
388
 
 
389
 
        add_empty_window(ses->tab->term, (void (*)(void *)) freeml, ml);
390
 
        do_menu(ses->tab->term, menu, ses, 0);
391
 
}
392
 
 
393
 
static int
394
 
do_move(struct session *ses, struct download **download_p)
395
 
{
396
 
        struct cache_entry *cached;
397
 
 
398
 
        assert(download_p && *download_p);
399
 
        assertm(ses->loading_uri, "no ses->loading_uri");
400
 
        if_assert_failed return 0;
401
 
 
402
 
        if (ses->loading_uri->protocol == PROTOCOL_UNKNOWN)
403
 
                return 0;
404
 
 
405
 
        /* Handling image map needs to scan the source of the loaded document
406
 
         * so all of it has to be available. */
407
 
        if (ses->task.type == TASK_IMGMAP && is_in_progress_state((*download_p)->state))
408
 
                return 0;
409
 
 
410
 
        cached = (*download_p)->cached;
411
 
        if (!cached) return 0;
412
 
 
413
 
        if (cached->redirect && ses->redirect_cnt++ < MAX_REDIRECTS) {
414
 
                enum task_type task = ses->task.type;
415
 
 
416
 
                if (task == TASK_HISTORY && !have_location(ses))
417
 
                        goto b;
418
 
 
419
 
                assertm(compare_uri(cached->uri, ses->loading_uri, URI_BASE),
420
 
                        "Redirecting using bad base URI");
421
 
 
422
 
                if (cached->redirect->protocol == PROTOCOL_UNKNOWN)
423
 
                        return 0;
424
 
 
425
 
                abort_loading(ses, 0);
426
 
                if (have_location(ses))
427
 
                        *download_p = &cur_loc(ses)->download;
428
 
                else
429
 
                        *download_p = NULL;
430
 
 
431
 
                set_session_referrer(ses, cached->uri);
432
 
 
433
 
                switch (task) {
434
 
                case TASK_NONE:
435
 
                        break;
436
 
                case TASK_FORWARD:
437
 
                {
438
 
                        protocol_external_handler *fn;
439
 
                        struct uri *uri = cached->redirect;
440
 
 
441
 
                        fn = get_protocol_external_handler(uri->protocol);
442
 
                        if (fn) {
443
 
                                fn(ses, uri);
444
 
                                *download_p = NULL;
445
 
                                return 0;
446
 
                        }
447
 
                }
448
 
                        /* Fall through. */
449
 
                case TASK_IMGMAP:
450
 
                        ses_goto(ses, cached->redirect, ses->task.target_frame, NULL,
451
 
                                 CACHE_MODE_NORMAL, task, 1);
452
 
                        return 2;
453
 
                case TASK_HISTORY:
454
 
                        ses_goto(ses, cached->redirect, NULL, ses->task.target_location,
455
 
                                 CACHE_MODE_NORMAL, TASK_RELOAD, 1);
456
 
                        return 2;
457
 
                case TASK_RELOAD:
458
 
                        ses_goto(ses, cached->redirect, NULL, NULL,
459
 
                                 ses->reloadlevel, TASK_RELOAD, 1);
460
 
                        return 2;
461
 
                }
462
 
        }
463
 
 
464
 
b:
465
 
        if (ses->display_timer != -1) {
466
 
                kill_timer(ses->display_timer);
467
 
                ses->display_timer = -1;
468
 
        }
469
 
 
470
 
        switch (ses->task.type) {
471
 
                case TASK_NONE:
472
 
                        break;
473
 
                case TASK_FORWARD:
474
 
                        if (ses_chktype(ses, &ses->loading, cached, 0)) {
475
 
                                free_task(ses);
476
 
                                reload(ses, CACHE_MODE_NORMAL);
477
 
                                return 2;
478
 
                        }
479
 
                        break;
480
 
                case TASK_IMGMAP:
481
 
                        ses_imgmap(ses);
482
 
                        break;
483
 
                case TASK_HISTORY:
484
 
                        ses_history_move(ses);
485
 
                        break;
486
 
                case TASK_RELOAD:
487
 
                        ses->task.target_location = cur_loc(ses)->prev;
488
 
                        ses_history_move(ses);
489
 
                        ses_forward(ses, 0);
490
 
                        break;
491
 
        }
492
 
 
493
 
        if (is_in_progress_state((*download_p)->state)) {
494
 
                if (have_location(ses))
495
 
                        *download_p = &cur_loc(ses)->download;
496
 
                change_connection(&ses->loading, *download_p, PRI_MAIN, 0);
497
 
        } else if (have_location(ses)) {
498
 
                cur_loc(ses)->download.state = ses->loading.state;
499
 
        }
500
 
 
501
 
        free_task(ses);
502
 
        return 1;
503
 
}
504
 
 
505
 
void
506
 
loading_callback(struct download *download, struct session *ses)
507
 
{
508
 
        int d;
509
 
 
510
 
        assertm(ses->task.type, "loading_callback: no ses->task");
511
 
        if_assert_failed return;
512
 
 
513
 
        d = do_move(ses, &download);
514
 
        if (!download) return;
515
 
        if (d == 2) goto end;
516
 
 
517
 
        if (d == 1) {
518
 
                download->callback = (void (*)(struct download *, void *)) doc_loading_callback;
519
 
                display_timer(ses);
520
 
        }
521
 
 
522
 
        if (is_in_result_state(download->state)) {
523
 
                if (ses->task.type) free_task(ses);
524
 
                if (d == 1) doc_loading_callback(download, ses);
525
 
        }
526
 
 
527
 
        if (is_in_result_state(download->state) && download->state != S_OK) {
528
 
                struct uri *uri = download->conn ? download->conn->uri : NULL;
529
 
                print_error_dialog(ses, download->state, uri, download->pri);
530
 
                if (d == 0) reload(ses, CACHE_MODE_NORMAL);
531
 
        }
532
 
 
533
 
end:
534
 
        check_questions_queue(ses);
535
 
        print_screen_status(ses);
536
 
}
537
 
 
538
 
 
539
 
static void
540
 
do_follow_url(struct session *ses, struct uri *uri, unsigned char *target,
541
 
              enum task_type task, enum cache_mode cache_mode, int do_referrer)
542
 
{
543
 
        struct uri *referrer = NULL;
544
 
        protocol_external_handler *external_handler;
545
 
 
546
 
        if (!uri) {
547
 
                print_error_dialog(ses, S_BAD_URL, uri, PRI_CANCEL);
548
 
                return;
549
 
        }
550
 
 
551
 
        external_handler = get_protocol_external_handler(uri->protocol);
552
 
        if (external_handler) {
553
 
                external_handler(ses, uri);
554
 
                return;
555
 
        }
556
 
 
557
 
        if (target && !strcmp(target, "_blank")) {
558
 
                int mode = get_opt_int("document.browse.links.target_blank");
559
 
 
560
 
                if (mode > 0) {
561
 
                        struct session *new_ses;
562
 
 
563
 
                        new_ses = init_session(ses, ses->tab->term, uri, (mode == 2));
564
 
                        if (new_ses) ses = new_ses;
565
 
                }
566
 
        }
567
 
 
568
 
        ses->reloadlevel = cache_mode;
569
 
 
570
 
        if (ses->task.type == task) {
571
 
                if (compare_uri(ses->loading_uri, uri, 0)) {
572
 
                        /* We're already loading the URL. */
573
 
                        return;
574
 
                }
575
 
        }
576
 
 
577
 
        abort_loading(ses, 0);
578
 
 
579
 
        if (do_referrer) {
580
 
                struct document_view *doc_view = current_frame(ses);
581
 
 
582
 
                if (doc_view && doc_view->document)
583
 
                        referrer = doc_view->document->uri;
584
 
        }
585
 
 
586
 
        set_session_referrer(ses, referrer);
587
 
 
588
 
        ses_goto(ses, uri, target, NULL, cache_mode, task, 0);
589
 
}
590
 
 
591
 
static void
592
 
follow_url(struct session *ses, struct uri *uri, unsigned char *target,
593
 
           enum task_type task, enum cache_mode cache_mode, int referrer)
594
 
{
595
 
#ifdef CONFIG_SCRIPTING
596
 
        static int follow_url_event_id = EVENT_NONE;
597
 
        unsigned char *uristring = uri ? get_uri_string(uri, URI_BASE | URI_FRAGMENT) : NULL;
598
 
 
599
 
        if (!uristring) {
600
 
                do_follow_url(ses, uri, target, task, cache_mode, referrer);
601
 
                return;
602
 
        }
603
 
 
604
 
        set_event_id(follow_url_event_id, "follow-url");
605
 
        trigger_event(follow_url_event_id, &uristring, ses);
606
 
 
607
 
        if (!uristring || !*uristring) {
608
 
                mem_free_if(uristring);
609
 
                return;
610
 
        }
611
 
 
612
 
        /* FIXME: Compare if uristring and struri(uri) are equal */
613
 
        /* FIXME: When uri->post will no longer be an encoded string (but
614
 
         * hopefully some refcounted object) we will have to assign the post
615
 
         * data object to the translated URI. */
616
 
        uri = get_translated_uri(uristring, ses->tab->term->cwd);
617
 
        mem_free(uristring);
618
 
#endif
619
 
 
620
 
        do_follow_url(ses, uri, target, task, cache_mode, referrer);
621
 
 
622
 
#ifdef CONFIG_SCRIPTING
623
 
        if (uri) done_uri(uri);
624
 
#endif
625
 
}
626
 
 
627
 
void
628
 
goto_uri(struct session *ses, struct uri *uri)
629
 
{
630
 
        follow_url(ses, uri, NULL, TASK_FORWARD, CACHE_MODE_NORMAL, 0);
631
 
}
632
 
 
633
 
void
634
 
goto_uri_frame(struct session *ses, struct uri *uri,
635
 
               unsigned char *target, enum cache_mode cache_mode)
636
 
{
637
 
        follow_url(ses, uri, target, TASK_FORWARD, cache_mode, 1);
638
 
}
639
 
 
640
 
/* menu_func */
641
 
void
642
 
map_selected(struct terminal *term, void *ld_, void *ses_)
643
 
{
644
 
        struct link_def *ld = ld_;
645
 
        struct session *ses = ses_;
646
 
        struct uri *uri = get_uri(ld->link, 0);
647
 
 
648
 
        goto_uri_frame(ses, uri, ld->target, CACHE_MODE_NORMAL);
649
 
        if (uri) done_uri(uri);
650
 
}
651
 
 
652
 
 
653
 
void
654
 
goto_url(struct session *ses, unsigned char *url)
655
 
{
656
 
        struct uri *uri = get_uri(url, 0);
657
 
 
658
 
        goto_uri(ses, uri);
659
 
        if (uri) done_uri(uri);
660
 
}
661
 
 
662
 
struct uri *
663
 
get_hooked_uri(unsigned char *uristring, struct session *ses, unsigned char *cwd)
664
 
{
665
 
        struct uri *uri;
666
 
 
667
 
#if defined(CONFIG_SCRIPTING) || defined(CONFIG_URI_REWRITE)
668
 
        static int goto_url_event_id = EVENT_NONE;
669
 
 
670
 
        uristring = stracpy(uristring);
671
 
        if (!uristring) return NULL;
672
 
 
673
 
        set_event_id(goto_url_event_id, "goto-url");
674
 
        trigger_event(goto_url_event_id, &uristring, ses);
675
 
        if (!uristring) return NULL;
676
 
#endif
677
 
 
678
 
        uri = *uristring ? get_translated_uri(uristring, cwd) : NULL;
679
 
 
680
 
#if defined(CONFIG_SCRIPTING) || defined(CONFIG_URI_REWRITE)
681
 
        mem_free(uristring);
682
 
#endif
683
 
        return uri;
684
 
}
685
 
 
686
 
void
687
 
goto_url_with_hook(struct session *ses, unsigned char *url)
688
 
{
689
 
        unsigned char *cwd = ses->tab->term->cwd;
690
 
        struct uri *uri;
691
 
 
692
 
        /* Bail out if passed empty string from goto-url dialog */
693
 
        if (!*url) return;
694
 
 
695
 
        uri = get_hooked_uri(url, ses, cwd);
696
 
        goto_uri(ses, uri);
697
 
        if (uri) done_uri(uri);
698
 
}
699
 
 
700
 
int
701
 
goto_url_home(struct session *ses)
702
 
{
703
 
        unsigned char *homepage = get_opt_str("ui.sessions.homepage");
704
 
 
705
 
        if (!*homepage) homepage = getenv("WWW_HOME");
706
 
        if (!homepage || !*homepage) homepage = WWW_HOME_URL;
707
 
 
708
 
        if (!homepage || !*homepage) return 0;
709
 
 
710
 
        goto_url_with_hook(ses, homepage);
711
 
        return 1;
712
 
}
713
 
 
714
 
/* TODO: Should there be goto_imgmap_reload() ? */
715
 
 
716
 
void
717
 
goto_imgmap(struct session *ses, struct uri *uri, unsigned char *target)
718
 
{
719
 
        follow_url(ses, uri, target, TASK_IMGMAP, CACHE_MODE_NORMAL, 1);
720
 
}