diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | marco.c | 25 | ||||
-rw-r--r-- | xxxterm.c | 1229 | ||||
-rw-r--r-- | xxxterm.h | 99 |
4 files changed, 127 insertions, 1228 deletions
diff --git a/Makefile b/Makefile index 92d3adc..9e5c31b 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ BINDIR=${PREFIX}/bin PROG=xxxterm MAN=xxxterm.1 -SRCS= xxxterm.c inspector.c marco.c +SRCS= inspector.c marco.c about.c xxxterm.c CFLAGS+= -O2 DEBUG= -ggdb3 LDADD= -lutil -lgcrypt diff --git a/marco.c b/marco.c index f126044..d64c7cb 100644 --- a/marco.c +++ b/marco.c @@ -15,11 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <stdlib.h> -#include <string.h> -#if defined(__linux__) -#include <bsd/stdlib.h> -#endif +#include "xxxterm.h" static const char *message[] = { "I fully support your right to put restrictions on how I can modify" @@ -54,3 +50,22 @@ marco_message(int *len) return str; } +int +marco(struct tab *t, struct karg *args) +{ + char *page, line[64 * 1024]; + int len; + + if (t == NULL) + show_oops(NULL, "marco invalid parameters"); + + line[0] = '\0'; + snprintf(line, sizeof line, "%s", marco_message(&len)); + + page = get_html_page("Marco Sez...", line, "", 0); + + load_webkit_string(t, page, XT_URI_ABOUT_MARCO); + g_free(page); + + return (0); +} diff --git a/xxxterm.c b/xxxterm.c index fdfd7fd..3da97be 100644 --- a/xxxterm.c +++ b/xxxterm.c @@ -21,7 +21,7 @@ #include "xxxterm.h" -static char *version = XXXTERM_VERSION; +char *version = XXXTERM_VERSION; /* hooked functions */ void (*_soup_cookie_jar_add_cookie)(SoupCookieJar *, SoupCookie *); @@ -61,27 +61,12 @@ char *icons[] = { "xxxtermicon128.png" }; -struct history { - RB_ENTRY(history) entry; - const gchar *uri; - const gchar *title; -}; -RB_HEAD(history_list, history); - struct session { TAILQ_ENTRY(session) entry; const gchar *name; }; TAILQ_HEAD(session_list, session); -struct download { - RB_ENTRY(download) entry; - int id; - WebKitDownload *download; - struct tab *tab; -}; -RB_HEAD(download_list, download); - struct domain { RB_ENTRY(domain) entry; gchar *d; @@ -110,17 +95,12 @@ struct command_entry { }; TAILQ_HEAD(command_list, command_entry); -/* starts from 1 to catch atoi() failures when calling xtp_handle_dl() */ -int next_download_id = 1; - /* defines */ -#define XT_NAME ("XXXTerm") #define XT_DIR (".xxxterm") #define XT_CACHE_DIR ("cache") #define XT_CERT_DIR ("certs/") #define XT_SESSIONS_DIR ("sessions/") #define XT_CONF_FILE ("xxxterm.conf") -#define XT_FAVS_FILE ("favorites") #define XT_QMARKS_FILE ("quickmarks") #define XT_SAVED_TABS_FILE ("main_session") #define XT_RESTART_TABS_FILE ("restart_tabs") @@ -131,31 +111,7 @@ int next_download_id = 1; #define XT_SAVE_SESSION_ID ("SESSION_NAME=") #define XT_SEARCH_FILE ("search_history") #define XT_COMMAND_FILE ("command_history") -#define XT_DOCTYPE "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>\n" -#define XT_HTML_TAG "<html xmlns='http://www.w3.org/1999/xhtml'>\n" #define XT_DLMAN_REFRESH "10" -#define XT_PAGE_STYLE "<style type='text/css'>\n" \ - "td{overflow: hidden;" \ - " padding: 2px 2px 2px 2px;" \ - " border: 1px solid black;" \ - " vertical-align:top;" \ - " word-wrap: break-word}\n" \ - "tr:hover{background: #ffff99}\n" \ - "th{background-color: #cccccc;" \ - " border: 1px solid black}\n" \ - "table{width: 100%%;" \ - " border: 1px black solid;" \ - " border-collapse:collapse}\n" \ - ".progress-outer{" \ - "border: 1px solid black;" \ - " height: 8px;" \ - " width: 90%%}\n" \ - ".progress-inner{float: left;" \ - " height: 8px;" \ - " background: green}\n" \ - ".dlstatus{font-size: small;" \ - " text-align: center}\n" \ - "</style>\n" #define XT_MAX_URL_LENGTH (4096) /* 1 page is atomic, don't make bigger */ #define XT_MAX_UNDO_CLOSE_TAB (32) #define XT_RESERVED_CHARS "$&+,/:;=?@ \"<>#%%{}|^~[]`" @@ -180,45 +136,6 @@ int next_download_id = 1; #define XT_PROTO_DELIM "://" -/* - * xxxterm "protocol" (xtp) - * We use this for managing stuff like downloads and favorites. They - * make magical HTML pages in memory which have xxxt:// links in order - * to communicate with xxxterm's internals. These links take the format: - * xxxt://class/session_key/action/arg - * - * Don't begin xtp class/actions as 0. atoi returns that on error. - * - * Typically we have not put addition of items in this framework, as - * adding items is either done via an ex-command or via a keybinding instead. - */ - -#define XT_XTP_STR "xxxt://" - -/* XTP classes (xxxt://<class>) */ -#define XT_XTP_INVALID 0 /* invalid */ -#define XT_XTP_DL 1 /* downloads */ -#define XT_XTP_HL 2 /* history */ -#define XT_XTP_CL 3 /* cookies */ -#define XT_XTP_FL 4 /* favorites */ - -/* XTP download actions */ -#define XT_XTP_DL_LIST 1 -#define XT_XTP_DL_CANCEL 2 -#define XT_XTP_DL_REMOVE 3 - -/* XTP history actions */ -#define XT_XTP_HL_LIST 1 -#define XT_XTP_HL_REMOVE 2 - -/* XTP cookie actions */ -#define XT_XTP_CL_LIST 1 -#define XT_XTP_CL_REMOVE 2 - -/* XTP cookie actions */ -#define XT_XTP_FL_LIST 1 -#define XT_XTP_FL_REMOVE 2 - /* actions */ #define XT_MOVE_INVALID (0) #define XT_MOVE_DOWN (1) @@ -628,73 +545,9 @@ struct settings { { "pl_wl", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_pl }, }; -int about(struct tab *, struct karg *); -int blank(struct tab *, struct karg *); -int ca_cmd(struct tab *, struct karg *); -int cookie_show_wl(struct tab *, struct karg *); -int js_show_wl(struct tab *, struct karg *); -int pl_show_wl(struct tab *, struct karg *); -int help(struct tab *, struct karg *); -int set(struct tab *, struct karg *); -int stats(struct tab *, struct karg *); -int marco(struct tab *, struct karg *); -int startpage(struct tab *, struct karg *); -const char * marco_message(int *); -int xtp_page_cl(struct tab *, struct karg *); -int xtp_page_dl(struct tab *, struct karg *); -int xtp_page_fl(struct tab *, struct karg *); -int xtp_page_hl(struct tab *, struct karg *); -void xt_icon_from_file(struct tab *, char *); const gchar *get_uri(struct tab *); const gchar *get_title(struct tab *, bool); -#define XT_URI_ABOUT ("about:") -#define XT_URI_ABOUT_LEN (strlen(XT_URI_ABOUT)) -#define XT_URI_ABOUT_ABOUT ("about") -#define XT_URI_ABOUT_BLANK ("blank") -#define XT_URI_ABOUT_CERTS ("certs") -#define XT_URI_ABOUT_COOKIEWL ("cookiewl") -#define XT_URI_ABOUT_COOKIEJAR ("cookiejar") -#define XT_URI_ABOUT_DOWNLOADS ("downloads") -#define XT_URI_ABOUT_FAVORITES ("favorites") -#define XT_URI_ABOUT_HELP ("help") -#define XT_URI_ABOUT_HISTORY ("history") -#define XT_URI_ABOUT_JSWL ("jswl") -#define XT_URI_ABOUT_PLUGINWL ("plwl") -#define XT_URI_ABOUT_SET ("set") -#define XT_URI_ABOUT_STATS ("stats") -#define XT_URI_ABOUT_MARCO ("marco") -#define XT_URI_ABOUT_STARTPAGE ("startpage") - -struct about_type { - char *name; - int (*func)(struct tab *, struct karg *); -} about_list[] = { - { XT_URI_ABOUT_ABOUT, about }, - { XT_URI_ABOUT_BLANK, blank }, - { XT_URI_ABOUT_CERTS, ca_cmd }, - { XT_URI_ABOUT_COOKIEWL, cookie_show_wl }, - { XT_URI_ABOUT_COOKIEJAR, xtp_page_cl }, - { XT_URI_ABOUT_DOWNLOADS, xtp_page_dl }, - { XT_URI_ABOUT_FAVORITES, xtp_page_fl }, - { XT_URI_ABOUT_HELP, help }, - { XT_URI_ABOUT_HISTORY, xtp_page_hl }, - { XT_URI_ABOUT_JSWL, js_show_wl }, - { XT_URI_ABOUT_SET, set }, - { XT_URI_ABOUT_STATS, stats }, - { XT_URI_ABOUT_MARCO, marco }, - { XT_URI_ABOUT_STARTPAGE, startpage }, - { XT_URI_ABOUT_PLUGINWL, pl_show_wl }, -}; - -/* xtp tab meanings - identifies which tabs have xtp pages in (corresponding to about_list indices) */ -#define XT_XTP_TAB_MEANING_NORMAL -1 /* normal url */ -#define XT_XTP_TAB_MEANING_BL 1 /* about:blank in this tab */ -#define XT_XTP_TAB_MEANING_CL 4 /* cookie manager in this tab */ -#define XT_XTP_TAB_MEANING_DL 5 /* download manager in this tab */ -#define XT_XTP_TAB_MEANING_FL 6 /* favorite manager in this tab */ -#define XT_XTP_TAB_MEANING_HL 8 /* history manager in this tab */ - /* globals */ extern char *__progname; char **start_argv; @@ -706,7 +559,6 @@ GtkWidget *arrow, *abtn; struct tab_list tabs; struct history_list hl; struct session_list sessions; -struct download_list downloads; struct domain_list c_wl; struct domain_list js_wl; struct domain_list pl_wl; @@ -718,10 +570,6 @@ struct command_list shl; struct command_entry *history_at; struct command_entry *search_at; int undo_count; -int updating_dl_tabs = 0; -int updating_hl_tabs = 0; -int updating_cl_tabs = 0; -int updating_fl_tabs = 0; int cmd_history_count = 0; int search_history_count = 0; char *global_search; @@ -730,11 +578,13 @@ char named_session[PATH_MAX]; GtkListStore *completion_model; GtkListStore *buffers_store; +/* starts from 1 to catch atoi() failures when calling xtp_handle_dl() */ +int next_download_id = 1; + void xxx_dir(char *); int icon_size_map(int); void completion_add(struct tab *); void completion_add_uri(const gchar *); -void show_oops(struct tab *, const char *, ...); void history_delete(struct command_list *l, int *counter) @@ -926,63 +776,6 @@ is_g_object_setting(GObject *o, char *str) return (0); } -gchar * -get_html_page(gchar *title, gchar *body, gchar *head, bool addstyles) -{ - gchar *r; - - r = g_strdup_printf(XT_DOCTYPE XT_HTML_TAG - "<head>\n" - "<title>%s</title>\n" - "%s" - "%s" - "</head>\n" - "<body>\n" - "<h1>%s</h1>\n" - "%s\n</body>\n" - "</html>", - title, - addstyles ? XT_PAGE_STYLE : "", - head, - title, - body); - - return r; -} - -/* - * Display a web page from a HTML string in memory, rather than from a URL - */ -void -load_webkit_string(struct tab *t, const char *str, gchar *title) -{ - char file[PATH_MAX]; - int i; - - /* we set this to indicate we want to manually do navaction */ - if (t->bfl) - t->item = webkit_web_back_forward_list_get_current_item(t->bfl); - - t->xtp_meaning = XT_XTP_TAB_MEANING_NORMAL; - if (title) { - /* set t->xtp_meaning */ - for (i = 0; i < LENGTH(about_list); i++) - if (!strcmp(title, about_list[i].name)) { - t->xtp_meaning = i; - break; - } - - webkit_web_view_load_string(t->wv, str, NULL, encoding, - "file://"); -#if GTK_CHECK_VERSION(2, 20, 0) - gtk_spinner_stop(GTK_SPINNER(t->spinner)); - gtk_widget_hide(t->spinner); -#endif - snprintf(file, sizeof file, "%s/%s", resource_dir, icons[0]); - xt_icon_from_file(t, file); - } -} - struct tab * get_current_tab(void) { @@ -1351,19 +1144,6 @@ set_download_dir(struct settings *s, char *val) return (0); } -/* - * Session IDs. - * We use these to prevent people putting xxxt:// URLs on - * websites in the wild. We generate 8 bytes and represent in hex (16 chars) - */ -#define XT_XTP_SES_KEY_SZ 8 -#define XT_XTP_SES_KEY_HEX_FMT \ - "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" -char *dl_session_key; /* downloads */ -char *hl_session_key; /* history list */ -char *cl_session_key; /* cookie list */ -char *fl_session_key; /* favorites list */ - char work_dir[PATH_MAX]; char certs_dir[PATH_MAX]; char cache_dir[PATH_MAX]; @@ -1442,45 +1222,6 @@ set_tab_style(struct settings *s, char *val) return (0); } -/* - * generate a session key to secure xtp commands. - * pass in a ptr to the key in question and it will - * be modified in place. - */ -void -generate_xtp_session_key(char **key) -{ - uint8_t rand_bytes[XT_XTP_SES_KEY_SZ]; - - /* free old key */ - if (*key) - g_free(*key); - - /* make a new one */ - arc4random_buf(rand_bytes, XT_XTP_SES_KEY_SZ); - *key = g_strdup_printf(XT_XTP_SES_KEY_HEX_FMT, - rand_bytes[0], rand_bytes[1], rand_bytes[2], rand_bytes[3], - rand_bytes[4], rand_bytes[5], rand_bytes[6], rand_bytes[7]); - - DNPRINTF(XT_D_DOWNLOAD, "%s: new session key '%s'\n", __func__, *key); -} - -/* - * validate a xtp session key. - * return (1) if OK - */ -int -validate_xtp_session_key(struct tab *t, char *trusted, char *untrusted) -{ - if (strcmp(trusted, untrusted) != 0) { - show_oops(t, "%s: xtp session key mismatch possible spoof", - __func__); - return (0); - } - - return (1); -} - int download_rb_cmp(struct download *e1, struct download *e2) { @@ -1596,7 +1337,7 @@ guess_url_type(char *url_in) /* see if we are an about page */ if (!strncmp(url_in, XT_URI_ABOUT, XT_URI_ABOUT_LEN)) - for (i = 0; i < LENGTH(about_list); i++) + for (i = 0; i < about_list_size(); i++) if (!strcmp(&url_in[XT_URI_ABOUT_LEN], about_list[i].name)) { url_out = g_strdup(url_in); @@ -1653,7 +1394,7 @@ load_uri(struct tab *t, gchar *uri) } if (!strncmp(uri, XT_URI_ABOUT, XT_URI_ABOUT_LEN)) { - for (i = 0; i < LENGTH(about_list); i++) + for (i = 0; i < about_list_size(); i++) if (!strcmp(&uri[XT_URI_ABOUT_LEN], about_list[i].name)) { bzero(&args, sizeof args); about_list[i].func(t, &args); @@ -2912,144 +2653,6 @@ focus(struct tab *t, struct karg *args) } int -stats(struct tab *t, struct karg *args) -{ - char *page, *body, *s, line[64 * 1024]; - long long unsigned int line_count = 0; - FILE *r_cookie_f; - - if (t == NULL) - show_oops(NULL, "stats invalid parameters"); - - line[0] = '\0'; - if (save_rejected_cookies) { - if ((r_cookie_f = fopen(rc_fname, "r"))) { - for (;;) { - s = fgets(line, sizeof line, r_cookie_f); - if (s == NULL || feof(r_cookie_f) || - ferror(r_cookie_f)) - break; - line_count++; - } - fclose(r_cookie_f); - snprintf(line, sizeof line, - "<br/>Cookies blocked(*) total: %llu", line_count); - } else - show_oops(t, "Can't open blocked cookies file: %s", - strerror(errno)); - } - - body = g_strdup_printf( - "Cookies blocked(*) this session: %llu" - "%s" - "<p><small><b>*</b> results vary based on settings</small></p>", - blocked_cookies, - line); - - page = get_html_page("Statistics", body, "", 0); - g_free(body); - - load_webkit_string(t, page, XT_URI_ABOUT_STATS); - g_free(page); - - return (0); -} - -int -marco(struct tab *t, struct karg *args) -{ - char *page, line[64 * 1024]; - int len; - - if (t == NULL) - show_oops(NULL, "marco invalid parameters"); - - line[0] = '\0'; - snprintf(line, sizeof line, "%s", marco_message(&len)); - - page = get_html_page("Marco Sez...", line, "", 0); - - load_webkit_string(t, page, XT_URI_ABOUT_MARCO); - g_free(page); - - return (0); -} - -int -blank(struct tab *t, struct karg *args) -{ - if (t == NULL) - show_oops(NULL, "blank invalid parameters"); - - load_webkit_string(t, "", XT_URI_ABOUT_BLANK); - - return (0); -} - -int -about(struct tab *t, struct karg *args) -{ - char *page, *body; - - if (t == NULL) - show_oops(NULL, "about invalid parameters"); - - body = g_strdup_printf("<b>Version: %s</b>" -#ifdef XXXTERM_BUILDSTR - "<br><b>Build: %s</b>" -#endif - "<p>" - "Authors:" - "<ul>" - "<li>Marco Peereboom <marco@peereboom.us></li>" - "<li>Stevan Andjelkovic <stevan@student.chalmers.se></li>" - "<li>Edd Barrett <vext01@gmail.com> </li>" - "<li>Todd T. Fries <todd@fries.net> </li>" - "<li>Raphael Graf <r@undefined.ch> </li>" - "</ul>" - "Copyrights and licenses can be found on the XXXTerm " - "<a href=\"http://opensource.conformal.com/wiki/XXXTerm\">website</a>" - "</p>", -#ifdef XXXTERM_BUILDSTR - version, XXXTERM_BUILDSTR -#else - version -#endif - ); - - page = get_html_page("About", body, "", 0); - g_free(body); - - load_webkit_string(t, page, XT_URI_ABOUT_ABOUT); - g_free(page); - - return (0); -} - -int -help(struct tab *t, struct karg *args) -{ - char *page, *head, *body; - - if (t == NULL) - show_oops(NULL, "help invalid parameters"); - - head = "<meta http-equiv=\"REFRESH\" content=\"0;" - "url=http://opensource.conformal.com/cgi-bin/man-cgi?xxxterm\">" - "</head>\n"; - body = "XXXTerm man page <a href=\"http://opensource.conformal.com/" - "cgi-bin/man-cgi?xxxterm\">http://opensource.conformal.com/" - "cgi-bin/man-cgi?xxxterm</a>"; - - page = get_html_page(XT_NAME, body, head, FALSE); - - load_webkit_string(t, page, XT_URI_ABOUT_HELP); - g_free(page); - - return (0); -} - -int startpage(struct tab *t, struct karg *args) { char *page, *body, *b; @@ -3096,127 +2699,6 @@ startpage_add(const char *fmt, ...) TAILQ_INSERT_TAIL(&spl, s, entry); } -/* - * update all favorite tabs apart from one. Pass NULL if - * you want to update all. - */ -void -update_favorite_tabs(struct tab *apart_from) -{ - struct tab *t; - if (!updating_fl_tabs) { - updating_fl_tabs = 1; /* stop infinite recursion */ - TAILQ_FOREACH(t, &tabs, entry) - if ((t->xtp_meaning == XT_XTP_TAB_MEANING_FL) - && (t != apart_from)) - xtp_page_fl(t, NULL); - updating_fl_tabs = 0; - } -} - -/* show a list of favorites (bookmarks) */ -int -xtp_page_fl(struct tab *t, struct karg *args) -{ - char file[PATH_MAX]; - FILE *f; - char *uri = NULL, *title = NULL; - size_t len, lineno = 0; - int i, failed = 0; - char *body, *tmp, *page = NULL; - const char delim[3] = {'\\', '\\', '\0'}; - - DNPRINTF(XT_D_FAVORITE, "%s:", __func__); - - if (t == NULL) - warn("%s: bad param", __func__); - - /* new session key */ - if (!updating_fl_tabs) - generate_xtp_session_key(&fl_session_key); - - /* open favorites */ - snprintf(file, sizeof file, "%s/%s", work_dir, XT_FAVS_FILE); - if ((f = fopen(file, "r")) == NULL) { - show_oops(t, "Can't open favorites file: %s", strerror(errno)); - return (1); - } - - /* body */ - body = g_strdup_printf("<table style='table-layout:fixed'><tr>" - "<th style='width: 40px'>#</th><th>Link</th>" - "<th style='width: 40px'>Rm</th></tr>\n"); - - for (i = 1;;) { - if ((title = fparseln(f, &len, &lineno, delim, 0)) == NULL) - break; - if (strlen(title) == 0 || title[0] == '#') { - free(title); - title = NULL; - continue; - } - - if ((uri = fparseln(f, &len, &lineno, delim, 0)) == NULL) - if (feof(f) || ferror(f)) { - show_oops(t, "favorites file corrupt"); - failed = 1; - break; - } - - tmp = body; - body = g_strdup_printf("%s<tr>" - "<td>%d</td>" - "<td><a href='%s'>%s</a></td>" - "<td style='text-align: center'>" - "<a href='%s%d/%s/%d/%d'>X</a></td>" - "</tr>\n", - body, i, uri, title, - XT_XTP_STR, XT_XTP_FL, fl_session_key, XT_XTP_FL_REMOVE, i); - - g_free(tmp); - - free(uri); - uri = NULL; - free(title); - title = NULL; - i++; - } - fclose(f); - - /* if none, say so */ - if (i == 1) { - tmp = body; - body = g_strdup_printf("%s<tr>" - "<td colspan='3' style='text-align: center'>" - "No favorites - To add one use the 'favadd' command." - "</td></tr>", body); - g_free(tmp); - } - - tmp = body; - body = g_strdup_printf("%s</table>", body); - g_free(tmp); - - if (uri) - free(uri); - if (title) - free(title); - - /* render */ - if (!failed) { - page = get_html_page("Favorites", body, "", 1); - load_webkit_string(t, page, XT_URI_ABOUT_FAVORITES); - g_free(page); - } - - update_favorite_tabs(t); - - if (body) - g_free(body); - - return (failed); -} - void show_certs(struct tab *t, gnutls_x509_crt_t *certs, size_t cert_count, char *title) @@ -4681,424 +4163,6 @@ command(struct tab *t, struct karg *args) return (XT_CB_HANDLED); } -/* - * Return a new string with a download row (in html) - * appended. Old string is freed. - */ -char * -xtp_page_dl_row(struct tab *t, char *html, struct download *dl) -{ - - WebKitDownloadStatus stat; - char *status_html = NULL, *cmd_html = NULL, *new_html; - gdouble progress; - char cur_sz[FMT_SCALED_STRSIZE]; - char tot_sz[FMT_SCALED_STRSIZE]; - char *xtp_prefix; - - DNPRINTF(XT_D_DOWNLOAD, "%s: dl->id %d\n", __func__, dl->id); - - /* All actions wil take this form: - * xxxt://class/seskey - */ - xtp_prefix = g_strdup_printf("%s%d/%s/", - XT_XTP_STR, XT_XTP_DL, dl_session_key); - - stat = webkit_download_get_status(dl->download); - - switch (stat) { - case WEBKIT_DOWNLOAD_STATUS_FINISHED: - status_html = g_strdup_printf("Finished"); - cmd_html = g_strdup_printf( - "<a href='%s%d/%d'>Remove</a>", - xtp_prefix, XT_XTP_DL_REMOVE, dl->id); - break; - case WEBKIT_DOWNLOAD_STATUS_STARTED: - /* gather size info */ - progress = 100 * webkit_download_get_progress(dl->download); - - fmt_scaled( - webkit_download_get_current_size(dl->download), cur_sz); - fmt_scaled( - webkit_download_get_total_size(dl->download), tot_sz); - - status_html = g_strdup_printf( - "<div style='width: 100%%' align='center'>" - "<div class='progress-outer'>" - "<div class='progress-inner' style='width: %.2f%%'>" - "</div></div></div>" - "<div class='dlstatus'>%s of %s (%.2f%%)</div>", - progress, cur_sz, tot_sz, progress); - - cmd_html = g_strdup_printf("<a href='%s%d/%d'>Cancel</a>", - xtp_prefix, XT_XTP_DL_CANCEL, dl->id); - - break; - /* LLL */ - case WEBKIT_DOWNLOAD_STATUS_CANCELLED: - status_html = g_strdup_printf("Cancelled"); - cmd_html = g_strdup_printf("<a href='%s%d/%d'>Remove</a>", - xtp_prefix, XT_XTP_DL_REMOVE, dl->id); - break; - case WEBKIT_DOWNLOAD_STATUS_ERROR: - status_html = g_strdup_printf("Error!"); - cmd_html = g_strdup_printf("<a href='%s%d/%d'>Remove</a>", - xtp_prefix, XT_XTP_DL_REMOVE, dl->id); - break; - case WEBKIT_DOWNLOAD_STATUS_CREATED: - cmd_html = g_strdup_printf("<a href='%s%d/%d'>Cancel</a>", - xtp_prefix, XT_XTP_DL_CANCEL, dl->id); - status_html = g_strdup_printf("Starting"); - break; - default: - show_oops(t, "%s: unknown download status", __func__); - }; - - new_html = g_strdup_printf( - "%s\n<tr><td>%s</td><td>%s</td>" - "<td style='text-align:center'>%s</td></tr>\n", - html, basename((char *)webkit_download_get_destination_uri(dl->download)), - status_html, cmd_html); - g_free(html); - - if (status_html) - g_free(status_html); - - if (cmd_html) - g_free(cmd_html); - - g_free(xtp_prefix); - - return new_html; -} - -/* - * update all download tabs apart from one. Pass NULL if - * you want to update all. - */ -void -update_download_tabs(struct tab *apart_from) -{ - struct tab *t; - if (!updating_dl_tabs) { - updating_dl_tabs = 1; /* stop infinite recursion */ - TAILQ_FOREACH(t, &tabs, entry) - if ((t->xtp_meaning == XT_XTP_TAB_MEANING_DL) - && (t != apart_from)) - xtp_page_dl(t, NULL); - updating_dl_tabs = 0; - } -} - -/* - * update all cookie tabs apart from one. Pass NULL if - * you want to update all. - */ -void -update_cookie_tabs(struct tab *apart_from) -{ - struct tab *t; - if (!updating_cl_tabs) { - updating_cl_tabs = 1; /* stop infinite recursion */ - TAILQ_FOREACH(t, &tabs, entry) - if ((t->xtp_meaning == XT_XTP_TAB_MEANING_CL) - && (t != apart_from)) - xtp_page_cl(t, NULL); - updating_cl_tabs = 0; - } -} - -/* - * update all history tabs apart from one. Pass NULL if - * you want to update all. - */ -void -update_history_tabs(struct tab *apart_from) -{ - struct tab *t; - - if (!updating_hl_tabs) { - updating_hl_tabs = 1; /* stop infinite recursion */ - TAILQ_FOREACH(t, &tabs, entry) - if ((t->xtp_meaning == XT_XTP_TAB_MEANING_HL) - && (t != apart_from)) - xtp_page_hl(t, NULL); - updating_hl_tabs = 0; - } -} - -/* cookie management XTP page */ -int -xtp_page_cl(struct tab *t, struct karg *args) -{ - char *body, *page, *tmp; - int i = 1; /* all ids start 1 */ - GSList *sc, *pc, *pc_start; - SoupCookie *c; - char *type, *table_headers, *last_domain; - - DNPRINTF(XT_D_CMD, "%s", __func__); - - if (t == NULL) { - show_oops(NULL, "%s invalid parameters", __func__); - return (1); - } - - /* Generate a new session key */ - if (!updating_cl_tabs) - generate_xtp_session_key(&cl_session_key); - - /* table headers */ - table_headers = g_strdup_printf("<table><tr>" - "<th>Type</th>" - "<th>Name</th>" - "<th style='width:200px'>Value</th>" - "<th>Path</th>" - "<th>Expires</th>" - "<th>Secure</th>" - "<th>HTTP<br />only</th>" - "<th style='width:40px'>Rm</th></tr>\n"); - - sc = soup_cookie_jar_all_cookies(s_cookiejar); - pc = soup_cookie_jar_all_cookies(p_cookiejar); - pc_start = pc; - - body = NULL; - last_domain = strdup(""); - for (; sc; sc = sc->next) { - c = sc->data; - - if (strcmp(last_domain, c->domain) != 0) { - /* new domain */ - free(last_domain); - last_domain = strdup(c->domain); - - if (body != NULL) { - tmp = body; - body = g_strdup_printf("%s</table>" - "<h2>%s</h2>%s\n", - body, c->domain, table_headers); - g_free(tmp); - } else { - /* first domain */ - body = g_strdup_printf("<h2>%s</h2>%s\n", - c->domain, table_headers); - } - } - - type = "Session"; - for (pc = pc_start; pc; pc = pc->next) - if (soup_cookie_equal(pc->data, c)) { - type = "Session + Persistent"; - break; - } - - tmp = body; - body = g_strdup_printf( - "%s\n<tr>" - "<td>%s</td>" - "<td style='word-wrap:normal'>%s</td>" - "<td>" - " <textarea rows='4'>%s</textarea>" - "</td>" - "<td>%s</td>" - "<td>%s</td>" - "<td>%d</td>" - "<td>%d</td>" - "<td style='text-align:center'>" - "<a href='%s%d/%s/%d/%d'>X</a></td></tr>\n", - body, - type, - c->name, - c->value, - c->path, - c->expires ? - soup_date_to_string(c->expires, SOUP_DATE_COOKIE) : "", - c->secure, - c->http_only, - - XT_XTP_STR, - XT_XTP_CL, - cl_session_key, - XT_XTP_CL_REMOVE, - i - ); - - g_free(tmp); - i++; - } - - soup_cookies_free(sc); - soup_cookies_free(pc); - - /* small message if there are none */ - if (i == 1) { - body = g_strdup_printf("%s\n<tr><td style='text-align:center'" - "colspan='8'>No Cookies</td></tr>\n", table_headers); - } - tmp = body; - body = g_strdup_printf("%s</table>", body); - g_free(tmp); - - page = get_html_page("Cookie Jar", body, "", TRUE); - g_free(body); - g_free(table_headers); - g_free(last_domain); - - load_webkit_string(t, page, XT_URI_ABOUT_COOKIEJAR); - update_cookie_tabs(t); - - g_free(page); - - return (0); -} - -int -xtp_page_hl(struct tab *t, struct karg *args) -{ - char *body, *page, *tmp; - struct history *h; - int i = 1; /* all ids start 1 */ - - DNPRINTF(XT_D_CMD, "%s", __func__); - - if (t == NULL) { - show_oops(NULL, "%s invalid parameters", __func__); - return (1); - } - - /* Generate a new session key */ - if (!updating_hl_tabs) - generate_xtp_session_key(&hl_session_key); - - /* body */ - body = g_strdup_printf("<table style='table-layout:fixed'><tr>" - "<th>URI</th><th>Title</th><th style='width: 40px'>Rm</th></tr>\n"); - - RB_FOREACH_REVERSE(h, history_list, &hl) { - tmp = body; - body = g_strdup_printf( - "%s\n<tr>" - "<td><a href='%s'>%s</a></td>" - "<td>%s</td>" - "<td style='text-align: center'>" - "<a href='%s%d/%s/%d/%d'>X</a></td></tr>\n", - body, h->uri, h->uri, h->title, - XT_XTP_STR, XT_XTP_HL, hl_session_key, - XT_XTP_HL_REMOVE, i); - - g_free(tmp); - i++; - } - - /* small message if there are none */ - if (i == 1) { - tmp = body; - body = g_strdup_printf("%s\n<tr><td style='text-align:center'" - "colspan='3'>No History</td></tr>\n", body); - g_free(tmp); - } - - tmp = body; - body = g_strdup_printf("%s</table>", body); - g_free(tmp); - - page = get_html_page("History", body, "", TRUE); - g_free(body); - - /* - * update all history manager tabs as the xtp session - * key has now changed. No need to update the current tab. - * Already did that above. - */ - update_history_tabs(t); - - load_webkit_string(t, page, XT_URI_ABOUT_HISTORY); - g_free(page); - - return (0); -} - -/* - * Generate a web page detailing the status of any downloads - */ -int -xtp_page_dl(struct tab *t, struct karg *args) -{ - struct download *dl; - char *body, *page, *tmp; - char *ref; - int n_dl = 1; - - DNPRINTF(XT_D_DOWNLOAD, "%s", __func__); - - if (t == NULL) { - show_oops(NULL, "%s invalid parameters", __func__); - return (1); - } - - /* - * Generate a new session key for next page instance. - * This only happens for the top level call to xtp_page_dl() - * in which case updating_dl_tabs is 0. - */ - if (!updating_dl_tabs) - generate_xtp_session_key(&dl_session_key); - - /* header - with refresh so as to update */ - if (refresh_interval >= 1) - ref = g_strdup_printf( - "<meta http-equiv='refresh' content='%u" - ";url=%s%d/%s/%d' />\n", - refresh_interval, - XT_XTP_STR, - XT_XTP_DL, - dl_session_key, - XT_XTP_DL_LIST); - else - ref = g_strdup(""); - - body = g_strdup_printf("<div align='center'>" - "<p>\n<a href='%s%d/%s/%d'>\n[ Refresh Downloads ]</a>\n" - "</p><table><tr><th style='width: 60%%'>" - "File</th>\n<th>Progress</th><th>Command</th></tr>\n", - XT_XTP_STR, XT_XTP_DL, dl_session_key, XT_XTP_DL_LIST); - - RB_FOREACH_REVERSE(dl, download_list, &downloads) { - body = xtp_page_dl_row(t, body, dl); - n_dl++; - } - - /* message if no downloads in list */ - if (n_dl == 1) { - tmp = body; - body = g_strdup_printf("%s\n<tr><td colspan='3'" - " style='text-align: center'>" - "No downloads</td></tr>\n", body); - g_free(tmp); - } - - tmp = body; - body = g_strdup_printf("%s</table></div>", body); - g_free(tmp); - - page = get_html_page("Downloads", body, ref, 1); - g_free(ref); - g_free(body); - - /* - * update all download manager tabs as the xtp session - * key has now changed. No need to update the current tab. - * Already did that above. - */ - update_download_tabs(t); - - load_webkit_string(t, page, XT_URI_ABOUT_DOWNLOADS); - g_free(page); - - return (0); -} - int search(struct tab *t, struct karg *args) { @@ -6133,281 +5197,6 @@ tab_close_cb(GtkWidget *btn, GdkEventButton *e, struct tab *t) return (FALSE); } -/* - * cancel, remove, etc. downloads - */ -void -xtp_handle_dl(struct tab *t, uint8_t cmd, int id) -{ - struct download find, *d = NULL; - - DNPRINTF(XT_D_DOWNLOAD, "download control: cmd %d, id %d\n", cmd, id); - - /* some commands require a valid download id */ - if (cmd != XT_XTP_DL_LIST) { - /* lookup download in question */ - find.id = id; - d = RB_FIND(download_list, &downloads, &find); - - if (d == NULL) { - show_oops(t, "%s: no such download", __func__); - return; - } - } - - /* decide what to do */ - switch (cmd) { - case XT_XTP_DL_CANCEL: - webkit_download_cancel(d->download); - break; - case XT_XTP_DL_REMOVE: - webkit_download_cancel(d->download); /* just incase */ - g_object_unref(d->download); - RB_REMOVE(download_list, &downloads, d); - break; - case XT_XTP_DL_LIST: - /* Nothing */ - break; - default: - show_oops(t, "%s: unknown command", __func__); - break; - }; - xtp_page_dl(t, NULL); -} - -/* - * Actions on history, only does one thing for now, but - * we provide the function for future actions - */ -void -xtp_handle_hl(struct tab *t, uint8_t cmd, int id) -{ - struct history *h, *next; - int i = 1; - - switch (cmd) { - case XT_XTP_HL_REMOVE: - /* walk backwards, as listed in reverse */ - for (h = RB_MAX(history_list, &hl); h != NULL; h = next) { - next = RB_PREV(history_list, &hl, h); - if (id == i) { - RB_REMOVE(history_list, &hl, h); - g_free((gpointer) h->title); - g_free((gpointer) h->uri); - g_free(h); - break; - } - i++; - } - break; - case XT_XTP_HL_LIST: - /* Nothing - just xtp_page_hl() below */ - break; - default: - show_oops(t, "%s: unknown command", __func__); - break; - }; - - xtp_page_hl(t, NULL); -} - -/* remove a favorite */ -void -remove_favorite(struct tab *t, int index) -{ - char file[PATH_MAX], *title, *uri = NULL; - char *new_favs, *tmp; - FILE *f; - int i; - size_t len, lineno; - - /* open favorites */ - snprintf(file, sizeof file, "%s/%s", work_dir, XT_FAVS_FILE); - - if ((f = fopen(file, "r")) == NULL) { - show_oops(t, "%s: can't open favorites: %s", - __func__, strerror(errno)); - return; - } - - /* build a string which will become the new favroites file */ - new_favs = g_strdup(""); - - for (i = 1;;) { - if ((title = fparseln(f, &len, &lineno, NULL, 0)) == NULL) - if (feof(f) || ferror(f)) - break; - /* XXX THIS IS NOT THE RIGHT HEURISTIC */ - if (len == 0) { - free(title); - title = NULL; - continue; - } - - if ((uri = fparseln(f, &len, &lineno, NULL, 0)) == NULL) { - if (feof(f) || ferror(f)) { - show_oops(t, "%s: can't parse favorites %s", - __func__, strerror(errno)); - goto clean; - } - } - - /* as long as this isn't the one we are deleting add to file */ - if (i != index) { - tmp = new_favs; - new_favs = g_strdup_printf("%s%s\n%s\n", - new_favs, title, uri); - g_free(tmp); - } - - free(uri); - uri = NULL; - free(title); - title = NULL; - i++; - } - fclose(f); - - /* write back new favorites file */ - if ((f = fopen(file, "w")) == NULL) { - show_oops(t, "%s: can't open favorites: %s", - __func__, strerror(errno)); - goto clean; - } - - if (fwrite(new_favs, strlen(new_favs), 1, f) != 1) - show_oops(t, "%s: can't fwrite"); /* shut gcc up */ - fclose(f); - -clean: - if (uri) - free(uri); - if (title) - free(title); - - g_free(new_favs); -} - -void -xtp_handle_fl(struct tab *t, uint8_t cmd, int arg) -{ - switch (cmd) { - case XT_XTP_FL_LIST: - /* nothing, just the below call to xtp_page_fl() */ - break; - case XT_XTP_FL_REMOVE: - remove_favorite(t, arg); - break; - default: - show_oops(t, "%s: invalid favorites command", __func__); - break; - }; - - xtp_page_fl(t, NULL); -} - -void -xtp_handle_cl(struct tab *t, uint8_t cmd, int arg) -{ - switch (cmd) { - case XT_XTP_CL_LIST: - /* nothing, just xtp_page_cl() */ - break; - case XT_XTP_CL_REMOVE: - remove_cookie(arg); - break; - default: - show_oops(t, "%s: unknown cookie xtp command", __func__); - break; - }; - - xtp_page_cl(t, NULL); -} - -/* link an XTP class to it's session key and handler function */ -struct xtp_despatch { - uint8_t xtp_class; - char **session_key; - void (*handle_func)(struct tab *, uint8_t, int); -}; - -struct xtp_despatch xtp_despatches[] = { - { XT_XTP_DL, &dl_session_key, xtp_handle_dl }, - { XT_XTP_HL, &hl_session_key, xtp_handle_hl }, - { XT_XTP_FL, &fl_session_key, xtp_handle_fl }, - { XT_XTP_CL, &cl_session_key, xtp_handle_cl }, - { XT_XTP_INVALID, NULL, NULL } -}; - -/* - * is the url xtp protocol? (xxxt://) - * if so, parse and despatch correct bahvior - */ -int -parse_xtp_url(struct tab *t, const char *url) -{ - char *dup = NULL, *p, *last = NULL; - uint8_t n_tokens = 0; - char *tokens[4] = {NULL, NULL, NULL, ""}; - struct xtp_despatch *dsp, *dsp_match = NULL; - uint8_t req_class; - int ret = FALSE; - - /* - * tokens array meaning: - * tokens[0] = class - * tokens[1] = session key - * tokens[2] = action - * tokens[3] = optional argument - */ - - DNPRINTF(XT_D_URL, "%s: url %s\n", __func__, url); - - if (strncmp(url, XT_XTP_STR, strlen(XT_XTP_STR))) - goto clean; - - dup = g_strdup(url + strlen(XT_XTP_STR)); - - /* split out the url */ - for ((p = strtok_r(dup, "/", &last)); p; - (p = strtok_r(NULL, "/", &last))) { - if (n_tokens < 4) - tokens[n_tokens++] = p; - } - - /* should be atleast three fields 'class/seskey/command/arg' */ - if (n_tokens < 3) - goto clean; - - dsp = xtp_despatches; - req_class = atoi(tokens[0]); - while (dsp->xtp_class) { - if (dsp->xtp_class == req_class) { - dsp_match = dsp; - break; - } - dsp++; - } - - /* did we find one atall? */ - if (dsp_match == NULL) { - show_oops(t, "%s: no matching xtp despatch found", __func__); - goto clean; - } - - /* check session key and call despatch function */ - if (validate_xtp_session_key(t, *(dsp_match->session_key), tokens[1])) { - ret = TRUE; /* all is well, this was a valid xtp request */ - dsp_match->handle_func(t, atoi(tokens[2]), atoi(tokens[3])); - } - -clean: - if (dup) - g_free(dup); - - return (ret); -} - void @@ -10474,11 +9263,7 @@ main(int argc, char *argv[]) init_keybindings(); - /* generate session keys for xtp pages */ - generate_xtp_session_key(&dl_session_key); - generate_xtp_session_key(&hl_session_key); - generate_xtp_session_key(&cl_session_key); - generate_xtp_session_key(&fl_session_key); + xtp_generate_keys(); /* signals */ bzero(&sact, sizeof(sact)); diff --git a/xxxterm.h b/xxxterm.h index ad49fc7..14b96f8 100644 --- a/xxxterm.h +++ b/xxxterm.h @@ -237,16 +237,115 @@ struct karg { int precount; }; +struct download { + RB_ENTRY(download) entry; + int id; + WebKitDownload *download; + struct tab *tab; +}; +RB_HEAD(download_list, download); +RB_PROTOTYPE(download_list, download, entry, download_rb_cmp); + +struct history { + RB_ENTRY(history) entry; + const gchar *uri; + const gchar *title; +}; +RB_HEAD(history_list, history); +RB_PROTOTYPE(history_list, history, entry, history_rb_cmp); + /* utility */ +#define XT_NAME ("XXXTerm") #define XT_CB_HANDLED (TRUE) #define XT_CB_PASSTHROUGH (FALSE) +#define XT_FAVS_FILE ("favorites") + +void xt_icon_from_file(struct tab *, char *); GtkWidget *create_window(const gchar *); +void show_oops(struct tab *, const char *, ...); +gchar *get_html_page(gchar *, gchar *, gchar *, bool); +void load_webkit_string(struct tab *, const char *, gchar *); + +/* cookies */ +int remove_cookie(int); /* inspector */ #define XT_INS_SHOW (1<<0) #define XT_INS_HIDE (1<<1) #define XT_INS_CLOSE (1<<2) + WebKitWebView* inspector_inspect_web_view_cb(WebKitWebInspector *, WebKitWebView*, struct tab *); void setup_inspector(struct tab *); int inspector_cmd(struct tab *, struct karg *); + +/* about */ +#define XT_XTP_STR "xxxt://" +#define XT_URI_ABOUT ("about:") +#define XT_URI_ABOUT_LEN (strlen(XT_URI_ABOUT)) +#define XT_URI_ABOUT_ABOUT ("about") +#define XT_URI_ABOUT_BLANK ("blank") +#define XT_URI_ABOUT_CERTS ("certs") +#define XT_URI_ABOUT_COOKIEWL ("cookiewl") +#define XT_URI_ABOUT_COOKIEJAR ("cookiejar") +#define XT_URI_ABOUT_DOWNLOADS ("downloads") +#define XT_URI_ABOUT_FAVORITES ("favorites") +#define XT_URI_ABOUT_HELP ("help") +#define XT_URI_ABOUT_HISTORY ("history") +#define XT_URI_ABOUT_JSWL ("jswl") +#define XT_URI_ABOUT_PLUGINWL ("plwl") +#define XT_URI_ABOUT_SET ("set") +#define XT_URI_ABOUT_STATS ("stats") +#define XT_URI_ABOUT_MARCO ("marco") +#define XT_URI_ABOUT_STARTPAGE ("startpage") + +struct about_type { + char *name; + int (*func)(struct tab *, struct karg *); +}; + +int blank(struct tab *, struct karg *); +int help(struct tab *, struct karg *); +int about(struct tab *, struct karg *); +int stats(struct tab *, struct karg *); +int xtp_page_cl(struct tab *, struct karg *); +int xtp_page_dl(struct tab *, struct karg *); +int xtp_page_fl(struct tab *, struct karg *); +int xtp_page_hl(struct tab *, struct karg *); +int parse_xtp_url(struct tab *, const char *); +void update_favorite_tabs(struct tab *); +void update_history_tabs(struct tab *); +void update_download_tabs(struct tab *); +void xtp_generate_keys(void); +size_t about_list_size(void); + +/* + * xtp tab meanings + * identifies which tabs have xtp pages in (corresponding to about_list indices) + */ +#define XT_XTP_TAB_MEANING_NORMAL (-1) /* normal url */ +#define XT_XTP_TAB_MEANING_BL (1) /* about:blank in this tab */ +#define XT_XTP_TAB_MEANING_CL (4) /* cookie manager in this tab */ +#define XT_XTP_TAB_MEANING_DL (5) /* download manager in this tab */ +#define XT_XTP_TAB_MEANING_FL (6) /* favorite manager in this tab */ +#define XT_XTP_TAB_MEANING_HL (8) /* history manager in this tab */ + +/* settings */ +extern char *encoding; +extern char *resource_dir; +extern int save_rejected_cookies; +extern int refresh_interval; + +/* globals */ +extern char *version; +extern char *icons[]; +extern char rc_fname[PATH_MAX]; +extern char work_dir[PATH_MAX]; +long long unsigned int blocked_cookies; +extern SoupCookieJar *s_cookiejar; +extern SoupCookieJar *p_cookiejar; + +extern struct history_list hl; +extern struct download_list downloads; +extern struct tab_list tabs; +extern struct about_type about_list[]; |