#include "HTUtils.h" #include "tcp.h" #include "HTAccess.h" #include "HTParse.h" #include "HTList.h" #include "HTFTP.h" #include "HTFile.h" #include "HTTP.h" #include "LYCurses.h" #include "LYGlobalDefs.h" #include "HTAlert.h" #include "LYUtils.h" #include "GridText.h" #include "LYStrings.h" #include "LYOptions.h" #include "LYSignal.h" #include "LYGetFile.h" #include "HTForms.h" #include "LYSearch.h" #include "LYClean.h" #include "LYHistory.h" #include "LYPrint.h" #include "LYMail.h" #include "LYEdit.h" #include "LYShowInfo.h" #include "LYBookmark.h" #include "LYSystem.h" #include "LYKeymap.h" #include "LYJump.h" #include "LYDownload.h" #include "LYList.h" #include "LYMap.h" #include "LYTraversal.h" #include "LYCharSets.h" #include "LYCharUtils.h" #include "LYCookie.h" #ifdef DOSPATH #include "HTDOS.h" #endif #ifdef VMS #include "HTVMSUtils.h" #endif /* VMS */ #ifdef DIRED_SUPPORT #include "LYLocal.h" #include "LYUpload.h" #endif /* DIRED_SUPPORT */ #include "LYexit.h" #include "LYLeaks.h" extern BOOL reloading; /* For Flushing Cache on Proxy Server */ PRIVATE int are_different PARAMS((document *doc1, document *doc2)); PUBLIC void HTGotoURLs_free NOPARAMS; PUBLIC void HTAddGotoURL PARAMS((char *url)); #define FASTTAB #ifdef FASTTAB PRIVATE int sametext ARGS2( char *, een, char *, twee) { if (een && twee) return (strcmp(een, twee) == 0); return TRUE; } #endif /* FASTTAB */ #define FREE(x) if (x) {free(x); x = NULL;} PUBLIC HTList * Goto_URLs = NULL; /* List of Goto URLs */ PUBLIC char * LYRequestTitle = NULL; /* newdoc.title in calls to getfile() */ PRIVATE document newdoc; PRIVATE document curdoc; PRIVATE char *traversal_host = NULL; PRIVATE char *traversal_link_to_add = NULL; PRIVATE char *CurrentUserAgent = NULL; /* * Function for freeing allocated mainloop() variables. - FM */ PRIVATE void free_mainloop_variables NOARGS { FREE(newdoc.title); FREE(newdoc.address); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); FREE(curdoc.title); FREE(curdoc.address); FREE(curdoc.post_data); FREE(curdoc.post_content_type); FREE(curdoc.bookmark); FREE(traversal_host); FREE(traversal_link_to_add); FREE(CurrentUserAgent); #ifdef DIRED_SUPPORT clear_tags(); #endif /* DIRED_SUPPORT */ return; } /* * Here's where we do all the work. * mainloop is basically just a big switch dependent on the users input. * I have tried to offload most of the work done here to procedures to * make it more modular, but this procedure still does a lot of variable * manipulation. This needs some work to make it neater. - Lou Moutilli * (memoir from the original Lynx - FM) */ int mainloop NOARGS { int c = 0, real_c = 0, old_c = 0, cmd; int arrowup = FALSE, show_help = FALSE; int lines_in_file = -1; int Newline = 0; char prev_target[512]; char user_input_buffer[1024]; char *owner_address = NULL; /* Holds the responsible owner's address */ char *ownerS_address = NULL; /* Holds owner's address during source fetch */ BOOLEAN first_file = TRUE; BOOLEAN refresh_screen = FALSE; BOOLEAN force_load = FALSE; BOOLEAN crawl_ok = FALSE; BOOLEAN rlink_exists; BOOLEAN rlink_allowed; BOOLEAN vi_keys_flag = vi_keys; BOOLEAN emacs_keys_flag = emacs_keys; BOOLEAN keypad_mode_flag = keypad_mode; BOOLEAN user_mode_flag = user_mode; BOOLEAN HTfileSortMethod_flag = HTfileSortMethod; int CurrentCharSet_flag = current_char_set; BOOLEAN show_dotfiles_flag = show_dotfiles; BOOLEAN LYRawMode_flag = LYRawMode; BOOLEAN LYSelectPopups_flag = LYSelectPopups; char cfile[128]; FILE *cfp; char *cp, *toolbar; #ifdef VMS extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig */ #endif /* VMS */ int ch, recall; int URLTotal; int URLNum; BOOLEAN FirstURLRecall = TRUE; char *temp = NULL; BOOLEAN ForcePush = FALSE; unsigned int len; int i; #ifdef DIRED_SUPPORT char *tp; char tmpbuf[1024]; struct stat dir_info; #endif /* DIRED_SUPPORT */ /* * curdoc.address contains the name of the file that is currently open. * newdoc.address contains the name of the file that will soon be * opened if it exits. * prev_target contains the last search string the user searched for. * newdoc.title contains the link name that the user last chose to get * into the current link (file). */ /* initalize some variables*/ newdoc.address = NULL; newdoc.title = NULL; newdoc.post_data = NULL; newdoc.post_content_type = NULL; newdoc.bookmark = NULL; curdoc.address = NULL; curdoc.title = NULL; curdoc.post_data = NULL; curdoc.post_content_type = NULL; curdoc.bookmark = NULL; nhist = 0; user_input_buffer[(sizeof(user_input_buffer) - 1)] = '\0'; *prev_target = '\0'; *user_input_buffer = '\0'; StrAllocCopy(CurrentUserAgent, (LYUserAgent ? LYUserAgent : "")); atexit(free_mainloop_variables); initialize: StrAllocCopy(newdoc.address, startfile); StrAllocCopy(startrealm, startfile); StrAllocCopy(newdoc.title, "Entry into main screen"); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.line = 1; newdoc.link = 0; #ifdef USE_SLANG if (TRACE && LYCursesON) { addstr("\n"); refresh(); } #endif /* USE_SLANG */ if (TRACE) fprintf(stderr,"Entering mainloop, startfile=%s\n",startfile); if (form_post_data) { StrAllocCopy(newdoc.post_data, form_post_data); StrAllocCopy(newdoc.post_content_type, "application/x-www-form-urlencoded"); } else if (form_get_data) { StrAllocCat(newdoc.address, form_get_data); } if (bookmark_start) { if (LYValidate) { _statusline(BOOKMARKS_DISABLED); sleep(AlertSecs); bookmark_start = FALSE; goto initialize; } else if (traversal) { _statusline(BOOKMARKS_NOT_TRAVERSED); sleep(AlertSecs); traversal = FALSE; crawl = FALSE; bookmark_start = FALSE; goto initialize; } else { /* * See if a bookmark page exists. If it does, * replace newdoc.address with it's name */ if ((cp = get_bookmark_filename(&newdoc.address)) != NULL && *cp != '\0' && strcmp(cp, " ")) { StrAllocCopy(newdoc.title, BOOKMARK_TITLE); StrAllocCopy(newdoc.bookmark, BookmarkPage); StrAllocCopy(startrealm, newdoc.address); FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; if (TRACE) fprintf(stderr, "Using bookmarks=%s\n", newdoc.address); } else { _statusline(BOOKMARKS_NOT_OPEN); sleep(MessageSecs); bookmark_start = FALSE; goto initialize; } } } FREE(form_post_data); FREE(form_get_data); if (user_mode == NOVICE_MODE) display_lines = LYlines-4; else display_lines = LYlines-2; while (TRUE) { /* * If newdoc.address is different then curdoc.address then * we need to go out and find and load newdoc.address. */ if (LYforce_no_cache || force_load || are_different(&curdoc, &newdoc)) { force_load = FALSE; /* done */ if (TRACE && LYCursesON) { move(LYlines-1, LYcols-1); /* make sure cursor is down */ #ifdef USE_SLANG addstr("\n"); #endif /* USE_SLANG */ refresh(); } try_again: /* * Push the old file onto the history stack. */ if (curdoc.address && newdoc.address) { LYpush(&curdoc, ForcePush); } else if (!newdoc.address) { /* * If newdoc.address is empty then pop a file * and load it. Force a no_cache override unless * it's a bookmark file or it has POST content * and LYresubmit_posts is set. - FM */ LYpop(&newdoc); if ((newdoc.bookmark != NULL) || (newdoc.post_data != NULL && LYresubmit_posts)) { LYoverride_no_cache = FALSE; } else { LYoverride_no_cache = TRUE; } } if (HEAD_request) { /* * Make SURE this is an appropriate request. - FM */ if (newdoc.address && !strncmp(newdoc.address, "http", 4)) newdoc.isHEAD = TRUE; HEAD_request = FALSE; } LYRequestTitle = newdoc.title; if (newdoc.bookmark) LYforce_HTML_mode = TRUE; if (LYValidate && startfile_ok && newdoc.address && startfile && homepage && (!strcmp(newdoc.address, startfile) || !strcmp(newdoc.address, homepage))) { LYPermitURL = TRUE; } switch(getfile(&newdoc)) { case NOT_FOUND: /* * OK! can't find the file, so it must not be around now. * Do any error logging, if appropriate. */ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */ if (error_logging && first_file && owner_address && !LYCancelledFetch) { /* * Email a bad link message to the owner of * the document (but NOT to lynx-dev). - FM */ if (strncasecomp(owner_address, "mailto:", 7)) { if (strncasecomp((owner_address + 7), "lynx-dev@", 9)) { mailmsg(curdoc.link, (owner_address+7), history[nhist-1].address, history[nhist-1].title); } } } if (traversal && !first_file && !LYCancelledFetch) { FILE *ofp; if ((ofp = fopen(TRAVERSE_ERRORS,"a+")) == NULL) { if ((ofp = fopen(TRAVERSE_ERRORS,"w")) == NULL) { perror(NOOPEN_TRAV_ERR_FILE); #ifndef NOSIGHUP (void) signal(SIGHUP, SIG_DFL); #endif /* NOSIGHUP */ (void) signal(SIGTERM, SIG_DFL); #ifndef VMS (void) signal(SIGINT, SIG_DFL); #endif /* !VMS */ #ifdef SIGTSTP if (no_suspend) (void) signal(SIGTSTP,SIG_DFL); #endif /* SIGTSTP */ exit(-1); } } fprintf(ofp, "%s %s in %s\n", links[curdoc.link].lname, links[curdoc.link].target, history[nhist-1].address); fclose(ofp); } /* * Fall through to do the NULL stuff and reload the * old file, unless the first file wasn't found or * has gone missing. */ if (!nhist) { /* * If nhist = 0 then it must be the first file. */ if (!dump_output_immediately) cleanup(); printf("\nlynx: Can't access startfile %s\n", startfile); if (!dump_output_immediately) { #ifndef NOSIGHUP (void) signal(SIGHUP, SIG_DFL); #endif /* NOSIGHUP */ (void) signal(SIGTERM, SIG_DFL); #ifndef VMS (void) signal(SIGINT, SIG_DFL); #endif /* !VMS */ #ifdef SIGTSTP if (no_suspend) (void) signal(SIGTSTP,SIG_DFL); #endif /* SIGTSTP */ exit(-1); } return(-1); } case NULLFILE: /* * Not supposed to return any file. */ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */ FREE(newdoc.address); /* to pop last doc */ FREE(newdoc.bookmark); LYJumpFileURL = FALSE; reloading = FALSE; LYPermitURL = FALSE; LYCancelledFetch = FALSE; ForcePush = FALSE; if (traversal) { crawl_ok = FALSE; if (traversal_link_to_add) { /* * It's a binary file, or the fetch attempt * failed. Add it to TRAVERSE_REJECT_FILE * so we don't try again in this run. */ if (!lookup_reject(traversal_link_to_add)) { add_to_reject_list(traversal_link_to_add); } FREE(traversal_link_to_add); } } /* * Make sure the first file was found and * has not gone missing. */ if (!nhist) { /* * If nhist = 0 then it must be the first file. */ if (first_file && homepage && #ifdef VMS strcasecomp(homepage, startfile) != 0) #else strcmp(homepage, startfile) != 0) #endif /* VMS */ { /* * Couldn't return to the first file but there is a * homepage we can use instead. Useful for when the * first URL causes a program to be invoked. - GL * * But first make sure homepage is different from * startfile (above), then make it the same (below) * so we don't enter an infinite getfile() loop on * on failures to find the files. - FM */ StrAllocCopy(newdoc.address, homepage); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); StrAllocCopy(startfile, homepage); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; } else { if (!dump_output_immediately) cleanup(); printf( "\nlynx: Start file could not be found or is not text/html or text/plain\n"); printf(" Exiting...\n"); if (!dump_output_immediately) { #ifndef NOSIGHUP (void) signal(SIGHUP, SIG_DFL); #endif /* NOSIGHUP */ (void) signal(SIGTERM, SIG_DFL); #ifndef VMS (void) signal(SIGINT, SIG_DFL); #endif /* !VMS */ #ifdef SIGTSTP if (no_suspend) (void) signal(SIGTSTP,SIG_DFL); #endif /* SIGTSTP */ exit(-1); } return(-1); } } goto try_again; break; case NORMAL: /* * Marvelously, we got the document! */ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */ *prev_target = '\0'; /* Reset for this document. - FM */ /* * If it's the first file and we're interactive, * check whether it's a bookmark file which was * not accessed via the -book switch. - FM */ if (((first_file == TRUE) && (dump_output_immediately == FALSE) && !(newdoc.bookmark && *newdoc.bookmark)) && ((LYisLocalFile(newdoc.address) == TRUE) && !(strcmp((HText_getTitle() ? HText_getTitle() : ""), BOOKMARK_TITLE))) && (temp = HTParse(newdoc.address, "", PARSE_PATH+PARSE_PUNCTUATION)) != NULL) { #ifdef DOSPATH cp = HTDOS_wwwName((char *)Home_Dir()); #else #ifdef VMS cp = HTVMS_wwwName((char *)Home_Dir()); #else cp = (char *)Home_Dir(); #endif /* VMS */ #endif /* DOSPATH */ len = strlen(cp); #ifdef VMS if (!strncasecomp(temp, cp, len) && #else if (!strncmp(temp, cp, len) && #endif /* VMS */ strlen(temp) > len) { /* * We're interactive and this might be a * bookmark file entered as a startfile * rather than invoked via -book. Check * if it's in our bookmark file list, and * if so, reload if with the relevant * bookmark elements set. - FM */ if ((cp = (char *)calloc(1, (strlen((char *)&temp[len]) + 2))) == NULL) outofmem(__FILE__, "mainloop"); if (temp[len] == '/') { if (strchr((char *)&temp[(len + 1)], '/')) { sprintf(cp, ".%s", (char *)&temp[len]); } else { strcpy(cp, (char *)&temp[(len + 1)]); } } else { strcpy(cp, (char *)&temp[len]); } for (i = 0; i <= MBM_V_MAXFILES; i++) { if (MBM_A_subbookmark[i] && #ifdef VMS !strcasecomp(cp, MBM_A_subbookmark[i])) #else !strcmp(cp, MBM_A_subbookmark[i])) #endif /* VMS */ { StrAllocCopy(BookmarkPage, MBM_A_subbookmark[i]); break; } } FREE(cp); if (i <= MBM_V_MAXFILES) { FREE(temp); if (LYValidate) { _statusline(BOOKMARKS_DISABLED); sleep(AlertSecs); return(-1); } if ((temp = HTParse(newdoc.address, "", PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION))) { StrAllocCopy(newdoc.address, temp); HTuncache_current_document(); FREE(curdoc.address); #ifdef DOSPATH StrAllocCat(newdoc.address, HTDOS_wwwName((char *)Home_Dir())); #else #ifdef VMS StrAllocCat(newdoc.address, HTVMS_wwwName((char *)Home_Dir())); #else StrAllocCat(newdoc.address, Home_Dir()); #endif /* VMS */ #endif /* DOSPATH */ StrAllocCat(newdoc.address, "/"); StrAllocCat(newdoc.address, (strncmp(BookmarkPage, "./", 2) ? BookmarkPage : (BookmarkPage + 2))); StrAllocCopy(newdoc.title, BOOKMARK_TITLE); StrAllocCopy(newdoc.bookmark, BookmarkPage); StrAllocCopy(startrealm, newdoc.address); FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; FREE(temp); if (!strcmp(homepage, startfile)) StrAllocCopy(homepage, newdoc.address); StrAllocCopy(startfile, newdoc.address); if (TRACE) fprintf(stderr, "Reloading as bookmarks=%s\n", newdoc.address); goto try_again; } } } cp = NULL; } FREE(temp); if (traversal) { /* * During traversal build up lists of all links * traversed. Traversal mode is a special * feature for traversing http links in the web. */ if (traversal_link_to_add) { /* * Add the address we sought to TRAVERSE_FILE. */ if (!lookup(traversal_link_to_add)) add_to_table(traversal_link_to_add); FREE(traversal_link_to_add); } if (curdoc.address && curdoc.title && strncasecomp(curdoc.address, "LYNXIMGMAP:", 11)) /* * Add the address we got to TRAVERSE_FOUND_FILE. */ add_to_traverse_list(curdoc.address, curdoc.title); } /* * If this was a NORMAL download, we still have curdoc, * not a newdoc, so reset the address, title and * positioning elements. - FM */ if (newdoc.address && curdoc.title && !strncmp(newdoc.address, "LYNXDOWNLOAD:", 13) && !strcmp(curdoc.title, DOWNLOAD_OPTIONS_TITLE)) { StrAllocCopy(newdoc.address, curdoc.address); StrAllocCopy(newdoc.title, curdoc.title); StrAllocCopy(newdoc.bookmark, curdoc.bookmark); newdoc.line = curdoc.line; newdoc.link = curdoc.link; } /* * Set Newline to the saved line. It contains the * line the user was on if s/he has been in the file * before, or it is 1 if this is a new file. */ Newline = newdoc.line; /* * If we are going to a target line, * override any www_search line result. */ if (Newline > 1) www_search_result = -1; /* * Make sure curdoc.line will not be equal * to Newline, so we get a redraw. */ curdoc.line = -1; break; } /* end switch */ if (TRACE) sleep(AlertSecs); /* allow me to look at the results */ /* * Set the files the same. */ StrAllocCopy(curdoc.address, newdoc.address); StrAllocCopy(curdoc.post_data, newdoc.post_data); StrAllocCopy(curdoc.post_content_type, newdoc.post_content_type); StrAllocCopy(curdoc.bookmark, newdoc.bookmark); curdoc.isHEAD = newdoc.isHEAD; /* * Set the remaining document elements and add to * the visitied links list. - FM */ if (ownerS_address != NULL) { if (HTOutputFormat == WWW_SOURCE && !HText_getOwner()) HText_setMainTextOwner(ownerS_address); FREE(ownerS_address); } if (HText_getTitle()) { StrAllocCopy(curdoc.title, HText_getTitle()); } else if (!dump_output_immediately) { StrAllocCopy(curdoc.title, newdoc.title); } owner_address = HText_getOwner(); curdoc.safe = HTLoadedDocumentIsSafe(); if (!dump_output_immediately) { LYAddVisitedLink(&curdoc); } /* * Reset WWW present mode so that if we were getting * the source, we get rendered HTML from now on. */ HTOutputFormat = WWW_PRESENT; /* * Reset all of the other relevant flags. - FM */ LYUserSpecifiedURL = FALSE; /* only set for goto's and jumps's */ LYJumpFileURL = FALSE; /* only set for jump's */ LYNoRefererForThis = FALSE; /* always reset on return here */ reloading = FALSE; /* only set for RELOAD and RESUBMIT */ HEAD_request = FALSE; /* only set for HEAD requests */ LYPermitURL = FALSE; /* only set for LYValidate */ ForcePush = FALSE; /* only set for some PRINT requests. */ } /* end if (STREQ(newdoc.address, curdoc.address) */ if (dump_output_immediately) { if (crawl) { print_crawl_to_fd(stdout, curdoc.address, curdoc.title); } else { print_wwwfile_to_fd(stdout,0); } return(0); } /* * If the resent_sizechange variable is set to TRUE * then the window size changed recently. */ if (recent_sizechange) { stop_curses(); start_curses(); clear(); refresh_screen = TRUE; /* to force a redraw */ recent_sizechange=FALSE; if (user_mode==NOVICE_MODE) { display_lines = LYlines-4; } else { display_lines = LYlines-2; } } if (www_search_result != -1) { /* * This was a WWW search, set the line * to the result of the search. */ Newline = www_search_result; www_search_result = -1; /* reset */ more = HText_canScrollDown(); } if (first_file == TRUE) { /* * We can never again have the first file. */ first_file = FALSE; temp = HTParse(curdoc.address, "", PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION); if (!temp || *temp == '\0') { StrAllocCopy(startrealm, "None"); } else { StrAllocCopy(startrealm, temp); FREE(temp); if (!(temp = HTParse(curdoc.address, "", PARSE_PATH+PARSE_PUNCTUATION))) { if (startrealm[strlen(startrealm)-1] != '/') { StrAllocCat(startrealm, "/"); } } else { if ((cp = strrchr(temp, '/')) != NULL) { *(cp+1) = '\0'; StrAllocCat(startrealm, temp); } } } FREE(temp); if (TRACE) { fprintf(stderr, "Starting realm is '%s'\n\n", startrealm); } if (traversal) { /* * Set up the crawl output stuff. */ if (curdoc.address && !lookup(curdoc.address)) { if (strncasecomp(curdoc.address, "LYNXIMGMAP:", 11)) crawl_ok = TRUE; add_to_table(curdoc.address); } /* * Set up the traversal_host comparison string. */ if (strncmp((curdoc.address ? curdoc.address : "NULL"), "http", 4)) { StrAllocCopy(traversal_host, "None"); } else if (check_realm) { StrAllocCopy(traversal_host, startrealm); } else { temp = HTParse(curdoc.address, "", PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION); if (!temp || *temp == '\0') { StrAllocCopy(traversal_host, "None"); } else { StrAllocCopy(traversal_host, temp); if (traversal_host[strlen(traversal_host)-1] != '/') { StrAllocCat(traversal_host, "/"); } } FREE(temp); } if (TRACE) { fprintf(stderr, "Traversal host is '%s'\n\n", traversal_host); } } if (startfile) { /* * If homepage was not equated to startfile, * make the homepage URL the first goto * entry. - FM */ if (homepage && strcmp(startfile, homepage)) HTAddGotoURL(homepage); /* * If we are not starting up with startfile * (e.g., had -book), or if we are using the * startfile and it has no POST content, make * the startfile URL a goto entry. - FM */ if (strcmp(startfile, newdoc.address) || newdoc.post_data == NULL) HTAddGotoURL(startfile); } if (TRACE) { refresh_screen = TRUE; sleep(AlertSecs); } } /* * If the curdoc.line is different than Newline then there * must have been a change since last update. Run showpage. * showpage will put a fresh screen of text out. If this is * a WWW document then use the WWW routine HText_pageDisplay * to put the page on the screen. */ if (curdoc.line != Newline) { refresh_screen = FALSE; HText_pageDisplay(Newline, prev_target); #ifdef DIRED_SUPPORT if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged)) showtags(tagged); #endif /* DIRED_SUPPORT */ /* * If more equals TRUE, then there is more * info below this page . */ more = HText_canScrollDown(); curdoc.line = Newline = HText_getTopOfScreen()+1; lines_in_file = HText_getNumOfLines(); if (curdoc.title == NULL) { /* * If we don't yet have a title, try to get it, * or set to that for newdoc.title. - FM */ if (HText_getTitle()) { StrAllocCopy(curdoc.title, HText_getTitle()); } else { StrAllocCopy(curdoc.title, newdoc.title); } } if (arrowup) { /* * arrowup is set if we just came up from * a page below. */ curdoc.link = nlinks - 1; arrowup = FALSE; } else { curdoc.link = newdoc.link; if (curdoc.link >= nlinks) { curdoc.link = nlinks - 1; } else if (curdoc.link < 0 && nlinks > 0) { /* * We may have popped a doc (possibly in local_dired) * which didn't have any links when it was pushed, but * does have links now (e.g. a file was created) - KW */ curdoc.link = 0; } } show_help = FALSE; /* reset */ newdoc.line = 1; newdoc.link = 0; curdoc.line = Newline; /* set */ } /* * Refesh the screen if neccessary. */ if (refresh_screen) { clear(); HText_pageDisplay(Newline, prev_target); #ifdef DIRED_SUPPORT if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged)) showtags(tagged); #endif /* DIRED_SUPPORT */ if (user_mode == NOVICE_MODE) noviceline(more); /* print help message */ refresh_screen=FALSE; } /* * Report unread or new mail, if appropriate. */ if (check_mail && !no_mail && LYCheckMail()) sleep(MessageSecs); /* * If help is not on the screen, * then put a message on the screen * to tell the user other misc info. */ if (!show_help) { /* * Make sure form novice lines are replaced. */ if (user_mode == NOVICE_MODE) { noviceline(more); } /* * If we are in forms mode then explicitly * tell the user what each kind of link is. */ if (HTisDocumentSource()) { /* * Currently displaying HTML source. */ _statusline(SOURCE_HELP); #ifdef INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0) { #else #ifdef NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0 && links[curdoc.link].type != WWW_LINK_TYPE) { #else } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0 && !(user_mode == ADVANCED_MODE && links[curdoc.link].type == WWW_LINK_TYPE)) { #endif /* NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES */ #endif /* INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE */ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) switch(links[curdoc.link].form->type) { case F_PASSWORD_TYPE: if (links[curdoc.link].form->disabled == YES) statusline(FORM_LINK_PASSWORD_UNM_MSG); else statusline(FORM_LINK_PASSWORD_MESSAGE); break; case F_OPTION_LIST_TYPE: if (links[curdoc.link].form->disabled == YES) statusline(FORM_LINK_OPTION_LIST_UNM_MSG); else statusline(FORM_LINK_OPTION_LIST_MESSAGE); break; case F_CHECKBOX_TYPE: if (links[curdoc.link].form->disabled == YES) statusline(FORM_LINK_CHECKBOX_UNM_MSG); else statusline(FORM_LINK_CHECKBOX_MESSAGE); break; case F_RADIO_TYPE: if (links[curdoc.link].form->disabled == YES) statusline(FORM_LINK_RADIO_UNM_MSG); else statusline(FORM_LINK_RADIO_MESSAGE); break; case F_TEXT_SUBMIT_TYPE: if (links[curdoc.link].form->disabled == YES) { statusline(FORM_LINK_TEXT_SUBMIT_UNM_MSG); } else if (links[curdoc.link].form->submit_method == URL_MAIL_METHOD) { if (no_mail) statusline( FORM_LINK_TEXT_SUBMIT_MAILTO_DIS_MSG); else statusline(FORM_LINK_TEXT_SUBMIT_MAILTO_MSG); } else if (links[curdoc.link].form->no_cache) { statusline(FORM_LINK_TEXT_RESUBMIT_MESSAGE); } else { statusline(FORM_LINK_TEXT_SUBMIT_MESSAGE); } break; case F_SUBMIT_TYPE: case F_IMAGE_SUBMIT_TYPE: if (links[curdoc.link].form->disabled == YES) { statusline(FORM_LINK_SUBMIT_DIS_MSG); } else if (links[curdoc.link].form->submit_method == URL_MAIL_METHOD) { if (no_mail) { statusline(FORM_LINK_SUBMIT_MAILTO_DIS_MSG); } else { statusline(FORM_LINK_SUBMIT_MAILTO_MSG); } } else if (links[curdoc.link].form->no_cache) { statusline(FORM_LINK_RESUBMIT_MESSAGE); } else { statusline(FORM_LINK_SUBMIT_MESSAGE); } break; case F_RESET_TYPE: if (links[curdoc.link].form->disabled == YES) statusline(FORM_LINK_RESET_DIS_MSG); else statusline(FORM_LINK_RESET_MESSAGE); break; case F_TEXT_TYPE: case F_TEXTAREA_TYPE: if (links[curdoc.link].form->disabled == YES) statusline(FORM_LINK_TEXT_UNM_MSG); else statusline(FORM_LINK_TEXT_MESSAGE); break; } else statusline(NORMAL_LINK_MESSAGE); /* * Let them know if it's an index -- very rare. */ if (is_www_index) { move(LYlines-1,LYcols-8); start_reverse(); addstr("-index-"); stop_reverse(); } } else if (user_mode == ADVANCED_MODE && nlinks > 0) { /* * Show the URL. */ if (more) if (is_www_index) _user_message("-more- -index- %s", links[curdoc.link].lname); else _user_message("-more- %s",links[curdoc.link].lname); else if (is_www_index) _user_message("-index- %s",links[curdoc.link].lname); else statusline(links[curdoc.link].lname); } else if (is_www_index && more) { char buf[128]; sprintf(buf, WWW_INDEX_MORE_MESSAGE, key_for_func(LYK_INDEX_SEARCH)); _statusline(buf); } else if (is_www_index) { char buf[128]; sprintf(buf, WWW_INDEX_MESSAGE, key_for_func(LYK_INDEX_SEARCH)); _statusline(buf); } else if (more) { if (user_mode == NOVICE_MODE) _statusline(MORE); else _statusline(MOREHELP); } else { _statusline(HELP); } } else { show_help = FALSE; } if (!(nlinks > 0 && links[curdoc.link].type == WWW_FORM_LINK_TYPE && (links[curdoc.link].form->type == F_TEXT_TYPE || links[curdoc.link].form->type == F_TEXTAREA_TYPE))) highlight(ON, curdoc.link); /* highlight current link */ if (traversal) { /* * Don't go interactively into forms, * or accept keystrokes from the user */ if (crawl && crawl_ok) { crawl_ok = FALSE; sprintf(cfile,"lnk%08d.dat",ccount); ccount = ccount + 1; if ((cfp = fopen(cfile,"w")) != NULL) { print_crawl_to_fd(cfp,curdoc.address,curdoc.title); fclose(cfp); } else { if (!dump_output_immediately) cleanup(); printf( "Fatal error - could not open output file %s\n",cfile); if (!dump_output_immediately) { #ifndef NOSIGHUP (void) signal(SIGHUP, SIG_DFL); #endif /* NOSIGHUP */ (void) signal(SIGTERM, SIG_DFL); #ifndef VMS (void) signal(SIGINT, SIG_DFL); #endif /* !VMS */ #ifdef SIGTSTP if (no_suspend) (void) signal(SIGTSTP,SIG_DFL); #endif /* SIGTSTP */ exit(-1); } return(-1); } } } else { /* * Normal, non-traversal handling. */ if (nlinks > 0 && links[curdoc.link].type == WWW_FORM_LINK_TYPE && (links[curdoc.link].form->type == F_TEXT_TYPE || links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE || links[curdoc.link].form->type == F_PASSWORD_TYPE || links[curdoc.link].form->type == F_TEXTAREA_TYPE)) { /* * Replace novice lines if in NOVICE_MODE. */ if (user_mode==NOVICE_MODE) { move(LYlines-2,0); clrtoeol(); addstr(FORM_NOVICELINE_ONE); move(LYlines-1,0); clrtoeol(); addstr(FORM_NOVICELINE_TWO); } c=change_form_link(&links[curdoc.link], FORM_UP, &newdoc, &refresh_screen, links[curdoc.link].form->name, links[curdoc.link].form->value); if (c == '\n' || c == '\r') #ifdef FASTTAB /* * Make return act like down-arrow. */ c = DNARROW; #else /* * Make return act like tab. */ c = '\t'; #endif /* FASTTAB */ } else { /* * Get a keystroke from the user. * Save the last keystroke to avoid * redundant error reporting. */ real_c = c = LYgetch(); /* get user input */ #ifndef VMS if (c == 3) { /* ^C */ /* * This shouldn't happen. We'll try to * deal with whatever bug caused it. - FM */ signal(SIGINT, cleanup_sig); old_c = 0; cmd = LYK_QUIT; goto new_cmd; } #endif /* !VMS */ if (old_c != real_c) { old_c = 0; } } } #ifdef VMS if (HadVMSInterrupt) { HadVMSInterrupt = FALSE; c = DO_NOTHING; } #else if (recent_sizechange) { if (c <= 0) c = DO_NOTHING; } #endif /* VMS */ new_keyboard_input: /* * A goto point for new input without going * back through the getch() loop. */ if (traversal) { /* * This is a special feature to traverse every http link * derived from startfile and check for errors or create * crawl ouput 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!). */ rlink_exists = (nlinks > 0 && links[curdoc.link].lname != NULL); if (rlink_exists) { rlink_allowed = (!lookup_reject(links[curdoc.link].lname) && traversal_host && links[curdoc.link].lname && !strncmp(traversal_host, (strncasecomp(links[curdoc.link].lname, "LYNXIMGMAP:", 11) ? links[curdoc.link].lname : (links[curdoc.link].lname + 11)), strlen(traversal_host))); } 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(); #ifndef NOSIGHUP (void) signal(SIGHUP, SIG_DFL); #endif /* NOSIGHUP */ (void) signal(SIGTERM, SIG_DFL); #ifndef VMS (void) signal(SIGINT, SIG_DFL); #endif /* !VMS */ #ifdef SIGTSTP if (no_suspend) (void) signal(SIGTSTP,SIG_DFL); #endif /* SIGTSTP */ exit(-1); } return(-1); } c=LTARROW; } } else { StrAllocCopy(traversal_link_to_add, links[curdoc.link].lname); if (strncasecomp(traversal_link_to_add, "LYNXIMGMAP:", 11)) crawl_ok = TRUE; c = RTARROW; } } else { /* no good right link, so only down and left arrow ok*/ if (rlink_exists) 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(); #ifndef NOSIGHUP (void) signal(SIGHUP, SIG_DFL); #endif /* NOSIGHUP */ (void) signal(SIGTERM, SIG_DFL); #ifndef VMS (void) signal(SIGINT, SIG_DFL); #endif /* !VMS */ #ifdef SIGTSTP if (no_suspend) (void) signal(SIGTSTP,SIG_DFL); #endif /* SIGTSTP */ exit(-1); } return(-1); } c=LTARROW; } } /* right link not NULL or link to another site*/ } /* traversal */ cmd=keymap[c+1]; /* add 1 to map EOF to 0 */ #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) if (lynx_edit_mode && override[c+1] && !no_dired_support) cmd = override[c+1]; #endif /* DIRED_SUPPORT && OK_OVERRIDE */ new_cmd: /* * A goto point for new input without going * back through the getch() loop. */ switch(cmd) { case 0: /* unmapped character */ default: if (more) _statusline(MOREHELP); else _statusline(HELP); show_help = TRUE; if (TRACE) { sprintf(cfile, "%d", c); addstr(cfile); /* show the user input */ cfile[0] = '\0'; } break; case LYK_INTERRUPT: /* * No network transmission to interrupt - 'til we multithread. */ break; case LYK_1: case LYK_2: case LYK_3: case LYK_4: case LYK_5: case LYK_6: case LYK_7: case LYK_8: case LYK_9: /* * Get a number from the user and follow that link number. */ switch(follow_link_number(c, ((nlinks > 0) ? curdoc.link : 0))) { case DO_LINK_STUFF: /* * Follow a normal link. */ if (nlinks > 0) StrAllocCopy(newdoc.address, links[curdoc.link].lname); else StrAllocCopy(newdoc.address, links[0].lname); /* * 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)) { FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; } force_load = TRUE; /* force MainLoop to reload */ break; case PRINT_ERROR: if (old_c == real_c) break; old_c = real_c; _statusline(BAD_LINK_NUM_ENTERED); sleep(MessageSecs); break; } break; case LYK_SOURCE: /* toggle view source mode */ /* * 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) { _statusline(CANCELLED); sleep(InfoSecs); break; } if (HTisDocumentSource()) { HTOutputFormat = WWW_PRESENT; } else { if (HText_getOwner()) StrAllocCopy(ownerS_address, HText_getOwner()); HTOutputFormat = WWW_SOURCE; } HTuncache_current_document(); FREE(curdoc.address); /* so it doesn't get pushed */ break; case LYK_RELOAD: /* control-R to reload and refresh */ /* * 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) { _statusline(CANCELLED); sleep(InfoSecs); break; } /* * Check to see if should reload source, or load html */ if (HTisDocumentSource()) { HTOutputFormat = WWW_SOURCE; } HEAD_request = HTLoadedDocumentIsHEAD(); HTuncache_current_document(); #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) */ if (lynx_mode == FORMS_LYNX_MODE) { /* * Note that if there are no form links on the current * page, lynx_mode won't have this setting and we won't * know that this warning should be issued. - FM */ _statusline(RELOADING_FORM); sleep(AlertSecs); } newdoc.line = ((curdoc.line > 0) ? curdoc.line : 1); newdoc.link = ((curdoc.link > -1) ? curdoc.link : 0); #endif /* NO_ASSUME_SAME_DOC */ FREE(curdoc.address); /* so it doesn't get pushed */ #ifdef VMS clearok(curscr, TRUE); #endif /* VMS */ /* * Reload should force a cache refresh on a proxy. * -- Ari L. */ reloading = TRUE; break; case LYK_HISTORICAL: /* * 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) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { _statusline(WILL_NOT_RELOAD_DOC); sleep(InfoSecs); } else { HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); FREE(curdoc.address); } if (historical_comments) historical_comments = FALSE; else historical_comments = TRUE; if (minimal_comments) { _statusline(historical_comments ? HISTORICAL_ON_MINIMAL_OFF : HISTORICAL_OFF_MINIMAL_ON); } else { _statusline(historical_comments ? HISTORICAL_ON_VALID_OFF : HISTORICAL_OFF_VALID_ON); } sleep(AlertSecs); break; case LYK_MINIMAL: if (!historical_comments) { /* * 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) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { _statusline(WILL_NOT_RELOAD_DOC); sleep(InfoSecs); } else { HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); FREE(curdoc.address); } } if (minimal_comments) minimal_comments = FALSE; else minimal_comments = TRUE; if (!historical_comments) { _statusline(minimal_comments ? MINIMAL_ON_IN_EFFECT : MINIMAL_OFF_VALID_ON); } else { _statusline(minimal_comments ? MINIMAL_ON_BUT_HISTORICAL : MINIMAL_OFF_HISTORICAL_ON); } sleep(AlertSecs); break; case LYK_SOFT_DQUOTES: /* * 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) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { _statusline(WILL_NOT_RELOAD_DOC); sleep(InfoSecs); } else { HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); FREE(curdoc.address); } if (soft_dquotes) soft_dquotes = FALSE; else soft_dquotes = TRUE; _statusline(soft_dquotes ? SOFT_DOUBLE_QUOTE_ON : SOFT_DOUBLE_QUOTE_OFF); sleep(MessageSecs); break; #ifdef NOT_DONE_YET case LYK_PIPE: /* ignore for now */ break; #endif /* NOT_DONE_YET */ case LYK_QUIT: /* quit */ _statusline(REALLY_QUIT); c = LYgetch(); #ifdef QUIT_DEFAULT_YES if (TOUPPER(c) != 'N') #else if (TOUPPER(c) == 'Y') #endif /* QUIT_DEFAULT_YES */ return(0); else { statusline(NO_CANCEL); sleep(InfoSecs); } break; case LYK_ABORT: /* don't ask the user about quitting */ return(0); break; case LYK_NEXT_PAGE: /* next page */ if (more) { Newline += display_lines; } else if (curdoc.link < nlinks-1) { highlight(OFF,curdoc.link); curdoc.link = nlinks-1; /* put on last link */ } else if (old_c != real_c) { old_c = real_c; _statusline(ALREADY_AT_END); sleep(MessageSecs); } break; case LYK_PREV_PAGE: /* page up */ if (Newline > 1) { Newline -= display_lines; } else if (curdoc.link > 0) { highlight(OFF,curdoc.link); curdoc.link = 0; /* put on last link */ } else if (old_c != real_c) { old_c = real_c; _statusline(ALREADY_AT_BEGIN); sleep(MessageSecs); } break; case LYK_UP_TWO: if (Newline > 1) { Newline -= 2; if (nlinks > 0 && curdoc.link > -1) { if (links[curdoc.link].ly <= (display_lines - 2)) { newdoc.link = curdoc.link + HText_LinksInLines(HTMainText, Newline, 2); } else { arrowup = TRUE; } } } else if (old_c != real_c) { old_c = real_c; _statusline(ALREADY_AT_BEGIN); sleep(MessageSecs); } break; case LYK_DOWN_TWO: 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; _statusline(ALREADY_AT_END); sleep(MessageSecs); } break; case LYK_UP_HALF: if (Newline > 1) { Newline -= display_lines/2; if (nlinks > 0 && curdoc.link > -1) { if (links[curdoc.link].ly <= (display_lines/2)) { newdoc.link = curdoc.link + HText_LinksInLines(HTMainText, Newline, (display_lines/2)); } else { arrowup = TRUE; } } } else if (old_c != real_c) { old_c = real_c; _statusline(ALREADY_AT_BEGIN); sleep(MessageSecs); } break; case LYK_DOWN_HALF: 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; _statusline(ALREADY_AT_END); sleep(MessageSecs); } break; case LYK_REFRESH: refresh_screen=TRUE; #ifdef VMS clearok(curscr, TRUE); #endif /* VMS */ break; case LYK_HOME: if (curdoc.line > 1) Newline = 1; else { cmd = LYK_PREV_PAGE; goto new_cmd; } break; case LYK_END: if (more) { Newline = MAXINT; /* go to end of file */ arrowup = TRUE; /* position on last link */ } else { cmd = LYK_NEXT_PAGE; goto new_cmd; } break; case LYK_PREV_LINK: if (curdoc.link > 0) { /* previous link */ highlight(OFF, curdoc.link); /* unhighlight the current link */ curdoc.link--; } 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, then just move the cursor to * last link on the page. */ highlight(OFF,curdoc.link); /* unhighlight the current link */ curdoc.link = nlinks-1; /* the last link */ } else if (curdoc.line > 1) { /* previous page */ /* * Go back to the previous page. */ Newline -= (display_lines); arrowup = TRUE; } else if (old_c != real_c) { old_c = real_c; _statusline(ALREADY_AT_BEGIN); sleep(MessageSecs); } break; case LYK_NEXT_LINK: if (curdoc.link < nlinks-1) { /* next link */ highlight(OFF, curdoc.link); #ifdef FASTTAB /* * Move to different textarea if TAB in textarea. */ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].form->type == F_TEXTAREA_TYPE && c=='\t') { int thisgroup = links[curdoc.link].form->number; char *thisname = links[curdoc.link].form->name; do curdoc.link++; while ((curdoc.link < nlinks-1) && links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].form->type == F_TEXTAREA_TYPE && links[curdoc.link].form->number == thisgroup && sametext(links[curdoc.link].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) { highlight(OFF,curdoc.link); curdoc.link = 0; } else if (more) { /* next page */ Newline += (display_lines); } else if (old_c != real_c) { old_c = real_c; _statusline(ALREADY_AT_END); sleep(MessageSecs); } break; case LYK_UP_LINK: if (curdoc.link > 0) { /* more links above? */ int newlink = -1; for (i = curdoc.link; i >= 0; i--) { if (links[i].ly < links[curdoc.link].ly) { newlink = i; break; } } if (newlink > -1) { highlight(OFF, curdoc.link); curdoc.link = newlink; #ifdef NOTDEFINED } else if (!more && Newline == 1 && curdoc.link == 0) { highlight(OFF, curdoc.link); curdoc.link = (nlinks-1); } else if (more) { /* next page */ Newline += (display_lines); } #else } else if (old_c != real_c) { old_c = real_c; _statusline(NO_LINKS_ABOVE); sleep(MessageSecs); } #endif /* NOTDEFINED */ #ifdef NOTDEFINED /* * 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)) { highlight(OFF, curdoc.link); curdoc.link = 0; #endif /* NOTDEFINED */ } else if (curdoc.line > 1 && Newline > 1) { /* previous page */ Newline -= (display_lines); arrowup = TRUE; } else if (old_c != real_c) { old_c = real_c; _statusline(ALREADY_AT_BEGIN); sleep(MessageSecs); } break; case LYK_DOWN_LINK: if (curdoc.link < (nlinks-1)) { /* more links? */ int newlink = -1; for (i = curdoc.link; i < nlinks; i++) if (links[i].ly > links[curdoc.link].ly) { newlink = i; break; } if (newlink > -1) { highlight(OFF, curdoc.link); curdoc.link = newlink; #ifdef NOTDEFINED } else if (!more && Newline == 1 && curdoc.link == (nlinks-1)) { highlight(OFF, curdoc.link); curdoc.link = 0; #endif /* NOTDEFINED */ } else if (more) { /* next page */ Newline += (display_lines); } else if (old_c != real_c) { old_c = real_c; _statusline(NO_LINKS_BELOW); sleep(MessageSecs); break; } #ifdef NOTDEFINED /* * 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)) { highlight(OFF, curdoc.link); curdoc.link = 0; #endif /* NOTDEFINED */ } else if (more) { /* next page */ Newline += (display_lines); } else if (old_c != real_c) { old_c = real_c; _statusline(ALREADY_AT_END); sleep(MessageSecs); } break; case LYK_RIGHT_LINK: if (curdoc.link0 && links[curdoc.link].ly == links[curdoc.link-1].ly) { highlight(OFF,curdoc.link); curdoc.link--; } break; case LYK_COOKIE_JAR: /* show the cookie jar */ /* * Don't do if already viewing the cookie jar. */ if (strcmp(curdoc.title, COOKIE_JAR_TITLE)) { StrAllocCopy(newdoc.address, "LYNXCOOKIE:/"); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; LYforce_no_cache = TRUE; if (LYValidate || check_realm) { LYPermitURL = TRUE; } } else { /* * If already in the cookie jar, get out. */ cmd = LYK_PREV_DOC; goto new_cmd; } break; case LYK_HISTORY: /* show the history page */ if (curdoc.title && strcmp(curdoc.title, HISTORY_PAGE_TITLE)) { /* * 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 && LYCursesON) { move(LYlines-1, LYcols-1); /* make sure cursor is down */ #ifdef USE_SLANG addstr("\n"); #endif /* USE_SLANG */ refresh(); } LYpush(&curdoc, ForcePush); /* * Print history options to file. */ if (showhistory(&newdoc.address) < 0) { LYpop(&curdoc); break; } FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; FREE(curdoc.address); /* so it doesn't get pushed */ refresh_screen = TRUE; if (LYValidate || check_realm) { LYPermitURL = TRUE; } break; } /* end if strncmp */ /* * Don't put break here so that if the backspace key * is pressed in the history page, we fall though, * i.e., it acts like a left arrow. */ case LYK_PREV_DOC: /* back up a level */ 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; while (nhist > 0) { if (history[(nhist - 1)].post_data == NULL) { break; } WWWDoc.address = history[(nhist - 1)].address; WWWDoc.post_data = history[(nhist - 1)].post_data; WWWDoc.post_content_type = history[(nhist - 1)].post_content_type; WWWDoc.bookmark = history[(nhist - 1)].bookmark; WWWDoc.isHEAD = history[(nhist - 1)].isHEAD; WWWDoc.safe = history[(nhist - 1)].safe; tmpanchor = HTAnchor_parent(HTAnchor_findAddress(&WWWDoc)); if (HTAnchor_safe(tmpanchor)) { break; } if ((LYresubmit_posts || (HText *)HTAnchor_document(tmpanchor) == NULL) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { if (nhist == 1) { _statusline(CANCELLED); sleep(InfoSecs); old_c = 0; cmd = LYK_DO_NOTHING; goto new_cmd; } else { _user_message(WWW_SKIP_MESSAGE, WWWDoc.address); sleep(MessageSecs); LYpop(&curdoc); continue; } } else { break; } } /* * Set newdoc.address to empty to pop a file. */ FREE(newdoc.address); #ifdef DIRED_SUPPORT if (lynx_edit_mode) HTuncache_current_document(); #endif /* DIRED_SUPPORT */ } else if (child_lynx == TRUE) { return(0); /* exit on left arrow in main screen */ } else if (old_c != real_c) { old_c = real_c; _statusline(ALREADY_AT_FIRST); sleep(MessageSecs); } break; case LYK_NOCACHE: /* Force submission of form or link with no-cache */ if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].form->type != F_SUBMIT_TYPE && links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE) { if (old_c == real_c) break; old_c = real_c; _statusline(NOT_ON_SUBMIT_OR_LINK); sleep(MessageSecs); break; } else { LYforce_no_cache = TRUE; reloading = TRUE; } } /* fall through to LYK_ACTIVATE */ case LYK_ACTIVATE: /* follow a link */ { /* Is there a mouse-clicked link waiting? */ int mouse_tmp = get_mouse_link(); /* If yes, use it as the link */ if (mouse_tmp != -1) curdoc.link = mouse_tmp; } if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) { /* * Don't try to submit forms with bad actions. - FM */ if (links[curdoc.link].form->type == F_SUBMIT_TYPE || links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE || links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE) { /* * Do nothing if it's disabled. - FM */ if (links[curdoc.link].form->disabled == YES) { HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; break; } /* * Make sure we have an action. - FM */ if (!links[curdoc.link].form->submit_action || *links[curdoc.link].form->submit_action == '\0') { _statusline(NO_FORM_ACTION); sleep(MessageSecs); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; break; } /* * Check for no_mail if the form action * is a mailto URL. - FM */ if (links[curdoc.link].form->submit_method == URL_MAIL_METHOD && no_mail) { HTAlert(FORM_MAILTO_DISALLOWED); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; break; } /* * Make sure this isn't a spoof in an account * with restrictions on file URLs. - FM */ if (no_file_url && !strncasecomp( links[curdoc.link].form->submit_action, "file:", 5)) { HTAlert(FILE_ACTIONS_DISALLOWED); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; break; } #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].form->submit_enctype) { if (!strcmp( links[curdoc.link].form->submit_enctype, "multipart/form-data")) { HTAlert( "Enctype multipart/form-data not yet supported! Cannot submit."); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; break; } } #endif /* NOTDEFINED */ if (check_realm) { LYPermitURL = TRUE; } if (no_filereferer == TRUE && !strncasecomp(curdoc.address, "file:", 5)) { LYNoRefererForThis = TRUE; } } c = change_form_link(&links[curdoc.link], FORM_UP, &newdoc, &refresh_screen, links[curdoc.link].form->name, links[curdoc.link].form->value); if (HTOutputFormat == HTAtom_for("www/download") && newdoc.post_data != NULL && newdoc.safe == FALSE) { if ((HText_POSTReplyLoaded(&newdoc) == TRUE) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { _statusline(CANCELLED); sleep(InfoSecs); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; StrAllocCopy(newdoc.address, curdoc.address); StrAllocCopy(newdoc.title, curdoc.title); StrAllocCopy(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; break; } } goto new_keyboard_input; } 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 && !strncasecomp(links[curdoc.link].lname, "file:", 5)) { if (strncasecomp(curdoc.address, "file:", 5)) { HTAlert(FILE_SERVED_LINKS_DISALLOWED); break; } else if (curdoc.bookmark != NULL) { HTAlert(FILE_BOOKMARKS_DISALLOWED); break; } } /* * Follow a normal link or anchor. */ StrAllocCopy(newdoc.address, links[curdoc.link].lname); StrAllocCopy(newdoc.title, links[curdoc.link].hightext); /* * 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)) { FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); } if (!no_jump && lynxjumpfile && curdoc.address && !strcmp(lynxjumpfile, curdoc.address)) { LYJumpFileURL = TRUE; LYUserSpecifiedURL = TRUE; } else if ((curdoc.title && !strcmp(curdoc.title, HISTORY_PAGE_TITLE)) || curdoc.bookmark != NULL || (lynxjumpfile && !strcmp(lynxjumpfile, curdoc.address))) { LYUserSpecifiedURL = TRUE; } else if (no_filereferer == TRUE && !strncasecomp(curdoc.address, "file:", 5)) { LYNoRefererForThis = TRUE; } newdoc.link = 0; force_load = TRUE; /* force MainLoop to reload */ #ifdef DIRED_SUPPORT if (lynx_edit_mode) { HTuncache_current_document(); /* * Unescaping any slash chars in the URL, * but avoid double unescaping and too-early * unescaping of other chars. - KW */ HTUnEscapeSome(newdoc.address,"/"); strip_trailing_slash(newdoc.address); } #endif /* DIRED_SUPPORT */ if (!strncasecomp(curdoc.address, "LYNXCOOKIE:", 11)) { HTuncache_current_document(); } } } break; case LYK_ECGOTO: /* edit current URL and go to to it */ if (no_goto && !LYValidate) { if (old_c != real_c) { old_c = real_c; _statusline(GOTO_DISALLOWED); sleep(MessageSecs); } break; } /* * Save the current user_input_buffer string, * and load the current document's address. */ StrAllocCopy(temp, user_input_buffer); LYstrncpy(user_input_buffer, curdoc.address, (sizeof(user_input_buffer) - 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, sizeof(user_input_buffer), RECALL)) >= 0) && user_input_buffer[0] != '\0' && strcmp(user_input_buffer, curdoc.address)) { LYTrimHead(user_input_buffer); if (!strncasecomp(user_input_buffer, "lynxexec:", 9) || !strncasecomp(user_input_buffer, "lynxprog:", 9)) { /* * The original implementations of these schemes expected * white space without hex escaping, and did not check * for hex escaping, so we'll continue to support that, * until that code is redone in conformance with SGML * principles. - FM */ HTUnEscapeSome(user_input_buffer, " \r\n\t"); convert_to_spaces(user_input_buffer, TRUE); } else { collapse_spaces(user_input_buffer); } if (user_input_buffer[0] != '\0') { goto check_goto_URL; } } /* * User cancelled via ^G, a full deletion, * or not modifying the URL. - FM */ _statusline(CANCELLED); sleep(InfoSecs); strcpy(user_input_buffer, temp); FREE(temp); break; case LYK_GOTO: /* 'g' to goto a random URL */ if (no_goto && !LYValidate) { if (old_c != real_c) { old_c = real_c; _statusline(GOTO_DISALLOWED); sleep(MessageSecs); } break; } StrAllocCopy(temp, 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 : NORECALL); URLNum = 0; FirstURLRecall = FALSE; } else { recall = ((URLTotal >= 1) ? RECALL : NORECALL); URLNum = URLTotal; FirstURLRecall = TRUE; } /* * Ask the user. */ _statusline(URL_TO_OPEN); if ((ch = LYgetstr(user_input_buffer, VISIBLE, sizeof(user_input_buffer), recall)) < 0 ) { /* * User cancelled the Goto via ^G. * Restore user_input_buffer and break. - FM */ strcpy(user_input_buffer, temp); FREE(temp); _statusline(CANCELLED); sleep(InfoSecs); break; } check_recall: /* * Get rid of leading spaces (and any other spaces). */ LYTrimHead(user_input_buffer); if (!strncasecomp(user_input_buffer, "lynxexec:", 9) || !strncasecomp(user_input_buffer, "lynxprog:", 9)) { /* * The original implementations of these schemes expected * white space without hex escaping, and did not check * for hex escaping, so we'll continue to support that, * until that code is redone in conformance with SGML * principles. - FM */ HTUnEscapeSome(user_input_buffer, " \r\n\t"); convert_to_spaces(user_input_buffer, TRUE); } else { collapse_spaces(user_input_buffer); } if (*user_input_buffer == '\0' && !(recall && (ch == UPARROW || ch == DNARROW))) { strcpy(user_input_buffer, temp); FREE(temp); _statusline(CANCELLED); sleep(InfoSecs); 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++; } if (URLNum >= URLTotal) /* * Roll around to the last URL in the list. - FM */ URLNum = 0; if ((cp = (char *)HTList_objectAt(Goto_URLs, URLNum)) != NULL) { strcpy(user_input_buffer, cp); if (goto_buffer && *temp && !strcmp(temp, 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, sizeof(user_input_buffer), recall)) < 0) { /* * User cancelled the Goto via ^G. * Restore user_input_buffer and break. - FM */ strcpy(user_input_buffer, temp); FREE(temp); _statusline(CANCELLED); sleep(InfoSecs); break; } goto check_recall; } } 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--; } 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) { strcpy(user_input_buffer, cp); if (goto_buffer && *temp && !strcmp(temp, 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, sizeof(user_input_buffer), recall)) < 0) { /* * User cancelled the Goto via ^G. * Restore user_input_buffer and break. - FM */ strcpy(user_input_buffer, temp); FREE(temp); _statusline(CANCELLED); sleep(InfoSecs); break; } goto check_recall; } } check_goto_URL: /* * If its not a URL then make it one. */ StrAllocCopy(temp, user_input_buffer); LYFillLocalFileURL((char **)&temp, "file://localhost"); LYEnsureAbsoluteURL((char **)&temp, ""); sprintf(user_input_buffer, "%.*s", (int)(sizeof(user_input_buffer) - 1), temp); FREE(temp); if ((no_file_url || no_goto_file) && !strncmp(user_input_buffer,"file:",5)) { _statusline(GOTO_FILE_DISALLOWED); sleep(MessageSecs); #ifdef EXEC_LINKS } else if ((no_shell || no_goto_lynxexec || local_exec_on_local_files) && #else } else if ((no_shell || no_goto_lynxexec) && #endif /* EXEC_LINKS */ !strncmp(user_input_buffer, "lynxexec:",9)) { _statusline(GOTO_EXEC_DISALLOWED); sleep(MessageSecs); #ifdef EXEC_LINKS } else if ((no_shell || no_goto_lynxprog || local_exec_on_local_files) && #else } else if ((no_shell || no_goto_lynxprog) && #endif /* EXEC_LINKS */ !strncmp(user_input_buffer, "lynxprog:",9)) { _statusline(GOTO_PROG_DISALLOWED); sleep(MessageSecs); } else if ((no_shell || no_goto_lynxcgi) && !strncmp(user_input_buffer, "lynxcgi:", 8)) { _statusline(GOTO_CGI_DISALLOWED); sleep(MessageSecs); } else if (LYValidate && strncmp(user_input_buffer, "http:", 5) && strncmp(user_input_buffer, "https:", 6)) { _statusline(GOTO_NON_HTTP_DISALLOWED); sleep(MessageSecs); } else if (no_goto_cso && !strncmp(user_input_buffer, "cso:", 4)) { _statusline(GOTO_CSO_DISALLOWED); sleep(MessageSecs); } else if (no_goto_finger && !strncmp(user_input_buffer, "finger:", 7)) { _statusline(GOTO_FINGER_DISALLOWED); sleep(MessageSecs); } else if (no_goto_ftp && !strncmp(user_input_buffer, "ftp:", 4)) { _statusline(GOTO_FTP_DISALLOWED); sleep(MessageSecs); } else if (no_goto_gopher && !strncmp(user_input_buffer, "gopher:", 7)) { _statusline(GOTO_GOPHER_DISALLOWED); sleep(MessageSecs); } else if (no_goto_http && !strncmp(user_input_buffer, "http:", 5)) { _statusline(GOTO_HTTP_DISALLOWED); sleep(MessageSecs); } else if (no_goto_https && !strncmp(user_input_buffer, "https:", 6)) { _statusline(GOTO_HTTPS_DISALLOWED); sleep(MessageSecs); } else if (no_goto_mailto && !strncmp(user_input_buffer, "mailto:", 7)) { _statusline(GOTO_MAILTO_DISALLOWED); sleep(MessageSecs); } else if (no_goto_news && !strncmp(user_input_buffer, "news:", 5)) { _statusline(GOTO_NEWS_DISALLOWED); sleep(MessageSecs); } else if (no_goto_nntp && !strncmp(user_input_buffer, "nntp:", 5)) { _statusline(GOTO_NNTP_DISALLOWED); sleep(MessageSecs); } else if (no_goto_rlogin && !strncmp(user_input_buffer, "rlogin:", 7)) { _statusline(GOTO_RLOGIN_DISALLOWED); sleep(MessageSecs); } else if (no_goto_snews && !strncmp(user_input_buffer, "snews:", 6)) { _statusline(GOTO_SNEWS_DISALLOWED); sleep(MessageSecs); } else if (no_goto_telnet && !strncmp(user_input_buffer, "telnet:", 7)) { _statusline(GOTO_TELNET_DISALLOWED); sleep(MessageSecs); } else if (no_goto_tn3270 && !strncmp(user_input_buffer, "tn3270:", 7)) { _statusline(GOTO_TN3270_DISALLOWED); sleep(MessageSecs); } else if (no_goto_wais && !strncmp(user_input_buffer, "wais:", 5)) { _statusline(GOTO_WAIS_DISALLOWED); sleep(MessageSecs); } else { StrAllocCopy(newdoc.address, 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, "A URL specified by the user"); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.safe = FALSE; force_load = TRUE; LYUserSpecifiedURL = TRUE; #ifdef DIRED_SUPPORT if (lynx_edit_mode) HTuncache_current_document(); #endif /* DIRED_SUPPORT */ HTAddGotoURL(newdoc.address); } } break; case LYK_HELP: /* show help file */ if (!STREQ(curdoc.address, helpfile)) { /* * Set the filename. */ StrAllocCopy(newdoc.address, helpfile); /* * Make a name for this help file. */ StrAllocCopy(newdoc.title, "Help Screen"); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; } break; case LYK_INDEX: /* index file */ /* * 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; _statusline(NO_INDEX_FILE); sleep(MessageSecs); } } else { StrAllocCopy(newdoc.address, indexfile); StrAllocCopy(newdoc.title, "System Index"); /* name it */ FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; } /* end else */ } /* end if */ break; #ifdef NOT_USED case LYK_FORM_UP: /* change form */ break; /* not implemented */ if (lynx_mode == FORMS_LYNX_MODE) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) { c = change_form_link(&links[curdoc.link], FORM_UP, &newdoc, &refresh_screen, links[curdoc.link].form->name, links[curdoc.link].form->value); /* * Code to handle multiple submit buttons? * Taken out due to bug it causes. if (links[curdoc.link].form->type == F_SUBMIT_TYPE || links[curdoc.link].form->type == F_IMAGESUBMIT_TYPE) { curdoc.address = NULL; } */ goto new_keyboard_input; } else { _statusline("'X' can only toggle a form link"); } } else { _statusline("'X' only toggles in forms mode"); } break; case LYK_FORM_DOWN: /* change form */ break; /* not implemented */ if (lynx_mode==FORMS_LYNX_MODE) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) { c = change_form_link(&links[curdoc.link], FORM_DOWN,&newdoc,&refresh_screen, links[curdoc.link].form->name, links[curdoc.link].form->value); goto new_keyboard_input; } else { _statusline("'Z' can only toggle a form link"); } } else { _statusline("'Z' only toggles in forms mode"); } break; #endif /* NOT_USED */ case LYK_MAIN_MENU: /* return to main screen */ /* * If its already the homepage then don't reload it. */ if (!STREQ(curdoc.address,homepage)) { _statusline(CONFIRM_MAIN_SCREEN); c = LYgetch(); if (TOUPPER(c)=='Y') { StrAllocCopy(newdoc.address, homepage); StrAllocCopy(newdoc.title, "Entry into main screen"); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; highlight(OFF,curdoc.link); #ifdef DIRED_SUPPORT if (lynx_edit_mode) HTuncache_current_document(); #endif /* DIRED_SUPPORT */ } #ifdef VMS if (HadVMSInterrupt) HadVMSInterrupt = FALSE; #endif /* VMS */ } else { if (old_c != real_c) { old_c = real_c; _statusline(IN_MAIN_SCREEN); sleep(MessageSecs); } } break; case LYK_OPTIONS: /* options screen */ #ifdef DIRED_SUPPORT c = dir_list_style; #endif /* DIRED_SUPPORT */ options(); /* do the 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) || #ifdef DIRED_SUPPORT (c != dir_list_style) || #endif /* DIRED_SUPPORT */ (show_dotfiles_flag != show_dotfiles)) && (!strncmp(curdoc.address, "file:", 5) || !strncmp(curdoc.address, "ftp:", 4))) || CurrentCharSet_flag != current_char_set || LYRawMode_flag != LYRawMode || LYSelectPopups_flag != LYSelectPopups || (strcmp(CurrentUserAgent, (LYUserAgent ? LYUserAgent : "")) && !strncmp(curdoc.address, "http", 4))) { /* * 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) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { _statusline(WILL_NOT_RELOAD_DOC); sleep(InfoSecs); } else { LYforce_no_cache = TRUE; StrAllocCopy(newdoc.address, curdoc.address); if (keypad_mode_flag != keypad_mode || (user_mode_flag != user_mode && (user_mode_flag == NOVICE_MODE || user_mode == NOVICE_MODE)) || (((HTfileSortMethod_flag != HTfileSortMethod) || #ifdef DIRED_SUPPORT (c != dir_list_style) || #endif /* DIRED_SUPPORT */ (show_dotfiles_flag != show_dotfiles)) && (!strncmp(curdoc.address, "file:", 5) || !strncmp(curdoc.address, "ftp:", 4))) || LYSelectPopups_flag != LYSelectPopups || (strcmp(CurrentUserAgent, (LYUserAgent ? LYUserAgent : "")) && !strncmp(curdoc.address, "http", 4))) { HTuncache_current_document(); FREE(curdoc.address); } else { } } keypad_mode_flag = keypad_mode; user_mode_flag = user_mode; HTfileSortMethod_flag = HTfileSortMethod; CurrentCharSet_flag = current_char_set; show_dotfiles_flag = show_dotfiles; LYRawMode_flag = LYRawMode; LYSelectPopups_flag = LYSelectPopups; StrAllocCopy(CurrentUserAgent, (LYUserAgent ? LYUserAgent : "")); } refresh_screen = TRUE; /* to repaint screen */ break; case LYK_INDEX_SEARCH: /* search for a user string */ 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 && LYCursesON) { /* * Make sure cursor is down. */ move(LYlines-1, LYcols-1); #ifdef USE_SLANG addstr("\n"); #endif /* USE_SLANG */ refresh(); } 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 gotton it. */ StrAllocCopy(curdoc.address, newdoc.address); StrAllocCopy(newdoc.post_data, curdoc.post_data); curdoc.line = -1; Newline = 0; refresh_screen = TRUE; /* redisplay it */ } else if (use_this_url_instead != NULL) { /* * Got back a redirecting URL. Check it out. */ _user_message("Using %s", use_this_url_instead); /* * Make a name for this URL. */ StrAllocCopy(newdoc.title, "A URL specified by redirection"); StrAllocCopy(newdoc.address, use_this_url_instead); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; FREE(use_this_url_instead); force_load = TRUE; break; } else { /* * Yuk, the search failed. Restore the old file. */ StrAllocCopy(newdoc.address, curdoc.address); StrAllocCopy(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; } } else if (old_c != real_c) { old_c = real_c; _statusline(NOT_ISINDEX); sleep(MessageSecs); } break; case LYK_WHEREIS: /* search within the document */ case LYK_NEXT: /* search for the next occurrence in the document */ /* user search */ if (cmd != LYK_NEXT) { /* * Reset prev_target to force prompting * for a new search string and to turn * off highlighting in no search string * is entered by the user. */ *prev_target = '\0'; textsearch(&curdoc, prev_target, FALSE); } else { /* * When the third argument is TRUE, the previous * search string, if any, will be recalled from * a buffer, loaded into prev_target, and used * for the search without prompting for a new * search string. This allows the LYK_NEXT * command to repeat a search in a new document, * after prev_target was reset on fetch of that * document. */ textsearch(&curdoc, prev_target, TRUE); } /* * Force a redraw to ensure highlighting of hits * even when found on the same page, or clearing * of highlighting is the default search string * was erased without replacement. - FM */ refresh_screen = TRUE; break; case LYK_COMMENT: /* reply by mail */ if (!owner_address && strncasecomp(curdoc.address, "http", 4)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_OWNER); sleep(MessageSecs); } } else if (no_mail) { if (old_c != real_c) { old_c = real_c; _statusline(MAIL_DISALLOWED); sleep(MessageSecs); } } else { _statusline(CONFIRM_COMMENT); c = LYgetch(); if (TOUPPER(c) == 'Y') { if (!owner_address) { /* * No owner defined, so make a guess and * and offer it to the user. - FM */ char *address = NULL; temp = HTParse(curdoc.address, "", PARSE_PATH); 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, "mailto:"); 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); FREE(temp); _user_message(NO_OWNER_USE, address); c = LYgetch(); if (TOUPPER(c) == 'Y') { StrAllocCopy(owner_address, address); FREE(address); } else { FREE(address); break; } } if (is_url(owner_address) != MAILTO_URL_TYPE) { /* * The address is a URL. Just follow the link. */ StrAllocCopy(newdoc.address, owner_address); } else { /* * The owner_address is a mailto: URL. */ cp = HText_getRevTitle(); if (strchr(owner_address,':')!=NULL) /* * Send a reply. The address is after the colon. */ reply_by_mail(strchr(owner_address,':')+1, curdoc.address, (cp ? cp : "")); else reply_by_mail(owner_address, curdoc.address, (cp ? cp : "")); refresh_screen=TRUE; /* to force a showpage */ } } } break; #ifdef DIRED_SUPPORT case LYK_TAG_LINK: /* tag or untag the current link */ if (lynx_edit_mode && nlinks > 0 && !no_dired_support) { if (!strcmp(links[curdoc.link].hightext, "..")) break; /* Never tag the parent directory */ if (dir_list_style == MIXED_STYLE) { if (!strcmp(links[curdoc.link].hightext, "../")) break; } else if (!strncmp(links[curdoc.link].hightext, "Up to ", 6)) break; { /* * 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) { highlight(OFF, curdoc.link); curdoc.link++; } else if (!more && Newline == 1 && curdoc.link == nlinks-1) { highlight(OFF,curdoc.link); curdoc.link = 0; } else if (more) { /* next page */ Newline += (display_lines); } } break; case LYK_MODIFY: /* rename a file or directory */ 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) { HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); FREE(curdoc.address); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.line = curdoc.line; newdoc.link = curdoc.link; clear(); } } break; case LYK_CREATE: /* create a new file or directory */ if (lynx_edit_mode && !no_dired_support) { if (local_create(&curdoc)) { HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); FREE(curdoc.address); FREE(curdoc.address); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.line = curdoc.line; newdoc.link = curdoc.link > -1 ? curdoc.link : 0; clear(); } } break; #endif /* DIRED_SUPPORT */ case LYK_EDIT: /* edit */ if (no_editor) { if (old_c != real_c) { old_c = real_c; _statusline(EDIT_DISABLED); sleep(MessageSecs); } break; } #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) { tp = cp; if (!strncmp(tp, "file://localhost", 16)) tp += 16; else if (!strncmp(tp, "file:", 5)) tp += 5; strcpy(tmpbuf, tp); HTUnEscape(tmpbuf); if (stat(tmpbuf, &dir_info) == -1) { _statusline(NO_STATUS); sleep(AlertSecs); } else { if (((dir_info.st_mode) & S_IFMT) == S_IFREG) { strcpy(tmpbuf, cp); HTUnEscapeSome(tmpbuf, "/"); if (edit_current_file(tmpbuf, curdoc.link, Newline)) { HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); FREE(curdoc.address); #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 > 0) ? curdoc.line : 1); newdoc.link = ((curdoc.link > -1) ? curdoc.link : 0); #endif /* NO_SEEK_OLD_POSITION */ clear(); /* clear the screen */ } } } } } } 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(curdoc.address); /* 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 */ clear(); /* clear the screen */ } } else { if (old_c != real_c) { old_c = real_c; _statusline(NO_EDITOR); sleep(MessageSecs); } } break; case LYK_DEL_BOOKMARK: /* remove a bookmark file link */ #ifdef DIRED_SUPPORT case LYK_REMOVE: /* remove files and directories */ c = 'N'; if (lynx_edit_mode && nlinks > 0 && !no_dired_support) { local_remove(&curdoc); c = 'Y'; } else #endif /* DIRED_SUPPORT */ if (curdoc.bookmark != NULL) { _statusline(CONFIRM_BOOKMARK_DELETE); c = LYgetch(); if (TOUPPER(c) != 'Y') break; remove_bookmark_link(links[curdoc.link].anchor_number-1, curdoc.bookmark); } else { /* behave like REFRESH for backward compatability */ refresh_screen = TRUE; break; } if (TOUPPER(c) == 'Y') { HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); FREE(curdoc.address); 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; } } break; #ifdef DIRED_SUPPORT case LYK_INSTALL: /* install a file into system area */ if (lynx_edit_mode && nlinks > 0 && !no_dired_support) local_install(NULL, links[curdoc.link].lname, &newdoc.address); break; #endif /* DIRED_SUPPORT */ case LYK_INFO: /* show document info */ /* * Don't do if already viewing info page. */ if (strcmp((curdoc.title ? curdoc.title : ""), SHOWINFO_TITLE)) { if (!showinfo(&curdoc, lines_in_file, &newdoc, owner_address)) break; FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; LYforce_no_cache = TRUE; if (LYValidate || check_realm) LYPermitURL = TRUE; } else { /* * If already in info page, get out. */ cmd = LYK_PREV_DOC; goto new_cmd; } break; case LYK_PRINT: /* print the file */ if (LYValidate) { if (old_c != real_c) { old_c = real_c; _statusline(PRINT_DISABLED); sleep(MessageSecs); } break; } /* * Don't do if already viewing print options page. */ if (strcmp((curdoc.title ? curdoc.title : ""), PRINT_OPTIONS_TITLE)) { if (print_options(&newdoc.address, lines_in_file) < 0) break; if (!strcmp((curdoc.title ? curdoc.title : ""), HISTORY_PAGE_TITLE)) FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; ForcePush = TRUE; if (check_realm) LYPermitURL = TRUE; refresh_screen=TRUE; /* redisplay */ } break; case LYK_LIST: /* list links in the current document */ /* * Don't do if already viewing list page. */ if (!strcmp((curdoc.title ? curdoc.title : ""), LIST_PAGE_TITLE)) { /* * Already viewing list page, so get out. */ cmd = LYK_PREV_DOC; goto new_cmd; } /* * Print list page to file. */ if (showlist(&newdoc.address, TRUE) < 0) break; FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; refresh_screen = TRUE; /* redisplay */ if (LYValidate || check_realm) { LYPermitURL = TRUE; StrAllocCopy(lynxlistfile, newdoc.address); } break; case LYK_VLINKS: /* list links visited during the current session */ if (!strcmp(curdoc.title, VISITED_LINKS_TITLE)) { /* * Already viewing visited links page, so get out. */ cmd = LYK_PREV_DOC; goto new_cmd; } /* * Print visited links page to file. */ if (LYShowVisitedLinks(&newdoc.address) < 0) { _statusline(VISITED_LINKS_EMPTY); sleep(MessageSecs); break; } FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; refresh_screen = TRUE; if (LYValidate || check_realm) { LYPermitURL = TRUE; StrAllocCopy(lynxlinksfile, newdoc.address); } break; case LYK_TOOLBAR: /* go to Toolbar or Banner in current document */ if (!HText_hasToolbar(HTMainText)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_TOOLBAR); sleep(MessageSecs); } } else if (old_c != real_c) { old_c = real_c; if ((cp = strchr(curdoc.address, '#')) != NULL) *cp = '\0'; toolbar = (char *)malloc(strlen(curdoc.address) + strlen(LYToolbarName) + 2); sprintf(toolbar, "%s#%s", curdoc.address, LYToolbarName); if (cp) *cp = '#'; StrAllocCopy(newdoc.address, toolbar); FREE(toolbar); force_load = TRUE; /* force MainLoop to reload */ } break; #if defined(DIRED_SUPPORT) || defined(VMS) case LYK_DIRED_MENU: /* provide full file management menu */ #ifdef VMS /* * Check if the CSwing Directory/File Manager is available. * Will be disabled if LYCSwingPath 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 (!(LYCSwingPath && *LYCSwingPath) || !strcasecomp(LYCSwingPath, "none") || no_file_url || no_goto_file || HTDirAccess == HT_DIR_FORBID || HTDirAccess == HT_DIR_SELECTIVE) { if (old_c != real_c) { old_c = real_c; _statusline(DFM_NOT_AVAILABLE); sleep(MessageSecs); } break; } /* * 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) { if (TRACE) fprintf(stderr, "mainloop: Can't stat %s\n", cp); FREE(cp); temp = (char *)calloc(1, (strlen(LYCSwingPath) + 4)); if (temp == NULL) outofmem(__FILE__, "mainloop"); sprintf(temp, "%s []", LYCSwingPath); refresh_screen = TRUE; /* redisplay */ } else { char *VMSdir = NULL; if (((stat_info.st_mode) & S_IFMT) == S_IFDIR) { /* * We're viewing a local directory. Make * that the CSwing argument. - FM */ if (cp[(strlen(cp) - 1)] != '/') StrAllocCat(cp, "/"); StrAllocCopy(VMSdir, HTVMS_name("", cp)); FREE(cp); } else { /* * We're viewing a local file. Make it's * 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; } } temp = (char *)calloc(1, (strlen(LYCSwingPath) + strlen(VMSdir) + 2)); if (temp == NULL) outofmem(__FILE__, "mainloop"); sprintf(temp, "%s %s", LYCSwingPath, VMSdir); FREE(VMSdir); /* * Uncache the current document in case we * change, move, or delete it during the * CSwing session. - FM */ HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); StrAllocCopy(newdoc.title, curdoc.title ? curdoc.title : ""); StrAllocCopy(newdoc.bookmark, curdoc.bookmark); FREE(curdoc.address); 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 */ temp = (char *)calloc(1, (strlen(LYCSwingPath) + 4)); if (temp == NULL) outofmem(__FILE__, "mainloop"); sprintf(temp, "%s []", LYCSwingPath); refresh_screen = TRUE; /* redisplay */ } stop_curses(); system(temp); start_curses(); FREE(temp); break; #else /* * Don't do if not allowed or already viewing the menu. */ if (lynx_edit_mode && !no_dired_support && strcmp((curdoc.title ? curdoc.title : ""), DIRED_MENU_TITLE)) { dired_options(&curdoc,&newdoc.address); refresh_screen = TRUE; /* redisplay */ } break; #endif /* VMS */ #endif /* DIRED_SUPPORT || VMS*/ case LYK_ADD_BOOKMARK: /* add link to bookmark file */ if (LYValidate) { if (old_c != real_c) { old_c = real_c; _statusline(BOOKMARKS_DISABLED); sleep(MessageSecs); } break; } if (strcmp((curdoc.title ? curdoc.title : ""), HISTORY_PAGE_TITLE) && strcmp((curdoc.title ? curdoc.title : ""), SHOWINFO_TITLE) && strcmp((curdoc.title ? curdoc.title : ""), PRINT_OPTIONS_TITLE) && #ifdef DIRED_SUPPORT strcmp((curdoc.title ? curdoc.title : ""), DIRED_MENU_TITLE) && strcmp((curdoc.title ? curdoc.title : ""), PERMIT_OPTIONS_TITLE) && strcmp((curdoc.title ? curdoc.title : ""), UPLOAD_OPTIONS_TITLE) && #endif /* DIRED_SUPPORT */ strcmp((curdoc.title ? curdoc.title : ""), DOWNLOAD_OPTIONS_TITLE) && strcmp((curdoc.title ? curdoc.title : ""), COOKIE_JAR_TITLE) && strcmp((curdoc.title ? curdoc.title : ""), LIST_PAGE_TITLE)) { if (nlinks > 0) { if (curdoc.post_data == NULL && curdoc.bookmark == NULL) { /* * Document doesn't have POST content, * and is not a bookmark file, so we can * save either that or the link. - FM */ _statusline(BOOK_D_L_OR_CANCEL); c = LYgetch(); if (TOUPPER(c) == 'D') { save_bookmark_link(curdoc.address, curdoc.title); refresh_screen = TRUE; /* MultiBookmark support */ goto check_add_bookmark_to_self; } } else { if (LYMultiBookmarks == FALSE && 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 { /* * 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(); } if (TOUPPER(c) == 'L') { /* * User does want to save the link. - FM */ if (links[curdoc.link].type != WWW_FORM_LINK_TYPE) { save_bookmark_link(links[curdoc.link].lname, links[curdoc.link].hightext); refresh_screen = TRUE; /* MultiBookmark support */ } else { _statusline(NOBOOK_FORM_FIELD); sleep(MessageSecs); break; } } else { break; } } else if (curdoc.post_data != NULL) { /* * No links, and document has POST content. - FM */ _statusline(NOBOOK_POST_FORM); sleep(MessageSecs); break; } else if (curdoc.bookmark != NULL) { /* * It's a bookmark file from which all * of the links were deleted. - FM */ _statusline(BOOKMARKS_NOLINKS); sleep(MessageSecs); break; } else { _statusline(BOOK_D_OR_CANCEL); c = LYgetch(); if (TOUPPER(c) == 'D') { save_bookmark_link(curdoc.address, curdoc.title); refresh_screen = TRUE; /* MultiBookmark support */ } else { break; } } check_add_bookmark_to_self: if (curdoc.bookmark && BookmarkPage && !strcmp(curdoc.bookmark, BookmarkPage)) { HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); StrAllocCopy(newdoc.bookmark, curdoc.bookmark); FREE(curdoc.address); newdoc.line = curdoc.line; newdoc.link = curdoc.link; } FREE(temp); } else { if (old_c != real_c) { old_c = real_c; _statusline(NOBOOK_HSML); sleep(MessageSecs); } } break; case LYK_VIEW_BOOKMARK: /* v to view home page */ if (LYValidate) { if (old_c != real_c) { old_c = real_c; _statusline(BOOKMARKS_DISABLED); sleep(MessageSecs); } break; } /* * See if a bookmark exists. * If it does replace newdoc.address with it's name. */ if ((cp = get_bookmark_filename(&newdoc.address)) != NULL) { if (*cp == '\0' || !strcmp(cp, " ") || !strcmp(curdoc.address, newdoc.address)) { if (LYMultiBookmarks == TRUE) refresh_screen = TRUE; break; } LYforce_no_cache = TRUE; /*force the document to be reloaded*/ StrAllocCopy(newdoc.title, BOOKMARK_TITLE); StrAllocCopy(newdoc.bookmark, BookmarkPage); FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; } else { if (old_c != real_c) { old_c = real_c; LYMBM_statusline(BOOKMARKS_NOT_OPEN); sleep(AlertSecs); if (LYMultiBookmarks == TRUE) { refresh_screen = TRUE; } } } break; case LYK_SHELL: /* shell escape */ if (!no_shell) { stop_curses(); printf(SPAWNING_MSG); fflush(stdout); #ifdef DOSPATH system("cls"); system("echo Type EXIT to return to Lynx."); system(getenv("COMSPEC") == NULL ? "command.com" : getenv("COMSPEC")); #else #ifdef VMS system(""); #else system("exec $SHELL"); #endif /* VMS */ #endif /* DOSPATH */ start_curses(); refresh_screen=TRUE; /* for a showpage */ } else { if (old_c != real_c) { old_c = real_c; _statusline(SPAWNING_DISABLED); sleep(MessageSecs); } } break; case LYK_DOWNLOAD: /* * 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; _statusline(DOWNLOAD_DISABLED); sleep(MessageSecs); } break; } /* * Don't do if already viewing download options page. */ if (!strcmp((curdoc.title ? curdoc.title : ""), DOWNLOAD_OPTIONS_TITLE)) break; if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) { if (links[curdoc.link].form->type == F_SUBMIT_TYPE || links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE) { if (links[curdoc.link].form->submit_method == URL_MAIL_METHOD) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_MAILTO_ACTION); sleep(MessageSecs); } break; } HTOutputFormat = HTAtom_for("www/download"); LYforce_no_cache = TRUE; cmd = LYK_ACTIVATE; goto new_cmd; } if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_INPUT); sleep(MessageSecs); } } else if (!strcmp((curdoc.title ? curdoc.title : ""), COOKIE_JAR_TITLE)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_COOKIES); sleep(MessageSecs); } } else if (!strcmp((curdoc.title ? curdoc.title : ""), PRINT_OPTIONS_TITLE)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_PRINT_OP); sleep(MessageSecs); } #ifdef DIRED_SUPPORT } else if (!strcmp((curdoc.title ? curdoc.title : ""), UPLOAD_OPTIONS_TITLE)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_UPLOAD_OP); sleep(MessageSecs); } } else if (!strcmp((curdoc.title ? curdoc.title : ""), PERMIT_OPTIONS_TITLE)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_PERMIT_OP); sleep(MessageSecs); } } else if (lynx_edit_mode && !no_dired_support) { /* * Don't bother making a /tmp copy of the local file. */ StrAllocCopy(temp, newdoc.address); StrAllocCopy(newdoc.address, links[curdoc.link].lname); if (LYdownload_options(&newdoc.address, links[curdoc.link].lname) < 0) StrAllocCopy(newdoc.address, temp); FREE(temp); #endif /* DIRED_SUPPORT */ } else if (!strcmp((curdoc.title ? curdoc.title : ""), HISTORY_PAGE_TITLE)) { int number = atoi(links[curdoc.link].lname+9); if ((history[number].post_data != NULL && history[number].safe != TRUE) && HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { _statusline(CANCELLED); sleep(InfoSecs); break; } StrAllocCopy(newdoc.address, history[number].address); StrAllocCopy(newdoc.title, links[curdoc.link].hightext); StrAllocCopy(newdoc.bookmark, history[number].bookmark); FREE(newdoc.post_data); FREE(newdoc.post_content_type); if (history[number].post_data) StrAllocCopy(newdoc.post_data, history[number].post_data); if (history[number].post_content_type) StrAllocCopy(newdoc.post_content_type, history[number].post_content_type); newdoc.isHEAD = history[number].isHEAD; newdoc.safe = history[number].safe; newdoc.link = 0; HTOutputFormat = HTAtom_for("www/download"); LYUserSpecifiedURL = TRUE; /* * Force the document to be reloaded. */ LYforce_no_cache = TRUE; } else if (!strncasecomp(links[curdoc.link].lname, "data:", 5)) { if (old_c != real_c) { old_c = real_c; HTAlert(UNSUPPORTED_DATA_URL); } } 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. */ StrAllocCopy(newdoc.address, links[curdoc.link].lname); StrAllocCopy(newdoc.title, links[curdoc.link].hightext); /* * 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)) { FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = 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; _statusline(NO_DOWNLOAD_CHOICE); sleep(MessageSecs); } break; #ifdef DIRED_SUPPORT case LYK_UPLOAD: /* * Don't do if already viewing upload options page. */ if (!strcmp((curdoc.title ? curdoc.title : ""), UPLOAD_OPTIONS_TITLE)) break; if (lynx_edit_mode && !no_dired_support) { LYUpload_options((char **)&newdoc.address, (char *)curdoc.address); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; /* * Uncache the current listing so that it will * be updated to included the uploaded file if * placed in the current directory. - FM */ HTuncache_current_document(); } break; #endif /* DIRED_SUPPORT */ case LYK_TRACE_TOGGLE: if (WWW_TraceFlag) WWW_TraceFlag = FALSE; else WWW_TraceFlag = TRUE; _statusline(WWW_TraceFlag ? TRACE_ON : TRACE_OFF); sleep(MessageSecs); break; case LYK_IMAGE_TOGGLE: if (clickable_images) clickable_images = FALSE; else clickable_images = TRUE; _statusline(clickable_images ? CLICKABLE_IMAGES_ON : CLICKABLE_IMAGES_OFF); sleep(MessageSecs); cmd = LYK_RELOAD; goto new_cmd; break; case LYK_INLINE_TOGGLE: if (pseudo_inline_alts) pseudo_inline_alts = FALSE; else pseudo_inline_alts = TRUE; _statusline(pseudo_inline_alts ? PSEUDO_INLINE_ALTS_ON : PSEUDO_INLINE_ALTS_OFF); sleep(MessageSecs); cmd = LYK_RELOAD; goto new_cmd; break; case LYK_RAW_TOGGLE: if (LYUseDefaultRawMode) LYUseDefaultRawMode = FALSE; else LYUseDefaultRawMode = TRUE; _statusline(LYRawMode ? RAWMODE_OFF : RAWMODE_ON); HTMLSetCharacterHandling(current_char_set); LYRawMode_flag = LYRawMode; sleep(MessageSecs); cmd = LYK_RELOAD; goto new_cmd; break; case LYK_HEAD: if (nlinks > 0 && (links[curdoc.link].type != WWW_FORM_LINK_TYPE || links[curdoc.link].form->type == F_SUBMIT_TYPE || links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE)) { _statusline(HEAD_D_L_OR_CANCEL); c = LYgetch(); if (TOUPPER(c) == 'D') { if (strncmp(curdoc.address, "http", 4)) { _statusline(DOC_NOT_HTTP_URL); sleep(MessageSecs); } 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_RESUBMISSION) == FALSE) { _statusline(CANCELLED); sleep(InfoSecs); break; } HEAD_request = TRUE; LYforce_no_cache = TRUE; if (HTLoadedDocumentIsHEAD()) { HTuncache_current_document(); FREE(curdoc.address); } } break; } else if (TOUPPER(c) == 'L') { if (links[curdoc.link].type != WWW_FORM_LINK_TYPE && strncmp(links[curdoc.link].lname, "http", 4)) { _statusline(LINK_NOT_HTTP_URL); sleep(MessageSecs); } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].form->disabled) { _statusline(FORM_ACTION_DISABLED); sleep(MessageSecs); } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && strncmp(links[curdoc.link].form->submit_action, "http", 4)) { _statusline(FORM_ACTION_NOT_HTTP_URL); sleep(MessageSecs); } else { HEAD_request = TRUE; LYforce_no_cache = TRUE; cmd = LYK_ACTIVATE; goto new_cmd; } break; } break; } 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_RESUBMISSION) == FALSE) { _statusline(CANCELLED); sleep(InfoSecs); break; } if (nlinks > 0) { _statusline(HEAD_D_OR_CANCEL); c = LYgetch(); } else { c = 'D'; } if (TOUPPER(c) == 'D') { if (strncmp(curdoc.address, "http", 4)) { _statusline(DOC_NOT_HTTP_URL); sleep(MessageSecs); } else { HEAD_request = TRUE; LYforce_no_cache = TRUE; if (HTLoadedDocumentIsHEAD()) { HTuncache_current_document(); FREE(curdoc.address); } } } } break; case LYK_TOGGLE_HELP: if (user_mode==NOVICE_MODE) { toggle_novice_line(); noviceline(more); } break; case LYK_KEYMAP: if (old_c != real_c) { old_c = real_c; StrAllocCopy(newdoc.address, "LYNXKEYMAP:"); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = 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. * Don't cache the keymap because it changes. - EF */ if (!no_dired_support) { prev_lynx_edit_mode = lynx_edit_mode; LYforce_no_cache = TRUE; } #endif /* DIRED_SUPPORT && OK_OVERRIDE */ } break; case LYK_JUMP: { char *ret; if (no_jump || JThead == NULL) { if (old_c != real_c) { old_c = real_c; if (no_jump) _statusline(JUMP_DISALLOWED); else _statusline(NO_JUMPFILE); sleep(MessageSecs); } } else { LYJumpFileURL = TRUE; if ((ret = LYJump(c)) != NULL) { #ifdef PERMIT_GOTO_FROM_JUMP if (!strncasecomp(ret, "Go ", 3)) { LYJumpFileURL = FALSE; StrAllocCopy(temp, user_input_buffer); URLTotal = (Goto_URLs ? HTList_count(Goto_URLs) : 0); recall = ((URLTotal >= 1) ? RECALL : NORECALL); URLNum = URLTotal; FirstURLRecall = TRUE; if (!strcasecomp(ret, "Go :")) { if (recall) { ch = UPARROW; goto check_recall; } FREE(temp); statusline(NO_RANDOM_URLS_YET); sleep(MessageSecs); break; } ret = HTParse((ret+3), startfile, PARSE_ALL); strcpy(user_input_buffer, ret); FREE(ret); goto check_recall; } #endif /* PERMIT_GOTO_FROM_JUMP */ ret = HTParse(ret, startfile, PARSE_ALL); LYTrimHead(ret); if (!strncasecomp(ret, "lynxexec:", 9) || !strncasecomp(ret, "lynxprog:", 9)) { /* * The original implementions of these schemes * expected white space without hex escaping, * and did not check for hex escaping, so we'll * continue to support that, until that code is * redone in conformance with SGML principles. * - FM */ HTUnEscapeSome(ret, " \r\n\t"); convert_to_spaces(ret, TRUE); } else { collapse_spaces(user_input_buffer); } StrAllocCopy(newdoc.address, ret); StrAllocCopy(lynxjumpfile, ret); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; FREE(ret); LYUserSpecifiedURL = TRUE; } else { LYJumpFileURL = FALSE; } } } break; #ifdef NOT_USED case LYK_VERSION: if (old_c != real_c) { char version[128]; old_c = real_c; sprintf(version, "*** %s Version %s ***", LYNX_NAME, LYNX_VERSION); statusline(version); sleep(AlertMessage); } break; #endif /* NOT_USED */ case LYK_DO_NOTHING: /* pretty self explanatory */ break; } /* end of BIG switch */ } } PRIVATE int are_different ARGS2( document *, doc1, document *, doc2) { char *cp1, *cp2; /* * Do we have two addresses? */ if (!doc1->address || !doc2->address) return (TRUE); /* * Do they differ in the type of request? */ if (doc1->isHEAD != doc2->isHEAD) return (TRUE); /* * See if the addresses are different, making sure * we're not tripped up by multiple anchors in the * the same document from a POST form. -- FM */ if ((cp1 = strchr(doc1->address, '#')) != NULL) *cp1 = '\0'; if ((cp2 = strchr(doc2->address, '#')) != NULL) *cp2 = '\0'; /* * Are the base addresses different? */ if (strcmp(doc1->address, doc2->address)) { if (cp1) *cp1 = '#'; if (cp2) *cp2 = '#'; return(TRUE); } if (cp1) *cp1 = '#'; if (cp2) *cp2 = '#'; /* * Do the docs have different contents? */ if (doc1->post_data) { if (doc2->post_data) { if (strcmp(doc1->post_data, doc2->post_data)) return(TRUE); } else return(TRUE); } else if (doc2->post_data) return(TRUE); /* * We'll assume the two documents in fact are the same. */ return(FALSE); } /* * Utility for freeing the list of goto URLs. - FM */ PUBLIC void HTGotoURLs_free NOARGS { char *url; HTList *cur = Goto_URLs; if (!cur) return; while (NULL != (url = (char *)HTList_nextObject(cur))) { FREE(url); } HTList_delete(Goto_URLs); Goto_URLs = NULL; return; } /* * Utility for listing Goto URLs, making any * repeated URLs the most current in the list. - FM */ PUBLIC void HTAddGotoURL ARGS1( char *, url) { char *new; char *old; HTList *cur; if (!(url && *url)) return; if ((new = (char *)calloc(1, (strlen(url) + 1))) == NULL) outofmem(__FILE__, "HTAddGotoURL"); strcpy(new, url); if (!Goto_URLs) { Goto_URLs = HTList_new(); atexit(HTGotoURLs_free); HTList_addObject(Goto_URLs, new); return; } cur = Goto_URLs; while (NULL != (old = (char *)HTList_nextObject(cur))) { if (!strcmp(old, new)) { HTList_removeObject(Goto_URLs, old); FREE(old); break; } } HTList_addObject(Goto_URLs, new); return; }