Blame src/LYGetFile.c

Packit f574b8
/* $LynxId: LYGetFile.c,v 1.96 2018/04/01 15:27:18 tom Exp $ */
Packit f574b8
#include <HTUtils.h>
Packit f574b8
#include <HTTP.h>
Packit f574b8
#include <HTAnchor.h>		/* Anchor class */
Packit f574b8
#include <HTAccess.h>
Packit f574b8
#include <HTParse.h>
Packit f574b8
#include <LYCurses.h>
Packit f574b8
#include <GridText.h>
Packit f574b8
#include <LYGlobalDefs.h>
Packit f574b8
#include <LYUtils.h>
Packit f574b8
#include <LYCharSets.h>
Packit f574b8
#include <LYCharUtils.h>
Packit f574b8
#include <HTAlert.h>
Packit f574b8
#include <LYSignal.h>
Packit f574b8
#include <LYGetFile.h>
Packit f574b8
#include <LYPrint.h>
Packit f574b8
#include <LYOptions.h>
Packit f574b8
#include <LYStrings.h>
Packit f574b8
#include <LYClean.h>
Packit f574b8
#include <LYDownload.h>
Packit f574b8
#include <LYNews.h>
Packit f574b8
#include <LYMail.h>
Packit f574b8
#include <LYKeymap.h>
Packit f574b8
#include <LYBookmark.h>
Packit f574b8
#include <LYMap.h>
Packit f574b8
#include <LYList.h>
Packit f574b8
#ifdef DIRED_SUPPORT
Packit f574b8
#include <LYLocal.h>
Packit f574b8
#endif /* DIRED_SUPPORT */
Packit f574b8
#include <LYReadCFG.h>
Packit f574b8
#include <LYHistory.h>
Packit f574b8
#include <LYPrettySrc.h>
Packit f574b8
Packit f574b8
#include <LYexit.h>
Packit f574b8
#include <LYLeaks.h>
Packit f574b8
Packit f574b8
static int fix_httplike_urls(DocInfo *doc, UrlTypes type);
Packit f574b8
Packit f574b8
#ifdef VMS
Packit f574b8
#define STRNADDRCOMP strncasecomp
Packit f574b8
#else
Packit f574b8
#define STRNADDRCOMP strncmp
Packit f574b8
#endif /* !VMS */
Packit f574b8
Packit f574b8
int HTNoDataOK = 0;
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * getfile is the main mechanism to load a new document (or a previously loaded
Packit f574b8
 * one whose rendering is cached in a HText structure) from mainloop, nearly
Packit f574b8
 * everything goes through it.
Packit f574b8
 * It should return one of the values
Packit f574b8
 *     NORMAL     - requested document loaded successfully, usually [always?]
Packit f574b8
 *                  its rendering is available as HTMainText.  It can be an
Packit f574b8
 *                  HTTP error message page or similar, we make no
Packit f574b8
 *                  distinction here.
Packit f574b8
 *     NOT_FOUND  - requested document cannot be accessed, and the reason
Packit f574b8
 *                  is a real error (as may be caused by an invalid link),
Packit f574b8
 *                  not just that lynx disallows access because of some
Packit f574b8
 *                  permission restrictions, and we have no error page
Packit f574b8
 *                  to show for it either.
Packit f574b8
 *     NULLFILE   - requested document not loaded into HTMainText, either
Packit f574b8
 *                  some interactive protocol was requested (like telnet),
Packit f574b8
 *                  or lynx does not allow access.
Packit f574b8
 * The distinction between NOT_FOUND and NULLFILE is not very crucial, but
Packit f574b8
 * getting it right prevents mainloop from exiting with the wrong message if it
Packit f574b8
 * happens for the first file, and from logging (or not logging) errors
Packit f574b8
 * inappropriately with -traversal, and from sending bogus error mail with
Packit f574b8
 * MAIL_SYSTEM_ERROR_LOGGING:TRUE.  - kw
Packit f574b8
 */
Packit f574b8
int getfile(DocInfo *doc, int *target)
Packit f574b8
{
Packit f574b8
    UrlTypes url_type = NOT_A_URL_TYPE;
Packit f574b8
    char *pound;
Packit f574b8
    char *cp = NULL;
Packit f574b8
    char *temp = NULL;
Packit f574b8
    DocAddress WWWDoc;		/* a WWW absolute doc address struct */
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Reset LYCancelDownload to prevent unwanted delayed effect.  - KW
Packit f574b8
     */
Packit f574b8
    if (LYCancelDownload) {
Packit f574b8
	CTRACE((tfp, "getfile:    resetting LYCancelDownload to FALSE\n"));
Packit f574b8
	LYCancelDownload = FALSE;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Reset fake 'Z' to prevent unwanted delayed effect.  - kw
Packit f574b8
     */
Packit f574b8
    LYFakeZap(NO);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Reset redirection counter to prevent bogus TOO_MANY_REDIRECTIONS in rare
Packit f574b8
     * situations if the previous cycle got to the limit, but did not fail for
Packit f574b8
     * that reason because the URL of the final location was handled specially,
Packit f574b8
     * not via HTLoadAbsolute.  - kw
Packit f574b8
     */
Packit f574b8
    redirection_attempts = 0;
Packit f574b8
Packit f574b8
  Try_Redirected_URL:
Packit f574b8
    /*
Packit f574b8
     * Load the WWWDoc struct in case we need to use it.
Packit f574b8
     */
Packit f574b8
    WWWDoc.address = doc->address;
Packit f574b8
    WWWDoc.post_data = doc->post_data;
Packit f574b8
    WWWDoc.post_content_type = doc->post_content_type;
Packit f574b8
    WWWDoc.bookmark = doc->bookmark;
Packit f574b8
    WWWDoc.isHEAD = doc->isHEAD;
Packit f574b8
    WWWDoc.safe = doc->safe;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Reset HTPermitRedir, it has done its job if it was set.  - kw
Packit f574b8
     */
Packit f574b8
    HTPermitRedir = FALSE;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Reset WWW_Download_File just in case.
Packit f574b8
     */
Packit f574b8
    FREE(WWW_Download_File);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Reset redirect_post_content just in case.
Packit f574b8
     */
Packit f574b8
    redirect_post_content = FALSE;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * This flag is a hack to allow us to pass on the fact that 'no data' may
Packit f574b8
     * not really be an error although HTLoadAbsolute returned NO.  There
Packit f574b8
     * should be a better way...  HT_NO_DATA should always mean 'not data but
Packit f574b8
     * not an error', and be passed on to us as that, but current usage if
Packit f574b8
     * HT_NO_DATA vs HT_NOT_LOADED has to be reviewed everywhere.  Anyway, some
Packit f574b8
     * protocol module can set it to say 'I really mean it', we have to reset
Packit f574b8
     * it here.  - kw
Packit f574b8
     */
Packit f574b8
    HTNoDataOK = 0;
Packit f574b8
Packit f574b8
    CTRACE((tfp, "getfile: getting %s\n\n", doc->address));
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Protect against denial of service attacks via the port 19 CHARGEN
Packit f574b8
     * service, and block connections to the port 25 ESMTP service.  Also
Packit f574b8
     * reject any likely spoof attempts via wrap arounds at 65536.  - FM
Packit f574b8
     */
Packit f574b8
    if ((temp = HTParse(doc->address, "", PARSE_HOST)) != NULL &&
Packit f574b8
	strlen(temp) > 3) {
Packit f574b8
	char *cp1;
Packit f574b8
Packit f574b8
	if ((cp1 = StrChr(temp, '@')) == NULL)
Packit f574b8
	    cp1 = temp;
Packit f574b8
	if ((cp = strrchr(cp1, ':')) != NULL) {
Packit f574b8
	    long int value;
Packit f574b8
Packit f574b8
	    cp++;
Packit f574b8
	    if (sscanf(cp, "%ld", &value) == 1) {
Packit f574b8
		if (value == 19 || value == 65555) {
Packit f574b8
		    HTAlert(PORT_NINETEEN_INVALID);
Packit f574b8
		    FREE(temp);
Packit f574b8
		    return (NULLFILE);
Packit f574b8
		} else if (value == 25 || value == 65561) {
Packit f574b8
		    HTAlert(PORT_TWENTYFIVE_INVALID);
Packit f574b8
		    FREE(temp);
Packit f574b8
		    return (NULLFILE);
Packit f574b8
		} else if (value > 65535 || value < 0) {
Packit f574b8
		    char *msg = 0;
Packit f574b8
Packit f574b8
		    HTSprintf0(&msg, PORT_INVALID, (unsigned long) value);
Packit f574b8
		    HTAlert(msg);
Packit f574b8
		    FREE(msg);
Packit f574b8
		    FREE(temp);
Packit f574b8
		    return (NULLFILE);
Packit f574b8
		}
Packit f574b8
	    } else if (isdigit(UCH(*cp))) {
Packit f574b8
		HTAlert(URL_PORT_BAD);
Packit f574b8
		FREE(temp);
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    cp = NULL;
Packit f574b8
    FREE(temp);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Check to see if this is a universal document ID that lib WWW wants to
Packit f574b8
     * handle.
Packit f574b8
     *
Packit f574b8
     * Some special URL's we handle ourselves.  :)
Packit f574b8
     */
Packit f574b8
    if ((url_type = is_url(doc->address)) != 0) {
Packit f574b8
	if (LYValidate && !LYPermitURL) {
Packit f574b8
	    if (!(url_type == HTTP_URL_TYPE ||
Packit f574b8
		  url_type == HTTPS_URL_TYPE ||
Packit f574b8
		  url_type == LYNXHIST_URL_TYPE ||
Packit f574b8
		  url_type == LYNXEDITMAP_URL_TYPE ||
Packit f574b8
		  url_type == LYNXKEYMAP_URL_TYPE ||
Packit f574b8
		  url_type == LYNXIMGMAP_URL_TYPE ||
Packit f574b8
		  url_type == LYNXCOOKIE_URL_TYPE ||
Packit f574b8
#ifdef USE_CACHEJAR
Packit f574b8
		  url_type == LYNXCACHE_URL_TYPE ||
Packit f574b8
#endif
Packit f574b8
		  url_type == LYNXMESSAGES_URL_TYPE ||
Packit f574b8
		  (url_type == LYNXOPTIONS_URL_TYPE &&
Packit f574b8
		   WWWDoc.post_data) ||
Packit f574b8
		  (non_empty(helpfilepath) &&
Packit f574b8
		   0 == STRNADDRCOMP(WWWDoc.address, helpfilepath,
Packit f574b8
				     strlen(helpfilepath))) ||
Packit f574b8
		  (non_empty(lynxlistfile) &&
Packit f574b8
		   0 == STRNADDRCOMP(WWWDoc.address, lynxlistfile,
Packit f574b8
				     strlen(lynxlistfile))) ||
Packit f574b8
		  (non_empty(lynxlinksfile) &&
Packit f574b8
		   0 == STRNADDRCOMP(WWWDoc.address, lynxlinksfile,
Packit f574b8
				     strlen(lynxlinksfile))) ||
Packit f574b8
		  (non_empty(lynxjumpfile) &&
Packit f574b8
		   0 == STRNADDRCOMP(WWWDoc.address, lynxjumpfile,
Packit f574b8
				     strlen(lynxjumpfile))))) {
Packit f574b8
		HTUserMsg(NOT_HTTP_URL_OR_ACTION);
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
	if (traversal) {
Packit f574b8
	    /*
Packit f574b8
	     * Only traverse http URLs.
Packit f574b8
	     */
Packit f574b8
	    if (url_type != HTTP_URL_TYPE &&
Packit f574b8
		url_type != LYNXIMGMAP_URL_TYPE) {
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    }
Packit f574b8
	} else if (check_realm && !LYPermitURL && !LYJumpFileURL) {
Packit f574b8
	    if (!(0 == StrNCmp(startrealm, WWWDoc.address,
Packit f574b8
			       strlen(startrealm)) ||
Packit f574b8
		  url_type == LYNXHIST_URL_TYPE ||
Packit f574b8
		  url_type == LYNXEDITMAP_URL_TYPE ||
Packit f574b8
		  url_type == LYNXKEYMAP_URL_TYPE ||
Packit f574b8
		  url_type == LYNXIMGMAP_URL_TYPE ||
Packit f574b8
		  url_type == LYNXCOOKIE_URL_TYPE ||
Packit f574b8
#ifdef USE_CACHEJAR
Packit f574b8
		  url_type == LYNXCACHE_URL_TYPE ||
Packit f574b8
#endif
Packit f574b8
		  url_type == LYNXPRINT_URL_TYPE ||
Packit f574b8
		  url_type == LYNXOPTIONS_URL_TYPE ||
Packit f574b8
		  url_type == LYNXCFG_URL_TYPE ||
Packit f574b8
		  url_type == LYNXCOMPILE_OPTS_URL_TYPE ||
Packit f574b8
		  url_type == LYNXMESSAGES_URL_TYPE ||
Packit f574b8
		  url_type == LYNXDOWNLOAD_URL_TYPE ||
Packit f574b8
		  url_type == MAILTO_URL_TYPE ||
Packit f574b8
		  url_type == NEWSPOST_URL_TYPE ||
Packit f574b8
		  url_type == NEWSREPLY_URL_TYPE ||
Packit f574b8
		  url_type == SNEWSPOST_URL_TYPE ||
Packit f574b8
		  url_type == SNEWSREPLY_URL_TYPE ||
Packit f574b8
		  (!LYUserSpecifiedURL &&
Packit f574b8
		   (url_type == LYNXEXEC_URL_TYPE ||
Packit f574b8
		    url_type == LYNXPROG_URL_TYPE ||
Packit f574b8
		    url_type == LYNXCGI_URL_TYPE)) ||
Packit f574b8
		  (WWWDoc.bookmark != NULL &&
Packit f574b8
		   *WWWDoc.bookmark != '\0') ||
Packit f574b8
		  0 == STRNADDRCOMP(WWWDoc.address, helpfilepath,
Packit f574b8
				    strlen(helpfilepath)) ||
Packit f574b8
		  (lynxlistfile != NULL &&
Packit f574b8
		   0 == STRNADDRCOMP(WWWDoc.address, lynxlistfile,
Packit f574b8
				     strlen(lynxlistfile))) ||
Packit f574b8
		  (lynxjumpfile != NULL &&
Packit f574b8
		   0 == STRNADDRCOMP(WWWDoc.address, lynxjumpfile,
Packit f574b8
				     strlen(lynxjumpfile))))) {
Packit f574b8
		HTUserMsg(NOT_IN_STARTING_REALM);
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
	if (WWWDoc.post_data &&
Packit f574b8
	    url_type != HTTP_URL_TYPE &&
Packit f574b8
	    url_type != HTTPS_URL_TYPE &&
Packit f574b8
	    url_type != LYNXCGI_URL_TYPE &&
Packit f574b8
	    url_type != LYNXIMGMAP_URL_TYPE &&
Packit f574b8
	    url_type != GOPHER_URL_TYPE &&
Packit f574b8
	    url_type != CSO_URL_TYPE &&
Packit f574b8
	    url_type != PROXY_URL_TYPE &&
Packit f574b8
	    url_type != LYNXOPTIONS_URL_TYPE &&
Packit f574b8
	    !(url_type == FILE_URL_TYPE &&
Packit f574b8
	      (LYIsUIPage(WWWDoc.address, UIP_LIST_PAGE) ||
Packit f574b8
	       LYIsUIPage(WWWDoc.address, UIP_ADDRLIST_PAGE)))) {
Packit f574b8
	    CTRACE((tfp, "getfile: dropping post_data!\n"));
Packit f574b8
	    HTAlert(IGNORED_POST);
Packit f574b8
	    LYFreePostData(doc);
Packit f574b8
	    WWWDoc.post_data = NULL;
Packit f574b8
	    WWWDoc.post_content_type = NULL;
Packit f574b8
	}
Packit f574b8
#ifdef SYSLOG_REQUESTED_URLS
Packit f574b8
	LYSyslog(doc->address);
Packit f574b8
#endif
Packit f574b8
	if (url_type == UNKNOWN_URL_TYPE ||
Packit f574b8
	    url_type == AFS_URL_TYPE ||
Packit f574b8
	    url_type == PROSPERO_URL_TYPE) {
Packit f574b8
	    HTAlert(UNSUPPORTED_URL_SCHEME);
Packit f574b8
	    return (NULLFILE);
Packit f574b8
Packit f574b8
	} else if (url_type == DATA_URL_TYPE) {
Packit f574b8
	    HTAlert(UNSUPPORTED_DATA_URL);
Packit f574b8
	    return (NULLFILE);
Packit f574b8
Packit f574b8
	} else if (url_type == LYNXPRINT_URL_TYPE) {
Packit f574b8
	    return (printfile(doc));
Packit f574b8
Packit f574b8
#ifndef NO_OPTION_FORMS
Packit f574b8
	} else if (url_type == LYNXOPTIONS_URL_TYPE) {
Packit f574b8
	    /* proceed forms-based options menu */
Packit f574b8
	    return (postoptions(doc));
Packit f574b8
#endif
Packit f574b8
Packit f574b8
	} else if (url_type == LYNXCFG_URL_TYPE &&
Packit f574b8
		   !no_lynxcfg_info) {
Packit f574b8
	    /* @@@ maybe we should generate a specific error message
Packit f574b8
	       if attempted but restricted. - kw */
Packit f574b8
	    /* show/change/reload lynx.cfg settings */
Packit f574b8
	    return (lynx_cfg_infopage(doc));
Packit f574b8
Packit f574b8
#if defined(HAVE_CONFIG_H) && !defined(NO_CONFIG_INFO)
Packit f574b8
	} else if (url_type == LYNXCOMPILE_OPTS_URL_TYPE &&
Packit f574b8
		   !no_compileopts_info) {
Packit f574b8
	    /* @@@ maybe we should generate a specific error message
Packit f574b8
	       if attempted but restricted or not supported. - kw */
Packit f574b8
	    /* show compile-time settings */
Packit f574b8
	    return (lynx_compile_opts(doc));
Packit f574b8
#endif
Packit f574b8
Packit f574b8
#ifndef DISABLE_NEWS
Packit f574b8
	} else if (url_type == NEWSPOST_URL_TYPE ||
Packit f574b8
		   url_type == NEWSREPLY_URL_TYPE ||
Packit f574b8
		   url_type == SNEWSPOST_URL_TYPE ||
Packit f574b8
		   url_type == SNEWSREPLY_URL_TYPE) {
Packit f574b8
Packit f574b8
	    if (no_newspost) {
Packit f574b8
		HTUserMsg(NEWSPOSTING_DISABLED);
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    } else if (!news_ok && (url_type == NEWSPOST_URL_TYPE ||
Packit f574b8
				    url_type == NEWSREPLY_URL_TYPE)) {
Packit f574b8
		HTUserMsg(NEWS_DISABLED);
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    } else {
Packit f574b8
		HTLoadAbsolute(&WWWDoc);
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    }
Packit f574b8
#endif
Packit f574b8
Packit f574b8
	} else if (url_type == LYNXDOWNLOAD_URL_TYPE) {
Packit f574b8
	    LYDownload(doc->address);
Packit f574b8
#ifdef VMS
Packit f574b8
	    if (LYDidRename) {
Packit f574b8
		/*
Packit f574b8
		 * The temporary file was saved to disk via a rename(), so we
Packit f574b8
		 * can't access the temporary file again via the download menu. 
Packit f574b8
		 * Clear the flag, and return NULLFILE to pop.  - FM
Packit f574b8
		 */
Packit f574b8
		LYDidRename = FALSE;
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    }
Packit f574b8
#endif /* VMS */
Packit f574b8
	    return (NORMAL);
Packit f574b8
	} else if (url_type == LYNXDIRED_URL_TYPE) {
Packit f574b8
#ifdef DIRED_SUPPORT
Packit f574b8
	    if (!no_dired_support) {
Packit f574b8
		local_dired(doc);
Packit f574b8
		WWWDoc.address = doc->address;
Packit f574b8
		WWWDoc.post_data = doc->post_data;
Packit f574b8
		WWWDoc.post_content_type = doc->post_content_type;
Packit f574b8
		WWWDoc.bookmark = doc->bookmark;
Packit f574b8
		WWWDoc.isHEAD = doc->isHEAD;
Packit f574b8
		WWWDoc.safe = doc->safe;
Packit f574b8
Packit f574b8
		if (!HTLoadAbsolute(&WWWDoc)) {
Packit f574b8
		    return (NOT_FOUND);
Packit f574b8
		}
Packit f574b8
		return (NORMAL);
Packit f574b8
	    }
Packit f574b8
#endif /* DIRED_SUPPORT */
Packit f574b8
	    HTUserMsg(DIRED_DISABLED);
Packit f574b8
	    return (NULLFILE);
Packit f574b8
	}
Packit f574b8
Packit f574b8
	if (LYNoRefererHeader == FALSE &&
Packit f574b8
	    LYNoRefererForThis == FALSE) {
Packit f574b8
	    const char *ref_url = HTLoadedDocumentURL();
Packit f574b8
Packit f574b8
	    if (isLYNXIMGMAP(ref_url))
Packit f574b8
		ref_url += LEN_LYNXIMGMAP;
Packit f574b8
	    if (no_filereferer == TRUE && isFILE_URL(ref_url)) {
Packit f574b8
		LYNoRefererForThis = TRUE;
Packit f574b8
	    }
Packit f574b8
	    if (LYNoRefererForThis == FALSE &&
Packit f574b8
		(cp = StrChr(ref_url, '?')) != NULL &&
Packit f574b8
		StrChr(cp, '=') != NULL) {
Packit f574b8
		/*
Packit f574b8
		 * Don't send a Referer header if the URL is the reply from a
Packit f574b8
		 * form with method GET, in case the content has personal data
Packit f574b8
		 * (e.g., a password or credit card number) which would become
Packit f574b8
		 * visible in logs.  - FM
Packit f574b8
		 *
Packit f574b8
		 * Changed 1999-11-01 to be controlled by REFERER_WITH_QUERY
Packit f574b8
		 * option.  - kw
Packit f574b8
		 */
Packit f574b8
		if (LYRefererWithQuery == 'S') {	/* SEND */
Packit f574b8
		    StrAllocCopy(LYRequestReferer, ref_url);
Packit f574b8
		} else if (LYRefererWithQuery == 'P') {		/* PARTIAL */
Packit f574b8
		    FREE(LYRequestReferer);	/* just to be sure */
Packit f574b8
		    LYRequestReferer = HTParse(ref_url, "",
Packit f574b8
					       PARSE_ACCESS
Packit f574b8
					       | PARSE_HOST
Packit f574b8
					       | PARSE_STRICTPATH
Packit f574b8
					       | PARSE_PUNCTUATION);
Packit f574b8
		} else {	/* Everything else - don't send Referer */
Packit f574b8
		    LYNoRefererForThis = TRUE;
Packit f574b8
		}
Packit f574b8
		cp = NULL;
Packit f574b8
	    } else if (LYNoRefererForThis == FALSE) {
Packit f574b8
		StrAllocCopy(LYRequestReferer, ref_url);
Packit f574b8
	    }
Packit f574b8
	} else {
Packit f574b8
	    StrAllocCopy(LYRequestReferer, HTLoadedDocumentURL());
Packit f574b8
	}
Packit f574b8
	if (url_type == LYNXHIST_URL_TYPE) {
Packit f574b8
	    /*
Packit f574b8
	     * 'doc' will change to the new file if we had a successful
Packit f574b8
	     * LYpop_num(), and the return value will be FALSE if we had a
Packit f574b8
	     * cancel.  - FM
Packit f574b8
	     */
Packit f574b8
	    if ((historytarget(doc) == FALSE) ||
Packit f574b8
		!doc || !doc->address) {
Packit f574b8
		return (NOT_FOUND);
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * We changed it so reload.
Packit f574b8
	     */
Packit f574b8
	    WWWDoc.address = doc->address;
Packit f574b8
	    WWWDoc.post_data = doc->post_data;
Packit f574b8
	    WWWDoc.post_content_type = doc->post_content_type;
Packit f574b8
	    WWWDoc.bookmark = doc->bookmark;
Packit f574b8
	    WWWDoc.isHEAD = doc->isHEAD;
Packit f574b8
	    WWWDoc.safe = doc->safe;
Packit f574b8
	    if (track_internal_links && doc->internal_link && !reloading) {
Packit f574b8
		LYinternal_flag = TRUE;
Packit f574b8
	    }
Packit f574b8
#ifdef DIRED_SUPPORT
Packit f574b8
	    lynx_edit_mode = FALSE;
Packit f574b8
#endif /* DIRED_SUPPORT */
Packit f574b8
	    if (!HTLoadAbsolute(&WWWDoc)) {
Packit f574b8
		return (NOT_FOUND);
Packit f574b8
	    }
Packit f574b8
	    return (NORMAL);
Packit f574b8
Packit f574b8
	} else if (url_type == LYNXEXEC_URL_TYPE ||
Packit f574b8
		   url_type == LYNXPROG_URL_TYPE) {
Packit f574b8
#ifdef EXEC_LINKS
Packit f574b8
	    if (no_exec &&
Packit f574b8
		!exec_ok(HTLoadedDocumentURL(),
Packit f574b8
			 doc->address + 9, ALWAYS_EXEC_PATH)) {
Packit f574b8
		HTUserMsg(EXECUTION_DISABLED);
Packit f574b8
	    } else if (no_bookmark_exec &&
Packit f574b8
		       HTLoadedDocumentBookmark()) {
Packit f574b8
		HTUserMsg(BOOKMARK_EXEC_DISABLED);
Packit f574b8
	    } else if (local_exec || (local_exec_on_local_files &&
Packit f574b8
				      exec_ok(HTLoadedDocumentURL(),
Packit f574b8
					      doc->address + 9, EXEC_PATH))) {
Packit f574b8
Packit f574b8
		char *p = NULL;
Packit f574b8
Packit f574b8
		/*
Packit f574b8
		 * Bug puts slash on end if none is in the string.
Packit f574b8
		 */
Packit f574b8
		char *last_slash = strrchr(doc->address, '/');
Packit f574b8
Packit f574b8
		if (last_slash - doc->address
Packit f574b8
		    == (int) strlen(doc->address) - 1)
Packit f574b8
		    doc->address[strlen(doc->address) - 1] = '\0';
Packit f574b8
Packit f574b8
		/*
Packit f574b8
		 * Convert '~' to $HOME.
Packit f574b8
		 */
Packit f574b8
		StrAllocCopy(p, doc->address);
Packit f574b8
		LYTildeExpand(&p, TRUE);
Packit f574b8
Packit f574b8
		/*
Packit f574b8
		 * Show URL before executing it.
Packit f574b8
		 */
Packit f574b8
		HTInfoMsg(doc->address);
Packit f574b8
		stop_curses();
Packit f574b8
		/*
Packit f574b8
		 * Run the command.
Packit f574b8
		 */
Packit f574b8
		if (strstr(p, "//") == p + 9)
Packit f574b8
		    LYSystem(p + 11);
Packit f574b8
		else
Packit f574b8
		    LYSystem(p + 9);
Packit f574b8
		FREE(p);
Packit f574b8
Packit f574b8
		if (url_type != LYNXPROG_URL_TYPE) {
Packit f574b8
		    /*
Packit f574b8
		     * Make sure user gets to see screen output.
Packit f574b8
		     */
Packit f574b8
#ifndef VMS
Packit f574b8
		    signal(SIGINT, SIG_IGN);
Packit f574b8
#endif /* !VMS */
Packit f574b8
		    printf("\n%s", RETURN_TO_LYNX);
Packit f574b8
		    fflush(stdout);
Packit f574b8
		    (void) LYgetch();
Packit f574b8
#ifdef VMS
Packit f574b8
		    HadVMSInterrupt = FALSE;
Packit f574b8
#endif /* VMS */
Packit f574b8
		}
Packit f574b8
		if (!dump_output_immediately) {
Packit f574b8
		    start_curses();
Packit f574b8
		    LYAddVisitedLink(doc);
Packit f574b8
		}
Packit f574b8
Packit f574b8
	    } else {
Packit f574b8
		char *buf = 0;
Packit f574b8
Packit f574b8
		HTSprintf0(&buf,
Packit f574b8
			   EXECUTION_DISABLED_FOR_FILE,
Packit f574b8
			   key_for_func(LYK_OPTIONS));
Packit f574b8
		HTAlert(buf);
Packit f574b8
		FREE(buf);
Packit f574b8
	    }
Packit f574b8
#else /* no exec_links */
Packit f574b8
	    HTUserMsg(EXECUTION_NOT_COMPILED);
Packit f574b8
#endif /* EXEC_LINKS */
Packit f574b8
	    return (NULLFILE);
Packit f574b8
Packit f574b8
	} else if (url_type == MAILTO_URL_TYPE) {
Packit f574b8
	    if (no_mail) {
Packit f574b8
		HTUserMsg(MAIL_DISABLED);
Packit f574b8
	    } else if (!dump_output_immediately) {
Packit f574b8
		HTParentAnchor *tmpanchor = HTAnchor_findAddress(&WWWDoc);
Packit f574b8
		const char *title;
Packit f574b8
		char *tmptitle = NULL;
Packit f574b8
Packit f574b8
		title = "";
Packit f574b8
		if (HTAnchor_title(tmpanchor)) {
Packit f574b8
		    title = HTAnchor_title(tmpanchor);
Packit f574b8
		} else if (HTMainAnchor && !LYUserSpecifiedURL) {
Packit f574b8
		    title = HTAnchor_subject(HTMainAnchor);
Packit f574b8
		    if (non_empty(title)) {
Packit f574b8
			if (strncasecomp(title, "Re:", 3)) {
Packit f574b8
			    StrAllocCopy(tmptitle, "Re: ");
Packit f574b8
			    StrAllocCat(tmptitle, title);
Packit f574b8
			    title = tmptitle;
Packit f574b8
			}
Packit f574b8
		    } else {
Packit f574b8
			title = "";
Packit f574b8
		    }
Packit f574b8
		}
Packit f574b8
		cp = StrChr(doc->address, ':') + 1;
Packit f574b8
		reply_by_mail(cp,
Packit f574b8
			      ((HTMainAnchor && !LYUserSpecifiedURL)
Packit f574b8
			       ? (char *) HTMainAnchor->address
Packit f574b8
			       : (char *) doc->address),
Packit f574b8
			      title,
Packit f574b8
			      (HTMainAnchor && !LYUserSpecifiedURL)
Packit f574b8
			      ? HTMainAnchor->message_id
Packit f574b8
			      : NULL);
Packit f574b8
		FREE(tmptitle);
Packit f574b8
	    }
Packit f574b8
	    return (NULLFILE);
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * From here on we could have a remote host, so check if that's
Packit f574b8
	     * allowed.
Packit f574b8
	     */
Packit f574b8
	} else if (local_host_only &&
Packit f574b8
		   url_type != LYNXEDITMAP_URL_TYPE &&
Packit f574b8
		   url_type != LYNXKEYMAP_URL_TYPE &&
Packit f574b8
		   url_type != LYNXIMGMAP_URL_TYPE &&
Packit f574b8
		   url_type != LYNXCOOKIE_URL_TYPE &&
Packit f574b8
		   url_type != LYNXMESSAGES_URL_TYPE &&
Packit f574b8
#ifdef USE_CACHEJAR
Packit f574b8
		   url_type != LYNXCACHE_URL_TYPE &&
Packit f574b8
#endif
Packit f574b8
		   url_type != LYNXCGI_URL_TYPE &&
Packit f574b8
		   !(url_type == NEWS_URL_TYPE &&
Packit f574b8
		     StrNCmp(doc->address, "news://", 7)) &&
Packit f574b8
		   !(LYisLocalHost(doc->address) ||
Packit f574b8
		     LYisLocalAlias(doc->address))) {
Packit f574b8
	    HTUserMsg(ACCESS_ONLY_LOCALHOST);
Packit f574b8
	    return (NULLFILE);
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Disable www telnet access if not telnet_ok.
Packit f574b8
	     */
Packit f574b8
	} else if (url_type == TELNET_URL_TYPE ||
Packit f574b8
		   url_type == TN3270_URL_TYPE ||
Packit f574b8
		   url_type == TELNET_GOPHER_URL_TYPE) {
Packit f574b8
	    char *proxy;
Packit f574b8
Packit f574b8
	    if (!telnet_ok) {
Packit f574b8
		HTUserMsg(TELNET_DISABLED);
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    } else if (no_telnet_port && StrChr(doc->address + 7, ':')) {
Packit f574b8
		HTUserMsg(TELNET_PORT_SPECS_DISABLED);
Packit f574b8
		return (NULLFILE);
Packit f574b8
		/*
Packit f574b8
		 * Detect weird case where interactive protocol would be
Packit f574b8
		 * proxied, and to a non-interactive protocol at that.
Packit f574b8
		 */
Packit f574b8
	    } else if ((proxy = LYGetEnv(((url_type == TN3270_URL_TYPE)
Packit f574b8
					  ? "tn3270_proxy"
Packit f574b8
					  :
Packit f574b8
					  ((url_type == TELNET_GOPHER_URL_TYPE)
Packit f574b8
					   ? "gopher_proxy"
Packit f574b8
					   : "telnet_proxy")))) != NULL &&
Packit f574b8
		       !override_proxy(doc->address) &&
Packit f574b8
		       (!isTELNET_URL(proxy) &&
Packit f574b8
			!isTN3270_URL(proxy) &&
Packit f574b8
			!isRLOGIN_URL(proxy))) {
Packit f574b8
		/* Do nothing, fall through to generic code - kw */
Packit f574b8
	    } else {
Packit f574b8
		stop_curses();
Packit f574b8
		HTLoadAbsolute(&WWWDoc);
Packit f574b8
		if (!dump_output_immediately) {
Packit f574b8
		    start_curses();
Packit f574b8
		    fflush(stdout);
Packit f574b8
		    LYAddVisitedLink(doc);
Packit f574b8
		}
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Disable www news access if not news_ok.
Packit f574b8
	     */
Packit f574b8
#ifndef DISABLE_NEWS
Packit f574b8
	} else if (!news_ok && (url_type == NEWS_URL_TYPE ||
Packit f574b8
				url_type == NNTP_URL_TYPE)) {
Packit f574b8
	    HTUserMsg(NEWS_DISABLED);
Packit f574b8
	    return (NULLFILE);
Packit f574b8
#endif
Packit f574b8
Packit f574b8
	} else if (url_type == RLOGIN_URL_TYPE) {
Packit f574b8
	    char *proxy;
Packit f574b8
Packit f574b8
	    if (!rlogin_ok) {
Packit f574b8
		HTUserMsg(RLOGIN_DISABLED);
Packit f574b8
		return (NULLFILE);
Packit f574b8
		/*
Packit f574b8
		 * Detect weird case where interactive protocol would be
Packit f574b8
		 * proxied, and to a non-interactive protocol at that.
Packit f574b8
		 */
Packit f574b8
	    } else if ((proxy = LYGetEnv("rlogin_proxy")) != NULL &&
Packit f574b8
		       !override_proxy(doc->address) &&
Packit f574b8
		       (!isTELNET_URL(proxy) &&
Packit f574b8
			!isTN3270_URL(proxy) &&
Packit f574b8
			!isRLOGIN_URL(proxy))) {
Packit f574b8
		/* Do nothing, fall through to generic code - kw */
Packit f574b8
	    } else {
Packit f574b8
		stop_curses();
Packit f574b8
		HTLoadAbsolute(&WWWDoc);
Packit f574b8
		fflush(stdout);
Packit f574b8
		if (!dump_output_immediately) {
Packit f574b8
		    start_curses();
Packit f574b8
		    LYAddVisitedLink(doc);
Packit f574b8
		}
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * If it's a gopher index type and there isn't a search term
Packit f574b8
	     * already attached then do this.  Otherwise just load it!
Packit f574b8
	     */
Packit f574b8
	} else if (url_type == INDEX_GOPHER_URL_TYPE &&
Packit f574b8
		   StrChr(doc->address, '?') == NULL) {
Packit f574b8
	    int status;
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Make sure we don't have a gopher+ escaped tab instead of a
Packit f574b8
	     * gopher0 question mark delimiting the search term.  - FM
Packit f574b8
	     */
Packit f574b8
	    if ((cp = strstr(doc->address, "%09")) != NULL) {
Packit f574b8
		*cp = '\0';
Packit f574b8
		StrAllocCopy(temp, doc->address);
Packit f574b8
		cp += 3;
Packit f574b8
		if (*cp && StrNCmp(cp, "%09", 3)) {
Packit f574b8
		    StrAllocCat(temp, "?");
Packit f574b8
		    StrAllocCat(temp, cp);
Packit f574b8
		    if ((cp = strstr(temp, "%09")) != NULL) {
Packit f574b8
			*cp = '\0';
Packit f574b8
		    }
Packit f574b8
		}
Packit f574b8
		StrAllocCopy(doc->address, temp);
Packit f574b8
		FREE(temp);
Packit f574b8
		goto Try_Redirected_URL;
Packit f574b8
	    }
Packit f574b8
	    /*
Packit f574b8
	     * Load it because the do_www_search routine uses the base url of
Packit f574b8
	     * the currently loaded document :(
Packit f574b8
	     */
Packit f574b8
	    if (!HTLoadAbsolute(&WWWDoc)) {
Packit f574b8
		return (NOT_FOUND);
Packit f574b8
	    }
Packit f574b8
	    status = do_www_search(doc);
Packit f574b8
	    if (status == NULLFILE) {
Packit f574b8
		LYpop(doc);
Packit f574b8
		WWWDoc.address = doc->address;
Packit f574b8
		WWWDoc.post_data = doc->post_data;
Packit f574b8
		WWWDoc.post_content_type = doc->post_content_type;
Packit f574b8
		WWWDoc.bookmark = doc->bookmark;
Packit f574b8
		WWWDoc.isHEAD = doc->isHEAD;
Packit f574b8
		WWWDoc.safe = doc->safe;
Packit f574b8
		status = HTLoadAbsolute(&WWWDoc);
Packit f574b8
#ifdef DIRED_SUPPORT
Packit f574b8
	    } else {
Packit f574b8
		lynx_edit_mode = FALSE;
Packit f574b8
#endif /* DIRED_SUPPORT */
Packit f574b8
	    }
Packit f574b8
	    return (status);
Packit f574b8
	}
Packit f574b8
Packit f574b8
	if (!ftp_ok
Packit f574b8
	    && (url_type == FTP_URL_TYPE
Packit f574b8
		|| url_type == NCFTP_URL_TYPE)) {
Packit f574b8
	    HTUserMsg(FTP_DISABLED);
Packit f574b8
	    return (NULLFILE);
Packit f574b8
	} else if (url_type == HTML_GOPHER_URL_TYPE) {
Packit f574b8
	    char *tmp = NULL;
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * If tuple's Path=GET%20/...  convert to an http URL.
Packit f574b8
	     */
Packit f574b8
	    if ((cp = StrChr(doc->address + 9, '/')) != NULL &&
Packit f574b8
		0 == StrNCmp(++cp, "hGET%20/", 8)) {
Packit f574b8
		StrAllocCopy(tmp, "http://");
Packit f574b8
		CTRACE((tfp, "getfile: URL '%s'\n",
Packit f574b8
			doc->address));
Packit f574b8
		*cp = '\0';
Packit f574b8
		StrAllocCat(tmp, doc->address + 9);
Packit f574b8
		/*
Packit f574b8
		 * If the port is defaulted, it should stay 70.
Packit f574b8
		 */
Packit f574b8
		if (StrChr(tmp + 6, ':') == NULL) {
Packit f574b8
		    StrAllocCat(tmp, "70/");
Packit f574b8
		    tmp[strlen(tmp) - 4] = ':';
Packit f574b8
		}
Packit f574b8
		if (strlen(cp + 7) > 1)
Packit f574b8
		    StrAllocCat(tmp, cp + 8);
Packit f574b8
		StrAllocCopy(doc->address, tmp);
Packit f574b8
		CTRACE((tfp, "  changed to '%s'\n",
Packit f574b8
			doc->address));
Packit f574b8
		FREE(tmp);
Packit f574b8
		url_type = HTTP_URL_TYPE;
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
Packit f574b8
	if (url_type == HTTP_URL_TYPE ||
Packit f574b8
	    url_type == HTTPS_URL_TYPE ||
Packit f574b8
	    url_type == FTP_URL_TYPE ||
Packit f574b8
	    url_type == NCFTP_URL_TYPE ||
Packit f574b8
	    url_type == CSO_URL_TYPE) {
Packit f574b8
	    fix_httplike_urls(doc, url_type);
Packit f574b8
	}
Packit f574b8
Packit f574b8
	WWWDoc.address = doc->address;	/* possible reload */
Packit f574b8
#ifdef DIRED_SUPPORT
Packit f574b8
	lynx_edit_mode = FALSE;
Packit f574b8
#endif /* DIRED_SUPPORT */
Packit f574b8
Packit f574b8
#ifndef DISABLE_BIBP
Packit f574b8
	if (url_type == BIBP_URL_TYPE) {
Packit f574b8
	    char *bibpTmp = NULL;
Packit f574b8
Packit f574b8
	    if (!BibP_bibhost_checked)
Packit f574b8
		LYCheckBibHost();
Packit f574b8
	    if (BibP_bibhost_available) {
Packit f574b8
		StrAllocCopy(bibpTmp, BibP_bibhost);
Packit f574b8
	    } else if (HTMainAnchor && HTAnchor_citehost(HTMainAnchor)) {
Packit f574b8
		StrAllocCopy(bibpTmp, HTAnchor_citehost(HTMainAnchor));
Packit f574b8
	    } else {
Packit f574b8
		StrAllocCopy(bibpTmp, BibP_globalserver);
Packit f574b8
	    }
Packit f574b8
	    if (HTMainAnchor && HTAnchor_citehost(HTMainAnchor)) {
Packit f574b8
		StrAllocCat(bibpTmp, "bibp1.0/resolve?citehost=");
Packit f574b8
		StrAllocCat(bibpTmp, HTAnchor_citehost(HTMainAnchor));
Packit f574b8
		StrAllocCat(bibpTmp, "&usin=");
Packit f574b8
	    } else {
Packit f574b8
		StrAllocCat(bibpTmp, "bibp1.0/resolve?usin=");
Packit f574b8
	    }
Packit f574b8
	    StrAllocCat(bibpTmp, doc->address + 5);	/* USIN after bibp: */
Packit f574b8
	    StrAllocCopy(doc->address, bibpTmp);
Packit f574b8
	    WWWDoc.address = doc->address;
Packit f574b8
	    FREE(bibpTmp);
Packit f574b8
	}
Packit f574b8
#endif /* !DISABLE_BIBP */
Packit f574b8
Packit f574b8
	if (url_type == FILE_URL_TYPE) {
Packit f574b8
	    /*
Packit f574b8
	     * If a file URL has a '~' as the lead character of its first
Packit f574b8
	     * symbolic element, convert the '~' to Home_Dir(), then append
Packit f574b8
	     * the rest of of path, if present, skipping "user" if "~user"
Packit f574b8
	     * was entered, simplifying, and eliminating any residual
Packit f574b8
	     * relative elements.  - FM
Packit f574b8
	     */
Packit f574b8
	    LYTildeExpand(&(doc->address), TRUE);
Packit f574b8
	    WWWDoc.address = doc->address;
Packit f574b8
	}
Packit f574b8
	CTRACE_SLEEP(MessageSecs);
Packit f574b8
	user_message(WWW_WAIT_MESSAGE, doc->address);
Packit f574b8
Packit f574b8
	if (TRACE) {
Packit f574b8
#ifdef USE_SLANG
Packit f574b8
	    if (LYCursesON) {
Packit f574b8
		LYaddstr("*\n");
Packit f574b8
		LYrefresh();
Packit f574b8
	    }
Packit f574b8
#endif /* USE_SLANG */
Packit f574b8
	    CTRACE((tfp, "\n"));
Packit f574b8
	}
Packit f574b8
Packit f574b8
	if (!HTLoadAbsolute(&WWWDoc)) {
Packit f574b8
	    /*
Packit f574b8
	     * Check for redirection.
Packit f574b8
	     */
Packit f574b8
	    if (use_this_url_instead != NULL) {
Packit f574b8
		if (!is_url(use_this_url_instead)) {
Packit f574b8
		    /*
Packit f574b8
		     * The server did not return a complete URL in its
Packit f574b8
		     * Location:  header, probably due to a FORM or other
Packit f574b8
		     * CGI script written by someone who doesn't know that
Packit f574b8
		     * the http protocol requires that it be a complete
Packit f574b8
		     * URL, or using a server which does not treat such a
Packit f574b8
		     * redirect string from the script as an instruction to
Packit f574b8
		     * resolve it versus the initial request, check
Packit f574b8
		     * authentication with that URL, and then act on it
Packit f574b8
		     * without returning redirection to us.  We'll violate
Packit f574b8
		     * the http protocol and resolve it ourselves using the
Packit f574b8
		     * URL of the original request as the BASE, rather than
Packit f574b8
		     * doing the RIGHT thing and returning an invalid
Packit f574b8
		     * address message.  - FM
Packit f574b8
		     */
Packit f574b8
		    HTUserMsg(LOCATION_NOT_ABSOLUTE);
Packit f574b8
		    temp = HTParse(use_this_url_instead,
Packit f574b8
				   WWWDoc.address,
Packit f574b8
				   PARSE_ALL);
Packit f574b8
		    if (non_empty(temp)) {
Packit f574b8
			StrAllocCopy(use_this_url_instead, temp);
Packit f574b8
		    }
Packit f574b8
		    FREE(temp);
Packit f574b8
		}
Packit f574b8
		url_type = is_url(use_this_url_instead);
Packit f574b8
		if (!HTPermitRedir &&
Packit f574b8
		    (url_type == LYNXDOWNLOAD_URL_TYPE ||
Packit f574b8
		     url_type == LYNXEXEC_URL_TYPE ||
Packit f574b8
		     url_type == LYNXPROG_URL_TYPE ||
Packit f574b8
#ifdef DIRED_SUPPORT
Packit f574b8
		     url_type == LYNXDIRED_URL_TYPE ||
Packit f574b8
#endif /* DIRED_SUPPORT */
Packit f574b8
		     url_type == LYNXPRINT_URL_TYPE ||
Packit f574b8
		     url_type == LYNXOPTIONS_URL_TYPE ||
Packit f574b8
		     url_type == LYNXCFG_URL_TYPE ||
Packit f574b8
		     url_type == LYNXCOMPILE_OPTS_URL_TYPE ||
Packit f574b8
		     url_type == LYNXHIST_URL_TYPE ||
Packit f574b8
		     url_type == LYNXCOOKIE_URL_TYPE ||
Packit f574b8
#ifdef USE_CACHEJAR
Packit f574b8
		     url_type == LYNXCACHE_URL_TYPE ||
Packit f574b8
#endif
Packit f574b8
		     url_type == LYNXMESSAGES_URL_TYPE ||
Packit f574b8
		     (LYValidate &&
Packit f574b8
		      url_type != HTTP_URL_TYPE &&
Packit f574b8
		      url_type != HTTPS_URL_TYPE) ||
Packit f574b8
		     ((no_file_url || no_goto_file) &&
Packit f574b8
		      url_type == FILE_URL_TYPE) ||
Packit f574b8
		     (no_goto_lynxcgi &&
Packit f574b8
		      url_type == LYNXCGI_URL_TYPE) ||
Packit f574b8
#ifndef DISABLE_BIBP
Packit f574b8
		     (no_goto_bibp &&
Packit f574b8
		      url_type == BIBP_URL_TYPE) ||
Packit f574b8
#endif
Packit f574b8
		     (no_goto_cso &&
Packit f574b8
		      url_type == CSO_URL_TYPE) ||
Packit f574b8
		     (no_goto_finger &&
Packit f574b8
		      url_type == FINGER_URL_TYPE) ||
Packit f574b8
		     (no_goto_ftp &&
Packit f574b8
		      (url_type == FTP_URL_TYPE ||
Packit f574b8
		       url_type == NCFTP_URL_TYPE)) ||
Packit f574b8
		     (no_goto_gopher &&
Packit f574b8
		      url_type == GOPHER_URL_TYPE) ||
Packit f574b8
		     (no_goto_http &&
Packit f574b8
		      url_type == HTTP_URL_TYPE) ||
Packit f574b8
		     (no_goto_https &&
Packit f574b8
		      url_type == HTTPS_URL_TYPE) ||
Packit f574b8
		     (no_goto_mailto &&
Packit f574b8
		      url_type == MAILTO_URL_TYPE) ||
Packit f574b8
#ifndef DISABLE_NEWS
Packit f574b8
		     (no_goto_news &&
Packit f574b8
		      url_type == NEWS_URL_TYPE) ||
Packit f574b8
		     (no_goto_nntp &&
Packit f574b8
		      url_type == NNTP_URL_TYPE) ||
Packit f574b8
#endif
Packit f574b8
		     (no_goto_rlogin &&
Packit f574b8
		      url_type == RLOGIN_URL_TYPE) ||
Packit f574b8
#ifndef DISABLE_NEWS
Packit f574b8
		     (no_goto_snews &&
Packit f574b8
		      url_type == SNEWS_URL_TYPE) ||
Packit f574b8
#endif
Packit f574b8
		     (no_goto_telnet &&
Packit f574b8
		      url_type == TELNET_URL_TYPE) ||
Packit f574b8
		     (no_goto_tn3270 &&
Packit f574b8
		      url_type == TN3270_URL_TYPE) ||
Packit f574b8
		     (no_goto_wais &&
Packit f574b8
		      url_type == WAIS_URL_TYPE))) {
Packit f574b8
		    /*
Packit f574b8
		     * Some schemes are not acceptable from server
Packit f574b8
		     * redirections.  - KW & FM
Packit f574b8
		     */
Packit f574b8
		    HTAlert(ILLEGAL_REDIRECTION_URL);
Packit f574b8
		    if (LYCursesON) {
Packit f574b8
			HTUserMsg2(WWW_ILLEGAL_URL_MESSAGE,
Packit f574b8
				   use_this_url_instead);
Packit f574b8
		    } else {
Packit f574b8
			fprintf(stderr,
Packit f574b8
				WWW_ILLEGAL_URL_MESSAGE,
Packit f574b8
				use_this_url_instead);
Packit f574b8
		    }
Packit f574b8
		    FREE(use_this_url_instead);
Packit f574b8
		    return (NULLFILE);
Packit f574b8
		}
Packit f574b8
		if ((pound = findPoundSelector(doc->address)) != NULL
Packit f574b8
		    && findPoundSelector(use_this_url_instead) == NULL) {
Packit f574b8
		    /*
Packit f574b8
		     * Our requested URL had a fragment associated with it,
Packit f574b8
		     * and the redirection URL doesn't, so we'll append the
Packit f574b8
		     * fragment associated with the original request.  If
Packit f574b8
		     * it's bogus for the redirection URL, we'll be
Packit f574b8
		     * positioned at the top of that document, so there's
Packit f574b8
		     * no harm done.  - FM
Packit f574b8
		     */
Packit f574b8
		    CTRACE((tfp,
Packit f574b8
			    "getfile: Adding fragment '%s' to redirection URL.\n",
Packit f574b8
			    pound));
Packit f574b8
		    StrAllocCat(use_this_url_instead, pound);
Packit f574b8
		    doc->link = -1;
Packit f574b8
		}
Packit f574b8
		CTRACE_SLEEP(MessageSecs);
Packit f574b8
		HTUserMsg2(WWW_USING_MESSAGE, use_this_url_instead);
Packit f574b8
		CTRACE((tfp, "\n"));
Packit f574b8
		StrAllocCopy(doc->address,
Packit f574b8
			     use_this_url_instead);
Packit f574b8
		FREE(use_this_url_instead);
Packit f574b8
		if (redirect_post_content == FALSE) {
Packit f574b8
		    /*
Packit f574b8
		     * Freeing the content also yields a GET request.  - FM
Packit f574b8
		     */
Packit f574b8
		    LYFreePostData(doc);
Packit f574b8
		}
Packit f574b8
		/*
Packit f574b8
		 * Go to top to check for URL's which get special handling
Packit f574b8
		 * and/or security checks in Lynx.  - FM
Packit f574b8
		 */
Packit f574b8
		goto Try_Redirected_URL;
Packit f574b8
	    }
Packit f574b8
	    if (HTNoDataOK) {
Packit f574b8
		return (NULLFILE);
Packit f574b8
	    } else {
Packit f574b8
		return (NOT_FOUND);
Packit f574b8
	    }
Packit f574b8
	} else {
Packit f574b8
Packit f574b8
	    lynx_mode = NORMAL_LYNX_MODE;
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Some URL's don't actually return a document; compare
Packit f574b8
	     * doc->address with the document that is actually loaded and
Packit f574b8
	     * return NULLFILE if not loaded.  If www_search_result is not -1
Packit f574b8
	     * then this is a reference to a named anchor within the same
Packit f574b8
	     * document; do NOT return NULLFILE in that case.
Packit f574b8
	     */
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Check for a #fragment selector.
Packit f574b8
	     */
Packit f574b8
	    pound = findPoundSelector(doc->address);
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Check to see if there is a temp file waiting for us to
Packit f574b8
	     * download.
Packit f574b8
	     */
Packit f574b8
	    if (WWW_Download_File) {
Packit f574b8
		HTParentAnchor *tmpanchor = HTAnchor_findAddress(&WWWDoc);
Packit f574b8
		char *fname = NULL;
Packit f574b8
Packit f574b8
		/*
Packit f574b8
		 * Check for a suggested filename from the
Packit f574b8
		 * Content-Disposition header.  - FM
Packit f574b8
		 */
Packit f574b8
		if (HTAnchor_SugFname(tmpanchor) != NULL) {
Packit f574b8
		    StrAllocCopy(fname, HTAnchor_SugFname(tmpanchor));
Packit f574b8
		} else {
Packit f574b8
		    StrAllocCopy(fname, doc->address);
Packit f574b8
		}
Packit f574b8
		/*
Packit f574b8
		 * Check whether this is a compressed file, which we don't
Packit f574b8
		 * uncompress for downloads, and adjust any suffix
Packit f574b8
		 * appropriately.  - FM
Packit f574b8
		 */
Packit f574b8
		HTCheckFnameForCompression(&fname, tmpanchor, FALSE);
Packit f574b8
Packit f574b8
		if (LYdownload_options(&fname,
Packit f574b8
				       WWW_Download_File) < 0) {
Packit f574b8
		    FREE(fname);
Packit f574b8
		    return (NOT_FOUND);
Packit f574b8
		}
Packit f574b8
		LYAddVisitedLink(doc);
Packit f574b8
		StrAllocCopy(doc->address, fname);
Packit f574b8
		FREE(fname);
Packit f574b8
		doc->internal_link = FALSE;
Packit f574b8
		WWWDoc.address = doc->address;
Packit f574b8
		LYFreePostData(doc);
Packit f574b8
		WWWDoc.post_data = NULL;
Packit f574b8
		WWWDoc.post_content_type = NULL;
Packit f574b8
		WWWDoc.bookmark = doc->bookmark = FALSE;
Packit f574b8
		WWWDoc.isHEAD = doc->isHEAD = FALSE;
Packit f574b8
		WWWDoc.safe = doc->safe = FALSE;
Packit f574b8
		HTOutputFormat = WWW_PRESENT;
Packit f574b8
		if (!HTLoadAbsolute(&WWWDoc)) {
Packit f574b8
		    return (NOT_FOUND);
Packit f574b8
		} else {
Packit f574b8
		    return (NORMAL);
Packit f574b8
		}
Packit f574b8
Packit f574b8
	    } else if (pound == NULL &&
Packit f574b8
		/*
Packit f574b8
		 * HTAnchor hash-table searches are now case-sensitive
Packit f574b8
		 * (hopefully, without anchor deletion problems), so this
Packit f574b8
		 * is too.  - FM
Packit f574b8
		 */
Packit f574b8
		       (strcmp(doc->address,
Packit f574b8
			       HTLoadedDocumentURL()) ||
Packit f574b8
		/*
Packit f574b8
		 * Also check the post_data elements.  - FM
Packit f574b8
		 */
Packit f574b8
			!BINEQ(doc->post_data,
Packit f574b8
			       HTLoadedDocumentPost_data()) ||
Packit f574b8
		/*
Packit f574b8
		 * Also check the isHEAD element.  - FM
Packit f574b8
		 */
Packit f574b8
			doc->isHEAD != HTLoadedDocumentIsHEAD())) {
Packit f574b8
		/*
Packit f574b8
		 * Nothing needed to be shown.
Packit f574b8
		 */
Packit f574b8
		LYAddVisitedLink(doc);
Packit f574b8
		return (NULLFILE);
Packit f574b8
Packit f574b8
	    } else {
Packit f574b8
		if (pound != NULL) {
Packit f574b8
		    if (!HTMainText) {	/* this should not happen... */
Packit f574b8
			return (NULLFILE);	/* but it can. - kw */
Packit f574b8
		    }
Packit f574b8
		    /*
Packit f574b8
		     * May set www_search_result.
Packit f574b8
		     */
Packit f574b8
		    if (HTFindPoundSelector(pound + 1)) {
Packit f574b8
			*target = www_search_result;
Packit f574b8
			doc->link = -1;
Packit f574b8
		    }
Packit f574b8
		}
Packit f574b8
		return (NORMAL);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
    } else {
Packit f574b8
	CTRACE_SLEEP(MessageSecs);
Packit f574b8
	HTUserMsg2(WWW_BAD_ADDR_MESSAGE, doc->address);
Packit f574b8
	CTRACE((tfp, "\n"));
Packit f574b8
	return (NULLFILE);
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * Set source mode for the next retrieval via getfile or HTreparse_document.
Packit f574b8
 * mode == -1:  force normal presentation
Packit f574b8
 * mode == 1:  force source presentation
Packit f574b8
 * mode == 0:  reset to normal if it was set to source
Packit f574b8
 * - kw
Packit f574b8
 */
Packit f574b8
void srcmode_for_next_retrieval(int mode)
Packit f574b8
{
Packit f574b8
    if (mode < 0) {
Packit f574b8
	HTOutputFormat = WWW_PRESENT;
Packit f574b8
#ifdef USE_PRETTYSRC
Packit f574b8
	psrc_view = FALSE;
Packit f574b8
#endif
Packit f574b8
Packit f574b8
    } else if (mode == 0) {
Packit f574b8
	if (HTOutputFormat == WWW_SOURCE)
Packit f574b8
	    HTOutputFormat = WWW_PRESENT;
Packit f574b8
#ifdef USE_PRETTYSRC
Packit f574b8
	else if (LYpsrc)
Packit f574b8
	    psrc_view = FALSE;
Packit f574b8
#endif
Packit f574b8
Packit f574b8
    } else {
Packit f574b8
#ifdef USE_PRETTYSRC
Packit f574b8
	if (LYpsrc)
Packit f574b8
	    psrc_view = TRUE;
Packit f574b8
	else
Packit f574b8
	    HTOutputFormat = WWW_SOURCE;
Packit f574b8
#else
Packit f574b8
	HTOutputFormat = WWW_SOURCE;
Packit f574b8
#endif
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * The user wants to select a link or page by number.
Packit f574b8
 *
Packit f574b8
 * If follow_link_number returns DO_LINK_STUFF do_link will be run immediately
Packit f574b8
 * following its execution.
Packit f574b8
 *
Packit f574b8
 * If follow_link_number returns DO_GOTOLINK_STUFF it has updated the passed in
Packit f574b8
 * doc for positioning on a link.
Packit f574b8
 *
Packit f574b8
 * If follow_link_number returns DO_GOTOPAGE_STUFF it has set doc->line to the
Packit f574b8
 * top line of the desired page for displaying that page.
Packit f574b8
 *
Packit f574b8
 * If follow_link_number returns PRINT_ERROR an error message will be given to
Packit f574b8
 * the user.
Packit f574b8
 *
Packit f574b8
 * If follow_link_number returns DO_FORMS_STUFF some forms stuff will be done. 
Packit f574b8
 * (Not yet implemented.)
Packit f574b8
 *
Packit f574b8
 * If follow_link_number returns DO_NOTHING nothing special will run after it.
Packit f574b8
 */
Packit f574b8
int follow_link_number(int c,
Packit f574b8
		       int cur,
Packit f574b8
		       DocInfo *doc,
Packit f574b8
		       int *num)
Packit f574b8
{
Packit f574b8
    bstring *temp = NULL;
Packit f574b8
    char *p;
Packit f574b8
    int rel = 0;
Packit f574b8
    int new_top, new_link;
Packit f574b8
    BOOL want_go;
Packit f574b8
    int curline = *num;		/* passed in from mainloop() */
Packit f574b8
    int code;
Packit f574b8
Packit f574b8
    CTRACE((tfp, "follow_link_number(%d,%d,...)\n", c, cur));
Packit f574b8
    BStrCopy0(temp, "?");
Packit f574b8
    temp->str[0] = (char) c;
Packit f574b8
    *num = -1;
Packit f574b8
    _statusline(FOLLOW_LINK_NUMBER);
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Get the number, possibly with a letter suffix, from the user.
Packit f574b8
     */
Packit f574b8
    if (LYgetBString(&temp, FALSE, 120, NORECALL) < 0 ||
Packit f574b8
	isBEmpty(temp)) {
Packit f574b8
	HTInfoMsg(CANCELLED);
Packit f574b8
	return (DO_NOTHING);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    p = temp->str;
Packit f574b8
    *num = atoi(p);
Packit f574b8
    while (isdigit(UCH(*p)))
Packit f574b8
	++p;
Packit f574b8
    c = *p;			/* reuse c; 0 or g or p or + or - */
Packit f574b8
    switch (c) {
Packit f574b8
    case '+':
Packit f574b8
    case '-':
Packit f574b8
	/* 123+ or 123- */
Packit f574b8
	rel = c;
Packit f574b8
	c = *++p;
Packit f574b8
	break;
Packit f574b8
    default:
Packit f574b8
	rel = *++p;
Packit f574b8
	break;
Packit f574b8
    case 0:
Packit f574b8
	break;
Packit f574b8
    }
Packit f574b8
    /* don't currently check for errors typing suffix */
Packit f574b8
Packit f574b8
    CTRACE((tfp, "  temp=%s, *num=%d, rel='%c'\n", temp->str, *num, rel));
Packit f574b8
    /*
Packit f574b8
     * Check if we had a 'p' or 'P' following the number as a flag for
Packit f574b8
     * displaying the page with that number.  - FM
Packit f574b8
     */
Packit f574b8
    if ((c == 'p' || c == 'P') && display_lines == 0) {
Packit f574b8
	CTRACE((tfp, " curline=%d, LYlines=%d, display too small!\n",
Packit f574b8
		curline, LYlines));
Packit f574b8
	code = PRINT_ERROR;
Packit f574b8
    } else if (c == 'p' || c == 'P') {
Packit f574b8
	int nlines = HText_getNumOfLines();
Packit f574b8
	int npages = (((nlines + 1) > display_lines)
Packit f574b8
		      ? (((nlines + 1) + (display_lines - 1)) / (display_lines))
Packit f574b8
		      : 1);
Packit f574b8
	int curpage = (((curline + 1) > display_lines)
Packit f574b8
		       ? (((curline + 1) + (display_lines - 1)) / (display_lines))
Packit f574b8
		       : 1);
Packit f574b8
Packit f574b8
	CTRACE((tfp, " nlines=%d, npages=%d, curline=%d, curpage=%d\n",
Packit f574b8
		nlines, npages, curline, curpage));
Packit f574b8
	if (*num < 1)
Packit f574b8
	    *num = rel ? 0 : 1;
Packit f574b8
	if (rel == '+')
Packit f574b8
	    *num = curpage + *num;
Packit f574b8
	else if (rel == '-')
Packit f574b8
	    *num = curpage - *num;
Packit f574b8
	doc->line = ((npages <= 1)
Packit f574b8
		     ? 1
Packit f574b8
		     : ((*num <= npages)
Packit f574b8
			? (((*num - 1) * display_lines) + 1)
Packit f574b8
			: (((npages - 1) * display_lines) + 1)));
Packit f574b8
	code = DO_GOTOPAGE_STUFF;
Packit f574b8
    } else {
Packit f574b8
Packit f574b8
	/*
Packit f574b8
	 * Check if we want to make the link corresponding to the number the
Packit f574b8
	 * current link, rather than ACTIVATE-ing it.
Packit f574b8
	 */
Packit f574b8
	want_go = (BOOL) (c == 'g' || c == 'G');
Packit f574b8
Packit f574b8
	/* If rel, add or subtract num from current link, or
Packit f574b8
	 * nearest previous/subsequent link if current link is not on screen.
Packit f574b8
	 */
Packit f574b8
	if (rel)
Packit f574b8
	    *num = HTGetRelLinkNum(*num, rel, cur);
Packit f574b8
	/*
Packit f574b8
	 * If we have a valid number, act on it.
Packit f574b8
	 */
Packit f574b8
	if (*num > 0) {
Packit f574b8
	    int info;
Packit f574b8
	    char *text = NULL;
Packit f574b8
Packit f574b8
	    /*
Packit f574b8
	     * Get the lname, and hightext, directly from www structures and
Packit f574b8
	     * add it to the cur link so that we can pass it transparently on
Packit f574b8
	     * to getfile(), and load new_top and new_link if we instead want
Packit f574b8
	     * to make the link number current.  These things are done so that
Packit f574b8
	     * a link can be selected anywhere in the current document, whether
Packit f574b8
	     * it is displayed on the screen or not!
Packit f574b8
	     */
Packit f574b8
	    info = HTGetLinkInfo(*num,
Packit f574b8
				 want_go,
Packit f574b8
				 &new_top,
Packit f574b8
				 &new_link,
Packit f574b8
				 &text,
Packit f574b8
				 &links[cur].lname);
Packit f574b8
	    if (text != NULL)
Packit f574b8
		LYSetHilite(cur, text);
Packit f574b8
Packit f574b8
	    if (info == WWW_INTERN_LINK_TYPE) {
Packit f574b8
		links[cur].type = WWW_INTERN_LINK_TYPE;
Packit f574b8
		code = DO_LINK_STUFF;
Packit f574b8
	    } else if (info == LINK_LINE_FOUND) {
Packit f574b8
		doc->line = new_top + 1;
Packit f574b8
		doc->link = new_link;
Packit f574b8
		code = DO_GOTOLINK_STUFF;
Packit f574b8
	    } else if (info) {
Packit f574b8
		links[cur].type = WWW_LINK_TYPE;
Packit f574b8
		code = DO_LINK_STUFF;
Packit f574b8
	    } else {
Packit f574b8
		code = PRINT_ERROR;
Packit f574b8
	    }
Packit f574b8
	} else {
Packit f574b8
	    code = PRINT_ERROR;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    BStrFree(temp);
Packit f574b8
    return code;
Packit f574b8
}
Packit f574b8
Packit f574b8
#if defined(EXEC_LINKS) || defined(LYNXCGI_LINKS)
Packit f574b8
Packit f574b8
struct trust {
Packit f574b8
    char *src;
Packit f574b8
    char *path;
Packit f574b8
    int type;
Packit f574b8
    struct trust *next;
Packit f574b8
};
Packit f574b8
Packit f574b8
static struct trust *trusted_exec = 0;
Packit f574b8
static struct trust *always_trusted_exec;
Packit f574b8
static struct trust *trusted_cgi = 0;
Packit f574b8
Packit f574b8
static struct trust *new_trust(const char *src, const char *path, int type)
Packit f574b8
{
Packit f574b8
    struct trust *tp;
Packit f574b8
Packit f574b8
    tp = typecalloc(struct trust);
Packit f574b8
Packit f574b8
    if (tp == NULL)
Packit f574b8
	outofmem(__FILE__, "new_trust");
Packit f574b8
Packit f574b8
    tp->type = type;
Packit f574b8
    StrAllocCopy(tp->src, src);
Packit f574b8
    StrAllocCopy(tp->path, path);
Packit f574b8
Packit f574b8
    return tp;
Packit f574b8
}
Packit f574b8
Packit f574b8
static struct trust *get_trust(struct trust **table, const char *src, int type)
Packit f574b8
{
Packit f574b8
    if (*table == 0) {
Packit f574b8
	*table = new_trust(src, "", type);
Packit f574b8
    }
Packit f574b8
    return *table;
Packit f574b8
}
Packit f574b8
Packit f574b8
#ifdef LY_FIND_LEAKS
Packit f574b8
static void free_data(struct trust **data)
Packit f574b8
{
Packit f574b8
    struct trust *cur = (*data);
Packit f574b8
    struct trust *next;
Packit f574b8
Packit f574b8
    while (cur) {
Packit f574b8
	FREE(cur->src);
Packit f574b8
	FREE(cur->path);
Packit f574b8
	next = cur->next;
Packit f574b8
	FREE(cur);
Packit f574b8
	cur = next;
Packit f574b8
    }
Packit f574b8
    *data = NULL;
Packit f574b8
}
Packit f574b8
Packit f574b8
static void LYTrusted_free(void)
Packit f574b8
{
Packit f574b8
    free_data(&trusted_exec);
Packit f574b8
    free_data(&always_trusted_exec);
Packit f574b8
    free_data(&trusted_cgi);
Packit f574b8
Packit f574b8
    return;
Packit f574b8
}
Packit f574b8
#endif /* LY_FIND_LEAKS */
Packit f574b8
Packit f574b8
void add_trusted(char *str,
Packit f574b8
		 int type)
Packit f574b8
{
Packit f574b8
    struct trust *tp;
Packit f574b8
    char *path;
Packit f574b8
    char *src = str;
Packit f574b8
    const char *after_tab;
Packit f574b8
    int Type = type;
Packit f574b8
    static BOOLEAN first = TRUE;
Packit f574b8
Packit f574b8
    if (!src)
Packit f574b8
	return;
Packit f574b8
    if (first) {
Packit f574b8
#ifdef LY_FIND_LEAKS
Packit f574b8
	atexit(LYTrusted_free);
Packit f574b8
#endif
Packit f574b8
	first = FALSE;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    path = StrChr(src, '\t');
Packit f574b8
    if (path) {
Packit f574b8
	*path++ = '\0';
Packit f574b8
	after_tab = path;
Packit f574b8
    } else {
Packit f574b8
	after_tab = "";
Packit f574b8
    }
Packit f574b8
Packit f574b8
    tp = new_trust(src, after_tab, Type);
Packit f574b8
Packit f574b8
    if (Type == EXEC_PATH) {
Packit f574b8
	tp->next = trusted_exec;
Packit f574b8
	trusted_exec = tp;
Packit f574b8
    } else if (Type == ALWAYS_EXEC_PATH) {
Packit f574b8
	tp->next = always_trusted_exec;
Packit f574b8
	always_trusted_exec = tp;
Packit f574b8
    } else if (Type == CGI_PATH) {
Packit f574b8
	tp->next = trusted_cgi;
Packit f574b8
	trusted_cgi = tp;
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * Check to see if the supplied paths is allowed to be executed.
Packit f574b8
 */
Packit f574b8
BOOLEAN exec_ok(const char *source,
Packit f574b8
		const char *linktext,
Packit f574b8
		int type)
Packit f574b8
{
Packit f574b8
    struct trust *tp;
Packit f574b8
    const char *cp;
Packit f574b8
    const char *allowed_extra_chars;
Packit f574b8
    int Type = type;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Always OK if it is a jump file shortcut.
Packit f574b8
     */
Packit f574b8
    if (LYJumpFileURL)
Packit f574b8
	return TRUE;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Choose the trust structure based on the type.
Packit f574b8
     */
Packit f574b8
    if (Type == EXEC_PATH) {
Packit f574b8
	tp = get_trust(&trusted_exec, "file://localhost/", EXEC_PATH);
Packit f574b8
    } else if (Type == ALWAYS_EXEC_PATH) {
Packit f574b8
	tp = get_trust(&always_trusted_exec, "none", ALWAYS_EXEC_PATH);
Packit f574b8
    } else if (Type == CGI_PATH) {
Packit f574b8
	tp = get_trust(&trusted_cgi, "none", CGI_PATH);
Packit f574b8
    } else {
Packit f574b8
	HTAlert(MALFORMED_EXEC_REQUEST);
Packit f574b8
	return FALSE;
Packit f574b8
    }
Packit f574b8
Packit f574b8
#ifdef VMS
Packit f574b8
    /*
Packit f574b8
     * Security:  reject on relative path.
Packit f574b8
     */
Packit f574b8
    if ((cp = StrChr(linktext, '[')) != NULL) {
Packit f574b8
	char *cp1;
Packit f574b8
Packit f574b8
	if (((cp1 = StrChr(cp, '-')) != NULL) &&
Packit f574b8
	    StrChr(cp1, ']') != NULL) {
Packit f574b8
	    while (cp1[1] == '-')
Packit f574b8
		cp1++;
Packit f574b8
	    if (cp1[1] == ']' ||
Packit f574b8
		cp1[1] == '.') {
Packit f574b8
		HTAlert(RELPATH_IN_EXEC_LINK);
Packit f574b8
		return FALSE;
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
#else
Packit f574b8
    /*
Packit f574b8
     * Security:  reject on relative path.
Packit f574b8
     */
Packit f574b8
    if (strstr(linktext, "../") != NULL) {
Packit f574b8
	HTAlert(RELPATH_IN_EXEC_LINK);
Packit f574b8
	return FALSE;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * Security:  reject on strange character.
Packit f574b8
     */
Packit f574b8
    if (Type == CGI_PATH)
Packit f574b8
	allowed_extra_chars = " _-:./@~$&+=\t";
Packit f574b8
    else
Packit f574b8
	allowed_extra_chars = " _-:./@~$+=\t";
Packit f574b8
    for (cp = linktext; *cp != '\0'; cp++) {
Packit f574b8
	if (!isalnum(UCH(*cp)) && !StrChr(allowed_extra_chars, *cp)) {
Packit f574b8
	    char *buf = 0;
Packit f574b8
Packit f574b8
	    HTSprintf0(&buf,
Packit f574b8
		       BADCHAR_IN_EXEC_LINK,
Packit f574b8
		       *cp);
Packit f574b8
	    HTAlert(buf);
Packit f574b8
	    FREE(buf);
Packit f574b8
	    return FALSE;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
#endif /* VMS */
Packit f574b8
Packit f574b8
  check_tp_for_entry:
Packit f574b8
    while (tp) {
Packit f574b8
	if (tp->type == Type) {
Packit f574b8
	    char const *command = linktext;
Packit f574b8
Packit f574b8
	    if (strstr(command, "//") == linktext) {
Packit f574b8
		command += 2;
Packit f574b8
	    }
Packit f574b8
	    CTRACE((tfp, "comparing source\n\t'%s'\n\t'%s'\n", source, tp->src));
Packit f574b8
	    CTRACE((tfp, "comparing command\n\t'%s'\n\t'%s'\n", command, tp->path));
Packit f574b8
	    if (STRNADDRCOMP(source, tp->src, strlen(tp->src)) == 0 &&
Packit f574b8
		STRNADDRCOMP(command, tp->path, strlen(tp->path)) == 0)
Packit f574b8
		return TRUE;
Packit f574b8
	}
Packit f574b8
	tp = tp->next;
Packit f574b8
    }
Packit f574b8
    if (Type == EXEC_PATH &&
Packit f574b8
	always_trusted_exec->next != 0) {
Packit f574b8
	Type = ALWAYS_EXEC_PATH;
Packit f574b8
	tp = always_trusted_exec;
Packit f574b8
	goto check_tp_for_entry;
Packit f574b8
    }
Packit f574b8
    if (!(no_exec && type == ALWAYS_EXEC_PATH))
Packit f574b8
	HTAlert(BADLOCPATH_IN_EXEC_LINK);
Packit f574b8
    return FALSE;
Packit f574b8
}
Packit f574b8
#endif /* EXEC_LINKS || LYNXCGI_LINKS */
Packit f574b8
Packit f574b8
static int fix_httplike_urls(DocInfo *doc, UrlTypes type)
Packit f574b8
{
Packit f574b8
    char *slash;
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * If there's a fragment present, our simplistic methods won't work.  - kw
Packit f574b8
     */
Packit f574b8
    if (findPoundSelector(doc->address) != NULL)
Packit f574b8
	return 0;
Packit f574b8
Packit f574b8
#ifndef DISABLE_FTP
Packit f574b8
    /*
Packit f574b8
     * If it's an ftp URL with a trailing slash, trim it off.
Packit f574b8
     */
Packit f574b8
    if (type == FTP_URL_TYPE &&
Packit f574b8
	LYIsHtmlSep(doc->address[strlen(doc->address) - 1])) {
Packit f574b8
	char *path = HTParse(doc->address, "", PARSE_PATH | PARSE_PUNCTUATION);
Packit f574b8
Packit f574b8
	/*
Packit f574b8
	 * If the path is a lone slash, we're done.  - FM
Packit f574b8
	 */
Packit f574b8
	if (path) {
Packit f574b8
	    if (LYIsHtmlSep(path[0]) && path[1] == '\0') {
Packit f574b8
		FREE(path);
Packit f574b8
		return 0;
Packit f574b8
	    }
Packit f574b8
	    FREE(path);
Packit f574b8
	}
Packit f574b8
Packit f574b8
	/*
Packit f574b8
	 * If we're proxying ftp, don't trim anything.  - KW
Packit f574b8
	 */
Packit f574b8
	if ((LYGetEnv("ftp_proxy") != NULL) &&
Packit f574b8
	    !override_proxy(doc->address))
Packit f574b8
	    return 0;
Packit f574b8
Packit f574b8
	/*
Packit f574b8
	 * If we get to here, trim the trailing slash.  - FM
Packit f574b8
	 */
Packit f574b8
	CTRACE((tfp, "fix_httplike_urls: URL '%s'\n", doc->address));
Packit f574b8
	LYTrimHtmlSep(doc->address);
Packit f574b8
	CTRACE((tfp, "            changed to '%s'\n", doc->address));
Packit f574b8
	CTRACE_SLEEP(MessageSecs);
Packit f574b8
    } else if (type == NCFTP_URL_TYPE) {
Packit f574b8
	char *path = NULL;
Packit f574b8
	char *first = doc->address;
Packit f574b8
	char *second = StrChr(first, ':');
Packit f574b8
Packit f574b8
	CTRACE((tfp, "fix_httplike_urls: URL '%s'\n", doc->address));
Packit f574b8
	if (second == 0)
Packit f574b8
	    second = first + strlen(first);
Packit f574b8
	else
Packit f574b8
	    *second++ = '\0';
Packit f574b8
	HTSprintf0(&path, "%s//%s%s", STR_FTP_URL, first, second);
Packit f574b8
	FREE(doc->address);
Packit f574b8
	doc->address = path;
Packit f574b8
Packit f574b8
	CTRACE((tfp, "            changed to '%s'\n", doc->address));
Packit f574b8
	CTRACE_SLEEP(MessageSecs);
Packit f574b8
    }
Packit f574b8
#endif /* DISABLE_FTP */
Packit f574b8
Packit f574b8
    /*
Packit f574b8
     * If there isn't a slash besides the two at the beginning, append one.
Packit f574b8
     */
Packit f574b8
    if ((slash = strrchr(doc->address, '/')) != NULL) {
Packit f574b8
	if (!LYIsHtmlSep(*(slash - 1)) || *(slash - 2) != ':') {
Packit f574b8
	    return (0);
Packit f574b8
	}
Packit f574b8
	if (type == HTTP_URL_TYPE ||
Packit f574b8
	    type == HTTPS_URL_TYPE) {
Packit f574b8
	    if ((slash - 2) != StrChr(doc->address, ':')) {
Packit f574b8
		/*
Packit f574b8
		 * Turns out we were not looking at the right slash after all,
Packit f574b8
		 * there must have been more than one "://" which is valid at
Packit f574b8
		 * least for http URLs (later occurrences can be part of a
Packit f574b8
		 * query string, for example), so leave this alone, too.  - kw
Packit f574b8
		 */
Packit f574b8
		return (0);
Packit f574b8
	    }
Packit f574b8
	    if (StrChr(doc->address, '?')) {
Packit f574b8
		/*
Packit f574b8
		 * If there is a question mark that appears to be part of the
Packit f574b8
		 * hostname, don't append anything either.  Leave it to HTParse
Packit f574b8
		 * to interpret the question mark as ending the hostname.  - kw
Packit f574b8
		 */
Packit f574b8
		return (0);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    CTRACE((tfp, "fix_httplike_urls: URL '%s'\n", doc->address));
Packit f574b8
    LYAddHtmlSep(&(doc->address));
Packit f574b8
    CTRACE((tfp, "            changed to '%s'\n", doc->address));
Packit f574b8
    CTRACE_SLEEP(MessageSecs);
Packit f574b8
Packit f574b8
    return (1);
Packit f574b8
}