Esempio n. 1
0
NETLIBHTTPHEADER* facebook_client::get_request_headers(int request_type, int* headers_count)
{
	if (request_type == REQUEST_POST)
		*headers_count = 5;
	else
		*headers_count = 4;

	NETLIBHTTPHEADER* headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER)*(*headers_count));

	if (request_type == REQUEST_POST)
	{
		headers[4].szName = "Content-Type";
		headers[4].szValue = "application/x-www-form-urlencoded; charset=utf-8";
	}

	headers[3].szName = "Cookie";
	headers[3].szValue = load_cookies();
	headers[2].szName = "User-Agent";
	headers[2].szValue = (char *)g_strUserAgent.c_str();
	headers[1].szName = "Accept";
	headers[1].szValue = "*/*";
	headers[0].szName = "Accept-Language";
	headers[0].szValue = "en,en-US;q=0.9";

	return headers;
}
Esempio n. 2
0
void add_http_test(testitem_t *t)
{
	http_data_t *httptest;

	char *dnsip = NULL;
	ssloptions_t *sslopt = NULL;
	char *sslopt_ciphers = NULL;
	int sslopt_version = SSLVERSION_DEFAULT;
	char *sslopt_clientcert = NULL;
	int  httpversion = HTTPVER_11;
	cookielist_t *ck = NULL;
	int firstcookie = 1;
	char *decodedurl;
	strbuffer_t *httprequest = newstrbuffer(0);

	/* Allocate the private data and initialize it */
	httptest = (http_data_t *) calloc(1, sizeof(http_data_t));
	t->privdata = (void *) httptest;

	decodedurl = decode_url(t->testspec, &httptest->weburl);
	if (!decodedurl) {
		errprintf("Invalid URL for http check: %s\n", t->testspec);
		return;
	}

	httptest->url = strdup(decodedurl);
	httptest->contlen = -1;
	httptest->parsestatus = (httptest->weburl.proxyurl ? httptest->weburl.proxyurl->parseerror : httptest->weburl.desturl->parseerror);

	/* If there was a parse error in the URL, dont run the test */
	if (httptest->parsestatus) return;


	if (httptest->weburl.proxyurl && (httptest->weburl.proxyurl->ip == NULL)) {
		dnsip = dnsresolve(httptest->weburl.proxyurl->host);
		if (dnsip) {
			httptest->weburl.proxyurl->ip = strdup(dnsip);
		}
		else {
			dbgprintf("Could not resolve URL hostname '%s'\n", httptest->weburl.proxyurl->host);
		}
	}
	else if (httptest->weburl.desturl->ip == NULL) {
		dnsip = dnsresolve(httptest->weburl.desturl->host);
		if (dnsip) {
			httptest->weburl.desturl->ip = strdup(dnsip);
		}
		else {
			dbgprintf("Could not resolve URL hostname '%s'\n", httptest->weburl.desturl->host);
		}
	}

	switch (httptest->weburl.testtype) {
	  case WEBTEST_PLAIN:
	  case WEBTEST_STATUS:
		httptest->contentcheck = CONTENTCHECK_NONE;
		break;

	  case WEBTEST_CONTENT:
		{
			FILE *contentfd;
			char contentfn[PATH_MAX];
			sprintf(contentfn, "%s/content/%s.substring", xgetenv("XYMONHOME"), commafy(t->host->hostname));
			contentfd = fopen(contentfn, "r");
			if (contentfd) {
				char l[MAX_LINE_LEN];
				char *p;

				if (fgets(l, sizeof(l), contentfd)) {
					p = strchr(l, '\n'); if (p) { *p = '\0'; };
					httptest->weburl.expdata = strdup(l);
				}
				else {
					httptest->contstatus = STATUS_CONTENTMATCH_NOFILE;
				}
				fclose(contentfd);
			}
			else {
				httptest->contstatus = STATUS_CONTENTMATCH_NOFILE;
			}
			httptest->contentcheck = CONTENTCHECK_REGEX;
		}
		break;

	  case WEBTEST_CONT:
		httptest->contentcheck = ((*httptest->weburl.expdata == '#') ?  CONTENTCHECK_DIGEST : CONTENTCHECK_REGEX);
		break;

	  case WEBTEST_NOCONT:
		httptest->contentcheck = CONTENTCHECK_NOREGEX;
		break;

	  case WEBTEST_POST:
	  case WEBTEST_SOAP:
		if (httptest->weburl.expdata == NULL) {
			httptest->contentcheck = CONTENTCHECK_NONE;
		}
		else {
			httptest->contentcheck = ((*httptest->weburl.expdata == '#') ?  CONTENTCHECK_DIGEST : CONTENTCHECK_REGEX);
		}
		break;

	  case WEBTEST_NOPOST:
	  case WEBTEST_NOSOAP:
		if (httptest->weburl.expdata == NULL) {
			httptest->contentcheck = CONTENTCHECK_NONE;
		}
		else {
			httptest->contentcheck = CONTENTCHECK_NOREGEX;
		}
		break;

	  case WEBTEST_TYPE:
		httptest->contentcheck = CONTENTCHECK_CONTENTTYPE;
		break;
	}

	/* Compile the hashes and regex's for those tests that use it */
	switch (httptest->contentcheck) {
	  case CONTENTCHECK_DIGEST:
		{
			char *hashfunc;

			httptest->exp = (void *) strdup(httptest->weburl.expdata+1);
			hashfunc = strchr(httptest->exp, ':');
			if (hashfunc) {
				*hashfunc = '\0';
				httptest->digestctx = digest_init(httptest->exp);
				*hashfunc = ':';
			}
		}
		break;

	  case CONTENTCHECK_REGEX:
	  case CONTENTCHECK_NOREGEX:
		{
			int status;

			httptest->exp = (void *) malloc(sizeof(regex_t));
			status = regcomp((regex_t *)httptest->exp, httptest->weburl.expdata, REG_EXTENDED|REG_NOSUB);
			if (status) {
				errprintf("Failed to compile regexp '%s' for URL %s\n", httptest->weburl.expdata, httptest->url);
				httptest->contstatus = STATUS_CONTENTMATCH_BADREGEX;
			}
		}
		break;

	  case CONTENTCHECK_CONTENTTYPE:
		httptest->exp = httptest->weburl.expdata;
		break;
	}

	if (httptest->weburl.desturl->schemeopts) {
		if      (strstr(httptest->weburl.desturl->schemeopts, "3"))      sslopt_version = SSLVERSION_V3;
		else if (strstr(httptest->weburl.desturl->schemeopts, "2"))      sslopt_version = SSLVERSION_V2;

		if      (strstr(httptest->weburl.desturl->schemeopts, "h"))      sslopt_ciphers = ciphershigh;
		else if (strstr(httptest->weburl.desturl->schemeopts, "m"))      sslopt_ciphers = ciphersmedium;

		if      (strstr(httptest->weburl.desturl->schemeopts, "10"))     httpversion    = HTTPVER_10;
		else if (strstr(httptest->weburl.desturl->schemeopts, "11"))     httpversion    = HTTPVER_11;
	}

	/* Get any cookies */
	load_cookies();

	/* Generate the request */
	addtobuffer(httprequest, (httptest->weburl.postdata ? "POST " : "GET "));
	switch (httpversion) {
		case HTTPVER_10: 
			addtobuffer(httprequest, (httptest->weburl.proxyurl ? httptest->url : httptest->weburl.desturl->relurl));
			addtobuffer(httprequest, " HTTP/1.0\r\n"); 
			break;

		case HTTPVER_11: 
			/*
			 * Experience shows that even though HTTP/1.1 says you should send the
			 * full URL, some servers (e.g. SunOne App server 7) choke on it.
			 * So just send the good-old relative URL unless we're proxying.
			 */
			addtobuffer(httprequest, (httptest->weburl.proxyurl ? httptest->url : httptest->weburl.desturl->relurl));
			addtobuffer(httprequest, " HTTP/1.1\r\n"); 
			addtobuffer(httprequest, "Connection: close\r\n"); 
			break;
	}

	addtobuffer(httprequest, "Host: ");
	addtobuffer(httprequest, httptest->weburl.desturl->host);
	if ((httptest->weburl.desturl->port != 80) && (httptest->weburl.desturl->port != 443)) {
		char hostporthdr[20];

		sprintf(hostporthdr, ":%d", httptest->weburl.desturl->port);
		addtobuffer(httprequest, hostporthdr);
	}
	addtobuffer(httprequest, "\r\n");

	if (httptest->weburl.postdata) {
		char hdr[100];
		int contlen = strlen(httptest->weburl.postdata);

		if (strncmp(httptest->weburl.postdata, "file:", 5) == 0) {
			/* Load the POST data from a file */
			FILE *pf = fopen(httptest->weburl.postdata+5, "r");
			if (pf == NULL) {
				errprintf("Cannot open POST data file %s\n", httptest->weburl.postdata+5);
				xfree(httptest->weburl.postdata);
				httptest->weburl.postdata = strdup("");
				contlen = 0;
			}
			else {
				struct stat st;

				if (fstat(fileno(pf), &st) == 0) {
					int n;

					xfree(httptest->weburl.postdata);
					httptest->weburl.postdata = (char *)malloc(st.st_size + 1); *(httptest->weburl.postdata) = '\0';
					n = fread(httptest->weburl.postdata, 1, st.st_size, pf);
					if (n == st.st_size) {
						*(httptest->weburl.postdata+n) = '\0';
						contlen = n;
					}
					else {
						errprintf("Cannot read file %s: %s\n", httptest->weburl.postdata+5, strerror(errno));
						contlen = 0;
					}
				}
				else {
					errprintf("Cannot stat file %s\n", httptest->weburl.postdata+5);
					httptest->weburl.postdata = strdup("");
					contlen = 0;
				}

				fclose(pf);
			}
		}

		addtobuffer(httprequest, "Content-type: ");
		if      (httptest->weburl.postcontenttype) 
			addtobuffer(httprequest, httptest->weburl.postcontenttype);
		else if ((httptest->weburl.testtype == WEBTEST_SOAP) || (httptest->weburl.testtype == WEBTEST_NOSOAP)) 
			addtobuffer(httprequest, "application/soap+xml; charset=utf-8");
		else 
			addtobuffer(httprequest, "application/x-www-form-urlencoded");
		addtobuffer(httprequest, "\r\n");

		sprintf(hdr, "Content-Length: %d\r\n", contlen);
		addtobuffer(httprequest, hdr);
	}
	{
		char useragent[100];
		void *hinfo;
		char *browser = NULL;

		hinfo = hostinfo(t->host->hostname);
		if (hinfo) browser = xmh_item(hinfo, XMH_BROWSER);

		if (browser) {
			sprintf(useragent, "User-Agent: %s\r\n", browser);
		}
		else {
			sprintf(useragent, "User-Agent: Xymon xymonnet/%s\r\n", VERSION);
		}

		addtobuffer(httprequest, useragent);
	}
	if (httptest->weburl.desturl->auth) {
		if (strncmp(httptest->weburl.desturl->auth, "CERT:", 5) == 0) {
			sslopt_clientcert = httptest->weburl.desturl->auth+5;
		}
		else {
			addtobuffer(httprequest, "Authorization: Basic ");
			addtobuffer(httprequest, base64encode(httptest->weburl.desturl->auth));
			addtobuffer(httprequest, "\r\n");
		}
	}
	if (httptest->weburl.proxyurl && httptest->weburl.proxyurl->auth) {
		addtobuffer(httprequest, "Proxy-Authorization: Basic ");
		addtobuffer(httprequest, base64encode(httptest->weburl.proxyurl->auth));
		addtobuffer(httprequest, "\r\n");
	}
	for (ck = cookiehead; (ck); ck = ck->next) {
		int useit = 0;

		if (ck->tailmatch) {
			int startpos = strlen(httptest->weburl.desturl->host) - strlen(ck->host);

			if (startpos > 0) useit = (strcmp(httptest->weburl.desturl->host+startpos, ck->host) == 0);
		}
		else useit = (strcmp(httptest->weburl.desturl->host, ck->host) == 0);
		if (useit) useit = (strncmp(ck->path, httptest->weburl.desturl->relurl, strlen(ck->path)) == 0);

		if (useit) {
			if (firstcookie) {
				addtobuffer(httprequest, "Cookie: ");
				firstcookie = 0;
			}
			addtobuffer(httprequest, ck->name);
			addtobuffer(httprequest, "=");
			addtobuffer(httprequest, ck->value);
			addtobuffer(httprequest, "\r\n");
		}
	}

	/* Some standard stuff */
	addtobuffer(httprequest, "Accept: */*\r\n");
	addtobuffer(httprequest, "Pragma: no-cache\r\n");

	if ((httptest->weburl.testtype == WEBTEST_SOAP) || (httptest->weburl.testtype == WEBTEST_NOSOAP)) {
		/* Must provide a SOAPAction header */
		addtobuffer(httprequest, "SOAPAction: ");
		addtobuffer(httprequest, httptest->url);
		addtobuffer(httprequest, "\r\n");
	}
	
	/* The final blank line terminates the headers */
	addtobuffer(httprequest, "\r\n");

	/* Post data goes last */
	if (httptest->weburl.postdata) addtobuffer(httprequest, httptest->weburl.postdata);

	/* Pickup any SSL options the user wants */
	if (sslopt_ciphers || (sslopt_version != SSLVERSION_DEFAULT) || sslopt_clientcert){
		sslopt = (ssloptions_t *) malloc(sizeof(ssloptions_t));
		sslopt->cipherlist = sslopt_ciphers;
		sslopt->sslversion = sslopt_version;
		sslopt->clientcert = sslopt_clientcert;
	}

	/* Add to TCP test queue */
	if (httptest->weburl.proxyurl == NULL) {
		httptest->tcptest = add_tcp_test(httptest->weburl.desturl->ip, 
						 httptest->weburl.desturl->port, 
						 httptest->weburl.desturl->scheme,
						 sslopt, t->srcip,
						 t->testspec, t->silenttest, grabstrbuffer(httprequest), 
						 httptest, tcp_http_data_callback, tcp_http_final_callback);
	}
	else {
		httptest->tcptest = add_tcp_test(httptest->weburl.proxyurl->ip, 
						 httptest->weburl.proxyurl->port, 
						 httptest->weburl.proxyurl->scheme,
						 sslopt, t->srcip,
						 t->testspec, t->silenttest, grabstrbuffer(httprequest), 
						 httptest, tcp_http_data_callback, tcp_http_final_callback);
	}
}
Esempio n. 3
0
NETLIBHTTPHEADER* facebook_client::get_request_headers( int request_type, int* headers_count )
{
	switch ( request_type )
	{
	case FACEBOOK_REQUEST_LOGIN:
	case FACEBOOK_REQUEST_SETUP_MACHINE:
	case FACEBOOK_REQUEST_BUDDY_LIST:
	case FACEBOOK_REQUEST_LOAD_FRIENDS:
	case FACEBOOK_REQUEST_STATUS_SET:
	case FACEBOOK_REQUEST_MESSAGE_SEND:
	case FACEBOOK_REQUEST_VISIBILITY:
	case FACEBOOK_REQUEST_TABS:
	case FACEBOOK_REQUEST_ASYNC:
	case FACEBOOK_REQUEST_TYPING_SEND:
	case FACEBOOK_REQUEST_DELETE_FRIEND:
	case FACEBOOK_REQUEST_ADD_FRIEND:
		*headers_count = 5;
		break;

	case FACEBOOK_REQUEST_HOME:
	case FACEBOOK_REQUEST_FEEDS:
	case FACEBOOK_REQUEST_NOTIFICATIONS:
	case FACEBOOK_REQUEST_RECONNECT:
	case FACEBOOK_REQUEST_MESSAGES_RECEIVE:
	default:
		*headers_count = 4;
		break;
	}

	NETLIBHTTPHEADER* headers = ( NETLIBHTTPHEADER* )utils::mem::allocate( sizeof( NETLIBHTTPHEADER )*( *headers_count ) );

	switch ( request_type )
	{
	case FACEBOOK_REQUEST_LOGIN:
	case FACEBOOK_REQUEST_SETUP_MACHINE:
	case FACEBOOK_REQUEST_BUDDY_LIST:
	case FACEBOOK_REQUEST_LOAD_FRIENDS:
	case FACEBOOK_REQUEST_STATUS_SET:
	case FACEBOOK_REQUEST_MESSAGE_SEND:
	case FACEBOOK_REQUEST_VISIBILITY:
	case FACEBOOK_REQUEST_TABS:
	case FACEBOOK_REQUEST_ASYNC:
	case FACEBOOK_REQUEST_TYPING_SEND:
	case FACEBOOK_REQUEST_DELETE_FRIEND:
	case FACEBOOK_REQUEST_ADD_FRIEND:
		headers[4].szName = "Content-Type";
		headers[4].szValue = "application/x-www-form-urlencoded; charset=utf-8";

	case FACEBOOK_REQUEST_HOME:
	case FACEBOOK_REQUEST_RECONNECT:
	case FACEBOOK_REQUEST_MESSAGES_RECEIVE:
	default:
		headers[3].szName = "Cookie";
		headers[3].szValue = load_cookies( );
		headers[2].szName = "User-Agent";
		headers[2].szValue = (char *)g_strUserAgent.c_str( );
		headers[1].szName = "Accept";
		headers[1].szValue = "*/*";
		headers[0].szName = "Accept-Language";
		headers[0].szValue = "en,en-US;q=0.9";
		break;
	}

	return headers;
}
Esempio n. 4
0
/* Many execution paths may lead to this code so it needs to take appropriate
 * precausions to stuff like doc_view and doc_view->vs being NULL. */
enum frame_event_status
do_action(struct session *ses, enum main_action action_id, int verbose)
{
	enum frame_event_status status = FRAME_EVENT_OK;
	struct terminal *term = ses->tab->term;
	struct document_view *doc_view = current_frame(ses);
	struct link *link = NULL;

	if (action_id == -1) goto unknown_action;

	if (doc_view && doc_view->vs) {
		if (action_prefix_is_link_number(KEYMAP_MAIN, action_id)
		    && !try_jump_to_link_number(ses, doc_view))
			goto ignore_action;

		link = get_current_link(doc_view);

	} else if (action_requires_view_state(KEYMAP_MAIN, action_id)) {
		goto ignore_action;
	}

	if (action_requires_location(KEYMAP_MAIN, action_id)
	    && !have_location(ses))
		return FRAME_EVENT_OK;

	if (action_requires_link(KEYMAP_MAIN, action_id)
	    && !link)
		goto ignore_action;

	if (action_requires_form(KEYMAP_MAIN, action_id)
	    && (!link || !link_is_form(link)))
		goto ignore_action;

	if (!action_is_anonymous_safe(KEYMAP_MAIN, action_id)
	    && get_cmd_opt_bool("anonymous"))
		goto ignore_action;

	/* Please keep in alphabetical order for now. Later we can sort by most
	 * used or something. */
	switch (action_id) {
		case ACT_MAIN_ABORT_CONNECTION:
			abort_loading(ses, 1);
			print_screen_status(ses);
			break;

		case ACT_MAIN_ADD_BOOKMARK:
#ifdef CONFIG_BOOKMARKS
			launch_bm_add_doc_dialog(term, NULL, ses);
#endif
			break;
		case ACT_MAIN_ADD_BOOKMARK_LINK:
#ifdef CONFIG_BOOKMARKS
			launch_bm_add_link_dialog(term, NULL, ses);
#endif
			break;
		case ACT_MAIN_ADD_BOOKMARK_TABS:
#ifdef CONFIG_BOOKMARKS
			bookmark_terminal_tabs_dialog(term);
#endif
			break;

		case ACT_MAIN_AUTH_MANAGER:
			auth_manager(ses);
			break;

		case ACT_MAIN_BACKSPACE_PREFIX:

			if (!ses->kbdprefix.repeat_count) break;

			set_kbd_repeat_count(ses,
			                     ses->kbdprefix.repeat_count / 10);

			/* Keep send_event from resetting repeat_count. */
			status = FRAME_EVENT_SESSION_DESTROYED;

			break;

		case ACT_MAIN_BOOKMARK_MANAGER:
#ifdef CONFIG_BOOKMARKS
			bookmark_manager(ses);
#endif
			break;

		case ACT_MAIN_CACHE_MANAGER:
			cache_manager(ses);
			break;

		case ACT_MAIN_CACHE_MINIMIZE:
			shrink_memory(1);
			break;

		case ACT_MAIN_COOKIES_LOAD:
#ifdef CONFIG_COOKIES
			if (!get_opt_bool("cookies.save", NULL)) break;
			load_cookies();
#endif
			break;

		case ACT_MAIN_COOKIE_MANAGER:
#ifdef CONFIG_COOKIES
			cookie_manager(ses);
#endif
			break;

		case ACT_MAIN_COPY_CLIPBOARD:
			status = copy_current_link_to_clipboard(ses, doc_view, 0);
			break;

		case ACT_MAIN_DOCUMENT_INFO:
			document_info_dialog(ses);
			break;

		case ACT_MAIN_DOWNLOAD_MANAGER:
			download_manager(ses);
			break;

		case ACT_MAIN_EXMODE:
#ifdef CONFIG_EXMODE
			exmode_start(ses);
#endif
			break;

		case ACT_MAIN_FILE_MENU:
			activate_bfu_technology(ses, 0);
			break;

		case ACT_MAIN_FIND_NEXT:
			status = find_next(ses, doc_view, 1);
			break;

		case ACT_MAIN_FIND_NEXT_BACK:
			status = find_next(ses, doc_view, -1);
			break;

		case ACT_MAIN_FORGET_CREDENTIALS:
			free_auth();
			shrink_memory(1); /* flush caches */
			break;

		case ACT_MAIN_FORMHIST_MANAGER:
#ifdef CONFIG_FORMHIST
			formhist_manager(ses);
#endif
			break;

		case ACT_MAIN_FRAME_EXTERNAL_COMMAND:
			status = pass_uri_to_command(ses, doc_view,
			                             PASS_URI_FRAME);
			break;

		case ACT_MAIN_FRAME_NEXT:
			next_frame(ses, 1);
			draw_formatted(ses, 0);
			break;

		case ACT_MAIN_FRAME_MAXIMIZE:
			status = set_frame(ses, doc_view, 0);
			break;

		case ACT_MAIN_FRAME_PREV:
			next_frame(ses, -1);
			draw_formatted(ses, 0);
			break;

		case ACT_MAIN_GOTO_URL:
			goto_url_action(ses, NULL);
			break;

		case ACT_MAIN_GOTO_URL_CURRENT:
			goto_url_action(ses, get_current_url);
			break;

		case ACT_MAIN_GOTO_URL_CURRENT_LINK:
			goto_url_action(ses, get_current_link_url);
			break;

		case ACT_MAIN_GOTO_URL_HOME:
			goto_url_home(ses);
			break;

		case ACT_MAIN_HEADER_INFO:
			protocol_header_dialog(ses);
			break;

		case ACT_MAIN_HISTORY_MANAGER:
#ifdef CONFIG_GLOBHIST
			history_manager(ses);
#endif
			break;

		case ACT_MAIN_HISTORY_MOVE_BACK:
		{
			int count = int_max(1, eat_kbd_repeat_count(ses));

			go_history_by_n(ses, -count);
			break;
		}
		case ACT_MAIN_HISTORY_MOVE_FORWARD:
		{
			int count = int_max(1, eat_kbd_repeat_count(ses));

			go_history_by_n(ses, count);
			break;
		}
		case ACT_MAIN_JUMP_TO_LINK:
			break;

		case ACT_MAIN_KEYBINDING_MANAGER:
			keybinding_manager(ses);
			break;

		case ACT_MAIN_KILL_BACKGROUNDED_CONNECTIONS:
			abort_background_connections();
			break;

		case ACT_MAIN_LINK_DIALOG:
			open_link_dialog(ses);
			break;

		case ACT_MAIN_LINK_DOWNLOAD:
		case ACT_MAIN_LINK_DOWNLOAD_IMAGE:
		case ACT_MAIN_LINK_DOWNLOAD_RESUME:
			status = download_link(ses, doc_view, action_id);
			break;

		case ACT_MAIN_LINK_EXTERNAL_COMMAND:
			status = pass_uri_to_command(ses, doc_view,
			                             PASS_URI_LINK);
			break;

		case ACT_MAIN_LINK_FOLLOW:
			status = enter(ses, doc_view, 0);
			break;

		case ACT_MAIN_LINK_FOLLOW_RELOAD:
			status = enter(ses, doc_view, 1);
			break;

		case ACT_MAIN_LINK_INFO:
			link_info_dialog(ses);
			break;
			
		case ACT_MAIN_LINK_MENU:
			link_menu(term, NULL, ses);
			break;

		case ACT_MAIN_LINK_FORM_MENU:
			link_form_menu(ses);
			break;

		case ACT_MAIN_LUA_CONSOLE:
#ifdef CONFIG_SCRIPTING_LUA
			trigger_event_name("dialog-lua-console", ses);
#endif
			break;

		case ACT_MAIN_MARK_SET:
#ifdef CONFIG_MARKS
			ses->kbdprefix.mark = KP_MARK_SET;
			status = FRAME_EVENT_REFRESH;
#endif
			break;

		case ACT_MAIN_MARK_GOTO:
#ifdef CONFIG_MARKS
			/* TODO: Show promptly a menu (or even listbox?)
			 * with all the marks. But the next letter must
			 * still choose a mark directly! --pasky */
			ses->kbdprefix.mark = KP_MARK_GOTO;
			status = FRAME_EVENT_REFRESH;
#endif
			break;

		case ACT_MAIN_MENU:
			activate_bfu_technology(ses, -1);
			break;

		case ACT_MAIN_MOVE_CURRENT_TOP:
			status = move_current_top(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_CURSOR_UP:
			status = move_cursor_up(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_CURSOR_DOWN:
			status = move_cursor_down(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_CURSOR_LEFT:
			status = move_cursor_left(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_CURSOR_RIGHT:
			status = move_cursor_right(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_CURSOR_LINE_START:
			status = move_cursor_line_start(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_HALF_PAGE_DOWN:
			status = move_half_page_down(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_HALF_PAGE_UP:
			status = move_half_page_up(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_DOWN:
			status = move_link_down(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_DOWN_LINE:
			status = move_link_down_line(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_LEFT:
			status = move_link_left(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_LEFT_LINE:
			status = move_link_prev_line(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_NEXT:
			status = move_link_next(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_PREV:
			status = move_link_prev(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_RIGHT:
			status = move_link_right(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_RIGHT_LINE:
			status = move_link_next_line(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_UP:
			status = move_link_up(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_LINK_UP_LINE:
			status = move_link_up_line(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_PAGE_DOWN:
			status = move_page_down(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_PAGE_UP:
			status = move_page_up(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_DOCUMENT_START:
			status = move_document_start(ses, doc_view);
			break;

		case ACT_MAIN_MOVE_DOCUMENT_END:
			status = move_document_end(ses, doc_view);
			break;

		case ACT_MAIN_OPEN_LINK_IN_NEW_TAB:
			open_current_link_in_new_tab(ses, 0);
			break;

		case ACT_MAIN_OPEN_LINK_IN_NEW_TAB_IN_BACKGROUND:
			open_current_link_in_new_tab(ses, 1);
			break;

		case ACT_MAIN_OPEN_LINK_IN_NEW_WINDOW:
			open_in_new_window(term, send_open_in_new_window, ses);
			break;

		case ACT_MAIN_OPEN_NEW_TAB:
			open_uri_in_new_tab(ses, NULL, 0, 1);
			break;

		case ACT_MAIN_OPEN_NEW_TAB_IN_BACKGROUND:
			open_uri_in_new_tab(ses, NULL, 1, 1);
			break;

		case ACT_MAIN_OPEN_NEW_WINDOW:
			open_in_new_window(term, send_open_new_window, ses);
			break;

		case ACT_MAIN_OPEN_OS_SHELL:
			exec_shell(term);
			break;

		case ACT_MAIN_OPTIONS_MANAGER:
			options_manager(ses);
			break;

		case ACT_MAIN_QUIT:
			exit_prog(ses, 1);
			break;

		case ACT_MAIN_REALLY_QUIT:
			exit_prog(ses, 0);
			break;

		case ACT_MAIN_REDRAW:
			redraw_terminal_cls(term);
			break;

		case ACT_MAIN_RELOAD:
			reload(ses, CACHE_MODE_INCREMENT);
			break;

		case ACT_MAIN_RERENDER:
			draw_formatted(ses, 2);
			break;

		case ACT_MAIN_RESET_FORM:
			status = reset_form(ses, doc_view, 0);
			break;

		case ACT_MAIN_RESOURCE_INFO:
			resource_info(term);
			break;

		case ACT_MAIN_SAVE_AS:
			status = save_as(ses, doc_view, 0);
			break;

		case ACT_MAIN_SAVE_FORMATTED:
			status = save_formatted_dlg(ses, doc_view, 0);
			break;

		case ACT_MAIN_SAVE_OPTIONS:
			write_config(term);
			break;

		case ACT_MAIN_SAVE_URL_AS:
			save_url_as(ses);
			break;

		case ACT_MAIN_SCROLL_DOWN:
			status = scroll_down(ses, doc_view);
			break;

		case ACT_MAIN_SCROLL_LEFT:
			status = scroll_left(ses, doc_view);
			break;

		case ACT_MAIN_SCROLL_RIGHT:
			status = scroll_right(ses, doc_view);
			break;

		case ACT_MAIN_SCROLL_UP:
			status = scroll_up(ses, doc_view);
			break;

		case ACT_MAIN_SEARCH:
			status = search_dlg(ses, doc_view, 1);
			break;

		case ACT_MAIN_SEARCH_BACK:
			status = search_dlg(ses, doc_view, -1);
			break;

		case ACT_MAIN_SEARCH_TYPEAHEAD:
		case ACT_MAIN_SEARCH_TYPEAHEAD_LINK:
		case ACT_MAIN_SEARCH_TYPEAHEAD_TEXT:
		case ACT_MAIN_SEARCH_TYPEAHEAD_TEXT_BACK:
			status = search_typeahead(ses, doc_view, action_id);
			break;

		case ACT_MAIN_SHOW_TERM_OPTIONS:
			terminal_options(term, NULL, ses);
			break;

		case ACT_MAIN_SUBMIT_FORM:
			status = submit_form(ses, doc_view, 0);
			break;

		case ACT_MAIN_SUBMIT_FORM_RELOAD:
			status = submit_form(ses, doc_view, 1);
			break;

		case ACT_MAIN_TAB_CLOSE:
			close_tab(term, ses);
			status = FRAME_EVENT_SESSION_DESTROYED;
			break;

		case ACT_MAIN_TAB_CLOSE_ALL_BUT_CURRENT:
			close_all_tabs_but_current(ses);
			break;

		case ACT_MAIN_TAB_EXTERNAL_COMMAND:
			status = pass_uri_to_command(ses, doc_view,
			                             PASS_URI_TAB);
			break;

		case ACT_MAIN_TAB_MOVE_LEFT:
			move_current_tab(ses, -1);
			break;

		case ACT_MAIN_TAB_MOVE_RIGHT:
			move_current_tab(ses, 1);
			break;

		case ACT_MAIN_TAB_MENU:
			assert(ses->tab == get_current_tab(term));

			if (ses->status.show_tabs_bar)
				tab_menu(ses, ses->tab->xpos,
					 term->height - 1
					  - ses->status.show_status_bar,
					 1);
			else
				tab_menu(ses, 0, 0, 0);

			break;

		case ACT_MAIN_TAB_NEXT:
			switch_current_tab(ses, 1);
			break;

		case ACT_MAIN_TAB_PREV:
			switch_current_tab(ses, -1);
			break;

		case ACT_MAIN_TERMINAL_RESIZE:
			resize_terminal_dialog(term);
			break;

		case ACT_MAIN_TOGGLE_CSS:
#ifdef CONFIG_CSS
			toggle_document_option(ses, "document.css.enable");
#endif
			break;

		case ACT_MAIN_TOGGLE_DISPLAY_IMAGES:
			toggle_document_option(ses, "document.browse.images.show_as_links");
			break;

		case ACT_MAIN_TOGGLE_DISPLAY_TABLES:
			toggle_document_option(ses, "document.html.display_tables");
			break;

		case ACT_MAIN_TOGGLE_DOCUMENT_COLORS:
			toggle_document_option(ses, "document.colors.use_document_colors");
			break;

		case ACT_MAIN_TOGGLE_HTML_PLAIN:
			toggle_plain_html(ses, ses->doc_view, 0);
			break;

		case ACT_MAIN_TOGGLE_MOUSE:
#ifdef CONFIG_MOUSE
			toggle_mouse();
#endif
			break;

		case ACT_MAIN_TOGGLE_NUMBERED_LINKS:
			toggle_document_option(ses, "document.browse.links.numbering");
			break;

		case ACT_MAIN_TOGGLE_PLAIN_COMPRESS_EMPTY_LINES:
			toggle_document_option(ses, "document.plain.compress_empty_lines");
			break;

		case ACT_MAIN_TOGGLE_WRAP_TEXT:
			toggle_wrap_text(ses, ses->doc_view, 0);
			break;

		case ACT_MAIN_VIEW_IMAGE:
			status = view_image(ses, doc_view, 0);
			break;

		case ACT_MAIN_SCRIPTING_FUNCTION:
		case ACT_MAIN_NONE:
		case MAIN_ACTIONS:
		default:
unknown_action:
			if (verbose) {
				INTERNAL("No action handling defined for '%s'.",
					 get_action_name(KEYMAP_MAIN, action_id));
			}

			status = FRAME_EVENT_IGNORED;
	}

ignore_action:
	/* XXX: At this point the session may have been destroyed */

	if (status != FRAME_EVENT_SESSION_DESTROYED
	    && ses->insert_mode == INSERT_MODE_ON
	    && link != get_current_link(doc_view))
		ses->insert_mode = INSERT_MODE_OFF;

	if (status == FRAME_EVENT_REFRESH && doc_view)
		refresh_view(ses, doc_view, 0);

	return status;
}