#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef KANJI_CODE_OVERRIDE #include #endif #ifdef KANJI_CODE_OVERRIDE PUBLIC char *str_kcode(HTkcode code) { char *p; static char buff[8]; if (current_char_set == TRANSPARENT) { p = "THRU"; } else if (!LYRawMode) { p = "RAW"; } else { switch (code) { case NOKANJI: p = "AUTO"; break; case EUC: p = "EUC+"; break; case SJIS: p = "SJIS"; break; case JIS: p = " JIS"; break; default: p = " ???"; break; } } if (no_table_center) { buff[0] = '!'; strcpy(buff + 1, p); } else { strcpy(buff, p); } return buff; } #endif #ifdef WIN_EX PRIVATE char *str_sjis(char *to, char *from) { if (!LYRawMode) { strcpy(to, from); #ifdef KANJI_CODE_OVERRIDE } else if (last_kcode == EUC) { EUC_TO_SJIS(from, to); } else if (last_kcode == SJIS) { strcpy(to, from); #endif } else { TO_SJIS(from, to); } return to; } PRIVATE void set_ws_title(char * str) { SetConsoleTitle(str); } #endif /* WIN_EX */ #ifdef SH_EX /* 1998/10/30 (Fri) 10:06:47 */ #define NOT_EQU 1 PRIVATE int str_n_cmp(const char *p, const char *q, int n) { if (n == 0) return 0; if (p == NULL) return NOT_EQU; if (q == NULL) return NOT_EQU; return strncmp(p, q, n); } #undef strncmp #define strncmp(p, q, r) str_n_cmp(p, q, r) #endif /* SH_EX */ #if defined(USE_EXTERNALS) || defined(WIN_EX) #include #endif #ifdef __EMX__ #include #endif #ifdef DIRED_SUPPORT #include #include #endif /* DIRED_SUPPORT */ #include #include /* two constants: */ PUBLIC HTLinkType * HTInternalLink = 0; PUBLIC HTAtom * WWW_SOURCE = 0; #ifndef DONT_TRACK_INTERNAL_LINKS #define NO_INTERNAL_OR_DIFFERENT(c,n) TRUE #define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) (!curdoc.internal_link || \ are_phys_different(p,n)) #else /* TRACK_INTERNAL_LINKS */ #define NO_INTERNAL_OR_DIFFERENT(c,n) are_different(c,n) #define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) are_different(p,n) #endif /* TRACK_INTERNAL_LINKS */ PRIVATE void exit_immediately_with_error_message PARAMS((int state, BOOLEAN first_file)); PRIVATE void status_link PARAMS((char *curlink_name, BOOLEAN show_more, BOOLEAN show_indx)); PRIVATE void show_main_statusline PARAMS((CONST LinkInfo curlink, int for_what)); PRIVATE void form_noviceline PARAMS((int)); PRIVATE int are_different PARAMS((DocInfo *doc1, DocInfo *doc2)); #ifndef DONT_TRACK_INTERNAL_LINKS PRIVATE int are_phys_different PARAMS((DocInfo *doc1, DocInfo *doc2)); #endif #define FASTTAB PRIVATE int sametext ARGS2( char *, een, char *, twee) { if (een && twee) return (strcmp(een, twee) == 0); return TRUE; } PUBLIC HTList * Goto_URLs = NULL; /* List of Goto URLs */ PUBLIC char * LYRequestTitle = NULL; /* newdoc.title in calls to getfile() */ PUBLIC char * LYRequestReferer = NULL; /* Referer, may be set in getfile() */ PRIVATE char prev_target[512]; #ifdef DISP_PARTIAL PUBLIC BOOLEAN display_partial = FALSE; /* could be enabled in HText_new() */ PUBLIC int NumOfLines_partial = 0; /* number of lines displayed in partial mode */ #endif PRIVATE int Newline = 0; PRIVATE DocInfo newdoc; PRIVATE DocInfo curdoc; PRIVATE char *traversal_host = NULL; PRIVATE char *traversal_link_to_add = NULL; PRIVATE char *owner_address = NULL; /* Holds the responsible owner's address */ PRIVATE char *ownerS_address = NULL; /* Holds owner's address during source fetch */ #ifdef TEXTFIELDS_MAY_NEED_ACTIVATION PRIVATE BOOL textinput_activated = FALSE; #else #define textinput_activated TRUE /* a current text input is always active */ #endif #ifdef INACTIVE_INPUT_STYLE_VH PUBLIC BOOL textinput_redrawn = FALSE; /*must be public since used in LYhighlight(..)*/ #endif #ifdef LY_FIND_LEAKS /* * Function for freeing allocated mainloop() variables. - FM */ PRIVATE void free_mainloop_variables NOARGS { LYFreeDocInfo(&newdoc); LYFreeDocInfo(&curdoc); #ifdef USE_COLOR_STYLE FREE(curdoc.style); FREE(newdoc.style); #endif FREE(traversal_host); FREE(traversal_link_to_add); FREE(owner_address); FREE(ownerS_address); #ifdef DIRED_SUPPORT clear_tags(); reset_dired_menu(); #endif /* DIRED_SUPPORT */ FREE(WWW_Download_File); /* LYGetFile.c/HTFWriter.c */ FREE(LYRequestReferer); return; } #endif /* LY_FIND_LEAKS */ #ifndef NO_LYNX_TRACE PRIVATE void TracelogOpenFailed NOARGS { WWW_TraceFlag = FALSE; if (LYCursesON) { HTUserMsg(TRACELOG_OPEN_FAILED); } else { fprintf(stderr, "%s\n", TRACELOG_OPEN_FAILED); exit(EXIT_FAILURE); } } PRIVATE BOOLEAN LYReopenTracelog ARGS1(BOOLEAN *, trace_flag_ptr) { CTRACE((tfp, "\nTurning off TRACE for fetch of log.\n")); LYCloseTracelog(); if ((LYTraceLogFP = LYAppendToTxtFile(LYTraceLogPath)) == NULL) { TracelogOpenFailed(); return FALSE; } if (TRACE) { WWW_TraceFlag = FALSE; *trace_flag_ptr = TRUE; } return TRUE; } PRIVATE void turn_trace_back_on ARGS1(BOOLEAN *, trace_flag_ptr) { if (*trace_flag_ptr == TRUE) { WWW_TraceFlag = TRUE; *trace_flag_ptr = FALSE; fprintf(tfp, "Turning TRACE back on.\n\n"); } } #else #define LYReopenTracelog(flag) TRUE #define turn_trace_back_on(flag) /*nothing*/ #endif /* NO_LYNX_TRACE */ PUBLIC FILE *TraceFP NOARGS { #ifndef NO_LYNX_TRACE if (LYTraceLogFP != 0) { return LYTraceLogFP; } #endif /* NO_LYNX_TRACE */ return stderr; } PUBLIC BOOLEAN LYOpenTraceLog NOARGS { #ifndef NO_LYNX_TRACE if (TRACE && LYUseTraceLog && LYTraceLogFP == NULL) { /* * If we can't open it for writing, give up. Otherwise, on VMS close * it, delete it and any versions from previous sessions so they don't * accumulate, and open it again. - FM */ if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) { TracelogOpenFailed(); return FALSE; } #ifdef VMS LYCloseTracelog(); HTSYS_remove(LYTraceLogPath); if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) { TracelogOpenFailed(); return FALSE; } #endif /* VMS */ fflush(stdout); fflush(stderr); fprintf(tfp, "\t\t%s (%s)\n\n", LYNX_TRACELOG_TITLE, LYNX_VERSION); /* * If TRACE is on, indicate whether the * anonymous restrictions are set. - FM, LP, kw * This is only a summary for convenience - it doesn't * take the case of individual -restrictions= options * into account. - kw */ if (LYValidate) { if (LYRestricted && had_restrictions_default) { CTRACE((tfp, "Validate and some anonymous restrictions are set.\n")); } else if (had_restrictions_default) { CTRACE((tfp, "Validate restrictions set, restriction \"default\" was given.\n")); } else if (LYRestricted) { CTRACE((tfp, "Validate restrictions set, additional anonymous restrictions ignored.\n")); } else { CTRACE((tfp, "Validate restrictions are set.\n")); } /* But none of the above can actually happen, since there should * never be a Trace Log with -validate. If it appears in a log * file something went wrong! */ } else if (LYRestricted) { if (had_restrictions_all) { CTRACE((tfp, "Anonymous restrictions set, restriction \"all\" was given.\n")); } else { CTRACE((tfp, "Anonymous restrictions are set.\n")); } } else if (had_restrictions_all && had_restrictions_default) { CTRACE((tfp, "Restrictions \"all\" and \"default\" were given.\n")); } else if (had_restrictions_default) { CTRACE((tfp, "Restriction \"default\" was given.\n")); } else if (had_restrictions_all) { CTRACE((tfp, "\"all\" restrictions are set.\n")); } } #endif /* NO_LYNX_TRACE */ return TRUE; } PUBLIC void LYCloseTracelog NOARGS { #ifndef NO_LYNX_TRACE if (LYTraceLogFP != 0) { fflush(stdout); fflush(stderr); fclose(LYTraceLogFP); LYTraceLogFP = 0; } #endif /* NO_LYNX_TRACE */ } PUBLIC void handle_LYK_TRACE_TOGGLE NOARGS { #ifndef NO_LYNX_TRACE WWW_TraceFlag = ! WWW_TraceFlag; if (LYOpenTraceLog()) HTUserMsg(WWW_TraceFlag ? TRACE_ON : TRACE_OFF); #else HTUserMsg(TRACE_DISABLED); #endif /* NO_LYNX_TRACE */ } PUBLIC void LYSetNewline ARGS1( int, value) { Newline = value; } PUBLIC int LYGetNewline NOARGS { return Newline; } #ifdef USE_SOURCE_CACHE PRIVATE BOOLEAN from_source_cache = FALSE; /* * Like HTreparse_document(), but also set the flag. */ PRIVATE BOOLEAN reparse_document NOARGS { BOOLEAN ok; from_source_cache = TRUE; /* set for LYMainLoop_pageDisplay() */ if ((ok = HTreparse_document()) != FALSE) { from_source_cache = TRUE; /* set for mainloop refresh */ return ok; } from_source_cache = FALSE; return ok; } #endif /* USE_SOURCE_CACHE */ /* * Prefer reparsing if we can, but reload if we must - to force regeneration * of the display. */ PRIVATE BOOLEAN reparse_or_reload ARGS1( int *, cmd) { #ifdef USE_SOURCE_CACHE if (reparse_document()) { return FALSE; } #endif *cmd = LYK_RELOAD; return TRUE; } /* * Functions for setting the current address */ PRIVATE void set_address ARGS2( DocInfo *, doc, CONST char *, address) { StrAllocCopy(doc->address, address); } PRIVATE void copy_address ARGS2( DocInfo *, dst, DocInfo *, src) { StrAllocCopy(dst->address, src->address); } PRIVATE void free_address ARGS1( DocInfo *, doc) { FREE(doc->address); } PRIVATE void move_address ARGS2( DocInfo *, dst, DocInfo *, src) { copy_address(dst, src); free_address(src); } #ifdef DISP_PARTIAL /* * This is for traversal call from within partial mode in LYUtils.c * and HTFormat.c It simply calls HText_pageDisplay() but utilizes * LYMainLoop.c PRIVATE variables to manage proper newline position * in case of #fragment */ PUBLIC BOOL LYMainLoop_pageDisplay ARGS1( int, line_num) { CONST char * pound; int prev_newline = Newline; /* * Override Newline with a new value if user * scrolled the document while loading (in LYUtils.c). */ Newline = line_num; #ifdef USE_SOURCE_CACHE /* * reparse_document() acts on 'curdoc' which always on top of the * history stack: no need to resolve #fragment position since * we already know it (curdoc.line). * So bypass here. Sorry for possible confusion... */ if (!from_source_cache) #endif /* * If the requested URL has the #fragment, and we are not popped * from the history stack, and have not scrolled the document yet - * we should calculate correct newline position for the fragment. * (This is a bit suboptimal since HTFindPoundSelector() traverse * anchors list each time, so we have a quadratic complexity * and may load CPU in a worst case). */ if (display_partial && newdoc.line == 1 && line_num == 1 && prev_newline == 1 && (pound = findPoundSelector(newdoc.address)) && *pound && *(pound+1)) { if (HTFindPoundSelector(pound+1)) { /* HTFindPoundSelector will initialize www_search_result */ Newline = www_search_result; } else { Newline = prev_newline; /* restore ??? */ return NO; /* no repaint */ } } HText_pageDisplay(Newline, prev_target); return YES; } #endif /* DISP_PARTIAL */ PRIVATE void set_curdoc_link ARGS1( int, nextlink) { if (curdoc.link != nextlink && nextlink >= 0 && nextlink < nlinks) { if (curdoc.link >= 0 && curdoc.link < nlinks) LYhighlight(OFF, curdoc.link, prev_target); curdoc.link = nextlink; } } PRIVATE int do_change_link NOARGS { #ifdef USE_MOUSE /* Is there a mouse-clicked link waiting? */ int mouse_tmp = get_mouse_link(); /* If yes, use it as the link */ if (mouse_tmp != -1) { if (mouse_tmp < 0 || mouse_tmp >= nlinks) { char *msgtmp = NULL; HTSprintf0(&msgtmp, gettext("Internal error: Invalid mouse link %d!"), mouse_tmp); HTAlert(msgtmp); FREE(msgtmp); return(-1); /* indicates unexpected error */ } set_curdoc_link(mouse_tmp); } #endif /* USE_MOUSE */ return(0); /* indicates OK */ } #ifdef DIRED_SUPPORT #define DIRED_UNCACHE_1 if (LYAutoUncacheDirLists < 1) /*nothing*/ ;\ else HTuncache_current_document() #define DIRED_UNCACHE_2 if (LYAutoUncacheDirLists < 2) /*nothing*/ ;\ else HTuncache_current_document() #endif /* DIRED_SUPPORT */ PRIVATE void do_check_goto_URL ARGS3( char *, user_input_buffer, char **, old_user_input, BOOLEAN *, force_load) { static BOOLEAN always = TRUE; static struct { CONST char *name; BOOLEAN *flag; } table[] = { { STR_FILE_URL, &no_file_url }, { STR_FILE_URL, &no_goto_file }, { STR_LYNXEXEC, &no_goto_lynxexec }, { STR_LYNXPROG, &no_goto_lynxprog }, { STR_LYNXCGI, &no_goto_lynxcgi }, { STR_CSO_URL, &no_goto_cso }, { STR_FINGER_URL, &no_goto_finger }, { STR_FTP_URL, &no_goto_ftp }, { STR_GOPHER_URL, &no_goto_gopher }, { STR_HTTP_URL, &no_goto_http }, { STR_HTTPS_URL, &no_goto_https }, { STR_MAILTO_URL, &no_goto_mailto }, { STR_RLOGIN_URL, &no_goto_rlogin }, { STR_TELNET_URL, &no_goto_telnet }, { STR_TN3270_URL, &no_goto_tn3270 }, { STR_WAIS_URL, &no_goto_wais }, #ifndef DISABLE_BIBP { STR_BIBP_URL, &no_goto_bibp }, #endif #ifndef DISABLE_NEWS { STR_NEWS_URL, &no_goto_news }, { STR_NNTP_URL, &no_goto_nntp }, { STR_SNEWS_URL, &no_goto_snews }, #endif #ifdef EXEC_LINKS { STR_LYNXEXEC, &local_exec_on_local_files }, { STR_LYNXPROG, &local_exec_on_local_files }, #endif /* EXEC_LINKS */ { STR_LYNXCFG, &no_goto_configinfo }, { STR_LYNXCFLAGS, &no_goto_configinfo }, { STR_LYNXCOOKIE, &always }, { STR_LYNXDIRED, &always }, { STR_LYNXDOWNLOAD, &always }, { STR_LYNXOPTIONS, &always }, { STR_LYNXPRINT, &always }, }; unsigned n; BOOLEAN found = FALSE; /* allow going to anchors*/ if (*user_input_buffer == '#' ) { if ( user_input_buffer[1] && HTFindPoundSelector(user_input_buffer+1) ) { /* HTFindPoundSelector will initialize www_search_result, so we do nothing else. */ HTAddGotoURL(user_input_buffer); trimPoundSelector(curdoc.address); StrAllocCat(curdoc.address, user_input_buffer); } } else { /* * If it's not a URL then make it one. */ StrAllocCopy(*old_user_input, user_input_buffer); LYEnsureAbsoluteURL(old_user_input, "", TRUE); sprintf(user_input_buffer, "%.*s", (int)(MAX_LINE - 1), *old_user_input); FREE(*old_user_input); for (n = 0; n < TABLESIZE(table); n++) { if (*(table[n].flag) && !strncmp(user_input_buffer, table[n].name, strlen(table[n].name))) { found = TRUE; HTUserMsg2(GOTO_XXXX_DISALLOWED, table[n].name); break; } } if (found) { ; } else if (LYValidate && !isHTTP_URL(user_input_buffer) && !isHTTPS_URL(user_input_buffer)) { HTUserMsg(GOTO_NON_HTTP_DISALLOWED); } else { set_address(&newdoc, user_input_buffer); newdoc.isHEAD = FALSE; /* * Might be an anchor in the same doc from a POST * form. If so, dont't free the content. -- FM */ if (are_different(&curdoc, &newdoc)) { /* * Make a name for this new URL. */ StrAllocCopy(newdoc.title, gettext("A URL specified by the user")); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.safe = FALSE; newdoc.internal_link = FALSE; *force_load = TRUE; #ifdef DIRED_SUPPORT if (lynx_edit_mode) { DIRED_UNCACHE_2; } #endif /* DIRED_SUPPORT */ } LYUserSpecifiedURL = TRUE; HTAddGotoURL(newdoc.address); } } } /* returns FALSE if user cancelled input or URL was invalid, TRUE otherwise */ PRIVATE BOOL do_check_recall ARGS7( int, ch, char *, user_input_buffer, char **, old_user_input, int, URLTotal, int *, URLNum, int, recall, BOOLEAN *, FirstURLRecall) { char *cp; BOOL ret = FALSE; if (*old_user_input == 0) StrAllocCopy(*old_user_input, ""); for (;;) { #ifdef WIN_EX /* 1998/10/11 (Sun) 10:41:05 */ int len = strlen(user_input_buffer); if (len >= 3) { if (len < MAX_LINE - 1 && LYIsHtmlSep(user_input_buffer[len - 3]) && LYIsDosDrive(user_input_buffer + len - 2)) LYAddPathSep0(user_input_buffer); } else if (len == 2 && user_input_buffer[1] == ':') { if (LYIsDosDrive(user_input_buffer)) { LYAddPathSep0(user_input_buffer); } else { HTUserMsg2(WWW_ILLEGAL_URL_MESSAGE, user_input_buffer); LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1); FREE(*old_user_input); ret = FALSE; break; } } #endif /* * Get rid of leading spaces (and any other spaces). */ LYTrimAllStartfile(user_input_buffer); if (*user_input_buffer == '\0' && !(recall && (ch == UPARROW || ch == DNARROW))) { LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1); FREE(*old_user_input); HTInfoMsg(CANCELLED); ret = FALSE; break; } if (recall && ch == UPARROW) { if (*FirstURLRecall) { /* * Use last URL in the list. - FM */ *FirstURLRecall = FALSE; *URLNum = 0; } else { /* * Go back to the previous URL in the list. - FM */ *URLNum += 1; } if (*URLNum >= URLTotal) /* * Roll around to the last URL in the list. - FM */ *URLNum = 0; if ((cp = (char *)HTList_objectAt(Goto_URLs, *URLNum)) != NULL) { LYstrncpy(user_input_buffer, cp, MAX_LINE - 1); if (goto_buffer && **old_user_input && !strcmp(*old_user_input, user_input_buffer)) { _statusline(EDIT_CURRENT_GOTO); } else if ((goto_buffer && URLTotal == 2) || (!goto_buffer && URLTotal == 1)) { _statusline(EDIT_THE_PREV_GOTO); } else { _statusline(EDIT_A_PREV_GOTO); } if ((ch = LYgetstr(user_input_buffer, VISIBLE, MAX_LINE, recall)) < 0) { /* * User cancelled the Goto via ^G. * Restore user_input_buffer and break. - FM */ LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1); FREE(*old_user_input); HTInfoMsg(CANCELLED); ret = FALSE; break; } continue; } } else if (recall && ch == DNARROW) { if (*FirstURLRecall) { /* * Use the first URL in the list. - FM */ *FirstURLRecall = FALSE; *URLNum = URLTotal - 1; } else { /* * Advance to the next URL in the list. - FM */ *URLNum -= 1; } if (*URLNum < 0) /* * Roll around to the first URL in the list. - FM */ *URLNum = URLTotal - 1; if ((cp=(char *)HTList_objectAt(Goto_URLs, *URLNum)) != NULL) { LYstrncpy(user_input_buffer, cp, MAX_LINE - 1); if (goto_buffer && **old_user_input && !strcmp(*old_user_input, user_input_buffer)) { _statusline(EDIT_CURRENT_GOTO); } else if ((goto_buffer && URLTotal == 2) || (!goto_buffer && URLTotal == 1)) { _statusline(EDIT_THE_PREV_GOTO); } else { _statusline(EDIT_A_PREV_GOTO); } if ((ch = LYgetstr(user_input_buffer, VISIBLE, MAX_LINE, recall)) < 0) { /* * User cancelled the Goto via ^G. * Restore user_input_buffer and break. - FM */ LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1); FREE(*old_user_input); HTInfoMsg(CANCELLED); ret = FALSE; break; } continue; } } else { ret = TRUE; break; } } return ret; } PRIVATE void do_cleanup_after_delete NOARGS { HTuncache_current_document(); move_address(&newdoc, &curdoc); newdoc.line = curdoc.line; if (curdoc.link == nlinks-1) { /* * We deleted the last link on the page. - FM */ newdoc.link = curdoc.link-1; } else { newdoc.link = curdoc.link; } } PRIVATE int find_link_near_col ARGS2( int, col, int, delta) { int i; for (i = curdoc.link; delta > 0 ? (i < nlinks) : (i >= 0); i += delta) { if ( (links[i].ly - links[curdoc.link].ly) * delta > 0 ) { int cy = links[i].ly, best = -1, dist = 1000000; while ((delta > 0 ? (i < nlinks) : (i >= 0)) && cy == links[i].ly) { int cx = links[i].lx; char *text = LYGetHiliteStr(i, 0); if (text != NULL) cx += strlen(text) / 2; cx -= col; if (cx < 0) cx = -cx; if (cx < dist) { dist = cx; best = i; } i += delta; } return(best); } } return(-1); } /* * This is a special feature to traverse every http link derived from startfile * and check for errors or create crawl output files. Only URL's that begin * with "traversal_host" are searched - this keeps the search from crossing to * other servers (a feature, not a bug!). */ PRIVATE int DoTraversal ARGS2( int, c, BOOLEAN *, crawl_ok) { BOOLEAN rlink_rejected = FALSE; BOOLEAN rlink_exists; BOOLEAN rlink_allowed; rlink_exists = (BOOL) (nlinks > 0 && links[curdoc.link].type != WWW_FORM_LINK_TYPE && links[curdoc.link].lname != NULL); if (rlink_exists) { rlink_rejected = lookup_reject(links[curdoc.link].lname); if (!rlink_rejected && traversal_host && links[curdoc.link].lname) { if (!isLYNXIMGMAP(links[curdoc.link].lname)) { rlink_allowed = (BOOL) !strncmp(traversal_host, links[curdoc.link].lname, strlen(traversal_host)); } else { rlink_allowed = (BOOL) !strncmp(traversal_host, links[curdoc.link].lname + LEN_LYNXIMGMAP, strlen(traversal_host)); } } else { rlink_allowed = FALSE; } } else { rlink_allowed = FALSE; } if (rlink_exists && rlink_allowed) { if (lookup(links[curdoc.link].lname)) { if (more_links || (curdoc.link > -1 && curdoc.link < nlinks -1)) c= DNARROW; else { if (STREQ(curdoc.title,"Entry into main screen") || (nhist <= 0 )) { if (!dump_output_immediately) { cleanup(); exit_immediately(EXIT_FAILURE); } return(-1); } c = LTARROW; } } else { StrAllocCopy(traversal_link_to_add, links[curdoc.link].lname); if (!isLYNXIMGMAP(traversal_link_to_add)) *crawl_ok = TRUE; c = RTARROW; } } else { /* no good right link, so only down and left arrow ok*/ if (rlink_exists /* && !rlink_rejected */) /* uncomment in previous line to avoid duplicates - kw */ add_to_reject_list(links[curdoc.link].lname); if (more_links || (curdoc.link > -1 && curdoc.link < nlinks-1)) c = DNARROW; else { /* * curdoc.title doesn't always work, so * bail out if the history list is empty. */ if (STREQ(curdoc.title,"Entry into main screen") || (nhist <= 0 )) { if (!dump_output_immediately) { cleanup(); exit_immediately(EXIT_FAILURE); } return(-1); } c = LTARROW; } } /* right link not NULL or link to another site*/ return c; } #ifndef DONT_TRACK_INTERNAL_LINKS PRIVATE BOOLEAN check_history NOARGS { CONST char *base; if (!curdoc.post_data) /* * Normal case - List Page is not associated * with post data. - kw */ return TRUE; if (nhist > 0 && !LYresubmit_posts && HDOC(nhist - 1).post_data && BINEQ(curdoc.post_data, HDOC(nhist - 1).post_data) && (base = HText_getContentBase()) != 0) { char *text = !isLYNXIMGMAP(HDOC(nhist - 1).address) ? HDOC(nhist - 1).address : HDOC(nhist - 1).address + LEN_LYNXIMGMAP; if (!strncmp(base, text, strlen(base))) { /* * Normal case - as best as we can check, the document at the top * of the history stack seems to be the document the List Page is * about (or a LYNXIMGMAP derived from it), and LYresubmit_posts is * not set, so don't prompt here. If we actually have to repeat a * POST because, against expectations, the underlying document * isn't cached any more, HTAccess will prompt for confirmation, * unless we had LYK_NOCACHE -kw */ return TRUE; } } return FALSE; } #endif PRIVATE int handle_LYK_ACTIVATE ARGS6( int *, c, int, cmd GCC_UNUSED, BOOLEAN *, try_internal GCC_UNUSED, BOOLEAN *, refresh_screen, BOOLEAN *, force_load, int, real_cmd) { if (do_change_link() == -1) { LYforce_no_cache = FALSE; reloading = FALSE; return 1; /* mouse stuff was confused, ignore - kw */ } if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) { #ifdef TEXTFIELDS_MAY_NEED_ACTIVATION if (real_cmd == LYK_ACTIVATE && textfields_need_activation && F_TEXTLIKE(links[curdoc.link].l_form->type)) { textinput_activated = TRUE; show_main_statusline(links[curdoc.link], FOR_INPUT); textfields_need_activation = textfields_activation_option; return 0; } #endif /* * Don't try to submit forms with bad actions. - FM */ if (links[curdoc.link].l_form->type == F_SUBMIT_TYPE || links[curdoc.link].l_form->type == F_IMAGE_SUBMIT_TYPE || links[curdoc.link].l_form->type == F_TEXT_SUBMIT_TYPE) { /* * Do nothing if it's disabled. - FM */ if (links[curdoc.link].l_form->disabled == YES) { HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; reloading = FALSE; return 0; } /* * Make sure we have an action. - FM */ if (!links[curdoc.link].l_form->submit_action || *links[curdoc.link].l_form->submit_action == '\0') { HTUserMsg(NO_FORM_ACTION); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; reloading = FALSE; return 0; } /* * Check for no_mail if the form action * is a mailto URL. - FM */ if (links[curdoc.link].l_form->submit_method == URL_MAIL_METHOD && no_mail) { HTAlert(FORM_MAILTO_DISALLOWED); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; reloading = FALSE; return 0; } /* * Make sure this isn't a spoof in an account * with restrictions on file URLs. - FM */ if (no_file_url && isFILE_URL(links[curdoc.link].l_form->submit_action)) { HTAlert(FILE_ACTIONS_DISALLOWED); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; reloading = FALSE; return 0; } /* * Make sure this isn't a spoof attempt * via an internal URL. - FM */ if (isLYNXCOOKIE(links[curdoc.link].l_form->submit_action) || #ifdef DIRED_SUPPORT #ifdef OK_PERMIT (isLYNXDIRED(links[curdoc.link].l_form->submit_action) && (no_dired_support || strncasecomp( (links[curdoc.link].l_form->submit_action + 10), "//PERMIT_LOCATION", 17) || !LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS))) || #else isLYNXDIRED(links[curdoc.link].l_form->submit_action) || #endif /* OK_PERMIT */ #endif /* DIRED_SUPPORT */ isLYNXDOWNLOAD(links[curdoc.link].l_form->submit_action) || isLYNXHIST(links[curdoc.link].l_form->submit_action) || isLYNXKEYMAP(links[curdoc.link].l_form->submit_action) || isLYNXIMGMAP(links[curdoc.link].l_form->submit_action) || isLYNXPRINT(links[curdoc.link].l_form->submit_action) || isLYNXEXEC(links[curdoc.link].l_form->submit_action) || isLYNXPROG(links[curdoc.link].l_form->submit_action)) { HTAlert(SPECIAL_ACTION_DISALLOWED); CTRACE((tfp, "LYMainLoop: Rejected '%s'\n", links[curdoc.link].l_form->submit_action)); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; reloading = FALSE; return 0; } #ifdef NOTDEFINED /* We're disabling form inputs instead of using this. - FM */ /* * Check for enctype and let user know we * don't yet support multipart/form-data - FM */ if (links[curdoc.link].l_form->submit_enctype) { if (!strcmp( links[curdoc.link].l_form->submit_enctype, "multipart/form-data")) { HTAlert( gettext("Enctype multipart/form-data not yet supported! Cannot submit.")); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; reloading = FALSE; return 0; } } #endif /* NOTDEFINED */ if (check_realm) { LYPermitURL = TRUE; } if (no_filereferer == TRUE && isFILE_URL(curdoc.address)) { LYNoRefererForThis = TRUE; } if (links[curdoc.link].l_form->submit_method != URL_MAIL_METHOD) { StrAllocCopy(newdoc.title, LYGetHiliteStr(curdoc.link, 0)); } } /* * Normally we don't get here for text input fields, * but it can happen as a result of mouse positioning. * In that case the statusline will not have updated * info, so update it now. - kw */ if (F_TEXTLIKE(links[curdoc.link].l_form->type)) { show_formlink_statusline(links[curdoc.link].l_form, (real_cmd == LYK_NOCACHE || real_cmd == LYK_DOWNLOAD || real_cmd == LYK_HEAD || (real_cmd == LYK_SUBMIT && !textinput_activated)) ? FOR_PANEL : FOR_INPUT); if (user_mode == NOVICE_MODE && textinput_activated && (real_cmd == LYK_ACTIVATE || real_cmd == LYK_SUBMIT)) { form_noviceline(links[curdoc.link].l_form->disabled); } } *c = change_form_link(curdoc.link, &newdoc, refresh_screen, FALSE, (BOOLEAN)(real_cmd == LYK_SUBMIT || real_cmd == LYK_NOCACHE || real_cmd == LYK_DOWNLOAD || real_cmd == LYK_HEAD)); if (*c != LKC_DONE || *refresh_screen) { /* * Cannot have been a submit field for which * newdoc was filled in. - kw */ if ((links[curdoc.link].l_form->type == F_SUBMIT_TYPE || links[curdoc.link].l_form->type == F_IMAGE_SUBMIT_TYPE || links[curdoc.link].l_form->type == F_TEXT_SUBMIT_TYPE) && links[curdoc.link].l_form->submit_method != URL_MAIL_METHOD) { /* * Try to undo change of newdoc.title done above. */ if (HText_getTitle()) { StrAllocCopy(newdoc.title, HText_getTitle()); } else if (curdoc.title) { StrAllocCopy(newdoc.title, curdoc.title); } } } else { if (HTOutputFormat == HTAtom_for("www/download") && newdoc.post_data != NULL && newdoc.safe == FALSE) { if ((HText_POSTReplyLoaded(&newdoc) == TRUE) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { HTInfoMsg(CANCELLED); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; copy_address(&newdoc, &curdoc); StrAllocCopy(newdoc.title, curdoc.title); BStrCopy(newdoc.post_data, curdoc.post_data); StrAllocCopy(newdoc.post_content_type, curdoc.post_content_type); StrAllocCopy(newdoc.bookmark, curdoc.bookmark); newdoc.isHEAD = curdoc.isHEAD; newdoc.safe = curdoc.safe; newdoc.internal_link = curdoc.internal_link; return 0; } } /* * Moved here from earlier to only apply when it * should. Anyway, why should realm checking be * overridden for form submissions, this seems to * be an unnecessary loophole?? But that's the way * it was, maybe there is some reason. * However, at least make sure this doesn't weaken * restrictions implied by -validate! * - kw 1999-05-25 */ if (check_realm && !LYValidate) { LYPermitURL = TRUE; } } if (*c == LKC_DONE) { *c = DO_NOTHING; } else if (*c == 23) { *c = DO_NOTHING; *refresh_screen = TRUE; } else { /* Avoid getting stuck with repeatedly calling ** handle_LYK_ACTIVATE(), instead of calling ** change_form_link() directly from mainloop(), ** for text input fields. - kw */ switch (LKC_TO_C(*c)) { case '\n': case '\r': default: if ((real_cmd == LYK_ACTIVATE || real_cmd == LYK_SUBMIT) && F_TEXTLIKE(links[curdoc.link].l_form->type) && textinput_activated) return 3; break; } } return 2; } else { /* * Not a forms link. * * Make sure this isn't a spoof in an account * with restrictions on file URLs. - FM */ if (no_file_url && isFILE_URL(links[curdoc.link].lname)) { if (!isFILE_URL(curdoc.address) && !((isLYNXKEYMAP(curdoc.address) || isLYNXCOOKIE(curdoc.address)) && !strncmp(links[curdoc.link].lname, helpfilepath, strlen(helpfilepath)))) { HTAlert(FILE_SERVED_LINKS_DISALLOWED); reloading = FALSE; return 0; } else if (curdoc.bookmark != NULL) { HTAlert(FILE_BOOKMARKS_DISALLOWED); reloading = FALSE; return 0; } } /* * Make sure this isn't a spoof attempt * via an internal URL in a non-internal * document. - FM */ if ((isLYNXCOOKIE(links[curdoc.link].lname) && (strcmp(NonNull(curdoc.title), COOKIE_JAR_TITLE) || !isLYNXCOOKIE(curdoc.address))) || #ifdef DIRED_SUPPORT (isLYNXDIRED(links[curdoc.link].lname) && !LYIsUIPage(curdoc.address, UIP_DIRED_MENU) && !LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS) && #ifdef OK_INSTALL !LYIsUIPage(curdoc.address, UIP_INSTALL) && #endif /* OK_INSTALL */ !LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS)) || #endif /* DIRED_SUPPORT */ (isLYNXDOWNLOAD(links[curdoc.link].lname) && !LYIsUIPage(curdoc.address, UIP_DOWNLOAD_OPTIONS)) || (isLYNXHIST(links[curdoc.link].lname) && !LYIsUIPage(curdoc.address, UIP_HISTORY) && !LYIsUIPage(curdoc.address, UIP_LIST_PAGE) && !LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE)) || (isLYNXPRINT(links[curdoc.link].lname) && !LYIsUIPage(curdoc.address, UIP_PRINT_OPTIONS))) { HTAlert(SPECIAL_VIA_EXTERNAL_DISALLOWED); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; reloading = FALSE; return 0; } #ifdef USE_EXTERNALS if (run_external(links[curdoc.link].lname, TRUE)) { *refresh_screen = TRUE; return 0; } #endif /* USE_EXTERNALS */ /* * Follow a normal link or anchor. */ set_address(&newdoc, links[curdoc.link].lname); StrAllocCopy(newdoc.title, LYGetHiliteStr(curdoc.link, 0)); #ifndef DONT_TRACK_INTERNAL_LINKS /* * For internal links, retain POST content if present. * If we are on the List Page, prevent pushing it on * the history stack. Otherwise set try_internal to * signal that the top of the loop should attempt to * reposition directly, without calling getfile. - kw */ /* * Might be an internal link anchor in the same doc. * If so, take the try_internal shortcut if we didn't * fall through from LYK_NOCACHE. - kw */ newdoc.internal_link = (links[curdoc.link].type == WWW_INTERN_LINK_TYPE); if (newdoc.internal_link) { /* * Special case of List Page document with an * internal link indication, which may really stand * for an internal link within the document the * List Page is about. - kw */ if (LYIsListpageTitle(NonNull(curdoc.title)) && (LYIsUIPage(curdoc.address, UIP_LIST_PAGE) || LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE))) { if (check_history()) { LYinternal_flag = TRUE; } else { HTLastConfirmCancelled(); /* reset flag */ if (!confirm_post_resub(newdoc.address, newdoc.title, (LYresubmit_posts && HText_POSTReplyLoaded(&newdoc)) ? 1 : 2, 2)) { if (HTLastConfirmCancelled() || (LYresubmit_posts && cmd != LYK_NOCACHE && !HText_POSTReplyLoaded(&newdoc))) { /* cancel the whole thing */ LYforce_no_cache = FALSE; reloading = FALSE; copy_address(&newdoc, &curdoc); StrAllocCopy(newdoc.title, curdoc.title); newdoc.internal_link = curdoc.internal_link; HTInfoMsg(CANCELLED); return 1; } else if (LYresubmit_posts && cmd != LYK_NOCACHE) { /* If LYresubmit_posts is set, and the answer was No, and the key wasn't NOCACHE, and we have a cached copy, then use it. - kw */ LYforce_no_cache = FALSE; } else { /* if No, but not ^C or ^G, drop * the post data. Maybe the link * wasn't meant to be internal after * all, here we can recover from that * assumption. - kw */ LYFreePostData(&newdoc); newdoc.internal_link = FALSE; HTAlert(DISCARDING_POST_DATA); } } } /* * Don't push the List Page if we follow an * internal link given by it. - kw */ free_address(&curdoc); } else if (cmd != LYK_NOCACHE) { *try_internal = TRUE; } if (!(LYresubmit_posts && newdoc.post_data)) LYinternal_flag = TRUE; /* We still set force_load so that history pushing ** etc. will be done. - kw */ *force_load = TRUE; return 1; } else { /* * Free POST content if not an internal link. - kw */ LYFreePostData(&newdoc); } #endif /* TRACK_INTERNAL_LINKS */ /* * Might be an anchor in the same doc from a POST * form. If so, don't free the content. -- FM */ if (are_different(&curdoc, &newdoc)) { LYFreePostData(&newdoc); FREE(newdoc.bookmark); if (isLYNXMESSAGES(newdoc.address)) LYforce_no_cache = TRUE; } if (!no_jump && lynxjumpfile && curdoc.address && !strcmp(lynxjumpfile, curdoc.address)) { LYJumpFileURL = TRUE; LYUserSpecifiedURL = TRUE; } else if ((curdoc.title && (LYIsUIPage(curdoc.address, UIP_HISTORY) || !strcmp(curdoc.title, HISTORY_PAGE_TITLE))) || curdoc.bookmark != NULL || (lynxjumpfile && !strcmp(lynxjumpfile, curdoc.address))) { LYUserSpecifiedURL = TRUE; } else if (no_filereferer == TRUE && isFILE_URL(curdoc.address)) { LYNoRefererForThis = TRUE; } newdoc.link = 0; *force_load = TRUE; /* force MainLoop to reload */ #ifdef USE_PRETTYSRC psrc_view = FALSE; /* we get here if link is not internal */ #endif #if defined(DIRED_SUPPORT) && !defined(__DJGPP__) if (lynx_edit_mode) { DIRED_UNCACHE_2; /* * Unescaping any slash chars in the URL, * but avoid double unescaping and too-early * unescaping of other chars. - KW */ HTUnEscapeSome(newdoc.address,"/"); /* avoid stripping final slash for root dir - kw */ if (strcasecomp(newdoc.address, "file://localhost/")) strip_trailing_slash(newdoc.address); } #endif /* DIRED_SUPPORT && !__DJGPP__ */ if (isLYNXCOOKIE(curdoc.address)) { HTuncache_current_document(); } } } return 0; } #ifdef EXP_ADDRLIST_PAGE PRIVATE BOOLEAN handle_LYK_ADDRLIST ARGS1( int *, cmd) { /* * Don't do if already viewing list addresses page. */ if (LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE)) { /* * Already viewing list page, so get out. */ *cmd = LYK_PREV_DOC; return TRUE; } /* * Print address list page to file. */ if (showlist(&newdoc, FALSE) < 0) return FALSE; StrAllocCopy(newdoc.title, ADDRLIST_PAGE_TITLE); /* * showlist will set newdoc's other fields. It may leave * post_data intact so the list can be used to follow * internal links in the current document even if it is * a POST response. - kw */ if (LYValidate || check_realm) { LYPermitURL = TRUE; StrAllocCopy(lynxlistfile, newdoc.address); } return FALSE; } #endif /* EXP_ADDRLIST_PAGE */ PRIVATE void handle_LYK_ADD_BOOKMARK ARGS3( BOOLEAN *, refresh_screen, int *, old_c, int, real_c) { int c; if (LYValidate) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(BOOKMARKS_DISABLED); } return; } if (!LYIsUIPage(curdoc.address, UIP_HISTORY) && !LYIsUIPage(curdoc.address, UIP_SHOWINFO) && !LYIsUIPage(curdoc.address, UIP_PRINT_OPTIONS) && #ifdef DIRED_SUPPORT !LYIsUIPage(curdoc.address, UIP_DIRED_MENU) && !LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS) && !LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS) && #endif /* DIRED_SUPPORT */ !LYIsUIPage(curdoc.address, UIP_DOWNLOAD_OPTIONS) && !isLYNXCOOKIE(curdoc.address) && !LYIsUIPage(curdoc.address, UIP_OPTIONS_MENU) && ((nlinks <= 0) || (links[curdoc.link].lname != NULL && !isLYNXHIST(links[curdoc.link].lname) && !isLYNXPRINT(links[curdoc.link].lname) && !isLYNXDIRED(links[curdoc.link].lname) && !isLYNXDOWNLOAD(links[curdoc.link].lname) && !isLYNXCOOKIE(links[curdoc.link].lname) && !isLYNXPRINT(links[curdoc.link].lname)))) { if (nlinks > 0) { if (curdoc.post_data == NULL && curdoc.bookmark == NULL && !LYIsUIPage(curdoc.address, UIP_LIST_PAGE) && !LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE) && !LYIsUIPage(curdoc.address, UIP_VLINKS)) { /* * The document doesn't have POST content, * and is not a bookmark file, nor is the * list or visited links page, so we can * save either that or the link. - FM */ _statusline(BOOK_D_L_OR_CANCEL); if ((c = LYgetch_single()) == 'D') { save_bookmark_link(curdoc.address, curdoc.title); *refresh_screen = TRUE; /* MultiBookmark support */ goto check_add_bookmark_to_self; } } else { if (LYMultiBookmarks == MBM_OFF && curdoc.bookmark != NULL && strstr(curdoc.address, (*bookmark_page == '.' ? (bookmark_page+1) : bookmark_page)) != NULL) { /* * If multiple bookmarks are disabled, offer * the L)ink or C)ancel, but with wording * which indicates that the link already * exists in this bookmark file. - FM */ _statusline(MULTIBOOKMARKS_SELF); } else if (curdoc.post_data != NULL && links[curdoc.link].type == WWW_INTERN_LINK_TYPE) { /* * Internal link, and document has POST content. */ HTUserMsg(NOBOOK_POST_FORM); return; } else { /* * Only offer the link in a document with * POST content, or if the current document * is a bookmark file and multiple bookmarks * are enabled. - FM */ _statusline(BOOK_L_OR_CANCEL); } c = LYgetch_single(); } if (c == 'L') { if (curdoc.post_data != NULL && links[curdoc.link].type == WWW_INTERN_LINK_TYPE) { /* * Internal link, and document has POST content. */ HTUserMsg(NOBOOK_POST_FORM); return; } /* * User does want to save the link. - FM */ if (links[curdoc.link].type != WWW_FORM_LINK_TYPE) { save_bookmark_link(links[curdoc.link].lname, LYGetHiliteStr(curdoc.link, 0)); *refresh_screen = TRUE; /* MultiBookmark support */ } else { HTUserMsg(NOBOOK_FORM_FIELD); return; } } else { return; } } else if (curdoc.post_data != NULL) { /* * No links, and document has POST content. - FM */ HTUserMsg(NOBOOK_POST_FORM); return; } else if (curdoc.bookmark != NULL) { /* * It's a bookmark file from which all * of the links were deleted. - FM */ HTUserMsg(BOOKMARKS_NOLINKS); return; } else { _statusline(BOOK_D_OR_CANCEL); if (LYgetch_single() == 'D') { save_bookmark_link(curdoc.address, curdoc.title); *refresh_screen = TRUE; /* MultiBookmark support */ } else { return; } } check_add_bookmark_to_self: if (curdoc.bookmark && BookmarkPage && !strcmp(curdoc.bookmark, BookmarkPage)) { HTuncache_current_document(); move_address(&newdoc, &curdoc); StrAllocCopy(newdoc.bookmark, curdoc.bookmark); newdoc.line = curdoc.line; newdoc.link = curdoc.link; newdoc.internal_link = FALSE; } } else { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NOBOOK_HSML); } } } PRIVATE void handle_LYK_CLEAR_AUTH ARGS2( int *, old_c, int, real_c) { if (*old_c != real_c) { *old_c = real_c; if (HTConfirm(CLEAR_ALL_AUTH_INFO)) { FREE(authentication_info[0]); FREE(authentication_info[1]); FREE(proxyauth_info[0]); FREE(proxyauth_info[1]); HTClearHTTPAuthInfo(); #ifndef DISABLE_NEWS HTClearNNTPAuthInfo(); #endif #ifndef DISABLE_FTP HTClearFTPPassword(); #endif HTUserMsg(AUTH_INFO_CLEARED); } else { HTUserMsg(CANCELLED); } } } PRIVATE int handle_LYK_COMMAND ARGS1( char *, user_input_buffer) { int ch; Kcmd *mp; char *src, *tmp; *user_input_buffer = 0; _statusline(": "); if (LYgetstr(user_input_buffer, VISIBLE, MAX_LINE, RECALL_CMD) >= 0) { src = LYSkipBlanks(user_input_buffer); tmp = LYSkipNonBlanks(src); *tmp = 0; ch = ((mp = LYStringToKcmd(src)) != 0) ? mp->code : 0; CTRACE((tfp, "LYK_COMMAND(%s.%s) = %d\n", src, tmp, ch)); if (ch == 0) { return *src ? -1 : 0; } /* FIXME: reuse the rest of the buffer for parameters */ return ch; } return 0; } PRIVATE void handle_LYK_COMMENT ARGS4( BOOLEAN *, refresh_screen, char **, owner_address_p, int *, old_c, int, real_c) { int c; if (!*owner_address_p && strncasecomp(curdoc.address, "http", 4)) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_OWNER); } } else if (no_mail) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(MAIL_DISALLOWED); } } else { if (HTConfirmDefault(CONFIRM_COMMENT, NO)) { if (!*owner_address_p) { /* * No owner defined, so make a guess and * and offer it to the user. - FM */ char *address = NULL; char *temp = HTParse(curdoc.address, "", PARSE_PATH); char *cp; if (temp != NULL) { HTUnEscape(temp); if (*temp == '~' && strlen(temp) > 1) { /* * It's a ~user URL so guess user@host. - FM */ if ((cp = strchr((temp+1), '/')) != NULL) *cp = '\0'; StrAllocCopy(address, STR_MAILTO_URL); StrAllocCat(address, (temp+1)); StrAllocCat(address, "@"); } FREE(temp); } if (address == NULL) /* * Wasn't a ~user URL so guess WebMaster@host. - FM */ StrAllocCopy(address, "mailto:WebMaster@"); temp = HTParse(curdoc.address, "", PARSE_HOST); StrAllocCat(address, temp); HTSprintf0(&temp, NO_OWNER_USE, address); c = HTConfirmDefault(temp, NO); FREE(temp); if (c == YES) { StrAllocCopy(*owner_address_p, address); FREE(address); } else { FREE(address); return; } } if (is_url(*owner_address_p) != MAILTO_URL_TYPE) { /* * The address is a URL. Just follow the link. */ set_address(&newdoc, *owner_address_p); newdoc.internal_link = FALSE; } else { /* * The owner_address is a mailto: URL. */ CONST char *kp = HText_getRevTitle(); CONST char *id = HText_getMessageID(); char *tmptitle = NULL; if (!kp && HTMainAnchor) { kp = HTAnchor_subject(HTMainAnchor); if (kp && *kp) { if (strncasecomp(kp, "Re: ", 4)) { StrAllocCopy(tmptitle, "Re: "); StrAllocCat(tmptitle, kp); kp = tmptitle; } } } if (strchr(*owner_address_p, ':') != NULL) /* * Send a reply. The address is after the colon. */ reply_by_mail(strchr(*owner_address_p, ':') + 1, curdoc.address, NonNull(kp), id); else reply_by_mail(*owner_address_p, curdoc.address, NonNull(kp), id); FREE(tmptitle); *refresh_screen = TRUE; /* to force a showpage */ } } } } PRIVATE BOOLEAN handle_LYK_COOKIE_JAR ARGS1( int *, cmd) { /* * Don't do if already viewing the cookie jar. */ if (!isLYNXCOOKIE(curdoc.address)) { set_address(&newdoc, "LYNXCOOKIE:/"); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; LYforce_no_cache = TRUE; if (LYValidate || check_realm) { LYPermitURL = TRUE; } } else { /* * If already in the cookie jar, get out. */ *cmd = LYK_PREV_DOC; return TRUE; } return FALSE; } #if defined(DIRED_SUPPORT) PRIVATE void handle_LYK_CREATE NOARGS { if (lynx_edit_mode && !no_dired_support) { if (local_create(&curdoc) > 0) { DIRED_UNCACHE_1; move_address(&newdoc, &curdoc); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.line = curdoc.line; newdoc.link = curdoc.link > -1 ? curdoc.link : 0; LYclear(); } } } #endif /* DIRED_SUPPORT */ PRIVATE void handle_LYK_DEL_BOOKMARK ARGS3( BOOLEAN *, refresh_screen, int *, old_c, int, real_c) { if (curdoc.bookmark != NULL) { if (HTConfirmDefault(CONFIRM_BOOKMARK_DELETE,NO) != YES) return; remove_bookmark_link(links[curdoc.link].anchor_number-1, curdoc.bookmark); } else { /* behave like REFRESH for backward compatibility */ *refresh_screen = TRUE; if (*old_c != real_c) { *old_c = real_c; lynx_force_repaint(); } return; } do_cleanup_after_delete(); } #if defined(DIRED_SUPPORT) || defined(VMS) PRIVATE void handle_LYK_DIRED_MENU ARGS3( BOOLEAN *, refresh_screen, int *, old_c GCC_UNUSED, int, real_c GCC_UNUSED) { #ifdef VMS char *cp, *temp = 0; const char *test = HTGetProgramPath(ppCSWING); /* * Check if the CSwing Directory/File Manager is available. * Will be disabled if CSWING path is NULL, zero-length, * or "none" (case insensitive), if no_file_url was set via * the file_url restriction, if no_goto_file was set for * the anonymous account, or if HTDirAccess was set to * HT_DIR_FORBID or HT_DIR_SELECTIVE via the -nobrowse * or -selective switches. - FM */ if (isEmpty(test) || !strcasecomp(test, "none") || no_file_url || no_goto_file || HTDirAccess == HT_DIR_FORBID || HTDirAccess == HT_DIR_SELECTIVE) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(DFM_NOT_AVAILABLE); } return; } /* * If we are viewing a local directory listing or a * local file which is not temporary, invoke CSwing * with the URL's directory converted to VMS path specs * and passed as the argument, so we start up CSwing * positioned on that node of the directory tree. * Otherwise, pass the current default directory as * the argument. - FM */ if (LYisLocalFile(curdoc.address) && strncasecomp(curdoc.address, lynx_temp_space, strlen(lynx_temp_space))) { /* * We are viewing a local directory or a local file * which is not temporary. - FM */ struct stat stat_info; cp = HTParse(curdoc.address, "", PARSE_PATH|PARSE_PUNCTUATION); HTUnEscape(cp); if (HTStat(cp, &stat_info) == -1) { CTRACE((tfp, "mainloop: Can't stat %s\n", cp)); FREE(cp); HTSprintf0(&temp, "%s []", HTGetProgramPath(ppCSWING)); *refresh_screen = TRUE; /* redisplay */ } else { char *VMSdir = NULL; if (S_ISDIR(stat_info.st_mode)) { /* * We're viewing a local directory. Make * that the CSwing argument. - FM */ LYAddPathSep(&cp); StrAllocCopy(VMSdir, HTVMS_name("", cp)); FREE(cp); } else { /* * We're viewing a local file. Make its * directory the CSwing argument. - FM */ StrAllocCopy(VMSdir, HTVMS_name("", cp)); FREE(cp); if ((cp = strrchr(VMSdir, ']')) != NULL) { *(cp + 1) = '\0'; cp == NULL; } else if ((cp = strrchr(VMSdir, ':')) != NULL) { *(cp + 1) = '\0'; cp == NULL; } } HTSprintf0(&temp, "%s %s", HTGetProgramPath(ppCSWING), VMSdir); FREE(VMSdir); /* * Uncache the current document in case we * change, move, or delete it during the * CSwing session. - FM */ /* could use DIRED_UNCACHE_1 but it's currently only defined for dired - kw */ HTuncache_current_document(); move_address(&newdoc, &curdoc); StrAllocCopy(newdoc.title, NonNull(curdoc.title)); StrAllocCopy(newdoc.bookmark, curdoc.bookmark); newdoc.line = curdoc.line; newdoc.link = curdoc.link; } } else { /* * We're not viewing a local directory or file. * Pass CSwing the current default directory as * an argument and don't uncache the current * document. - FM */ HTSprintf0(&temp, "%s []", HTGetProgramPath(ppCSWING)); *refresh_screen = TRUE; /* redisplay */ } stop_curses(); LYSystem(temp); start_curses(); FREE(temp); #else /* * Don't do if not allowed or already viewing the menu. */ if (lynx_edit_mode && !no_dired_support && !LYIsUIPage(curdoc.address, UIP_DIRED_MENU) && strcmp(NonNull(curdoc.title), DIRED_MENU_TITLE)) { dired_options(&curdoc,&newdoc.address); *refresh_screen = TRUE; /* redisplay */ } #endif /* VMS */ } #endif /* defined(DIRED_SUPPORT) || defined(VMS) */ PRIVATE int handle_LYK_DOWNLOAD ARGS3( int *, cmd, int *, old_c, int, real_c) { /* * Don't do if both download and disk_save are restricted. */ if (LYValidate || (no_download && !override_no_download && no_disk_save)) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(DOWNLOAD_DISABLED); } return 0; } /* * Don't do if already viewing download options page. */ if (LYIsUIPage(curdoc.address, UIP_DOWNLOAD_OPTIONS)) return 0; if (do_change_link() == -1) return 1; /* mouse stuff was confused, ignore - kw */ if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) { if (links[curdoc.link].l_form->type == F_SUBMIT_TYPE || links[curdoc.link].l_form->type == F_IMAGE_SUBMIT_TYPE || links[curdoc.link].l_form->type == F_TEXT_SUBMIT_TYPE) { if (links[curdoc.link].l_form->submit_method == URL_MAIL_METHOD) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_DOWNLOAD_MAILTO_ACTION); } return 0; } if (isLYNXOPTIONS(links[curdoc.link].l_form->submit_action)) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_DOWNLOAD_SPECIAL); } return 0; } HTOutputFormat = HTAtom_for("www/download"); LYforce_no_cache = TRUE; *cmd = LYK_ACTIVATE; return 2; } if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_DOWNLOAD_INPUT); } } else if (isLYNXCOOKIE(curdoc.address)) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_DOWNLOAD_COOKIES); } } else if (LYIsUIPage(curdoc.address, UIP_PRINT_OPTIONS)) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_DOWNLOAD_PRINT_OP); } #ifdef DIRED_SUPPORT } else if (LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS)) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_DOWNLOAD_UPLOAD_OP); } } else if (LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS)) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_DOWNLOAD_PERMIT_OP); } } else if (lynx_edit_mode && !no_dired_support && !strstr(links[curdoc.link].lname, "/SugFile=")) { /* * Don't bother making a /tmp copy of the local file. */ static DocInfo temp; copy_address(&temp, &newdoc); set_address(&newdoc, links[curdoc.link].lname); if (LYdownload_options(&newdoc.address, links[curdoc.link].lname) < 0) copy_address(&newdoc, &temp); else newdoc.internal_link = FALSE; LYFreeDocInfo(&temp); #endif /* DIRED_SUPPORT */ } else if (LYIsUIPage(curdoc.address, UIP_HISTORY) && isLYNXHIST(links[curdoc.link].lname)) { int number = atoi(links[curdoc.link].lname + LEN_LYNXHIST); if (number >= nhist || number < 0) { HTUserMsg(NO_DOWNLOAD_SPECIAL); return 0; } if ((HDOC(number).post_data != NULL && HDOC(number).safe != TRUE) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { HTInfoMsg(CANCELLED); return 0; } /* * OK, we download from history page, restore URL from stack. */ copy_address(&newdoc, &HDOC(number)); StrAllocCopy(newdoc.title, LYGetHiliteStr(curdoc.link, 0)); StrAllocCopy(newdoc.bookmark, HDOC(number).bookmark); LYFreePostData(&newdoc); if (HDOC(number).post_data) BStrCopy(newdoc.post_data, HDOC(number).post_data); if (HDOC(number).post_content_type) StrAllocCopy(newdoc.post_content_type, HDOC(number).post_content_type); newdoc.isHEAD = HDOC(number).isHEAD; newdoc.safe = HDOC(number).safe; newdoc.internal_link = FALSE; newdoc.link = 0; HTOutputFormat = HTAtom_for("www/download"); LYUserSpecifiedURL = TRUE; /* * Force the document to be reloaded. */ LYforce_no_cache = TRUE; } else if (!strncmp(links[curdoc.link].lname, "data:", 5)) { if (*old_c != real_c) { *old_c = real_c; HTAlert(UNSUPPORTED_DATA_URL); } } else if (isLYNXCOOKIE(links[curdoc.link].lname) || isLYNXDIRED(links[curdoc.link].lname) || isLYNXDOWNLOAD(links[curdoc.link].lname) || isLYNXPRINT(links[curdoc.link].lname) || isLYNXOPTIONS(links[curdoc.link].lname) || isLYNXHIST(links[curdoc.link].lname) || /* handled above if valid - kw */ /* @@@ should next two be downloadable? - kw */ isLYNXHIST(links[curdoc.link].lname) || isLYNXCFLAGS(links[curdoc.link].lname) || isLYNXEXEC(links[curdoc.link].lname) || isLYNXPROG(links[curdoc.link].lname)) { HTUserMsg(NO_DOWNLOAD_SPECIAL); } else if (isMAILTO_URL(links[curdoc.link].lname)) { HTUserMsg(NO_DOWNLOAD_MAILTO_LINK); /* * From here on we could have a remote host, so check if * that's allowed. * * We copy all these checks from getfile() to LYK_DOWNLOAD * here because LYNXDOWNLOAD:// will NOT be pushing the * previous document into the history stack so preserve * getfile() from returning a wrong status (NULLFILE). */ } else if (local_host_only && !(LYisLocalHost(links[curdoc.link].lname) || LYisLocalAlias(links[curdoc.link].lname))) { HTUserMsg(ACCESS_ONLY_LOCALHOST); } else { /* Not a forms, options or history link */ /* * Follow a normal link or anchor. Note that * if it's an anchor within the same document, * entire document will be downloaded. */ set_address(&newdoc, links[curdoc.link].lname); StrAllocCopy(newdoc.title, LYGetHiliteStr(curdoc.link, 0)); #ifndef DONT_TRACK_INTERNAL_LINKS /* * Might be an internal link in the same doc from a * POST form. If so, don't free the content. - kw */ if (links[curdoc.link].type != WWW_INTERN_LINK_TYPE) #else /* * Might be an anchor in the same doc from a POST * form. If so, don't free the content. -- FM */ if (are_different(&curdoc, &newdoc)) #endif /* TRACK_INTERNAL_LINKS */ { LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; } newdoc.internal_link = FALSE; newdoc.link = 0; HTOutputFormat = HTAtom_for("www/download"); /* * Force the document to be reloaded. */ LYforce_no_cache = TRUE; } } else if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_DOWNLOAD_CHOICE); } return 0; } PRIVATE void handle_LYK_DOWN_HALF ARGS2( int *, old_c, int, real_c) { int i; if (more) { Newline += (display_lines/2); if (nlinks > 0 && curdoc.link > -1 && links[curdoc.link].ly > display_lines/2) { newdoc.link = curdoc.link; for (i = 0; links[i].ly <= (display_lines/2); i++) --newdoc.link; } } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_END); } } PRIVATE void handle_LYK_DOWN_LINK ARGS3( int *, follow_col, int *, old_c, int, real_c) { if (curdoc.link < (nlinks-1)) { /* more links? */ int newlink; if (*follow_col == -1) { char *text = LYGetHiliteStr(curdoc.link, 0); *follow_col = links[curdoc.link].lx; if (text != NULL) *follow_col += strlen(text) / 2; } newlink = find_link_near_col(*follow_col, 1); if (newlink > -1) { set_curdoc_link(newlink); } else if (more) { /* next page */ Newline += (display_lines); } else if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_LINKS_BELOW); return; } } else if (more) { /* next page */ Newline += (display_lines); } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_END); } } PRIVATE void handle_LYK_DOWN_TWO ARGS2( int *, old_c, int, real_c) { int i; if (more) { Newline += 2; if (nlinks > 0 && curdoc.link > -1 && links[curdoc.link].ly > 2) { newdoc.link = curdoc.link; for (i = 0; links[i].ly <= 2; i++) --newdoc.link; } } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_END); } } PRIVATE int handle_LYK_DWIMEDIT ARGS3( int *, cmd, int *, old_c, int, real_c) { #ifdef TEXTAREA_AUTOEXTEDIT /* * If we're in a forms TEXTAREA, invoke the editor on *its* * contents, rather than attempting to edit the html source * document. KED */ if (nlinks > 0 && links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type == F_TEXTAREA_TYPE) { *cmd = LYK_EDIT_TEXTAREA; return 2; } /* * If we're in a forms TEXT type, tell user the request * is bogus (though in reality, without this trap, if the * document with the TEXT field is local, the editor *would* * be invoked on the source .html file; eg, the o(ptions) * form tempfile). * * [This is done to avoid possible user confusion, due to * auto invocation of the editor on the TEXTAREA's contents * via the above if() statement.] */ if (nlinks > 0 && links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type == F_TEXT_TYPE) { HTUserMsg (CANNOT_EDIT_FIELD); return 1; } if (no_editor) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(ANYEDIT_DISABLED); } return 1; } #endif /* TEXTAREA_AUTOEXTEDIT */ return 0; } PRIVATE int handle_LYK_ECGOTO ARGS5( int *, ch, char *, user_input_buffer, char **, old_user_input, int *, old_c, int, real_c) { if (no_goto && !LYValidate) { /* * Go to not allowed. - FM */ if (*old_c != real_c) { *old_c = real_c; HTUserMsg(GOTO_DISALLOWED); } return 0; } #ifdef DIRED_SUPPORT if (LYIsUIPage(curdoc.address, UIP_DIRED_MENU) || LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS) || LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS)) { /* * Disallow editing of File Management URLs. - FM */ if (*old_c != real_c) { *old_c = real_c; HTUserMsg(EDIT_FM_MENU_URLS_DISALLOWED); } return 0; } #endif /* DIRED_SUPPORT */ /* * Save the current user_input_buffer string, * and load the current document's address. */ StrAllocCopy(*old_user_input, user_input_buffer); LYstrncpy(user_input_buffer, curdoc.address, (MAX_LINE - 1)); /* * Warn the user if the current document has POST * data associated with it. - FM */ if (curdoc.post_data) HTAlert(CURRENT_DOC_HAS_POST_DATA); /* * Offer the current document's URL for editing. - FM */ _statusline(EDIT_CURDOC_URL); if (((*ch = LYgetstr(user_input_buffer, VISIBLE, MAX_LINE, RECALL_URL)) >= 0) && user_input_buffer[0] != '\0' && strcmp(user_input_buffer, curdoc.address)) { LYTrimAllStartfile(user_input_buffer); if (user_input_buffer[0] != '\0') { return 2; } } /* * User cancelled via ^G, a full deletion, * or not modifying the URL. - FM */ HTInfoMsg(CANCELLED); LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1); FREE(*old_user_input); return 0; } PRIVATE void handle_LYK_EDIT ARGS2( int *, old_c, int, real_c) { #ifdef DIRED_SUPPORT char *cp; char *tp = NULL; struct stat dir_info; #endif /* DIRED_SUPPORT */ if (no_editor) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(EDIT_DISABLED); } } else #ifdef DIRED_SUPPORT /* * Allow the user to edit the link rather * than curdoc in edit mode. */ if (lynx_edit_mode && editor && *editor != '\0' && !no_dired_support) { if (nlinks > 0) { cp = links[curdoc.link].lname; if (is_url(cp) == FILE_URL_TYPE) { cp = HTfullURL_toFile(cp); StrAllocCopy(tp, cp); FREE(cp); if (stat(tp, &dir_info) == -1) { HTAlert(NO_STATUS); } else { if (S_ISREG(dir_info.st_mode)) { StrAllocCopy(tp, links[curdoc.link].lname); HTUnEscapeSome(tp, "/"); if (edit_current_file(tp, curdoc.link, Newline)) { DIRED_UNCACHE_1; move_address(&newdoc, &curdoc); #ifdef NO_SEEK_OLD_POSITION /* * Go to top of file. */ newdoc.line = 1; newdoc.link = 0; #else /* * Seek old position, * which probably changed. */ newdoc.line = curdoc.line; newdoc.link = curdoc.link; #endif /* NO_SEEK_OLD_POSITION */ LYclear(); /* clear the screen */ } } } FREE(tp); } } } else #endif /* DIRED_SUPPORT */ if (editor && *editor != '\0') { if (edit_current_file(newdoc.address, curdoc.link, Newline)) { HTuncache_current_document(); LYforce_no_cache = TRUE; /*force reload of document */ free_address(&curdoc); /* so it doesn't get pushed */ #ifdef NO_SEEK_OLD_POSITION /* * Go to top of file. */ newdoc.line = 1; newdoc.link = 0; #else /* * Seek old position, which probably changed. */ newdoc.line = curdoc.line; newdoc.link = curdoc.link; #endif /* NO_SEEK_OLD_POSITION */ LYclear(); /* clear the screen */ } } else { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_EDITOR); } } } PRIVATE void handle_LYK_DWIMHELP ARGS1( CONST char **, cshelpfile) { /* * Currently a help file different from the main * 'helpfile' is shown only if current link is a * text input form field. - kw */ if (curdoc.link >= 0 && curdoc.link < nlinks && links[curdoc.link].type == WWW_FORM_LINK_TYPE && !links[curdoc.link].l_form->disabled && F_TEXTLIKE(links[curdoc.link].l_form->type)) { *cshelpfile = LYLineeditHelpURL(); } } PRIVATE void handle_LYK_EDIT_TEXTAREA ARGS3( BOOLEAN *, refresh_screen, int *, old_c, int, real_c) { int n; if (no_editor) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(ANYEDIT_DISABLED); } } else if (!editor || *editor == '\0') { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_EDITOR); } } /* * See if the current link is in a form TEXTAREA. */ else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type == F_TEXTAREA_TYPE) { /* stop screen */ stop_curses(); n = HText_ExtEditForm (&links[curdoc.link]); /* * TODO: Move cursor "n" lines from the current line to * position it on the 1st trailing blank line in * the now edited TEXTAREA. If the target line/ * anchor requires us to scroll up/down, position * the target in the approximate center of the * screen. */ /* curdoc.link += n;*/ /* works, except for page crossing, */ /* damnit; why is nothing ever easy */ /* start screen */ start_curses(); *refresh_screen = TRUE; } else { HTInfoMsg (NOT_IN_TEXTAREA_NOEDIT); } } PRIVATE int handle_LYK_ELGOTO ARGS5( int *, ch, char *, user_input_buffer, char **, old_user_input, int *, old_c, int, real_c) { if (no_goto && !LYValidate) { /* * Go to not allowed. - FM */ if (*old_c != real_c) { *old_c = real_c; HTUserMsg(GOTO_DISALLOWED); } return 0; } if (!(nlinks > 0 && curdoc.link > -1) || (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type != F_SUBMIT_TYPE && links[curdoc.link].l_form->type != F_IMAGE_SUBMIT_TYPE && links[curdoc.link].l_form->type != F_TEXT_SUBMIT_TYPE)) { /* * No links on page, or not a normal link * or form submit button. - FM */ if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NOT_ON_SUBMIT_OR_LINK); } return 0; } if ((links[curdoc.link].type == WWW_FORM_LINK_TYPE) && (!links[curdoc.link].l_form->submit_action || *links[curdoc.link].l_form->submit_action == '\0')) { /* * Form submit button with no ACTION defined. - FM */ if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_FORM_ACTION); } return 0; } #ifdef DIRED_SUPPORT if (isLYNXDIRED(links[curdoc.link].lname) || LYIsUIPage(curdoc.address, UIP_DIRED_MENU) || LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS) || LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS)) { /* * Disallow editing of File Management URLs. - FM */ if (*old_c != real_c) { *old_c = real_c; HTUserMsg(EDIT_FM_MENU_URLS_DISALLOWED); } return 0; } #endif /* DIRED_SUPPORT */ /* * Save the current user_input_buffer string, * and load the current link's address. - FM */ StrAllocCopy(*old_user_input, user_input_buffer); LYstrncpy(user_input_buffer, ((links[curdoc.link].type == WWW_FORM_LINK_TYPE) ? links[curdoc.link].l_form->submit_action : links[curdoc.link].lname), (MAX_LINE - 1)); /* * Offer the current link's URL for editing. - FM */ _statusline(EDIT_CURLINK_URL); if (((*ch = LYgetstr(user_input_buffer, VISIBLE, MAX_LINE, RECALL_URL)) >= 0) && user_input_buffer[0] != '\0' && strcmp(user_input_buffer, ((links[curdoc.link].type == WWW_FORM_LINK_TYPE) ? links[curdoc.link].l_form->submit_action : links[curdoc.link].lname))) { LYTrimAllStartfile(user_input_buffer); if (user_input_buffer[0] != '\0') { return 2; } } /* * User cancelled via ^G, a full deletion, * or not modifying the URL. - FM */ HTInfoMsg(CANCELLED); LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1); FREE(*old_user_input); return 0; } #ifdef USE_EXTERNALS PRIVATE void handle_LYK_EXTERN_LINK ARGS1( BOOLEAN *, refresh_screen) { if ((nlinks > 0) && (links[curdoc.link].lname != NULL)) { run_external(links[curdoc.link].lname, FALSE); *refresh_screen = TRUE; } } PRIVATE void handle_LYK_EXTERN_PAGE ARGS1( BOOLEAN *, refresh_screen) { if (curdoc.address != NULL) { run_external(curdoc.address, FALSE); *refresh_screen = TRUE; } } #endif PRIVATE BOOLEAN handle_LYK_FASTBACKW_LINK ARGS3( int *, cmd, int *, old_c, int, real_c) { int samepage = 0, nextlink = curdoc.link; int res; if (nlinks > 1) { /* * If in textarea, move to first link or textarea group * before it if there is one on this screen. - kw */ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type == F_TEXTAREA_TYPE) { int thisgroup = links[curdoc.link].l_form->number; char *thisname = links[curdoc.link].l_form->name; if (curdoc.link > 0 && !(links[0].type == WWW_FORM_LINK_TYPE && links[0].l_form->type == F_TEXTAREA_TYPE && links[0].l_form->number == thisgroup && sametext(links[0].l_form->name, thisname))) { do nextlink--; while (links[nextlink].type == WWW_FORM_LINK_TYPE && links[nextlink].l_form->type == F_TEXTAREA_TYPE && links[nextlink].l_form->number == thisgroup && sametext(links[nextlink].l_form->name, thisname)); samepage = 1; } else if (!more && Newline == 1 && (links[0].type == WWW_FORM_LINK_TYPE && links[0].l_form->type == F_TEXTAREA_TYPE && links[0].l_form->number == thisgroup && sametext(links[0].l_form->name, thisname)) && !(links[nlinks-1].type == WWW_FORM_LINK_TYPE && links[nlinks-1].l_form->type == F_TEXTAREA_TYPE && links[nlinks-1].l_form->number == thisgroup && sametext(links[nlinks-1].l_form->name, thisname))) { nextlink = nlinks - 1; samepage = 1; } else if (!more && Newline == 1 && curdoc.link > 0) { nextlink = 0; samepage = 1; } } else if (curdoc.link > 0) { nextlink--; samepage = 1; } else if (!more && Newline == 1) { nextlink = nlinks - 1; samepage = 1; } } if (samepage) { /* * If the link as determined so far is part of a * group of textarea fields, try to use the first * of them that's on the screen instead. - kw */ if (nextlink > 0 && links[nextlink].type == WWW_FORM_LINK_TYPE && links[nextlink].l_form->type == F_TEXTAREA_TYPE) { int thisgroup = links[nextlink].l_form->number; char *thisname = links[nextlink].l_form->name; if (links[0].type == WWW_FORM_LINK_TYPE && links[0].l_form->type == F_TEXTAREA_TYPE && links[0].l_form->number == thisgroup && sametext(links[0].l_form->name, thisname)) { nextlink = 0; } else while (nextlink > 1 && links[nextlink-1].type == WWW_FORM_LINK_TYPE && links[nextlink-1].l_form->type == F_TEXTAREA_TYPE && links[nextlink-1].l_form->number == thisgroup && sametext(links[nextlink-1].l_form->name, thisname)) { nextlink--; } } set_curdoc_link(nextlink); return FALSE; /* and we are done. */ } else if (Newline > 1 && /* need a previous page */ (res = HTGetLinkOrFieldStart(curdoc.link, &Newline, &newdoc.link, -1, TRUE)) != NO) { if (res == LINK_DO_ARROWUP) { /* * It says we should use the normal PREV_LINK * mechanism, so we'll do that. - kw */ if (nlinks > 0) curdoc.link = 0; *cmd = LYK_PREV_LINK; return TRUE; } Newline++; /* our line counting starts with 1 not 0 */ /* nothing more to do here */ } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(NO_LINKS_ABOVE); } return FALSE; } PRIVATE void handle_LYK_FASTFORW_LINK ARGS2( int *, old_c, int, real_c) { int samepage = 0, nextlink = curdoc.link; if (nlinks > 1) { /* * If in textarea, move to first link or field * after it if there is one on this screen. - kw */ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type == F_TEXTAREA_TYPE) { int thisgroup = links[curdoc.link].l_form->number; char *thisname = links[curdoc.link].l_form->name; if (curdoc.link < nlinks-1 && !(links[nlinks-1].type == WWW_FORM_LINK_TYPE && links[nlinks-1].l_form->type == F_TEXTAREA_TYPE && links[nlinks-1].l_form->number == thisgroup && sametext(links[nlinks-1].l_form->name, thisname))) { do nextlink++; while (links[nextlink].type == WWW_FORM_LINK_TYPE && links[nextlink].l_form->type == F_TEXTAREA_TYPE && links[nextlink].l_form->number == thisgroup && sametext(links[nextlink].l_form->name, thisname)); samepage = 1; } else if (!more && Newline == 1 && curdoc.link > 0) { nextlink = 0; samepage = 1; } } else if (curdoc.link < nlinks-1) { nextlink++; samepage = 1; } else if (!more && Newline == 1 && curdoc.link > 0) { nextlink = 0; samepage = 1; } } if (samepage) { set_curdoc_link(nextlink); return; /* and we are done. */ /* * At the bottom of list and there is only one page. * Move to the top link on the page. */ } else if (!more && Newline == 1 && curdoc.link == nlinks-1) { set_curdoc_link(0); } else if (more && /* need a later page */ HTGetLinkOrFieldStart(curdoc.link, &Newline, &newdoc.link, 1, TRUE) != NO) { Newline++; /* our line counting starts with 1 not 0 */ /* nothing more to do here */ } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(NO_LINKS_BELOW); } return; } PRIVATE void handle_LYK_FIRST_LINK NOARGS { int i = curdoc.link; for (;;) { if (--i < 0 || links[i].ly != links[curdoc.link].ly) { set_curdoc_link(i + 1); break; } } } PRIVATE BOOLEAN handle_LYK_GOTO ARGS9( int *, ch, char *, user_input_buffer, char **, old_user_input, int *, recall, int *, URLTotal, int *, URLNum, BOOLEAN *, FirstURLRecall, int *, old_c, int, real_c) { if (no_goto && !LYValidate) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(GOTO_DISALLOWED); } return FALSE; } StrAllocCopy(*old_user_input, user_input_buffer); if (!goto_buffer) *user_input_buffer = '\0'; *URLTotal = (Goto_URLs ? HTList_count(Goto_URLs) : 0); if (goto_buffer && *user_input_buffer) { *recall = ((*URLTotal > 1) ? RECALL_URL : NORECALL); *URLNum = 0; *FirstURLRecall = FALSE; } else { *recall = ((*URLTotal >= 1) ? RECALL_URL : NORECALL); *URLNum = *URLTotal; *FirstURLRecall = TRUE; } /* * Ask the user. */ _statusline(URL_TO_OPEN); if ((*ch = LYgetstr(user_input_buffer, VISIBLE, MAX_LINE, *recall)) < 0 ) { /* * User cancelled the Goto via ^G. * Restore user_input_buffer and break. - FM */ LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1); FREE(*old_user_input); HTInfoMsg(CANCELLED); return FALSE; } return TRUE; } PRIVATE void handle_LYK_GROW_TEXTAREA ARGS1( BOOLEAN *, refresh_screen) { /* * See if the current link is in a form TEXTAREA. */ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type == F_TEXTAREA_TYPE) { HText_ExpandTextarea (&links[curdoc.link], TEXTAREA_EXPAND_SIZE); *refresh_screen = TRUE; } else { HTInfoMsg (NOT_IN_TEXTAREA); } } PRIVATE BOOLEAN handle_LYK_HEAD ARGS1( int *, cmd) { int c; if (nlinks > 0 && (links[curdoc.link].type != WWW_FORM_LINK_TYPE || links[curdoc.link].l_form->type == F_SUBMIT_TYPE || links[curdoc.link].l_form->type == F_IMAGE_SUBMIT_TYPE || links[curdoc.link].l_form->type == F_TEXT_SUBMIT_TYPE)) { /* * We have links, and the current link is a normal link or a form's * submit button. - FM */ _statusline(HEAD_D_L_OR_CANCEL); c = LYgetch_single(); if (c == 'D') { char *scheme = !isLYNXIMGMAP(curdoc.address) ? curdoc.address : curdoc.address + LEN_LYNXIMGMAP; if (LYCanDoHEAD(scheme) != TRUE) { HTUserMsg(DOC_NOT_HTTP_URL); } else { /* * Check if this is a reply from a POST, and if so, seek * confirmation if the safe element is not set. - FM */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && HTConfirm(CONFIRM_POST_DOC_HEAD) == FALSE) { HTInfoMsg(CANCELLED); } else { HEAD_request = TRUE; LYforce_no_cache = TRUE; StrAllocCopy(newdoc.title, curdoc.title); if (HTLoadedDocumentIsHEAD()) { HText_setNoCache(HTMainText); free_address(&curdoc); } else { StrAllocCat(newdoc.title, " - HEAD"); } } } } else if (c == 'L') { if (links[curdoc.link].type != WWW_FORM_LINK_TYPE && strncmp(links[curdoc.link].lname, "http", 4) && strncmp(links[curdoc.link].lname, "LYNXIMGMAP:http", 15) && LYCanDoHEAD(links[curdoc.link].lname) != TRUE && (links[curdoc.link].type != WWW_INTERN_LINK_TYPE || !curdoc.address || strncmp(curdoc.address, "http", 4))) { HTUserMsg(LINK_NOT_HTTP_URL); } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->disabled) { HTUserMsg(FORM_ACTION_DISABLED); } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && !isLYNXCGI(links[curdoc.link].l_form->submit_action) && strncmp(links[curdoc.link].l_form->submit_action, "http", 4)) { HTUserMsg(FORM_ACTION_NOT_HTTP_URL); } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->submit_method == URL_POST_METHOD && HTConfirm(CONFIRM_POST_LINK_HEAD) == FALSE) { HTInfoMsg(CANCELLED); } else { HEAD_request = TRUE; LYforce_no_cache = TRUE; *cmd = LYK_ACTIVATE; return TRUE; } } } else { /* * We can offer only this document for a HEAD request. Check if this * is a reply from a POST, and if so, seek confirmation if the safe * element is not set. - FM */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && HTConfirm(CONFIRM_POST_DOC_HEAD) == FALSE) { HTInfoMsg(CANCELLED); } else { if (nlinks > 0) { /* * The current link is a non-submittable form link, so prompt * the user to make it clear that the HEAD request would be for * the current document, not the form link. - FM */ _statusline(HEAD_D_OR_CANCEL); c = LYgetch_single(); } else { /* * No links, so we can just assume that the user wants a HEAD * request for the current document. - FM */ c = 'D'; } if (c == 'D') { char *scheme = !isLYNXIMGMAP(curdoc.address) ? curdoc.address : curdoc.address + LEN_LYNXIMGMAP; /* * The user didn't cancel, so check if a HEAD request is * appropriate for the current document. - FM */ if (LYCanDoHEAD(scheme) != TRUE) { HTUserMsg(DOC_NOT_HTTP_URL); } else { HEAD_request = TRUE; LYforce_no_cache = TRUE; StrAllocCopy(newdoc.title, curdoc.title); if (HTLoadedDocumentIsHEAD()) { HText_setNoCache(HTMainText); free_address(&curdoc); } else { StrAllocCat(newdoc.title, " - HEAD"); } } } } } return FALSE; } PRIVATE void handle_LYK_HELP ARGS1( CONST char **, cshelpfile) { if (*cshelpfile == NULL) *cshelpfile = helpfile; if (!STREQ(curdoc.address, *cshelpfile)) { /* * Set the filename. */ set_address(&newdoc, *cshelpfile); /* * Make a name for this help file. */ StrAllocCopy(newdoc.title, gettext("Help Screen")); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; } *cshelpfile = NULL; /* reset pointer - kw */ } PRIVATE void handle_LYK_HISTORICAL NOARGS { #ifdef USE_SOURCE_CACHE if (!HTcan_reparse_document()) { #endif /* * Check if this is a reply from a POST, and if so, * seek confirmation of reload if the safe element * is not set. - FM */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && confirm_post_resub(curdoc.address, NULL, 0, 0) == FALSE) { HTInfoMsg(WILL_NOT_RELOAD_DOC); } else { HText_setNoCache(HTMainText); move_address(&newdoc, &curdoc); newdoc.line = curdoc.line; newdoc.link = curdoc.link; } #ifdef USE_SOURCE_CACHE } /* end if no bypass */ #endif historical_comments = !historical_comments; if (minimal_comments) { HTAlert(historical_comments ? HISTORICAL_ON_MINIMAL_OFF : HISTORICAL_OFF_MINIMAL_ON); } else { HTAlert(historical_comments ? HISTORICAL_ON_VALID_OFF : HISTORICAL_OFF_VALID_ON); } #ifdef USE_SOURCE_CACHE (void) reparse_document(); #endif return; } PRIVATE BOOLEAN handle_LYK_HISTORY ARGS1( BOOLEAN, ForcePush) { if (curdoc.title && !LYIsUIPage(curdoc.address, UIP_HISTORY)) { /* * Don't do this if already viewing history page. * * Push the current file so that the history list * contains the current file for printing purposes. * Pop the file afterwards to prevent multiple copies. */ if (TRACE && !LYUseTraceLog && LYCursesON) { LYHideCursor(); /* make sure cursor is down */ #ifdef USE_SLANG LYaddstr("\n"); #endif /* USE_SLANG */ LYrefresh(); } LYpush(&curdoc, ForcePush); /* * Print history options to file. */ if (showhistory(&newdoc.address) < 0) { LYpop(&curdoc); return TRUE; } LYRegisterUIPage(newdoc.address, UIP_HISTORY); StrAllocCopy(newdoc.title, HISTORY_PAGE_TITLE); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; newdoc.link = 1; /*@@@ bypass "recent statusline messages" link */ free_address(&curdoc); /* so it doesn't get pushed */ if (LYValidate || check_realm) { LYPermitURL = TRUE; } return TRUE; } /* end if strncmp */ return FALSE; } PRIVATE BOOLEAN handle_LYK_IMAGE_TOGGLE ARGS1( int *, cmd) { clickable_images = !clickable_images; HTUserMsg(clickable_images ? CLICKABLE_IMAGES_ON : CLICKABLE_IMAGES_OFF); return reparse_or_reload(cmd); } PRIVATE void handle_LYK_INDEX ARGS2( int *, old_c, int, real_c) { /* * Make sure we are not in the index already. */ if (!STREQ(curdoc.address, indexfile)) { if (indexfile[0]=='\0') { /* no defined index */ if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_INDEX_FILE); } } else { #ifdef KANJI_CODE_OVERRIDE if (HTCJK == JAPANESE) { last_kcode = NOKANJI; /* AUTO */ } #endif set_address(&newdoc, indexfile); StrAllocCopy(newdoc.title, gettext("System Index")); /* name it */ LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; } /* end else */ } /* end if */ } PRIVATE void handle_LYK_INDEX_SEARCH ARGS4( BOOLEAN *, force_load, BOOLEAN, ForcePush, int *, old_c, int, real_c) { if (is_www_index) { /* * Perform a database search. * * do_www_search will try to go out and get the document. * If it returns TRUE, a new document was returned and is * named in the newdoc.address. */ newdoc.isHEAD = FALSE; newdoc.safe = FALSE; if (do_www_search(&newdoc) == NORMAL) { /* * Yah, the search succeeded. */ if (TRACE && !LYUseTraceLog && LYCursesON) { /* * Make sure cursor is down. */ LYHideCursor(); #ifdef USE_SLANG LYaddstr("\n"); #endif /* USE_SLANG */ LYrefresh(); } LYpush(&curdoc, ForcePush); /* * Make the curdoc.address the newdoc.address so that * getfile doesn't try to get the newdoc.address. * Since we have already gotten it. */ copy_address(&curdoc, &newdoc); BStrCopy(newdoc.post_data, curdoc.post_data); StrAllocCopy(newdoc.post_content_type, curdoc.post_content_type); newdoc.internal_link = FALSE; curdoc.line = -1; Newline = 0; } else if (use_this_url_instead != NULL) { /* * Got back a redirecting URL. Check it out. */ HTUserMsg2 (WWW_USING_MESSAGE, use_this_url_instead); /* * Make a name for this URL. */ StrAllocCopy(newdoc.title, "A URL specified by redirection"); set_address(&newdoc, use_this_url_instead); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; FREE(use_this_url_instead); *force_load = TRUE; } else { /* * Yuk, the search failed. Restore the old file. */ copy_address(&newdoc, &curdoc); BStrCopy(newdoc.post_data, curdoc.post_data); StrAllocCopy(newdoc.post_content_type, curdoc.post_content_type); StrAllocCopy(newdoc.bookmark, curdoc.bookmark); newdoc.isHEAD = curdoc.isHEAD; newdoc.safe = curdoc.safe; newdoc.internal_link = curdoc.internal_link; } } else if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NOT_ISINDEX); } } PRIVATE BOOLEAN handle_LYK_INFO ARGS1( int *, cmd) { /* * Don't do if already viewing info page. */ if (!LYIsUIPage(curdoc.address, UIP_SHOWINFO)) { if (do_change_link() != -1 && LYShowInfo(&curdoc, HText_getNumOfLines(), &newdoc, owner_address) >= 0) { LYRegisterUIPage(newdoc.address, UIP_SHOWINFO); StrAllocCopy(newdoc.title, SHOWINFO_TITLE); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; LYforce_no_cache = TRUE; if (LYValidate || check_realm) LYPermitURL = TRUE; } } else { /* * If already in info page, get out. */ *cmd = LYK_PREV_DOC; return TRUE; } return FALSE; } PRIVATE BOOLEAN handle_LYK_INLINE_TOGGLE ARGS1( int *, cmd) { pseudo_inline_alts = !pseudo_inline_alts; HTUserMsg(pseudo_inline_alts ? PSEUDO_INLINE_ALTS_ON : PSEUDO_INLINE_ALTS_OFF); return reparse_or_reload(cmd); } PRIVATE void handle_LYK_INSERT_FILE ARGS3( BOOLEAN *, refresh_screen, int *, old_c, int, real_c) { int n; /* * See if the current link is in a form TEXTAREA. */ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type == F_TEXTAREA_TYPE) { /* * Reject attempts to use this for gaining access to * local files when such access is restricted: * if no_file_url was set via the file_url restriction, * if no_goto_file was set for the anonymous account, * or if HTDirAccess was set to HT_DIR_FORBID or * HT_DIR_SELECTIVE via the -nobrowse or -selective * switches, it is assumed that inserting files or * checking for existence of files needs to be denied. - kw */ if (no_file_url || no_goto_file || HTDirAccess == HT_DIR_FORBID || HTDirAccess == HT_DIR_SELECTIVE) { if (*old_c != real_c) { *old_c = real_c; if (no_goto_file) HTUserMsg2(GOTO_XXXX_DISALLOWED, STR_FILE_URL); else HTUserMsg(NOAUTH_TO_ACCESS_FILES); HTInfoMsg(FILE_INSERT_CANCELLED); } return; } n = HText_InsertFile (&links[curdoc.link]); /* * TODO: Move cursor "n" lines from the current line to * position it on the 1st line following the text * that was inserted. If the target line/anchor * requires us to scroll up/down, position the * target in the approximate center of the screen. * * [Current behavior leaves cursor on the same line relative * to the start of the TEXTAREA that it was on before the * insertion. This is the same behavior that occurs with * (my) editor, so this TODO will stay unimplemented.] */ *refresh_screen = TRUE; } else { HTInfoMsg (NOT_IN_TEXTAREA); } } #if defined(DIRED_SUPPORT) && defined(OK_INSTALL) PRIVATE void handle_LYK_INSTALL NOARGS { if (lynx_edit_mode && nlinks > 0 && !no_dired_support) local_install(NULL, links[curdoc.link].lname, &newdoc.address); } #endif PRIVATE BOOLEAN handle_LYK_JUMP ARGS10( int, c, char *, user_input_buffer, char **, old_user_input GCC_UNUSED, int *, recall GCC_UNUSED, BOOLEAN *, FirstURLRecall GCC_UNUSED, int *, URLNum GCC_UNUSED, int *, URLTotal GCC_UNUSED, int *, ch GCC_UNUSED, int *, old_c, int, real_c) { char *ret; if (no_jump || JThead == NULL) { if (*old_c != real_c) { *old_c = real_c; if (no_jump) HTUserMsg(JUMP_DISALLOWED); else HTUserMsg(NO_JUMPFILE); } } else { LYJumpFileURL = TRUE; if ((ret = LYJump(c)) != NULL) { #ifdef PERMIT_GOTO_FROM_JUMP if (!strncasecomp(ret, "Go ", 3)) { LYJumpFileURL = FALSE; StrAllocCopy(*old_user_input, user_input_buffer); *URLTotal = (Goto_URLs ? HTList_count(Goto_URLs) : 0); *recall = ((*URLTotal >= 1) ? RECALL_URL : NORECALL); *URLNum = *URLTotal; *FirstURLRecall = TRUE; if (!strcasecomp(ret, "Go :")) { if (recall) { *ch = UPARROW; return TRUE; } FREE(*old_user_input); HTUserMsg(NO_RANDOM_URLS_YET); return FALSE; } ret = HTParse((ret+3), startfile, PARSE_ALL); LYstrncpy(user_input_buffer, ret, MAX_LINE - 1); FREE(ret); return TRUE; } #endif /* PERMIT_GOTO_FROM_JUMP */ ret = HTParse(ret, startfile, PARSE_ALL); if (!LYTrimStartfile(ret)) { LYRemoveBlanks(user_input_buffer); } set_address(&newdoc, ret); StrAllocCopy(lynxjumpfile, ret); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; FREE(ret); LYUserSpecifiedURL = TRUE; } else { LYJumpFileURL = FALSE; } } return FALSE; } PRIVATE void handle_LYK_KEYMAP ARGS4( BOOLEAN *, vi_keys_flag, BOOLEAN *, emacs_keys_flag, int *, old_c, int, real_c) { if (*old_c != real_c) { *old_c = real_c; set_address(&newdoc, STR_LYNXKEYMAP); StrAllocCopy(newdoc.title, CURRENT_KEYMAP_TITLE); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; /* * If vi_keys changed, the keymap did too, * so force no cache, and reset the flag. - FM */ if (*vi_keys_flag != vi_keys || *emacs_keys_flag != emacs_keys) { LYforce_no_cache = TRUE; *vi_keys_flag = vi_keys; *emacs_keys_flag = emacs_keys; } #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) /* * Remember whether we are in dired menu * so we can display the right keymap. */ if (!no_dired_support) { prev_lynx_edit_mode = lynx_edit_mode; } #endif /* DIRED_SUPPORT && OK_OVERRIDE */ LYforce_no_cache = TRUE; } } PRIVATE void handle_LYK_LAST_LINK NOARGS { int i = curdoc.link; for (;;) { if (++i >= nlinks || links[i].ly != links[curdoc.link].ly) { set_curdoc_link(i - 1); break; } } } PRIVATE void handle_LYK_LEFT_LINK NOARGS { if (curdoc.link>0 && links[curdoc.link].ly == links[curdoc.link-1].ly) { set_curdoc_link(curdoc.link-1); } } PRIVATE BOOLEAN handle_LYK_LIST ARGS1( int *, cmd) { /* * Don't do if already viewing list page. */ if (!strcmp(NonNull(curdoc.title), LIST_PAGE_TITLE) && LYIsUIPage(curdoc.address, UIP_LIST_PAGE)) { /* * Already viewing list page, so get out. */ *cmd = LYK_PREV_DOC; return TRUE; } /* * Print list page to file. */ if (showlist(&newdoc, TRUE) < 0) return FALSE; StrAllocCopy(newdoc.title, LIST_PAGE_TITLE); /* * showlist will set newdoc's other fields. It may leave * post_data intact so the list can be used to follow * internal links in the current document even if it is * a POST response. - kw */ if (LYValidate || check_realm) { LYPermitURL = TRUE; StrAllocCopy(lynxlistfile, newdoc.address); } return FALSE; } PRIVATE void handle_LYK_MAIN_MENU ARGS2( int *, old_c, int, real_c) { /* * If its already the homepage then don't reload it. */ if (!STREQ(curdoc.address,homepage)) { if (HTConfirmDefault(CONFIRM_MAIN_SCREEN, NO) == YES) { set_address(&newdoc, homepage); StrAllocCopy(newdoc.title, gettext("Entry into main screen")); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; LYhighlight(OFF, curdoc.link, prev_target); #ifdef DIRED_SUPPORT if (lynx_edit_mode) { DIRED_UNCACHE_2; } #endif /* DIRED_SUPPORT */ } } else { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(IN_MAIN_SCREEN); } } } PRIVATE void handle_LYK_MINIMAL NOARGS { if (!historical_comments) { #ifdef USE_SOURCE_CACHE if (!HTcan_reparse_document()) { #endif /* * Check if this is a reply from a POST, and if so, * seek confirmation of reload if the safe element * is not set. - FM */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && confirm_post_resub(curdoc.address, NULL, 0, 0) == FALSE) { HTInfoMsg(WILL_NOT_RELOAD_DOC); } else { HText_setNoCache(HTMainText); move_address(&newdoc, &curdoc); newdoc.line = curdoc.line; newdoc.link = curdoc.link; } #ifdef USE_SOURCE_CACHE } /* end if no bypass */ #endif } minimal_comments = !minimal_comments; if (!historical_comments) { HTAlert(minimal_comments ? MINIMAL_ON_IN_EFFECT : MINIMAL_OFF_VALID_ON); } else { HTAlert(minimal_comments ? MINIMAL_ON_BUT_HISTORICAL : MINIMAL_OFF_HISTORICAL_ON); } #ifdef USE_SOURCE_CACHE (void)reparse_document(); #endif return; } #if defined(DIRED_SUPPORT) PRIVATE void handle_LYK_MODIFY ARGS1( BOOLEAN *, refresh_screen) { if (lynx_edit_mode && nlinks > 0 && !no_dired_support) { int ret; ret = local_modify(&curdoc, &newdoc.address); if (ret == PERMIT_FORM_RESULT) { /* Permit form thrown up */ *refresh_screen = TRUE; } else if (ret) { DIRED_UNCACHE_1; move_address(&newdoc, &curdoc); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; newdoc.line = curdoc.line; newdoc.link = curdoc.link; LYclear(); } } } #endif /* DIRED_SUPPORT */ #ifdef EXP_NESTED_TABLES PRIVATE BOOLEAN handle_LYK_NESTED_TABLES ARGS1( int *, cmd) { nested_tables = !nested_tables; HTUserMsg(nested_tables ? NESTED_TABLES_ON : NESTED_TABLES_OFF); return reparse_or_reload(cmd); } #endif PRIVATE BOOLEAN handle_LYK_OPTIONS ARGS2( int *, cmd, BOOLEAN *, refresh_screen) { #ifndef NO_OPTION_MENU if (!LYUseFormsOptions) { BOOLEAN LYUseDefaultRawMode_flag = LYUseDefaultRawMode; BOOLEAN LYSelectPopups_flag = LYSelectPopups; BOOLEAN verbose_img_flag = verbose_img; BOOLEAN keypad_mode_flag = (BOOL) keypad_mode; BOOLEAN show_dotfiles_flag = show_dotfiles; BOOLEAN user_mode_flag = (BOOL) user_mode; int CurrentAssumeCharSet_flag = UCLYhndl_for_unspec; int CurrentCharSet_flag = current_char_set; int HTfileSortMethod_flag = HTfileSortMethod; char *CurrentUserAgent = NULL; char *CurrentNegoLanguage = NULL; char *CurrentNegoCharset = NULL; StrAllocCopy(CurrentUserAgent, (LYUserAgent ? LYUserAgent : "")); StrAllocCopy(CurrentNegoLanguage, (language ? language : "")); StrAllocCopy(CurrentNegoCharset, (pref_charset ? pref_charset : "")); LYoptions(); /** do the old-style options stuff **/ if (keypad_mode_flag != keypad_mode || (user_mode_flag != user_mode && (user_mode_flag == NOVICE_MODE || user_mode == NOVICE_MODE)) || (((HTfileSortMethod_flag != HTfileSortMethod) || (show_dotfiles_flag != show_dotfiles)) && (isFILE_URL(curdoc.address) || isFTP_URL(curdoc.address))) || CurrentCharSet_flag != current_char_set || CurrentAssumeCharSet_flag != UCLYhndl_for_unspec || verbose_img_flag != verbose_img || LYUseDefaultRawMode_flag != LYUseDefaultRawMode || LYSelectPopups_flag != LYSelectPopups || ((strcmp(CurrentUserAgent, (LYUserAgent ? LYUserAgent : "")) || strcmp(CurrentNegoLanguage, (language ? language : "")) || strcmp(CurrentNegoCharset, (pref_charset ? pref_charset : ""))) && (!strncmp(curdoc.address, "http", 4) || isLYNXCGI(curdoc.address)))) { BOOLEAN canreparse_post = FALSE; /* * Check if this is a reply from a POST, and if so, * seek confirmation of reload if the safe element * is not set. - FM */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && #ifdef USE_SOURCE_CACHE (!(canreparse_post = HTcan_reparse_document())) && #endif confirm_post_resub(curdoc.address, curdoc.title, 2, 1) == FALSE) { HTInfoMsg(WILL_NOT_RELOAD_DOC); } else { copy_address(&newdoc, &curdoc); if (((strcmp(CurrentUserAgent, (LYUserAgent ? LYUserAgent : "")) || strcmp(CurrentNegoLanguage, NonNull(language)) || strcmp(CurrentNegoCharset, NonNull(pref_charset))) && (strncmp(curdoc.address, "http", 4) == 0 || !isLYNXCGI(curdoc.address) == 0))) { /* * An option has changed which may influence * content negotiation, and the resource is from * a http or https or lynxcgi URL (the only protocols * which currently do anything with this information). * Set reloading = TRUE so that proxy caches will be * flushed, which is necessary until the time when * all proxies understand HTTP 1.1 Vary: and all * Servers properly use it... Treat like * case LYK_RELOAD (see comments there). - KW */ reloading = TRUE; } if (HTisDocumentSource()) { srcmode_for_next_retrieval(1); } #ifdef USE_SOURCE_CACHE if (reloading == FALSE) { /* one more attempt to be smart enough: */ if (reparse_document()) { FREE(CurrentUserAgent); FREE(CurrentNegoLanguage); FREE(CurrentNegoCharset); return FALSE; } } #endif if (canreparse_post && confirm_post_resub(curdoc.address, curdoc.title, 2, 1) == FALSE) { if (HTisDocumentSource()) { srcmode_for_next_retrieval(0); } FREE(CurrentUserAgent); FREE(CurrentNegoLanguage); FREE(CurrentNegoCharset); return FALSE; } HEAD_request = HTLoadedDocumentIsHEAD(); HText_setNoCache(HTMainText); #ifdef NO_ASSUME_SAME_DOC newdoc.line = 1; newdoc.link = 0; #else newdoc.line = curdoc.line; newdoc.link = curdoc.link; #endif /* NO_ASSUME_SAME_DOC */ LYforce_no_cache = TRUE; free_address(&curdoc); /* So it doesn't get pushed. */ } } FREE(CurrentUserAgent); FREE(CurrentNegoLanguage); FREE(CurrentNegoCharset); *refresh_screen = TRUE; /* to repaint screen */ return FALSE; } /* end if !LYUseFormsOptions */ #endif /* !NO_OPTION_MENU */ #ifndef NO_OPTION_FORMS /* * Generally stolen from LYK_COOKIE_JAR. Options menu handling is * done in postoptions(), called from getfile() currently. * * postoptions() is also responsible for reloading the document * before the 'options menu' but only when (a few) important * options were changed. * * It is critical that post_data is freed here since the * submission of changed options is done via the same protocol as * LYNXOPTIONS: */ /* * Don't do if already viewing options page. */ if (!LYIsUIPage(curdoc.address, UIP_OPTIONS_MENU)) { set_address(&newdoc, "LYNXOPTIONS:/"); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; LYforce_no_cache = TRUE; /* change to 'if (check_realm && !LYValidate)' and make change near top of getfile to forbid using forms options menu with -validate: - kw */ if (LYValidate || check_realm) { LYPermitURL = TRUE; } } else { /* * If already in the options menu, get out. */ *cmd = LYK_PREV_DOC; return TRUE; } #endif /* !NO_OPTION_FORMS */ return FALSE; } PRIVATE void handle_NEXT_DOC NOARGS { if (LYhist_next(&curdoc, &newdoc)) { free_address(&curdoc); /* avoid push */ return; } HTUserMsg(gettext("No next document present")); } PRIVATE void handle_LYK_NEXT_LINK ARGS3( int, c, int *, old_c, int, real_c) { if (curdoc.link < nlinks-1) { /* next link */ LYhighlight(OFF, curdoc.link, prev_target); #ifdef FASTTAB /* * Move to different textarea if TAB in textarea. */ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type == F_TEXTAREA_TYPE && c=='\t') { int thisgroup = links[curdoc.link].l_form->number; char *thisname = links[curdoc.link].l_form->name; do curdoc.link++; while ((curdoc.link < nlinks-1) && links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type == F_TEXTAREA_TYPE && links[curdoc.link].l_form->number == thisgroup && sametext(links[curdoc.link].l_form->name, thisname)); } else { curdoc.link++; } #else curdoc.link++; #endif /* FASTTAB */ /* * At the bottom of list and there is only one page. * Move to the top link on the page. */ } else if (!more && Newline == 1 && curdoc.link == nlinks-1) { set_curdoc_link(0); } else if (more) { /* next page */ Newline += (display_lines); } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_END); } } PRIVATE void handle_LYK_NEXT_PAGE ARGS2( int *, old_c, int, real_c) { if (more) { Newline += display_lines; } else if (curdoc.link < nlinks-1) { set_curdoc_link(nlinks - 1); } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_END); } } PRIVATE BOOLEAN handle_LYK_NOCACHE ARGS2( int *, old_c, int, real_c) { if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].l_form->type != F_SUBMIT_TYPE && links[curdoc.link].l_form->type != F_IMAGE_SUBMIT_TYPE && links[curdoc.link].l_form->type != F_TEXT_SUBMIT_TYPE) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NOT_ON_SUBMIT_OR_LINK); } return FALSE; } else { LYforce_no_cache = TRUE; reloading = TRUE; } } return TRUE; } PRIVATE void handle_LYK_PREV_LINK ARGS3( int *, arrowup, int *, old_c, int, real_c) { if (curdoc.link > 0) { /* previous link */ set_curdoc_link(curdoc.link - 1); } else if (!more && curdoc.link==0 && Newline==1) { /* at the top of list */ /* * If there is only one page of data and the user * goes off the top, just move the cursor to last link on * the page. */ set_curdoc_link(nlinks - 1); } else if (curdoc.line > 1) { /* previous page */ /* * Go back to the previous page. */ int scrollamount = (Newline > display_lines ? display_lines : Newline - 1); Newline -= scrollamount; if (scrollamount < display_lines && nlinks > 0 && curdoc.link == 0 && links[0].ly - 1 + scrollamount <= display_lines) { newdoc.link = HText_LinksInLines(HTMainText, 1, scrollamount) - 1; } else { *arrowup = TRUE; } } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_BEGIN); } } PRIVATE int handle_PREV_DOC ARGS3( int *, cmd, int *, old_c, int, real_c) { if (nhist > 0) { /* if there is anything to go back to */ /* * Check if the previous document is a reply from a POST, * and if so, seek confirmation of resubmission if the safe * element is not set and the document is not still in the * cache or LYresubmit_posts is set. If not confirmed and * it is not the startfile, pop it so we go to the yet * previous document, until we're OK or reach the startfile. * If we reach the startfile and its not OK or we don't get * confirmation, cancel. - FM */ DocAddress WWWDoc; HTParentAnchor *tmpanchor; HText *text; BOOLEAN conf = FALSE, first = TRUE; HTLastConfirmCancelled(); /* reset flag */ while (nhist > 0) { conf = FALSE; if (HDOC(nhist - 1).post_data == NULL) { break; } WWWDoc.address = HDOC(nhist - 1).address; WWWDoc.post_data = HDOC(nhist - 1).post_data; WWWDoc.post_content_type = HDOC(nhist - 1).post_content_type; WWWDoc.bookmark = HDOC(nhist - 1).bookmark; WWWDoc.isHEAD = HDOC(nhist - 1).isHEAD; WWWDoc.safe = HDOC(nhist - 1).safe; tmpanchor = HTAnchor_findAddress(&WWWDoc); if (HTAnchor_safe(tmpanchor)) { break; } if (((text = (HText *)HTAnchor_document(tmpanchor)) == NULL && (isLYNXIMGMAP(WWWDoc.address) || (conf = confirm_post_resub(WWWDoc.address, HDOC(nhist - 1).title, 0, 0)) == FALSE)) || ((LYresubmit_posts && !conf && (NONINTERNAL_OR_PHYS_DIFFERENT( (DocInfo *)&history[(nhist - 1)], &curdoc) || NONINTERNAL_OR_PHYS_DIFFERENT( (DocInfo *)&history[(nhist - 1)], &newdoc))) && !confirm_post_resub(WWWDoc.address, HDOC(nhist - 1).title, 2, 2))) { if (HTLastConfirmCancelled()) { if (!first && curdoc.internal_link) free_address(&curdoc); *cmd = LYK_DO_NOTHING; return 2; } if (nhist == 1) { HTInfoMsg(CANCELLED); *old_c = 0; *cmd = LYK_DO_NOTHING; return 2; } else { HTUserMsg2(WWW_SKIP_MESSAGE, WWWDoc.address); do { /* Should be LYhist_prev when _next supports */ LYpop(&curdoc); /* skipping of forms */ } while (nhist > 1 && !are_different( (DocInfo *)&history[(nhist - 1)], &curdoc)); first = FALSE; /* have popped at least one */ continue; } } else { /* * Break from loop; if user just confirmed to * load again because document wasn't in cache, * set LYforce_no_cache to avoid unnecessary * repeat question down the road. - kw */ if (conf) LYforce_no_cache = TRUE; break; } } if (!first) curdoc.internal_link = FALSE; /* * Set newdoc.address to empty to pop a file. */ LYhist_prev_register(&curdoc); /* Why not call _prev instead of zeroing address? */ free_address(&newdoc); #ifdef DIRED_SUPPORT if (lynx_edit_mode) { DIRED_UNCACHE_2; } #endif /* DIRED_SUPPORT */ } else if (child_lynx == TRUE) { return(1); /* exit on left arrow in main screen */ } else if (*old_c != real_c) { *old_c = real_c; HTUserMsg(ALREADY_AT_FIRST); } return 0; } PRIVATE void handle_LYK_PREV_PAGE ARGS2( int *, old_c, int, real_c) { if (Newline > 1) { Newline -= display_lines; } else if (curdoc.link > 0) { set_curdoc_link(0); } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_BEGIN); } } PRIVATE void handle_LYK_PRINT ARGS3( BOOLEAN *, ForcePush, int *, old_c, int, real_c) { if (LYValidate) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(PRINT_DISABLED); } return; } /* * Don't do if already viewing print options page. */ if (!LYIsUIPage(curdoc.address, UIP_PRINT_OPTIONS) && print_options(&newdoc.address, curdoc.address, HText_getNumOfLines()) >= 0) { LYRegisterUIPage(newdoc.address, UIP_PRINT_OPTIONS); StrAllocCopy(newdoc.title, PRINT_OPTIONS_TITLE); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; *ForcePush = TRUE; /* see LYpush() and print_options() */ if (check_realm) LYPermitURL = TRUE; } } PRIVATE BOOLEAN handle_LYK_QUIT NOARGS { int c; if (LYQuitDefaultYes == TRUE) { c = HTConfirmDefault(REALLY_QUIT, YES); } else { c = HTConfirmDefault(REALLY_QUIT, NO); } if (LYQuitDefaultYes == TRUE) { if (c != NO) { return(TRUE); } else { HTInfoMsg(NO_CANCEL); } } else if (c == YES) { return(TRUE); } else { HTInfoMsg(NO_CANCEL); } return FALSE; } PRIVATE BOOLEAN handle_LYK_RAW_TOGGLE ARGS1( int *, cmd) { if (HTLoadedDocumentCharset()) { HTUserMsg(gettext("charset for this document specified explicitly, sorry...")); return FALSE; } else { LYUseDefaultRawMode = (BOOL) !LYUseDefaultRawMode; HTUserMsg(LYRawMode ? RAWMODE_OFF : RAWMODE_ON); HTMLSetCharacterHandling(current_char_set); return reparse_or_reload(cmd); } } PRIVATE void handle_LYK_RELOAD ARGS1( int, real_cmd) { /* * Check if this is a reply from a POST, and if so, * seek confirmation if the safe element is not set. - FM */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { HTInfoMsg(CANCELLED); return; } /* * Check to see if should reload source, or load html */ if (HTisDocumentSource()) { if ((forced_UCLYhdnl = HTMainText_Get_UCLYhndl()) >= 0) force_old_UCLYhndl_on_reload = TRUE; srcmode_for_next_retrieval(1); } HEAD_request = HTLoadedDocumentIsHEAD(); HText_setNoCache(HTMainText); #ifdef NO_ASSUME_SAME_DOC /* * Don't assume the reloaded document will be the same. - FM */ newdoc.line = 1; newdoc.link = 0; #else /* * Do assume the reloaded document will be the same. - FM * (I don't remember all the reasons why we couldn't assume * this. As the problems show up, we'll try to fix them, * or add warnings. - FM) */ newdoc.line = curdoc.line; newdoc.link = curdoc.link; #endif /* NO_ASSUME_SAME_DOC */ free_address(&curdoc); /* so it doesn't get pushed */ #ifdef VMS lynx_force_repaint(); #endif /* VMS */ /* * Reload should force a cache refresh on a proxy. * -- Ari L. * * -- but only if this was really a reload requested by * the user, not if we jumped here to handle reloading for * INLINE_TOGGLE, IMAGE_TOGGLE, RAW_TOGGLE, etc. - KW */ if (real_cmd == LYK_RELOAD) reloading = TRUE; return; } #ifdef DIRED_SUPPORT PRIVATE void handle_LYK_REMOVE ARGS1( BOOLEAN *, refresh_screen) { if (lynx_edit_mode && nlinks > 0 && !no_dired_support) { int linkno = curdoc.link; /* may be changed in local_remove - kw */ local_remove(&curdoc); if (LYAutoUncacheDirLists >= 1) do_cleanup_after_delete(); else if (curdoc.link != linkno) *refresh_screen = TRUE; } } #endif /* DIRED_SUPPORT */ PRIVATE void handle_LYK_RIGHT_LINK NOARGS { if (curdoc.link 0 && !no_dired_support) { if (!strcmp(LYGetHiliteStr(curdoc.link, 0), "..")) return; /* Never tag the parent directory */ if (dir_list_style == MIXED_STYLE) { if (!strcmp(LYGetHiliteStr(curdoc.link, 0), "../")) return; } else if (!strncmp(LYGetHiliteStr(curdoc.link, 0), "Up to ", 6)) return; { /* * HTList-based management of tag list, see LYLocal.c - KW */ HTList * t1 = tagged; char * tagname = NULL; BOOLEAN found = FALSE; while ((tagname = (char *)HTList_nextObject(t1)) != NULL) { if (!strcmp(links[curdoc.link].lname, tagname)) { found = TRUE; HTList_removeObject(tagged, tagname); FREE(tagname); tagflag(OFF,curdoc.link); break; } } if (!found) { if (tagged == NULL) tagged = HTList_new(); tagname = NULL; StrAllocCopy(tagname,links[curdoc.link].lname); HTList_addObject(tagged,tagname); tagflag(ON,curdoc.link); } } if (curdoc.link < nlinks-1) { set_curdoc_link(curdoc.link + 1); } else if (!more && Newline == 1 && curdoc.link == nlinks-1) { set_curdoc_link(0); } else if (more) { /* next page */ Newline += (display_lines); } } } #endif /* DIRED_SUPPORT */ PRIVATE void handle_LYK_TOGGLE_HELP NOARGS { if (user_mode == NOVICE_MODE) { toggle_novice_line(); noviceline(more); } } PRIVATE void handle_LYK_TOOLBAR ARGS4( BOOLEAN *, try_internal, BOOLEAN *, force_load, int *, old_c, int, real_c) { char *cp; char *toolbar = NULL; if (!HText_hasToolbar(HTMainText)) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_TOOLBAR); } } else if (*old_c != real_c) { *old_c = real_c; cp = trimPoundSelector(curdoc.address); HTSprintf0(&toolbar, "%s#%s", curdoc.address, LYToolbarName); restorePoundSelector(cp); set_address(&newdoc, toolbar); FREE(toolbar); *try_internal = TRUE; *force_load = TRUE; /* force MainLoop to reload */ } } PRIVATE void handle_LYK_TRACE_LOG ARGS1( BOOLEAN *, trace_flag_ptr) { #ifndef NO_LYNX_TRACE /* * Check whether we've started a TRACE log * in this session. - FM */ if (LYTraceLogFP == NULL) { HTUserMsg(NO_TRACELOG_STARTED); return; } /* * Don't do if already viewing the TRACE log. - FM */ if (LYIsUIPage(curdoc.address, UIP_TRACELOG)) return; /* * If TRACE mode is on, turn it off during this fetch of the * TRACE log, so we don't enter stuff about this fetch, and * set a flag for turning it back on when we return to this * loop. Note that we'll miss any messages about memory * exhaustion if it should occur. It seems unlikely that * anything else bad might happen, but if it does, we'll * miss messages about that too. We also fflush(), close, * and open it again, to make sure all stderr messages thus * far will be in the log. - FM */ if (!LYReopenTracelog(trace_flag_ptr)) return; LYLocalFileToURL (&(newdoc.address), LYTraceLogPath); LYRegisterUIPage(newdoc.address, UIP_TRACELOG); StrAllocCopy(newdoc.title, LYNX_TRACELOG_TITLE); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; if (LYValidate || check_realm) { LYPermitURL = TRUE; } LYforce_no_cache = TRUE; #else HTUserMsg(TRACE_DISABLED); #endif /* NO_LYNX_TRACE */ } #ifdef DIRED_SUPPORT PRIVATE void handle_LYK_UPLOAD NOARGS { /* * Don't do if already viewing upload options page. */ if (LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS)) return; if (lynx_edit_mode && !no_dired_support) { LYUpload_options(&(newdoc.address), curdoc.address); StrAllocCopy(newdoc.title, UPLOAD_OPTIONS_TITLE); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; /* * Uncache the current listing so that it will * be updated to included the uploaded file if * placed in the current directory. - FM */ DIRED_UNCACHE_1; } } #endif /* DIRED_SUPPORT */ PRIVATE void handle_LYK_UP_HALF ARGS3( int *, arrowup, int *, old_c, int, real_c) { if (Newline > 1) { int scrollamount = display_lines/2; if (Newline - scrollamount < 1) scrollamount = Newline - 1; Newline -= scrollamount; if (nlinks > 0 && curdoc.link > -1) { if (links[curdoc.link].ly + scrollamount <= display_lines) { newdoc.link = curdoc.link + HText_LinksInLines(HTMainText, Newline, scrollamount); } else { *arrowup = TRUE; } } } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_BEGIN); } } PRIVATE void handle_LYK_UP_LINK ARGS4( int *, follow_col, int *, arrowup, int *, old_c, int, real_c) { if (curdoc.link > 0 && (links[0].ly != links[curdoc.link].ly || !HText_LinksInLines(HTMainText, 1, Newline - 1))) { /* more links before this on screen, and first of them on a different line or no previous links before this screen? */ int newlink; if (*follow_col == -1) { char *text = LYGetHiliteStr(curdoc.link, 0); *follow_col = links[curdoc.link].lx; if (text != NULL) *follow_col += strlen(text) / 2; } newlink = find_link_near_col(*follow_col, -1); if (newlink > -1) { set_curdoc_link(newlink); } else if (*old_c != real_c) { *old_c = real_c; HTUserMsg(NO_LINKS_ABOVE); } } else if (curdoc.line > 1 && Newline > 1) { /* previous page */ int scrollamount = (Newline > display_lines ? display_lines : Newline - 1); Newline -= scrollamount; if (scrollamount < display_lines && nlinks > 0 && curdoc.link > -1 && links[0].ly -1 + scrollamount <= display_lines) { newdoc.link = HText_LinksInLines(HTMainText, 1, scrollamount) - 1; } else { *arrowup = TRUE; } } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_BEGIN); } } PRIVATE void handle_LYK_UP_TWO ARGS3( int *, arrowup, int *, old_c, int, real_c) { if (Newline > 1) { int scrollamount = (Newline > 2 ? 2 : 1); Newline -= scrollamount; if (nlinks > 0 && curdoc.link > -1) { if (links[curdoc.link].ly + scrollamount <= display_lines) { newdoc.link = curdoc.link + HText_LinksInLines(HTMainText, Newline, scrollamount); } else { *arrowup = TRUE; } } } else if (*old_c != real_c) { *old_c = real_c; HTInfoMsg(ALREADY_AT_BEGIN); } } PRIVATE void handle_LYK_VIEW_BOOKMARK ARGS3( BOOLEAN *, refresh_screen, int *, old_c, int, real_c) { char *cp; if (LYValidate) { if (*old_c != real_c) { *old_c = real_c; HTUserMsg(BOOKMARKS_DISABLED); } return; } /* * See if a bookmark exists. * If it does replace newdoc.address with its name. */ if ((cp = get_bookmark_filename(&newdoc.address)) != NULL) { if (*cp == '\0' || !strcmp(cp, " ") || !strcmp(curdoc.address, newdoc.address)) { if (LYMultiBookmarks != MBM_OFF) *refresh_screen = TRUE; return; } #ifdef KANJI_CODE_OVERRIDE if (HTCJK == JAPANESE) { last_kcode = NOKANJI; /* AUTO */ } #endif LYforce_no_cache = TRUE; /*force the document to be reloaded*/ StrAllocCopy(newdoc.title, BOOKMARK_TITLE); StrAllocCopy(newdoc.bookmark, BookmarkPage); LYFreePostData(&newdoc); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; } else { if (*old_c != real_c) { *old_c = real_c; LYMBM_statusline(BOOKMARKS_NOT_OPEN); LYSleepAlert(); if (LYMultiBookmarks != MBM_OFF) { *refresh_screen = TRUE; } } } } PRIVATE BOOLEAN handle_LYK_VLINKS ARGS2( int *, cmd, BOOLEAN *, newdoc_link_is_absolute) { int c; if (LYIsUIPage(curdoc.address, UIP_VLINKS)) { /* * Already viewing visited links page, so get out. */ *cmd = LYK_PREV_DOC; return TRUE; } /* * Print visited links page to file. */ c = LYShowVisitedLinks(&newdoc.address); if (c < 0) { HTUserMsg(VISITED_LINKS_EMPTY); return FALSE; } StrAllocCopy(newdoc.title, VISITED_LINKS_TITLE); LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; if (c > 0) { /* Select a correct link. */ *newdoc_link_is_absolute = TRUE; newdoc.link = c - 1; } if (LYValidate || check_realm) { LYPermitURL = TRUE; StrAllocCopy(lynxlinksfile, newdoc.address); } return FALSE; } PUBLIC void handle_LYK_WHEREIS ARGS2( int, cmd, BOOLEAN *, refresh_screen) { BOOLEAN have_target_onscreen = (BOOLEAN) (*prev_target != '\0' && HText_pageHasPrevTarget()); BOOL found; int oldcur = curdoc.link; /* temporarily remember */ char *remember_old_target = NULL; if (have_target_onscreen) StrAllocCopy(remember_old_target, prev_target); else StrAllocCopy(remember_old_target, ""); if (cmd == LYK_WHEREIS) { /* * Reset prev_target to force prompting * for a new search string and to turn * off highlighting if no search string * is entered by the user. */ *prev_target = '\0'; } found = textsearch(&curdoc, prev_target, sizeof(prev_target)-1, (cmd == LYK_WHEREIS) ? 0 : ((cmd == LYK_NEXT) ? 1 : -1)); /* * Force a redraw to ensure highlighting of hits * even when found on the same page, or clearing * of highlighting if the default search string * was erased without replacement. - FM */ /* ** Well let's try to avoid it at least in a few cases ** where it is not needed. - kw */ if (www_search_result >= 0 && www_search_result != curdoc.line) { *refresh_screen = TRUE; /* doesn't really matter */ } else if (!found) { *refresh_screen = have_target_onscreen; } else if (!have_target_onscreen && found) { *refresh_screen = TRUE; } else if (www_search_result == curdoc.line && curdoc.link == oldcur && curdoc.link >= 0 && nlinks > 0 && links[curdoc.link].ly >= (display_lines/3)) { *refresh_screen = TRUE; } else if ((case_sensitive && 0!=strcmp(prev_target, remember_old_target)) || (!case_sensitive && 0!=strcasecomp8(prev_target, remember_old_target))) { *refresh_screen = TRUE; } FREE(remember_old_target); } /* * Get a number from the user and follow that link number. */ PRIVATE void handle_LYK_digit ARGS6( int, c, BOOLEAN *, force_load, char *, user_input_buffer, int *, old_c, int, real_c, BOOLEAN *, try_internal GCC_UNUSED) { int lindx = ((nlinks > 0) ? curdoc.link : 0); int number; char *temp = NULL; /* pass cur line num for use in follow_link_number() * Note: Current line may not equal links[cur].line */ number = curdoc.line; switch (follow_link_number(c, lindx, &newdoc, &number)) { case DO_LINK_STUFF: /* * Follow a normal link. */ set_address(&newdoc, links[lindx].lname); StrAllocCopy(newdoc.title, LYGetHiliteStr(lindx, 0)); #ifndef DONT_TRACK_INTERNAL_LINKS /* * For internal links, retain POST content if present. * If we are on the List Page, prevent pushing it on * the history stack. Otherwise set try_internal to * signal that the top of the loop should attempt to * reposition directly, without calling getfile. - kw */ if (links[lindx].type == WWW_INTERN_LINK_TYPE) { LYinternal_flag = TRUE; newdoc.internal_link = TRUE; if (LYIsListpageTitle(NonNull(curdoc.title)) && (LYIsUIPage(curdoc.address, UIP_LIST_PAGE) || LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE))) { if (check_history()) { LYinternal_flag = TRUE; } else { HTLastConfirmCancelled(); /* reset flag */ if (!confirm_post_resub(newdoc.address, newdoc.title, (LYresubmit_posts && HText_POSTReplyLoaded(&newdoc)) ? 1 : 2, 2)) { if (HTLastConfirmCancelled() || (LYresubmit_posts && !HText_POSTReplyLoaded(&newdoc))) { /* cancel the whole thing */ LYforce_no_cache = FALSE; reloading = FALSE; copy_address(&newdoc, &curdoc); StrAllocCopy(newdoc.title, curdoc.title); newdoc.internal_link = curdoc.internal_link; HTInfoMsg(CANCELLED); if (nlinks > 0) HText_pageDisplay(curdoc.line, prev_target); break; } else if (LYresubmit_posts) { /* If LYresubmit_posts is set, and the answer was No, and we have a cached copy, then use it. - kw */ LYforce_no_cache = FALSE; } else { /* if No, but not ^C or ^G, drop * the post data. Maybe the link * wasn't meant to be internal after * all, here we can recover from that * assumption. - kw */ LYFreePostData(&newdoc); newdoc.internal_link = FALSE; HTAlert(DISCARDING_POST_DATA); } } } /* * Don't push the List Page if we follow an * internal link given by it. - kw */ free_address(&curdoc); } else *try_internal = TRUE; if (!(LYresubmit_posts && newdoc.post_data)) LYinternal_flag = TRUE; *force_load = TRUE; break; } else { /* * Free POST content if not an internal link. - kw */ LYFreePostData(&newdoc); } #endif /* DONT_TRACK_INTERNAL_LINKS */ /* * Might be an anchor in the same doc from a POST * form. If so, don't free the content. -- FM */ if (are_different(&curdoc, &newdoc)) { LYFreePostData(&newdoc); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; if