2 * Copyright (c) 2010, 2011 Marco Peereboom <marco@peereboom.us>
3 * Copyright (c) 2011 Stevan Andjelkovic <stevan@student.chalmers.se>
4 * Copyright (c) 2010, 2011 Edd Barrett <vext01@gmail.com>
5 * Copyright (c) 2011 Todd T. Fries <todd@fries.net>
6 * Copyright (c) 2011 Raphael Graf <r@undefined.ch>
7 * Copyright (c) 2011 Michal Mazurek <akfaew@jasminek.net>
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 * xxxterm "protocol" (xtp)
26 * We use this for managing stuff like downloads and favorites. They
27 * make magical HTML pages in memory which have xxxt:// links in order
28 * to communicate with xxxterm's internals. These links take the format:
29 * xxxt://class/session_key/action/arg
31 * Don't begin xtp class/actions as 0. atoi returns that on error.
33 * Typically we have not put addition of items in this framework, as
34 * adding items is either done via an ex-command or via a keybinding instead.
37 #define XT_HTML_TAG "<html xmlns='http://www.w3.org/1999/xhtml'>\n"
38 #define XT_DOCTYPE "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>\n"
39 #define XT_PAGE_STYLE "<style type='text/css'>\n" \
40 "td{overflow: hidden;" \
41 " padding: 2px 2px 2px 2px;" \
42 " border: 1px solid black;" \
43 " vertical-align:top;" \
44 " word-wrap: break-word}\n" \
45 "tr:hover{background: #ffff99}\n" \
46 "th{background-color: #cccccc;" \
47 " border: 1px solid black}\n" \
48 "table{width: 100%%;" \
49 " border: 1px black solid;" \
50 " border-collapse:collapse}\n" \
52 "border: 1px solid black;" \
55 ".progress-inner{float: left;" \
57 " background: green}\n" \
58 ".dlstatus{font-size: small;" \
59 " text-align: center}\n" \
62 /* XTP classes (xxxt://<class>) */
63 #define XT_XTP_INVALID (0) /* invalid */
64 #define XT_XTP_DL (1) /* downloads */
65 #define XT_XTP_HL (2) /* history */
66 #define XT_XTP_CL (3) /* cookies */
67 #define XT_XTP_FL (4) /* favorites */
69 /* XTP download actions */
70 #define XT_XTP_DL_LIST (1)
71 #define XT_XTP_DL_CANCEL (2)
72 #define XT_XTP_DL_REMOVE (3)
74 /* XTP history actions */
75 #define XT_XTP_HL_LIST (1)
76 #define XT_XTP_HL_REMOVE (2)
78 /* XTP cookie actions */
79 #define XT_XTP_CL_LIST (1)
80 #define XT_XTP_CL_REMOVE (2)
82 /* XTP cookie actions */
83 #define XT_XTP_FL_LIST (1)
84 #define XT_XTP_FL_REMOVE (2)
86 int ca_cmd(struct tab
*, struct karg
*);
87 int cookie_show_wl(struct tab
*, struct karg
*);
88 int js_show_wl(struct tab
*, struct karg
*);
89 int pl_show_wl(struct tab
*, struct karg
*);
90 int set(struct tab
*, struct karg
*);
91 int marco(struct tab
*, struct karg
*);
92 int startpage(struct tab
*, struct karg
*);
93 const char * marco_message(int *);
95 struct about_type about_list
[] = {
96 { XT_URI_ABOUT_ABOUT
, about
},
97 { XT_URI_ABOUT_BLANK
, blank
},
98 { XT_URI_ABOUT_CERTS
, ca_cmd
},
99 { XT_URI_ABOUT_COOKIEWL
, cookie_show_wl
},
100 { XT_URI_ABOUT_COOKIEJAR
, xtp_page_cl
},
101 { XT_URI_ABOUT_DOWNLOADS
, xtp_page_dl
},
102 { XT_URI_ABOUT_FAVORITES
, xtp_page_fl
},
103 { XT_URI_ABOUT_HELP
, help
},
104 { XT_URI_ABOUT_HISTORY
, xtp_page_hl
},
105 { XT_URI_ABOUT_JSWL
, js_show_wl
},
106 { XT_URI_ABOUT_SET
, set
},
107 { XT_URI_ABOUT_STATS
, stats
},
108 { XT_URI_ABOUT_MARCO
, marco
},
109 { XT_URI_ABOUT_STARTPAGE
, startpage
},
110 { XT_URI_ABOUT_PLUGINWL
, pl_show_wl
},
115 * We use these to prevent people putting xxxt:// URLs on
116 * websites in the wild. We generate 8 bytes and represent in hex (16 chars)
118 #define XT_XTP_SES_KEY_SZ 8
119 #define XT_XTP_SES_KEY_HEX_FMT \
120 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
121 char *dl_session_key
; /* downloads */
122 char *hl_session_key
; /* history list */
123 char *cl_session_key
; /* cookie list */
124 char *fl_session_key
; /* favorites list */
126 int updating_fl_tabs
= 0;
127 int updating_dl_tabs
= 0;
128 int updating_hl_tabs
= 0;
129 int updating_cl_tabs
= 0;
130 struct download_list downloads
;
133 about_list_size(void)
135 return (LENGTH(about_list
));
139 get_html_page(gchar
*title
, gchar
*body
, gchar
*head
, bool addstyles
)
143 r
= g_strdup_printf(XT_DOCTYPE XT_HTML_TAG
145 "<title>%s</title>\n"
154 addstyles
? XT_PAGE_STYLE
: "",
163 * Display a web page from a HTML string in memory, rather than from a URL
166 load_webkit_string(struct tab
*t
, const char *str
, gchar
*title
)
171 /* we set this to indicate we want to manually do navaction */
173 t
->item
= webkit_web_back_forward_list_get_current_item(t
->bfl
);
175 t
->xtp_meaning
= XT_XTP_TAB_MEANING_NORMAL
;
177 /* set t->xtp_meaning */
178 for (i
= 0; i
< LENGTH(about_list
); i
++)
179 if (!strcmp(title
, about_list
[i
].name
)) {
184 webkit_web_view_load_string(t
->wv
, str
, NULL
, encoding
,
186 #if GTK_CHECK_VERSION(2, 20, 0)
187 gtk_spinner_stop(GTK_SPINNER(t
->spinner
));
188 gtk_widget_hide(t
->spinner
);
190 snprintf(file
, sizeof file
, "%s/%s", resource_dir
, icons
[0]);
191 xt_icon_from_file(t
, file
);
196 blank(struct tab
*t
, struct karg
*args
)
199 show_oops(NULL
, "blank invalid parameters");
201 load_webkit_string(t
, "", XT_URI_ABOUT_BLANK
);
207 about(struct tab
*t
, struct karg
*args
)
212 show_oops(NULL
, "about invalid parameters");
214 body
= g_strdup_printf("<b>Version: %s</b>"
215 #ifdef XXXTERM_BUILDSTR
216 "<br><b>Build: %s</b>"
221 "<li>Marco Peereboom <marco@peereboom.us></li>"
222 "<li>Stevan Andjelkovic <stevan@student.chalmers.se></li>"
223 "<li>Edd Barrett <vext01@gmail.com></li>"
224 "<li>Todd T. Fries <todd@fries.net></li>"
225 "<li>Raphael Graf <r@undefined.ch></li>"
226 "<li>Michal Mazurek <akfaew@jasminek.net><li>"
228 "Copyrights and licenses can be found on the XXXTerm "
229 "<a href=\"http://opensource.conformal.com/wiki/XXXTerm\">website</a>"
231 #ifdef XXXTERM_BUILDSTR
232 version
, XXXTERM_BUILDSTR
238 page
= get_html_page("About", body
, "", 0);
241 load_webkit_string(t
, page
, XT_URI_ABOUT_ABOUT
);
248 help(struct tab
*t
, struct karg
*args
)
250 char *page
, *head
, *body
;
253 show_oops(NULL
, "help invalid parameters");
255 head
= "<meta http-equiv=\"REFRESH\" content=\"0;"
256 "url=http://opensource.conformal.com/cgi-bin/man-cgi?xxxterm\">"
258 body
= "XXXTerm man page <a href=\"http://opensource.conformal.com/"
259 "cgi-bin/man-cgi?xxxterm\">http://opensource.conformal.com/"
260 "cgi-bin/man-cgi?xxxterm</a>";
262 page
= get_html_page(XT_NAME
, body
, head
, FALSE
);
264 load_webkit_string(t
, page
, XT_URI_ABOUT_HELP
);
271 stats(struct tab
*t
, struct karg
*args
)
273 char *page
, *body
, *s
, line
[64 * 1024];
274 long long unsigned int line_count
= 0;
278 show_oops(NULL
, "stats invalid parameters");
281 if (save_rejected_cookies
) {
282 if ((r_cookie_f
= fopen(rc_fname
, "r"))) {
284 s
= fgets(line
, sizeof line
, r_cookie_f
);
285 if (s
== NULL
|| feof(r_cookie_f
) ||
291 snprintf(line
, sizeof line
,
292 "<br/>Cookies blocked(*) total: %llu", line_count
);
294 show_oops(t
, "Can't open blocked cookies file: %s",
298 body
= g_strdup_printf(
299 "Cookies blocked(*) this session: %llu"
301 "<p><small><b>*</b> results vary based on settings</small></p>",
305 page
= get_html_page("Statistics", body
, "", 0);
308 load_webkit_string(t
, page
, XT_URI_ABOUT_STATS
);
315 * cancel, remove, etc. downloads
318 xtp_handle_dl(struct tab
*t
, uint8_t cmd
, int id
)
320 struct download find
, *d
= NULL
;
322 DNPRINTF(XT_D_DOWNLOAD
, "download control: cmd %d, id %d\n", cmd
, id
);
324 /* some commands require a valid download id */
325 if (cmd
!= XT_XTP_DL_LIST
) {
326 /* lookup download in question */
328 d
= RB_FIND(download_list
, &downloads
, &find
);
331 show_oops(t
, "%s: no such download", __func__
);
336 /* decide what to do */
338 case XT_XTP_DL_CANCEL
:
339 webkit_download_cancel(d
->download
);
341 case XT_XTP_DL_REMOVE
:
342 webkit_download_cancel(d
->download
); /* just incase */
343 g_object_unref(d
->download
);
344 RB_REMOVE(download_list
, &downloads
, d
);
350 show_oops(t
, "%s: unknown command", __func__
);
353 xtp_page_dl(t
, NULL
);
357 * Actions on history, only does one thing for now, but
358 * we provide the function for future actions
361 xtp_handle_hl(struct tab
*t
, uint8_t cmd
, int id
)
363 struct history
*h
, *next
;
367 case XT_XTP_HL_REMOVE
:
368 /* walk backwards, as listed in reverse */
369 for (h
= RB_MAX(history_list
, &hl
); h
!= NULL
; h
= next
) {
370 next
= RB_PREV(history_list
, &hl
, h
);
372 RB_REMOVE(history_list
, &hl
, h
);
373 g_free((gpointer
) h
->title
);
374 g_free((gpointer
) h
->uri
);
382 /* Nothing - just xtp_page_hl() below */
385 show_oops(t
, "%s: unknown command", __func__
);
389 xtp_page_hl(t
, NULL
);
392 /* remove a favorite */
394 remove_favorite(struct tab
*t
, int index
)
396 char file
[PATH_MAX
], *title
, *uri
= NULL
;
397 char *new_favs
, *tmp
;
403 snprintf(file
, sizeof file
, "%s/%s", work_dir
, XT_FAVS_FILE
);
405 if ((f
= fopen(file
, "r")) == NULL
) {
406 show_oops(t
, "%s: can't open favorites: %s",
407 __func__
, strerror(errno
));
411 /* build a string which will become the new favroites file */
412 new_favs
= g_strdup("");
415 if ((title
= fparseln(f
, &len
, &lineno
, NULL
, 0)) == NULL
)
416 if (feof(f
) || ferror(f
))
418 /* XXX THIS IS NOT THE RIGHT HEURISTIC */
425 if ((uri
= fparseln(f
, &len
, &lineno
, NULL
, 0)) == NULL
) {
426 if (feof(f
) || ferror(f
)) {
427 show_oops(t
, "%s: can't parse favorites %s",
428 __func__
, strerror(errno
));
433 /* as long as this isn't the one we are deleting add to file */
436 new_favs
= g_strdup_printf("%s%s\n%s\n",
437 new_favs
, title
, uri
);
449 /* write back new favorites file */
450 if ((f
= fopen(file
, "w")) == NULL
) {
451 show_oops(t
, "%s: can't open favorites: %s",
452 __func__
, strerror(errno
));
456 if (fwrite(new_favs
, strlen(new_favs
), 1, f
) != 1)
457 show_oops(t
, "%s: can't fwrite"); /* shut gcc up */
470 xtp_handle_fl(struct tab
*t
, uint8_t cmd
, int arg
)
474 /* nothing, just the below call to xtp_page_fl() */
476 case XT_XTP_FL_REMOVE
:
477 remove_favorite(t
, arg
);
480 show_oops(t
, "%s: invalid favorites command", __func__
);
484 xtp_page_fl(t
, NULL
);
488 xtp_handle_cl(struct tab
*t
, uint8_t cmd
, int arg
)
492 /* nothing, just xtp_page_cl() */
494 case XT_XTP_CL_REMOVE
:
498 show_oops(t
, "%s: unknown cookie xtp command", __func__
);
502 xtp_page_cl(t
, NULL
);
505 /* link an XTP class to it's session key and handler function */
506 struct xtp_despatch
{
509 void (*handle_func
)(struct tab
*, uint8_t, int);
512 struct xtp_despatch xtp_despatches
[] = {
513 { XT_XTP_DL
, &dl_session_key
, xtp_handle_dl
},
514 { XT_XTP_HL
, &hl_session_key
, xtp_handle_hl
},
515 { XT_XTP_FL
, &fl_session_key
, xtp_handle_fl
},
516 { XT_XTP_CL
, &cl_session_key
, xtp_handle_cl
},
517 { XT_XTP_INVALID
, NULL
, NULL
}
521 * generate a session key to secure xtp commands.
522 * pass in a ptr to the key in question and it will
523 * be modified in place.
526 generate_xtp_session_key(char **key
)
528 uint8_t rand_bytes
[XT_XTP_SES_KEY_SZ
];
535 arc4random_buf(rand_bytes
, XT_XTP_SES_KEY_SZ
);
536 *key
= g_strdup_printf(XT_XTP_SES_KEY_HEX_FMT
,
537 rand_bytes
[0], rand_bytes
[1], rand_bytes
[2], rand_bytes
[3],
538 rand_bytes
[4], rand_bytes
[5], rand_bytes
[6], rand_bytes
[7]);
540 DNPRINTF(XT_D_DOWNLOAD
, "%s: new session key '%s'\n", __func__
, *key
);
544 xtp_generate_keys(void)
546 /* generate session keys for xtp pages */
547 generate_xtp_session_key(&dl_session_key
);
548 generate_xtp_session_key(&hl_session_key
);
549 generate_xtp_session_key(&cl_session_key
);
550 generate_xtp_session_key(&fl_session_key
);
554 * validate a xtp session key.
558 validate_xtp_session_key(struct tab
*t
, char *trusted
, char *untrusted
)
560 if (strcmp(trusted
, untrusted
) != 0) {
561 show_oops(t
, "%s: xtp session key mismatch possible spoof",
570 * is the url xtp protocol? (xxxt://)
571 * if so, parse and despatch correct bahvior
574 parse_xtp_url(struct tab
*t
, const char *url
)
576 char *dup
= NULL
, *p
, *last
= NULL
;
577 uint8_t n_tokens
= 0;
578 char *tokens
[4] = {NULL
, NULL
, NULL
, ""};
579 struct xtp_despatch
*dsp
, *dsp_match
= NULL
;
584 * tokens array meaning:
586 * tokens[1] = session key
588 * tokens[3] = optional argument
591 DNPRINTF(XT_D_URL
, "%s: url %s\n", __func__
, url
);
593 if (strncmp(url
, XT_XTP_STR
, strlen(XT_XTP_STR
)))
596 dup
= g_strdup(url
+ strlen(XT_XTP_STR
));
598 /* split out the url */
599 for ((p
= strtok_r(dup
, "/", &last
)); p
;
600 (p
= strtok_r(NULL
, "/", &last
))) {
602 tokens
[n_tokens
++] = p
;
605 /* should be atleast three fields 'class/seskey/command/arg' */
609 dsp
= xtp_despatches
;
610 req_class
= atoi(tokens
[0]);
611 while (dsp
->xtp_class
) {
612 if (dsp
->xtp_class
== req_class
) {
619 /* did we find one atall? */
620 if (dsp_match
== NULL
) {
621 show_oops(t
, "%s: no matching xtp despatch found", __func__
);
625 /* check session key and call despatch function */
626 if (validate_xtp_session_key(t
, *(dsp_match
->session_key
), tokens
[1])) {
627 ret
= TRUE
; /* all is well, this was a valid xtp request */
628 dsp_match
->handle_func(t
, atoi(tokens
[2]), atoi(tokens
[3]));
639 * update all favorite tabs apart from one. Pass NULL if
640 * you want to update all.
643 update_favorite_tabs(struct tab
*apart_from
)
646 if (!updating_fl_tabs
) {
647 updating_fl_tabs
= 1; /* stop infinite recursion */
648 TAILQ_FOREACH(t
, &tabs
, entry
)
649 if ((t
->xtp_meaning
== XT_XTP_TAB_MEANING_FL
)
650 && (t
!= apart_from
))
651 xtp_page_fl(t
, NULL
);
652 updating_fl_tabs
= 0;
657 * update all download tabs apart from one. Pass NULL if
658 * you want to update all.
661 update_download_tabs(struct tab
*apart_from
)
664 if (!updating_dl_tabs
) {
665 updating_dl_tabs
= 1; /* stop infinite recursion */
666 TAILQ_FOREACH(t
, &tabs
, entry
)
667 if ((t
->xtp_meaning
== XT_XTP_TAB_MEANING_DL
)
668 && (t
!= apart_from
))
669 xtp_page_dl(t
, NULL
);
670 updating_dl_tabs
= 0;
675 * update all cookie tabs apart from one. Pass NULL if
676 * you want to update all.
679 update_cookie_tabs(struct tab
*apart_from
)
682 if (!updating_cl_tabs
) {
683 updating_cl_tabs
= 1; /* stop infinite recursion */
684 TAILQ_FOREACH(t
, &tabs
, entry
)
685 if ((t
->xtp_meaning
== XT_XTP_TAB_MEANING_CL
)
686 && (t
!= apart_from
))
687 xtp_page_cl(t
, NULL
);
688 updating_cl_tabs
= 0;
693 * update all history tabs apart from one. Pass NULL if
694 * you want to update all.
697 update_history_tabs(struct tab
*apart_from
)
701 if (!updating_hl_tabs
) {
702 updating_hl_tabs
= 1; /* stop infinite recursion */
703 TAILQ_FOREACH(t
, &tabs
, entry
)
704 if ((t
->xtp_meaning
== XT_XTP_TAB_MEANING_HL
)
705 && (t
!= apart_from
))
706 xtp_page_hl(t
, NULL
);
707 updating_hl_tabs
= 0;
711 /* show a list of favorites (bookmarks) */
713 xtp_page_fl(struct tab
*t
, struct karg
*args
)
717 char *uri
= NULL
, *title
= NULL
;
718 size_t len
, lineno
= 0;
720 char *body
, *tmp
, *page
= NULL
;
721 const char delim
[3] = {'\\', '\\', '\0'};
723 DNPRINTF(XT_D_FAVORITE
, "%s:", __func__
);
726 warn("%s: bad param", __func__
);
728 /* new session key */
729 if (!updating_fl_tabs
)
730 generate_xtp_session_key(&fl_session_key
);
733 snprintf(file
, sizeof file
, "%s/%s", work_dir
, XT_FAVS_FILE
);
734 if ((f
= fopen(file
, "r")) == NULL
) {
735 show_oops(t
, "Can't open favorites file: %s", strerror(errno
));
740 body
= g_strdup_printf("<table style='table-layout:fixed'><tr>"
741 "<th style='width: 40px'>#</th><th>Link</th>"
742 "<th style='width: 40px'>Rm</th></tr>\n");
745 if ((title
= fparseln(f
, &len
, &lineno
, delim
, 0)) == NULL
)
747 if (strlen(title
) == 0 || title
[0] == '#') {
753 if ((uri
= fparseln(f
, &len
, &lineno
, delim
, 0)) == NULL
)
754 if (feof(f
) || ferror(f
)) {
755 show_oops(t
, "favorites file corrupt");
761 body
= g_strdup_printf("%s<tr>"
763 "<td><a href='%s'>%s</a></td>"
764 "<td style='text-align: center'>"
765 "<a href='%s%d/%s/%d/%d'>X</a></td>"
768 XT_XTP_STR
, XT_XTP_FL
, fl_session_key
, XT_XTP_FL_REMOVE
, i
);
780 /* if none, say so */
783 body
= g_strdup_printf("%s<tr>"
784 "<td colspan='3' style='text-align: center'>"
785 "No favorites - To add one use the 'favadd' command."
791 body
= g_strdup_printf("%s</table>", body
);
801 page
= get_html_page("Favorites", body
, "", 1);
802 load_webkit_string(t
, page
, XT_URI_ABOUT_FAVORITES
);
806 update_favorite_tabs(t
);
815 * Return a new string with a download row (in html)
816 * appended. Old string is freed.
819 xtp_page_dl_row(struct tab
*t
, char *html
, struct download
*dl
)
822 WebKitDownloadStatus stat
;
823 char *status_html
= NULL
, *cmd_html
= NULL
, *new_html
;
825 char cur_sz
[FMT_SCALED_STRSIZE
];
826 char tot_sz
[FMT_SCALED_STRSIZE
];
829 DNPRINTF(XT_D_DOWNLOAD
, "%s: dl->id %d\n", __func__
, dl
->id
);
831 /* All actions wil take this form:
832 * xxxt://class/seskey
834 xtp_prefix
= g_strdup_printf("%s%d/%s/",
835 XT_XTP_STR
, XT_XTP_DL
, dl_session_key
);
837 stat
= webkit_download_get_status(dl
->download
);
840 case WEBKIT_DOWNLOAD_STATUS_FINISHED
:
841 status_html
= g_strdup_printf("Finished");
842 cmd_html
= g_strdup_printf(
843 "<a href='%s%d/%d'>Remove</a>",
844 xtp_prefix
, XT_XTP_DL_REMOVE
, dl
->id
);
846 case WEBKIT_DOWNLOAD_STATUS_STARTED
:
847 /* gather size info */
848 progress
= 100 * webkit_download_get_progress(dl
->download
);
851 webkit_download_get_current_size(dl
->download
), cur_sz
);
853 webkit_download_get_total_size(dl
->download
), tot_sz
);
855 status_html
= g_strdup_printf(
856 "<div style='width: 100%%' align='center'>"
857 "<div class='progress-outer'>"
858 "<div class='progress-inner' style='width: %.2f%%'>"
860 "<div class='dlstatus'>%s of %s (%.2f%%)</div>",
861 progress
, cur_sz
, tot_sz
, progress
);
863 cmd_html
= g_strdup_printf("<a href='%s%d/%d'>Cancel</a>",
864 xtp_prefix
, XT_XTP_DL_CANCEL
, dl
->id
);
868 case WEBKIT_DOWNLOAD_STATUS_CANCELLED
:
869 status_html
= g_strdup_printf("Cancelled");
870 cmd_html
= g_strdup_printf("<a href='%s%d/%d'>Remove</a>",
871 xtp_prefix
, XT_XTP_DL_REMOVE
, dl
->id
);
873 case WEBKIT_DOWNLOAD_STATUS_ERROR
:
874 status_html
= g_strdup_printf("Error!");
875 cmd_html
= g_strdup_printf("<a href='%s%d/%d'>Remove</a>",
876 xtp_prefix
, XT_XTP_DL_REMOVE
, dl
->id
);
878 case WEBKIT_DOWNLOAD_STATUS_CREATED
:
879 cmd_html
= g_strdup_printf("<a href='%s%d/%d'>Cancel</a>",
880 xtp_prefix
, XT_XTP_DL_CANCEL
, dl
->id
);
881 status_html
= g_strdup_printf("Starting");
884 show_oops(t
, "%s: unknown download status", __func__
);
887 new_html
= g_strdup_printf(
888 "%s\n<tr><td>%s</td><td>%s</td>"
889 "<td style='text-align:center'>%s</td></tr>\n",
890 html
, basename((char *)webkit_download_get_destination_uri(dl
->download
)),
891 status_html
, cmd_html
);
905 /* cookie management XTP page */
907 xtp_page_cl(struct tab
*t
, struct karg
*args
)
909 char *body
, *page
, *tmp
;
910 int i
= 1; /* all ids start 1 */
911 GSList
*sc
, *pc
, *pc_start
;
913 char *type
, *table_headers
, *last_domain
;
915 DNPRINTF(XT_D_CMD
, "%s", __func__
);
918 show_oops(NULL
, "%s invalid parameters", __func__
);
922 /* Generate a new session key */
923 if (!updating_cl_tabs
)
924 generate_xtp_session_key(&cl_session_key
);
927 table_headers
= g_strdup_printf("<table><tr>"
930 "<th style='width:200px'>Value</th>"
934 "<th>HTTP<br />only</th>"
935 "<th style='width:40px'>Rm</th></tr>\n");
937 sc
= soup_cookie_jar_all_cookies(s_cookiejar
);
938 pc
= soup_cookie_jar_all_cookies(p_cookiejar
);
942 last_domain
= strdup("");
943 for (; sc
; sc
= sc
->next
) {
946 if (strcmp(last_domain
, c
->domain
) != 0) {
949 last_domain
= strdup(c
->domain
);
953 body
= g_strdup_printf("%s</table>"
955 body
, c
->domain
, table_headers
);
959 body
= g_strdup_printf("<h2>%s</h2>%s\n",
960 c
->domain
, table_headers
);
965 for (pc
= pc_start
; pc
; pc
= pc
->next
)
966 if (soup_cookie_equal(pc
->data
, c
)) {
967 type
= "Session + Persistent";
972 body
= g_strdup_printf(
975 "<td style='word-wrap:normal'>%s</td>"
977 " <textarea rows='4'>%s</textarea>"
983 "<td style='text-align:center'>"
984 "<a href='%s%d/%s/%d/%d'>X</a></td></tr>\n",
991 soup_date_to_string(c
->expires
, SOUP_DATE_COOKIE
) : "",
1006 soup_cookies_free(sc
);
1007 soup_cookies_free(pc
);
1009 /* small message if there are none */
1011 body
= g_strdup_printf("%s\n<tr><td style='text-align:center'"
1012 "colspan='8'>No Cookies</td></tr>\n", table_headers
);
1015 body
= g_strdup_printf("%s</table>", body
);
1018 page
= get_html_page("Cookie Jar", body
, "", TRUE
);
1020 g_free(table_headers
);
1021 g_free(last_domain
);
1023 load_webkit_string(t
, page
, XT_URI_ABOUT_COOKIEJAR
);
1024 update_cookie_tabs(t
);
1032 xtp_page_hl(struct tab
*t
, struct karg
*args
)
1034 char *body
, *page
, *tmp
;
1036 int i
= 1; /* all ids start 1 */
1038 DNPRINTF(XT_D_CMD
, "%s", __func__
);
1041 show_oops(NULL
, "%s invalid parameters", __func__
);
1045 /* Generate a new session key */
1046 if (!updating_hl_tabs
)
1047 generate_xtp_session_key(&hl_session_key
);
1050 body
= g_strdup_printf("<table style='table-layout:fixed'><tr>"
1051 "<th>URI</th><th>Title</th><th style='width: 40px'>Rm</th></tr>\n");
1053 RB_FOREACH_REVERSE(h
, history_list
, &hl
) {
1055 body
= g_strdup_printf(
1057 "<td><a href='%s'>%s</a></td>"
1059 "<td style='text-align: center'>"
1060 "<a href='%s%d/%s/%d/%d'>X</a></td></tr>\n",
1061 body
, h
->uri
, h
->uri
, h
->title
,
1062 XT_XTP_STR
, XT_XTP_HL
, hl_session_key
,
1063 XT_XTP_HL_REMOVE
, i
);
1069 /* small message if there are none */
1072 body
= g_strdup_printf("%s\n<tr><td style='text-align:center'"
1073 "colspan='3'>No History</td></tr>\n", body
);
1078 body
= g_strdup_printf("%s</table>", body
);
1081 page
= get_html_page("History", body
, "", TRUE
);
1085 * update all history manager tabs as the xtp session
1086 * key has now changed. No need to update the current tab.
1087 * Already did that above.
1089 update_history_tabs(t
);
1091 load_webkit_string(t
, page
, XT_URI_ABOUT_HISTORY
);
1098 * Generate a web page detailing the status of any downloads
1101 xtp_page_dl(struct tab
*t
, struct karg
*args
)
1103 struct download
*dl
;
1104 char *body
, *page
, *tmp
;
1108 DNPRINTF(XT_D_DOWNLOAD
, "%s", __func__
);
1111 show_oops(NULL
, "%s invalid parameters", __func__
);
1116 * Generate a new session key for next page instance.
1117 * This only happens for the top level call to xtp_page_dl()
1118 * in which case updating_dl_tabs is 0.
1120 if (!updating_dl_tabs
)
1121 generate_xtp_session_key(&dl_session_key
);
1123 /* header - with refresh so as to update */
1124 if (refresh_interval
>= 1)
1125 ref
= g_strdup_printf(
1126 "<meta http-equiv='refresh' content='%u"
1127 ";url=%s%d/%s/%d' />\n",
1136 body
= g_strdup_printf("<div align='center'>"
1137 "<p>\n<a href='%s%d/%s/%d'>\n[ Refresh Downloads ]</a>\n"
1138 "</p><table><tr><th style='width: 60%%'>"
1139 "File</th>\n<th>Progress</th><th>Command</th></tr>\n",
1140 XT_XTP_STR
, XT_XTP_DL
, dl_session_key
, XT_XTP_DL_LIST
);
1142 RB_FOREACH_REVERSE(dl
, download_list
, &downloads
) {
1143 body
= xtp_page_dl_row(t
, body
, dl
);
1147 /* message if no downloads in list */
1150 body
= g_strdup_printf("%s\n<tr><td colspan='3'"
1151 " style='text-align: center'>"
1152 "No downloads</td></tr>\n", body
);
1157 body
= g_strdup_printf("%s</table></div>", body
);
1160 page
= get_html_page("Downloads", body
, ref
, 1);
1165 * update all download manager tabs as the xtp session
1166 * key has now changed. No need to update the current tab.
1167 * Already did that above.
1169 update_download_tabs(t
);
1171 load_webkit_string(t
, page
, XT_URI_ABOUT_DOWNLOADS
);