#include "HTUtils.h" #include "tcp.h" #include "HTAccess.h" #include "HTParse.h" #include "LYCurses.h" #include "LYGlobalDefs.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 "HTFTP.h" #include "HTTP.h" #include "HTAlert.h" #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(curdoc.title); FREE(curdoc.address); FREE(curdoc.post_data); FREE(curdoc.post_content_type); FREE(traversal_host); FREE(traversal_link_to_add); FREE(CurrentUserAgent); 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, 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 */ 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 HTfileSortMethod_flag = HTfileSortMethod; int CurrentCharSet_flag = current_char_set; BOOLEAN show_dotfiles_flag = show_dotfiles; BOOLEAN LYRawMode_flag = LYRawMode; 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; #ifdef DIRED_SUPPORT char *tp; char tmpbuf[1024]; struct stat dir_info; taglink *t1, *t2=NULL; #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; curdoc.address = NULL; curdoc.title = NULL; curdoc.post_data = NULL; curdoc.post_content_type = NULL; atexit(free_mainloop_variables); if (strcmp(startfile, homepage)) HTAddGotoURL(homepage); HTAddGotoURL(startfile); initialize: nhist = 0; StrAllocCopy(newdoc.address, startfile); StrAllocCopy(startrealm, startfile); StrAllocCopy(newdoc.title, "Entry into main screen"); newdoc.isHEAD=FALSE; newdoc.line=1; newdoc.link=0; *prev_target='\0'; *user_input_buffer='\0'; StrAllocCopy(CurrentUserAgent, (LYUserAgent ? LYUserAgent : "")); #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 (get_bookmark_filename(&newdoc.address) != NULL) { LYforce_HTML_mode = TRUE; /* force HTML */ StrAllocCopy(newdoc.title, "Bookmark File"); StrAllocCopy(startrealm, newdoc.address); FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = FALSE; if (TRACE) fprintf(stderr, "Using bookmarks=%s\n", newdoc.address); } else { _statusline(BOOKMARKS_NOT_OPEN); sleep(MessageSecs); bookmark_start = FALSE; goto initialize; } } } if (form_post_data) { FREE(form_post_data); } else if (form_get_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); } else if (!newdoc.address) { /* * If newdoc.address is empty then pop a file and load it. */ LYpop(&newdoc); if (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 (!strncmp(newdoc.address, "http", 4)) newdoc.isHEAD = TRUE; HEAD_request = FALSE; } LYRequestTitle = newdoc.title; if (LYValidate && startfile_ok && (!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) { /* * Send an error message. */ if (!strncasecomp(owner_address, "mailto:", 7)) { mailmsg(curdoc.link, (owner_address+7), history[nhist-1].address, history[nhist-1].title); } } else 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); (void) signal(SIGHUP, SIG_DFL); (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 start file %s\n", startfile); if (!dump_output_immediately) { (void) signal(SIGHUP, SIG_DFL); (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 */ LYJumpFileURL = FALSE; reloading = FALSE; LYPermitURL = FALSE; LYCancelledFetch = 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); StrAllocCopy(startfile, homepage); newdoc.isHEAD = 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) { (void) signal(SIGHUP, SIG_DFL); (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 (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) /* 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); 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); curdoc.isHEAD = newdoc.isHEAD; /* * 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 */ } /* end if (STREQ(newdoc.address,curdoc.address) */ if (dump_output_immediately) { if (crawl) { if (HText_getTitle()) StrAllocCopy(curdoc.title, HText_getTitle()); 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)) { 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 { char *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 (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 && tagged != NULL) 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 (HText_getTitle()) { StrAllocCopy(curdoc.title, HText_getTitle()); } else { StrAllocCopy(curdoc.title, newdoc.title); } owner_address = HText_getOwner(); if (arrowup) { /* arrow up 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; } 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 && tagged != NULL) 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: 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) { (void) signal(SIGHUP, SIG_DFL); (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 downarrow */ 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) && !strncmp(traversal_host, links[curdoc.link].lname, 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(); (void) signal(SIGHUP, SIG_DFL); (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); 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(); (void) signal(SIGHUP, SIG_DFL); (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) printw("%d", c); /* show the user input */ 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); newdoc.isHEAD = 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 */ if (HTisDocumentSource()) HTOutputFormat = WWW_PRESENT; else 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 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: 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) { 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: 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: return(0); /* dont ask the user about quitting */ 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) { int i; 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) { int i; 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_FIRST); 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 i, 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 i, 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_HISTORY: /* show the history page */ if (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); /* * Print history options to file. */ if (showhistory(&newdoc.address) < 0) break; FREE(curdoc.address); /* so it doesn't get pushed */ FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = FALSE; LYpop(&curdoc); 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 */ /* * 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) { 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 */ 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_TEXT_SUBMIT_TYPE) { /* * Do nothing if it's disabled. - FM */ if (links[curdoc.link].form->disabled == YES) 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); 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); 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); 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."); 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); 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 (bookmark_page && (strstr(curdoc.address, bookmark_page) || !strcmp(curdoc.title, MOSAIC_BOOKMARK_TITLE))) { 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); } if (!no_jump && lynxjumpfile && !strcmp(lynxjumpfile, curdoc.address)) { LYJumpFileURL = TRUE; LYUserSpecifiedURL = TRUE; } else if (!strcmp(curdoc.title, HISTORY_PAGE_TITLE) || (bookmark_page && (strstr(curdoc.address, bookmark_page) || !strcmp(curdoc.title, MOSAIC_BOOKMARK_TITLE))) || (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(); HTUnEscape(newdoc.address); strip_trailing_slash(newdoc.address); } #endif /* DIRED_SUPPORT */ } } 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). */ 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; } } /* * If its not a URL then make it one. */ if (!is_url(user_input_buffer)) { char *user_input_string = NULL; if (TRACE) fprintf(stderr, "\n'%s' is not a URL\n", user_input_buffer); StrAllocCopy(user_input_string, user_input_buffer); LYConvertToURL(&user_input_string); strcpy(user_input_buffer, user_input_string); FREE(user_input_string); } 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 { /* make a name for this new URL */ StrAllocCopy(newdoc.title, "A URL specified by the user"); /* * If it's a file URL and the host is defaulted, * force in "//localhost". We need this until * all the other Lynx code which performs security * checks based on the "localhost" string is changed * to assume "//localhost" when a host field is not * present in file URLs - FM */ if (!strncmp(user_input_buffer, "file:", 5)) { if (user_input_buffer[5] == '\0') { strcat(user_input_buffer, "//localhost"); } else if (!strcmp(user_input_buffer, "file://")) { strcat(user_input_buffer, "localhost"); } else if (!strncmp(user_input_buffer, "file:///", 8)) { StrAllocCopy(temp, (user_input_buffer+7)); strcpy(user_input_buffer, "file://localhost"); strcat(user_input_buffer, temp); FREE(temp); } else if (!strncmp(user_input_buffer, "file:/", 6) && user_input_buffer[6] != '/') { StrAllocCopy(temp, (user_input_buffer+5)); strcpy(user_input_buffer, "file://localhost"); strcat(user_input_buffer, temp); FREE(temp); } } /* * No path in a file://localhost URL means a * directory listing for the current default. - FM */ if (!strcmp(user_input_buffer, "file://localhost")) { #ifdef VMS strcat(user_input_buffer, HTVMS_wwwName(getenv("PATH"))); #else char curdir[DIRNAMESIZE]; #ifdef NO_GETCWD getwd (curdir); #else getcwd (curdir, DIRNAMESIZE); #endif /* NO_GETCWD */ strcat(user_input_buffer, curdir); #endif /* VMS */ } #ifdef VMS /* * On VMS, a file://localhost/ URL means * a listing for the login directory. - FM */ if (!strcmp(user_input_buffer, "file://localhost/")) strcat(user_input_buffer, (HTVMS_wwwName((char *)Home_Dir())+1)); #endif /* VMS */ 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)) { FREE(newdoc.post_data); FREE(newdoc.post_content_type); } force_load = TRUE; LYUserSpecifiedURL = TRUE; #ifdef DIRED_SUPPORT if (lynx_edit_mode) HTuncache_current_document(); #endif /* DIRED_SUPPORT */ HTAddGotoURL(user_input_buffer); } break; case LYK_HELP: /* show help file */ if (!STREQ(curdoc.address, helpfile)) { StrAllocCopy(newdoc.address, helpfile); /* set the filename */ /* make a name for this help file */ StrAllocCopy(newdoc.title, "Help Screen"); FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = 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); newdoc.isHEAD = 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) { 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); newdoc.isHEAD = 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 || #ifdef DIRED_SUPPORT c != dir_list_style || #endif /* DIRED_SUPPORT */ HTfileSortMethod_flag != HTfileSortMethod || CurrentCharSet_flag != current_char_set || show_dotfiles_flag != show_dotfiles || LYRawMode_flag != LYRawMode || strcmp(CurrentUserAgent, (LYUserAgent ? LYUserAgent : ""))) { HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); FREE(curdoc.address); keypad_mode_flag = keypad_mode; HTfileSortMethod_flag = HTfileSortMethod; CurrentCharSet_flag = current_char_set; show_dotfiles_flag = show_dotfiles; LYRawMode_flag = LYRawMode; 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 yes a new document was returned and is * named in the newdoc.address */ newdoc.isHEAD = FALSE; if (do_www_search(&newdoc) == NORMAL) { /* Yah, the search succeeded. */ if (TRACE && LYCursesON) { move(LYlines-1, LYcols-1); /* make sure cursor is down */ #ifdef USE_SLANG addstr("\n"); #endif /* USE_SLANG */ refresh(); } LYpush(&curdoc); /* 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); newdoc.isHEAD = 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); newdoc.isHEAD = curdoc.isHEAD; } } else if (old_c != real_c) { old_c = real_c; _statusline(NOT_ISINDEX); sleep(MessageSecs); } break; case LYK_WHEREIS: /* search within the document */ /* search for the next occurrence of the user string */ case LYK_NEXT: /* 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) { 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 (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 type */ 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 (dir_list_style == MIXED_STYLE) { if (!strcmp(links[curdoc.link].hightext,"../")) break; } else if (!strncmp(links[curdoc.link].hightext,"Up to ",6)) break; t1 = tagged; while (t1 != NULL) { if (!strcmp(links[curdoc.link].lname,t1->name)) { if (t1 == tagged) tagged = t1->next; else t2->next = t1->next; FREE(t1->name); FREE(t1); tagflag(OFF,curdoc.link); break; } t2 = t1; t1 = t1->next; } if (t1 == NULL) { t1 = (taglink *) malloc(sizeof(taglink)); if (tagged == NULL) tagged = t1; else t2->next = t1; t1->next = NULL; t1->name = NULL; StrAllocCopy(t1->name,links[curdoc.link].lname); 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); 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); 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); HTUnEscape(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 the document to be reloaded*/ 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: /* delete home page link */ #ifdef DIRED_SUPPORT case LYK_REMOVE: /* remove files and directories */ if (lynx_edit_mode && nlinks > 0 && !no_dired_support) local_remove(&curdoc); else #endif /* DIRED_SUPPORT */ if (bookmark_page && (strstr(curdoc.address, bookmark_page) || !strcmp(curdoc.title, MOSAIC_BOOKMARK_TITLE))) { _statusline(CONFIRM_BOOKMARK_DELETE); c = LYgetch(); if (TOUPPER(c) != 'Y') break; remove_bookmark_link(links[curdoc.link].anchor_number-1); } else { /* behave like REFRESH for backward compatability */ refresh_screen=TRUE; break; } HTuncache_current_document(); StrAllocCopy(newdoc.address, curdoc.address); FREE(curdoc.address); newdoc.line = curdoc.line; if (curdoc.link == nlinks-1) /* if we deleted the last link on the page */ 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, SHOWINFO_TITLE)) { showinfo(&curdoc, lines_in_file, &newdoc, owner_address); 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, PRINT_OPTIONS_TITLE)) { if (print_options(&newdoc.address, lines_in_file) < 0) break; 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, LIST_PAGE_TITLE)) { if (showlist(&newdoc.address, TRUE) < 0) break; refresh_screen=TRUE; /* redisplay */ if (LYValidate || check_realm) { LYPermitURL = TRUE; StrAllocCopy(lynxlistfile, 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; #ifdef DIRED_SUPPORT case LYK_DIRED_MENU: /* provide full file management menu */ /* don't do if not allowed or already viewing the menu */ if (lynx_edit_mode && !no_dired_support && strcmp(curdoc.title, DIRED_MENU_TITLE)) { dired_options(&curdoc,&newdoc.address); refresh_screen=TRUE; /* redisplay */ } break; #endif /* DIRED_SUPPORT */ case LYK_ADD_BOOKMARK: /* a to 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, HISTORY_PAGE_TITLE) && strcmp(curdoc.title, SHOWINFO_TITLE) && strcmp(curdoc.title, PRINT_OPTIONS_TITLE) && #ifdef DIRED_SUPPORT strcmp(curdoc.title, DIRED_MENU_TITLE) && strcmp(curdoc.title, PERMIT_OPTIONS_TITLE) && strcmp(curdoc.title, UPLOAD_OPTIONS_TITLE) && #endif /* DIRED_SUPPORT */ strcmp(curdoc.title, DOWNLOAD_OPTIONS_TITLE) && strcmp(curdoc.title, LIST_PAGE_TITLE)) { if (nlinks > 0) { if (curdoc.post_data == NULL) { /* * Document doesn't have POST content, so * we can save either that of the link. - FM */ _statusline(BOOK_D_L_OR_CANCEL); c = LYgetch(); if (TOUPPER(c) == 'D') { save_bookmark_link(curdoc.address, curdoc.title); break; } } else { /* * Only offer the link in a document * with POST content. - 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); } else { _statusline(NOBOOK_FORM_FIELD); sleep(MessageSecs); } } } else if (curdoc.post_data != NULL) { /* * No links, and document has POST content. - FM */ _statusline(NOBOOK_POST_FORM); sleep(MessageSecs); } else { _statusline(BOOK_D_OR_CANCEL); c = LYgetch(); if (TOUPPER(c) == 'D') save_bookmark_link(curdoc.address, curdoc.title); } } 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 (get_bookmark_filename(&newdoc.address) != NULL) { LYforce_HTML_mode = TRUE; /* force HTML */ LYforce_no_cache = TRUE; /*force the document to be reloaded*/ StrAllocCopy(newdoc.title, "Bookmark File"); FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = FALSE; if (check_realm) { StrAllocCopy(lynxbookfile, newdoc.address); } } else { if (old_c != real_c) { old_c = real_c; _statusline(BOOKMARKS_NOT_OPEN); sleep(MessageSecs); } } break; case LYK_SHELL: /* shell escape */ if (!no_shell) { stop_curses(); printf(SPAWNING_MSG); fflush(stdout); #ifdef VMS system(""); #else system("exec $SHELL"); #endif /* VMS */ 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 (0==strcmp(curdoc.title, DOWNLOAD_OPTIONS_TITLE)) break; if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_INPUT); sleep(MessageSecs); } } else if (0==strcmp(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 (0==strcmp(curdoc.title, UPLOAD_OPTIONS_TITLE)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_UPLOAD_OP); sleep(MessageSecs); } } else if (0==strcmp(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 (0==strcmp(curdoc.title, HISTORY_PAGE_TITLE)) { int number = atoi(links[curdoc.link].lname+9); StrAllocCopy(newdoc.address, history[number].address); StrAllocCopy(newdoc.title, links[curdoc.link].hightext); 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.link = 0; HTOutputFormat = HTAtom_for("www/download"); LYUserSpecifiedURL = TRUE; /*force the document to be reloaded*/ LYforce_no_cache = TRUE; force_load = TRUE; /* force MainLoop to reload */ } 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); newdoc.isHEAD = FALSE; } newdoc.link = 0; HTOutputFormat = HTAtom_for("www/download"); /*force the document to be reloaded*/ LYforce_no_cache = TRUE; force_load = TRUE; /* force MainLoop to reload */ } } 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 (0==strcmp(curdoc.title, UPLOAD_OPTIONS_TITLE)) break; if (lynx_edit_mode && !no_dired_support) { LYUpload_options((char **)&newdoc.address, (char *)curdoc.address); } 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)) { _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 { 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 { 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_DO_NOTHING: /* pretty self explanitory */ 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); newdoc.isHEAD = 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); StrAllocCopy(newdoc.address, ret); StrAllocCopy(lynxjumpfile, ret); FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = 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 */ } /* 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; }