Esempio n. 1
0
/*
 *  In edit mode invoke the given (or default) editor to display and edit the
 *  current file.  For editors listed in 'editor_can_position()', Lynx
 *  will open the file to the same line that the screen cursor is on (or
 *  close...) when editing is invoked.
 *
 *  Returns FALSE if file is uneditable.
 */
PUBLIC int edit_current_file ARGS3(
	char *,		newfile,
	int,		cur,
	int,		lineno)
{
    int result = FALSE;
    char *filename = NULL;
#if !(defined(VMS) || defined(USE_DOS_DRIVES))
    char *colon;
#endif
    char *number_sign;
    char position[80];
#if defined(VMS) || defined(CANT_EDIT_UNWRITABLE_FILES)
    FILE *fp;
#endif

    CTRACE((tfp, "edit_current_file(newfile=%s, cur=%d, lineno=%d)\n",
		 newfile, cur, lineno));

    /*
     *  If it's a remote file then we can't edit it.
     */
    if (!LYisLocalFile(newfile)) {
	HTUserMsg(CANNOT_EDIT_REMOTE_FILES);
	return FALSE;
    }

    /*
     *  If there's a fragment, trim it. - FM
     */
    number_sign = trimPoundSelector(newfile);

    /*
     *  On Unix, first try to open it as a completely referenced file,
     *  then via the path alone.
     *
     * On VMS, only try the path.
     */
#if defined (VMS) || defined (USE_DOS_DRIVES)
    filename = HTParse(newfile, "", PARSE_PATH+PARSE_PUNCTUATION);
    HTUnEscape(filename);
    StrAllocCopy(filename, HTSYS_name(filename));
    if (!LYCanReadFile(filename)) {
#ifdef SH_EX
	HTUserMsg2(COULD_NOT_EDIT_FILE, filename);
#else
	HTAlert(COULD_NOT_ACCESS_FILE);
#endif
	CTRACE((tfp, "filename: '%s'\n", filename));
	goto done;
    }
#else	/* something like UNIX */
    if (strncmp(newfile, "file://localhost/", 16) == 0)
	colon = newfile + 16;
    else
	colon = strchr(newfile, ':');
    StrAllocCopy(filename, (colon + 1));
    HTUnEscape(filename);
    if (!LYCanReadFile(filename)) {
	FREE(filename);
	filename = HTParse(newfile, "", PARSE_PATH+PARSE_PUNCTUATION);
	HTUnEscape(filename);
	if (!LYCanReadFile(HTSYS_name(filename))) {
	    HTAlert(COULD_NOT_ACCESS_FILE);
	    goto done;
	}
    }
#endif

#if defined(VMS) || defined(CANT_EDIT_UNWRITABLE_FILES)
    /*
     *  Don't allow editing if user lacks append access.
     */
    if ((fp = fopen(filename, TXT_A)) == NULL)
    {
	HTUserMsg(NOAUTH_TO_EDIT_FILE);
	goto done;
    }
    fclose(fp);
#endif /* VMS || CANT_EDIT_UNWRITABLE_FILES */

    /*
     *  Make sure cur is at least zero. - FM
     */
    if (cur < 0) {
	cur = 0;
    }

    /*
     *  Set up the command for the editor. - FM
     */
    *position = 0;
#ifdef VMS
    lineno--;
#endif
    lineno += (nlinks ? links[cur].ly : 0);
    if (lineno > 0)
	sprintf(position, "%d", lineno);

    edit_temporary_file(filename, position, NULL);
    result = TRUE;

done:
    /*
     *  Restore the fragment if there was one. - FM
     */
    restorePoundSelector(number_sign);

    FREE(filename);
    CTRACE((tfp, "edit_current_file returns %d\n", result));
    return (result);
}
Esempio n. 2
0
/*
 *  This function is called from HTLoadNews() to have the user
 *  create a file with news headers and a body for posting of
 *  a new message (based on a newspost://nntp_host/newsgroups
 *  or snewspost://secure_nntp_host/newsgroups URL), or to post
 *  a followup (based on a newsreply://nntp_host/newsgroups or
 *  snewsreply://secure_nntp_host/newsgroups URL). The group
 *  or comma-separated list of newsgroups is passed without
 *  a lead slash, and followup is TRUE for newsreply or
 *  snewsreply URLs.  - FM
 */
char *LYNewsPost(char *newsgroups,
		 BOOLEAN followup)
{
    char user_input[MAX_LINE];
    char CJKinput[MAX_LINE];
    char *cp = NULL;
    const char *kp = NULL;
    int c = 0;			/* user input */
    int len;
    FILE *fd = NULL;
    char my_tempfile[LY_MAXPATH];
    FILE *fc = NULL;
    char CJKfile[LY_MAXPATH];
    char *postfile = NULL;
    char *NewsGroups = NULL;
    char *References = NULL;
    char *org = NULL;
    FILE *fp = NULL;
    BOOLEAN nonempty = FALSE;
    BOOLEAN nonspaces = FALSE;

    /*
     * Make sure a non-zero length newspost, newsreply, snewspost or snewsreply
     * path was sent to us.  - FM
     */
    if (isEmpty(newsgroups))
	return (postfile);

    /*
     * Return immediately if we do get called, maybe by some quirk of HTNews.c,
     * when we shouldn't.  - kw
     */
    if (no_newspost)
	return (postfile);

    /*
     * Open a temporary file for the headers and message body.  - FM
     */
#ifdef __DJGPP__
    if ((fd = LYOpenTemp(my_tempfile, HTML_SUFFIX, BIN_W)) == NULL)
#else
    if ((fd = LYOpenTemp(my_tempfile, HTML_SUFFIX, "w")) == NULL)
#endif /* __DJGPP__ */
    {
	HTAlert(CANNOT_OPEN_TEMP);
	return (postfile);
    }

    /*
     * If we're using a Japanese display character set, open a temporary file
     * for a conversion to JIS.  - FM
     */
    CJKfile[0] = '\0';
    if (current_char_set == UCGetLYhndl_byMIME("euc-jp") ||
	current_char_set == UCGetLYhndl_byMIME("shift_jis")) {
	if ((fc = LYOpenTemp(CJKfile, HTML_SUFFIX, "w")) == NULL) {
	    HTAlert(CANNOT_OPEN_TEMP);
	    LYRemoveTemp(my_tempfile);
	    return (postfile);
	}
    }

    /*
     * The newsgroups could be a comma-seperated list.  It need not have
     * spaces, but deal with any that may also have been hex escaped.  - FM
     */
    StrAllocCopy(NewsGroups, newsgroups);
    if ((cp = strstr(NewsGroups, ";ref="))) {
	*cp = '\0';
	cp += 5;
	if (*cp == '<') {
	    StrAllocCopy(References, cp);
	} else {
	    StrAllocCopy(References, "<");
	    StrAllocCat(References, cp);
	    StrAllocCat(References, ">");
	}
	HTUnEscape(References);
	if (!((cp = strchr(References, '@')) && cp > References + 1 &&
	      isalnum(UCH(cp[1])))) {
	    FREE(References);
	}
    }
    HTUnEscape(NewsGroups);
    if (!*NewsGroups) {
	LYCloseTempFP(fd);	/* Close the temp file. */
	goto cleanup;
    }

    /*
     * Allow ^C to cancel the posting, i.e., don't let SIGINTs exit Lynx.
     */
    signal(SIGINT, terminate_message);
    term_message = FALSE;

    /*
     * Show the list of newsgroups.  - FM
     */
    LYclear();
    LYmove(2, 0);
    scrollok(LYwin, TRUE);	/* Enable scrolling. */
    LYaddstr(gettext("You will be posting to:"));
    LYaddstr("\n\t");
    LYaddstr(NewsGroups);
    LYaddch('\n');

    /*
     * Get the mail address for the From header, offering personal_mail_address
     * as default.
     */
    LYaddstr(gettext("\n\n Please provide your mail address for the From: header\n"));
    sprintf(user_input, "From: %.*s", (int) sizeof(user_input) - 8,
	    NonNull(personal_mail_address));
    if (LYgetstr(user_input, VISIBLE,
		 sizeof(user_input), NORECALL) < 0 ||
	term_message) {
	HTInfoMsg(NEWS_POST_CANCELLED);
	LYCloseTempFP(fd);	/* Close the temp file. */
	scrollok(LYwin, FALSE);	/* Stop scrolling.      */
	goto cleanup;
    }
    fprintf(fd, "%s\n", user_input);

    /*
     * Get the Subject header, offering the current document's title as the
     * default if this is a followup rather than a new post.  - FM
     */
    LYaddstr(gettext("\n\n Please provide or edit the Subject: header\n"));
    strcpy(user_input, "Subject: ");
    if ((followup == TRUE && nhist > 0) &&
	(kp = HText_getTitle()) != NULL) {
	/*
	 * Add the default subject.
	 */
	kp = LYSkipCBlanks(kp);
#ifdef CJK_EX			/* 1998/05/15 (Fri) 09:10:38 */
	if (HTCJK == JAPANESE) {
	    CJKinput[0] = '\0';
	    switch (kanji_code) {
	    case EUC:
		TO_EUC((const unsigned char *) kp, (unsigned char *) CJKinput);
		kp = CJKinput;
		break;
	    case SJIS:
		TO_SJIS((const unsigned char *) kp, (unsigned char *) CJKinput);
		kp = CJKinput;
		break;
	    default:
		break;
	    }
	}
#endif
	if (strncasecomp(kp, "Re:", 3)) {
	    strcat(user_input, "Re: ");
	}
	len = (int) strlen(user_input);
	LYstrncpy(user_input + len, kp, (int) sizeof(user_input) - len - 1);
    }
    cp = NULL;
    if (LYgetstr(user_input, VISIBLE,
		 sizeof(user_input), NORECALL) < 0 ||
	term_message) {
	HTInfoMsg(NEWS_POST_CANCELLED);
	LYCloseTempFP(fd);	/* Close the temp file. */
	scrollok(LYwin, FALSE);	/* Stop scrolling.      */
	goto cleanup;
    }
    fprintf(fd, "%s\n", user_input);

    /*
     * Add Organization:  header.
     */
    StrAllocCopy(cp, "Organization: ");
    if ((org = LYGetEnv("ORGANIZATION")) != NULL) {
	StrAllocCat(cp, org);
    } else if ((org = LYGetEnv("NEWS_ORGANIZATION")) != NULL) {
	StrAllocCat(cp, org);
    }
#ifdef UNIX
    else if ((fp = fopen("/etc/organization", TXT_R)) != NULL) {
	char *buffer = 0;

	if (LYSafeGets(&buffer, fp) != NULL) {
	    if (user_input[0] != '\0') {
		LYTrimNewline(buffer);
		StrAllocCat(cp, buffer);
	    }
	}
	FREE(buffer);
	LYCloseInput(fp);
    }
#else
#ifdef _WINDOWS			/* 1998/05/14 (Thu) 17:47:01 */
    else {
	char *p, fname[LY_MAXPATH];

	strcpy(fname, LynxSigFile);
	p = strrchr(fname, '/');
	if (p != 0 && (p - fname) < sizeof(fname) - 15) {
	    strcpy(p + 1, "LYNX_ETC.TXT");
	    if ((fp = fopen(fname, TXT_R)) != NULL) {
		if (fgets(user_input, sizeof(user_input), fp) != NULL) {
		    if ((org = strchr(user_input, '\n')) != NULL) {
			*org = '\0';
		    }
		    if (user_input[0] != '\0') {
			StrAllocCat(cp, user_input);
		    }
		}
		LYCloseInput(fp);
	    }
	}
    }
#endif /* _WINDOWS */
#endif /* !UNIX */
    LYstrncpy(user_input, cp, (sizeof(user_input) - 16));
    FREE(cp);
    LYaddstr(gettext("\n\n Please provide or edit the Organization: header\n"));
    if (LYgetstr(user_input, VISIBLE,
		 sizeof(user_input), NORECALL) < 0 ||
	term_message) {
	HTInfoMsg(NEWS_POST_CANCELLED);
	LYCloseTempFP(fd);	/* Close the temp file. */
	scrollok(LYwin, FALSE);	/* Stop scrolling.      */
	goto cleanup;
    }
    fprintf(fd, "%s\n", user_input);

    if (References) {
	fprintf(fd, "References: %s\n", References);
    }
    /*
     * Add Newsgroups Summary and Keywords headers.
     */
    fprintf(fd, "Newsgroups: %s\nSummary: \nKeywords: \n\n", NewsGroups);

    /*
     * Have the user create the message body.
     */
    if (!no_editor && non_empty(editor)) {

	if (followup && nhist > 0) {
	    /*
	     * Ask if the user wants to include the original message.
	     */
	    if (term_message) {
		_statusline(INC_ORIG_MSG_PROMPT);
	    } else if (HTConfirm(INC_ORIG_MSG_PROMPT) == YES) {
		/*
		 * The 'TRUE' will add the reply ">" in front of every line. 
		 * We're assuming that if the display character set is Japanese
		 * and the document did not have a CJK charset, any non-EUC or
		 * non-SJIS 8-bit characters in it where converted to 7-bit
		 * equivalents.  - FM
		 */
		print_wwwfile_to_fd(fd, FALSE, TRUE);
	    }
	}
	LYCloseTempFP(fd);	/* Close the temp file. */
	scrollok(LYwin, FALSE);	/* Stop scrolling.      */
	if (term_message || LYCharIsINTERRUPT(c))
	    goto cleanup;

	/*
	 * Spawn the user's editor on the news file.
	 */
	edit_temporary_file(my_tempfile, "", SPAWNING_EDITOR_FOR_NEWS);

	nonempty = message_has_content(my_tempfile, &nonspaces);

    } else {
	/*
	 * Use the built in line editior.
	 */
	LYaddstr(gettext("\n\n Please enter your message below."));
	LYaddstr(gettext("\n When you are done, press enter and put a single period (.)"));
	LYaddstr(gettext("\n on a line and press enter again."));
	LYaddstr("\n\n");
	LYrefresh();
	*user_input = '\0';
	if (LYgetstr(user_input, VISIBLE,
		     sizeof(user_input), NORECALL) < 0 ||
	    term_message) {
	    HTInfoMsg(NEWS_POST_CANCELLED);
	    LYCloseTempFP(fd);	/* Close the temp file. */
	    scrollok(LYwin, FALSE);	/* Stop scrolling.      */
	    goto cleanup;
	}
	while (!STREQ(user_input, ".") && !term_message) {
	    LYaddch('\n');
	    fprintf(fd, "%s\n", user_input);
	    if (!nonempty && strlen(user_input))
		nonempty = TRUE;
	    *user_input = '\0';
	    if (LYgetstr(user_input, VISIBLE,
			 sizeof(user_input), NORECALL) < 0) {
		HTInfoMsg(NEWS_POST_CANCELLED);
		LYCloseTempFP(fd);	/* Close the temp file. */
		scrollok(LYwin, FALSE);		/* Stop scrolling.      */
		goto cleanup;
	    }
	}
	fprintf(fd, "\n");
	LYCloseTempFP(fd);	/* Close the temp file. */
	scrollok(LYwin, FALSE);	/* Stop scrolling.      */
    }

    if (nonempty) {
	/*
	 * Confirm whether to post, and if so, whether to append the sig file. 
	 * - FM
	 */
	LYStatusLine = (LYlines - 1);
	c = HTConfirm(POST_MSG_PROMPT);
	LYStatusLine = -1;
	if (c != YES) {
	    LYclear();		/* clear the screen */
	    goto cleanup;
	}
    } else {
	HTAlert(gettext("Message has no original text!"));
	if (!nonspaces
	    || HTConfirmDefault(POST_MSG_PROMPT, NO) != YES)
	    goto cleanup;
    }
    if ((LynxSigFile != NULL) && (fp = fopen(LynxSigFile, TXT_R)) != NULL) {
	char *msg = NULL;

	HTSprintf0(&msg, APPEND_SIG_FILE, LynxSigFile);

	LYStatusLine = (LYlines - 1);
	if (term_message) {
	    _user_message(APPEND_SIG_FILE, LynxSigFile);
	} else if (HTConfirm(msg) == YES) {
	    if ((fd = LYAppendToTxtFile(my_tempfile)) != NULL) {
		char *buffer = NULL;

		fputs("-- \n", fd);
		while (LYSafeGets(&buffer, fp) != NULL) {
		    fputs(buffer, fd);
		}
		LYCloseOutput(fd);
	    }
	}
	LYCloseInput(fp);
	FREE(msg);
	LYStatusLine = -1;
    }
    LYclear();			/* clear the screen */

    /*
     * If we are using a Japanese display character set, convert the contents
     * of the temp file to JIS (nothing should change if it does not, in fact,
     * contain EUC or SJIS di-bytes).  Otherwise, use the temp file as is.  -
     * FM
     */
    if (CJKfile[0] != '\0') {
	if ((fd = fopen(my_tempfile, TXT_R)) != NULL) {
	    char *buffer = NULL;

	    while (LYSafeGets(&buffer, fd) != NULL) {
		TO_JIS((unsigned char *) buffer,
		       (unsigned char *) CJKinput);
		fputs(CJKinput, fc);
	    }
	    LYCloseTempFP(fc);
	    StrAllocCopy(postfile, CJKfile);
	    LYCloseInput(fd);
	    LYRemoveTemp(my_tempfile);
	    strcpy(my_tempfile, CJKfile);
	    CJKfile[0] = '\0';
	} else {
	    StrAllocCopy(postfile, my_tempfile);
	}
    } else {
	StrAllocCopy(postfile, my_tempfile);
    }
    if (!followup) {
	/*
	 * If it's not a followup, the current document most likely is the
	 * group listing, so force a to have the article show up in the list
	 * after the posting.  Note, that if it's a followup via a link in a
	 * news article, the user must do a reload manually on returning to the
	 * group listing.  - FM
	 */
	LYforce_no_cache = TRUE;
    }
    LYStatusLine = (LYlines - 1);
    HTUserMsg(POSTING_TO_NEWS);
    LYStatusLine = -1;

    /*
     * Come here to cleanup and exit.
     */
  cleanup:
#ifndef VMS
    signal(SIGINT, cleanup_sig);
#endif /* !VMS */
    term_message = FALSE;
    if (!postfile)
	LYRemoveTemp(my_tempfile);
    LYRemoveTemp(CJKfile);
    FREE(NewsGroups);
    FREE(References);

    return (postfile);
}
Esempio n. 3
0
static int LYLoadCGI(const char *arg,
		     HTParentAnchor *anAnchor,
		     HTFormat format_out,
		     HTStream *sink)
{
    int status = 0;

#ifdef LYNXCGI_LINKS
#ifndef VMS
    char *cp;
    struct stat stat_buf;
    char *pgm = NULL;		/* executable */
    char *pgm_args = NULL;	/* and its argument(s) */
    int statrv;
    char *orig_pgm = NULL;	/* Path up to ? as given, URL-escaped */
    char *document_root = NULL;	/* Corrected value of DOCUMENT_ROOT  */
    char *path_info = NULL;	/* PATH_INFO extracted from pgm      */
    char *pgm_buff = NULL;	/* PATH_INFO extraction buffer       */
    char *path_translated;	/* From document_root/path_info      */

    if (isEmpty(arg) || strlen(arg) <= 8) {
	HTAlert(BAD_REQUEST);
	status = -2;
	return (status);

    } else {
	if (StrNCmp(arg, "lynxcgi://localhost", 19) == 0) {
	    StrAllocCopy(pgm, arg + 19);
	} else {
	    StrAllocCopy(pgm, arg + 8);
	}
	if ((cp = StrChr(pgm, '?')) != NULL) {	/* Need to terminate executable */
	    *cp++ = '\0';
	    pgm_args = cp;
	}
    }

    StrAllocCopy(orig_pgm, pgm);
    if (trimPoundSelector(pgm) != NULL) {
	/*
	 * Strip a #fragment from path.  In this case any pgm_args found above
	 * will also be bogus, since the '?' came after the '#' and is part of
	 * the fragment.  Note that we don't handle the case where a '#'
	 * appears after a '?' properly according to URL rules.  - kw
	 */
	pgm_args = NULL;
    }
    HTUnEscape(pgm);

    /* BEGIN WebSter Mods */
    /* If pgm is not stat-able, see if PATH_INFO data is at the end of pgm */
    if ((statrv = stat(pgm, &stat_buf)) < 0) {
	StrAllocCopy(pgm_buff, pgm);
	while (statrv < 0 || (statrv = stat(pgm_buff, &stat_buf)) < 0) {
	    if ((cp = strrchr(pgm_buff, '/')) != NULL) {
		*cp = '\0';
		statrv = 1;	/* force new stat()  - kw */
	    } else {
		PERROR("strrchr(pgm_buff, '/') returned NULL");
		break;
	    }
	}

	if (statrv < 0) {
	    /* Did not find PATH_INFO data */
	    PERROR("stat() of pgm_buff failed");
	} else {
	    /* Found PATH_INFO data.  Strip it off of pgm and into path_info. */
	    StrAllocCopy(path_info, pgm + strlen(pgm_buff));
	    /* The following is safe since pgm_buff was derived from pgm
	       by stripping stuff off its end and by HTUnEscaping, so we
	       know we have enough memory allocated for pgm.  Note that
	       pgm_args may still point into that memory, so we cannot
	       reallocate pgm here. - kw */
	    strcpy(pgm, pgm_buff);
	    CTRACE((tfp,
		    "LYNXCGI: stat() of %s succeeded, path_info=\"%s\".\n",
		    pgm_buff, path_info));
	}
	FREE(pgm_buff);
    }
    /* END WebSter Mods */

    if (statrv != 0) {
	/*
	 * Neither the path as given nor any components examined by backing up
	 * were stat()able.  - kw
	 */
	HTAlert(gettext("Unable to access cgi script"));
	PERROR("stat() failed");
	status = -4;

    } else
#ifdef _WINDOWS			/* 1998/01/14 (Wed) 09:16:04 */
#define isExecutable(mode) (mode & (S_IXUSR))
#else
#define isExecutable(mode) (mode & (S_IXUSR|S_IXGRP|S_IXOTH))
#endif
    if (!(S_ISREG(stat_buf.st_mode) && isExecutable(stat_buf.st_mode))) {
	/*
	 * Not a runnable file, See if we can load it using "file:" code.
	 */
	char *new_arg = NULL;

	/*
	 * But try "file:" only if the file we are looking at is the path as
	 * given (no path_info was extracted), otherwise it will be to
	 * confusing to know just what file is loaded.  - kw
	 */
	if (path_info) {
	    CTRACE((tfp,
		    "%s is not a file and %s not an executable, giving up.\n",
		    orig_pgm, pgm));
	    FREE(path_info);
	    FREE(pgm);
	    FREE(orig_pgm);
	    status = -4;
	    return (status);
	}

	LYLocalFileToURL(&new_arg, orig_pgm);

	CTRACE((tfp, "%s is not an executable file, passing the buck.\n", arg));
	status = HTLoadFile(new_arg, anAnchor, format_out, sink);
	FREE(new_arg);

    } else if (path_info &&
	       anAnchor != HTMainAnchor &&
	       !(reloading && anAnchor->document) &&
	       strcmp(arg, HTLoadedDocumentURL()) &&
	       HText_AreDifferent(anAnchor, arg) &&
	       HTUnEscape(orig_pgm) &&
	       !can_exec_cgi(orig_pgm, "")) {
	/*
	 * If we have extra path info and are not just reloading the current,
	 * check the full file path (after unescaping) now to catch forbidden
	 * segments.  - kw
	 */
	status = HT_NOT_LOADED;

    } else if (no_lynxcgi) {
	HTUserMsg(CGI_DISABLED);
	status = HT_NOT_LOADED;

    } else if (no_bookmark_exec &&
	       anAnchor != HTMainAnchor &&
	       !(reloading && anAnchor->document) &&
	       strcmp(arg, HTLoadedDocumentURL()) &&
	       HText_AreDifferent(anAnchor, arg) &&
	       HTLoadedDocumentBookmark()) {
	/*
	 * If we are reloading a lynxcgi document that had already been loaded,
	 * the various checks above should allow it even if no_bookmark_exec is
	 * TRUE an we are not now coming from a bookmark page.  - kw
	 */
	HTUserMsg(BOOKMARK_EXEC_DISABLED);
	status = HT_NOT_LOADED;

    } else if (anAnchor != HTMainAnchor &&
	       !(reloading && anAnchor->document) &&
	       strcmp(arg, HTLoadedDocumentURL()) &&
	       HText_AreDifferent(anAnchor, arg) &&
	       !can_exec_cgi(pgm, pgm_args)) {
	/*
	 * If we are reloading a lynxcgi document that had already been loaded,
	 * the various checks above should allow it even if exec_ok() would
	 * reject it because we are not now coming from a document with a URL
	 * allowed by TRUSTED_LYNXCGI rules.  - kw
	 */
	status = HT_NOT_LOADED;

    } else {
	HTFormat format_in;
	HTStream *target = NULL;	/* Unconverted data */
	int fd1[2], fd2[2];
	char buf[MAX_LINE];
	int pid;

#ifdef HAVE_TYPE_UNIONWAIT
	union wait wstatus;

#else
	int wstatus;
#endif

	fd1[0] = -1;
	fd1[1] = -1;
	fd2[0] = -1;
	fd2[1] = -1;

	if (anAnchor->isHEAD || keep_mime_headers) {

	    /* Show output as plain text */
	    format_in = WWW_PLAINTEXT;
	} else {

	    /* Decode full HTTP response */
	    format_in = HTAtom_for("www/mime");
	}

	target = HTStreamStack(format_in,
			       format_out,
			       sink, anAnchor);

	if (!target || target == NULL) {
	    char *tmp = 0;

	    HTSprintf0(&tmp, CANNOT_CONVERT_I_TO_O,
		       HTAtom_name(format_in),
		       HTAtom_name(format_out));
	    HTAlert(tmp);
	    FREE(tmp);
	    status = HT_NOT_LOADED;

	} else if (anAnchor->post_data && pipe(fd1) < 0) {
	    HTAlert(CONNECT_SET_FAILED);
	    PERROR("pipe() failed");
	    status = -3;

	} else if (pipe(fd2) < 0) {
	    HTAlert(CONNECT_SET_FAILED);
	    PERROR("pipe() failed");
	    close(fd1[0]);
	    close(fd1[1]);
	    status = -3;

	} else {
	    static BOOL first_time = TRUE;	/* One time setup flag */

	    if (first_time) {	/* Set up static environment variables */
		first_time = FALSE;	/* Only once */

		add_environment_value("REMOTE_HOST=localhost");
		add_environment_value("REMOTE_ADDR=127.0.0.1");

		HTSprintf0(&user_agent, "HTTP_USER_AGENT=%s/%s libwww/%s",
			   LYNX_NAME, LYNX_VERSION, HTLibraryVersion);
		add_environment_value(user_agent);

		HTSprintf0(&server_software, "SERVER_SOFTWARE=%s/%s",
			   LYNX_NAME, LYNX_VERSION);
		add_environment_value(server_software);
	    }
	    fflush(stdout);
	    fflush(stderr);
	    CTRACE_FLUSH(tfp);

	    if ((pid = fork()) > 0) {	/* The good, */
		ssize_t chars;
		off_t total_chars;

		close(fd2[1]);

		if (anAnchor->post_data) {
		    ssize_t written;
		    int remaining, total_written = 0;

		    close(fd1[0]);

		    /* We have form data to push across the pipe */
		    if (TRACE) {
			CTRACE((tfp,
				"LYNXCGI: Doing post, content-type '%s'\n",
				anAnchor->post_content_type));
			CTRACE((tfp, "LYNXCGI: Writing:\n"));
			trace_bstring(anAnchor->post_data);
			CTRACE((tfp, "----------------------------------\n"));
		    }
		    remaining = BStrLen(anAnchor->post_data);
		    while ((written = write(fd1[1],
					    BStrData(anAnchor->post_data) + total_written,
					    (size_t) remaining)) != 0) {
			if (written < 0) {
#ifdef EINTR
			    if (errno == EINTR)
				continue;
#endif /* EINTR */
#ifdef ERESTARTSYS
			    if (errno == ERESTARTSYS)
				continue;
#endif /* ERESTARTSYS */
			    PERROR("write() of POST data failed");
			    break;
			}
			CTRACE((tfp, "LYNXCGI: Wrote %d bytes of POST data.\n",
				(int) written));
			total_written += (int) written;
			remaining -= (int) written;
			if (remaining == 0)
			    break;
		    }
		    if (remaining != 0) {
			CTRACE((tfp, "LYNXCGI: %d bytes remain unwritten!\n",
				remaining));
		    }
		    close(fd1[1]);
		}

		HTReadProgress(total_chars = 0, (off_t) 0);
		while ((chars = read(fd2[0], buf, sizeof(buf))) != 0) {
		    if (chars < 0) {
#ifdef EINTR
			if (errno == EINTR)
			    continue;
#endif /* EINTR */
#ifdef ERESTARTSYS
			if (errno == ERESTARTSYS)
			    continue;
#endif /* ERESTARTSYS */
			PERROR("read() of CGI output failed");
			break;
		    }
		    total_chars += (int) chars;
		    HTReadProgress(total_chars, (off_t) 0);
		    CTRACE((tfp, "LYNXCGI: Rx: %.*s\n", (int) chars, buf));
		    (*target->isa->put_block) (target, buf, (int) chars);
		}

		if (chars < 0 && total_chars == 0) {
		    status = HT_NOT_LOADED;
		    (*target->isa->_abort) (target, NULL);
		    target = NULL;
		} else if (chars != 0) {
		    status = HT_PARTIAL_CONTENT;
		} else {
		    status = HT_LOADED;
		}

#ifndef HAVE_WAITPID
		while (wait(&wstatus) != pid) ;		/* do nothing */
#else
		while (-1 == waitpid(pid, &wstatus, 0)) {	/* wait for child */
#ifdef EINTR
		    if (errno == EINTR)
			continue;
#endif /* EINTR */
#ifdef ERESTARTSYS
		    if (errno == ERESTARTSYS)
			continue;
#endif /* ERESTARTSYS */
		    break;
		}
#endif /* !HAVE_WAITPID */
		close(fd2[0]);

	    } else if (pid == 0) {	/* The Bad, */
		char **argv = NULL;
		int argv_cnt = 3;	/* name, one arg and terminator */
		char **cur_argv = NULL;
		int exec_errno;

		/* Set up output pipe */
		close(fd2[0]);
		dup2(fd2[1], fileno(stdout));	/* Should check success code */
		dup2(fd2[1], fileno(stderr));
		close(fd2[1]);

		if (non_empty(language)) {
		    HTSprintf0(&accept_language, "HTTP_ACCEPT_LANGUAGE=%s", language);
		    add_environment_value(accept_language);
		}

		if (non_empty(pref_charset)) {
		    cp = NULL;
		    StrAllocCopy(cp, "HTTP_ACCEPT_CHARSET=");
		    StrAllocCat(cp, pref_charset);
		    add_environment_value(cp);
		}

		if (anAnchor->post_data &&
		    anAnchor->post_content_type) {
		    cp = NULL;
		    StrAllocCopy(cp, "CONTENT_TYPE=");
		    StrAllocCat(cp, anAnchor->post_content_type);
		    add_environment_value(cp);
		}

		if (anAnchor->post_data) {	/* post script, read stdin */
		    close(fd1[1]);
		    dup2(fd1[0], fileno(stdin));
		    close(fd1[0]);

		    /* Build environment variables */

		    add_environment_value("REQUEST_METHOD=POST");

		    HTSprintf0(&post_len, "CONTENT_LENGTH=%d",
			       BStrLen(anAnchor->post_data));
		    add_environment_value(post_len);
		} else {
		    close(fileno(stdin));

		    if (anAnchor->isHEAD) {
			add_environment_value("REQUEST_METHOD=HEAD");
		    }
		}

		/*
		 * Set up argument line, mainly for <index> scripts
		 */
		if (pgm_args != NULL) {
		    for (cp = pgm_args; *cp != '\0'; cp++) {
			if (*cp == '+') {
			    argv_cnt++;
			}
		    }
		}

		argv = (char **) malloc((unsigned) argv_cnt * sizeof(char *));

		if (argv == NULL) {
		    outofmem(__FILE__, "LYCgi");
		}
		assert(argv != NULL);

		cur_argv = argv + 1;	/* For argv[0] */
		if (pgm_args != NULL) {
		    char *cr;

		    /* Data for a get/search form */
		    if (is_www_index) {
			add_environment_value("REQUEST_METHOD=SEARCH");
		    } else if (!anAnchor->isHEAD && !anAnchor->post_data) {
			add_environment_value("REQUEST_METHOD=GET");
		    }

		    cp = NULL;
		    StrAllocCopy(cp, "QUERY_STRING=");
		    StrAllocCat(cp, pgm_args);
		    add_environment_value(cp);

		    /*
		     * Split up arguments into argv array
		     */
		    cp = pgm_args;
		    cr = cp;
		    while (1) {
			if (*cp == '\0') {
			    *(cur_argv++) = HTUnEscape(cr);
			    break;

			} else if (*cp == '+') {
			    *cp++ = '\0';
			    *(cur_argv++) = HTUnEscape(cr);
			    cr = cp;
			}
			cp++;
		    }
		} else if (!anAnchor->isHEAD && !anAnchor->post_data) {
		    add_environment_value("REQUEST_METHOD=GET");
		}
		*cur_argv = NULL;	/* Terminate argv */
		argv[0] = pgm;

		/* Begin WebSter Mods  -jkt */
		if (LYCgiDocumentRoot != NULL) {
		    /* Add DOCUMENT_ROOT to env */
		    cp = NULL;
		    StrAllocCopy(cp, "DOCUMENT_ROOT=");
		    StrAllocCat(cp, LYCgiDocumentRoot);
		    add_environment_value(cp);
		}
		if (path_info != NULL) {
		    /* Add PATH_INFO to env */
		    cp = NULL;
		    StrAllocCopy(cp, "PATH_INFO=");
		    StrAllocCat(cp, path_info);
		    add_environment_value(cp);
		}
		if (LYCgiDocumentRoot != NULL && path_info != NULL) {
		    /* Construct and add PATH_TRANSLATED to env */
		    StrAllocCopy(document_root, LYCgiDocumentRoot);
		    LYTrimHtmlSep(document_root);
		    path_translated = document_root;
		    StrAllocCat(path_translated, path_info);
		    cp = NULL;
		    StrAllocCopy(cp, "PATH_TRANSLATED=");
		    StrAllocCat(cp, path_translated);
		    add_environment_value(cp);
		    FREE(path_translated);
		}
		/* End WebSter Mods  -jkt */

		execve(argv[0], argv, env);
		exec_errno = errno;
		PERROR("execve failed");
		printf("Content-Type: text/plain\r\n\r\n");
		if (!anAnchor->isHEAD) {
		    printf("exec of %s failed", pgm);
		    printf(": %s.\r\n", LYStrerror(exec_errno));
		}
		fflush(stdout);
		fflush(stderr);
		_exit(1);

	    } else {		/* and the Ugly */
		HTAlert(CONNECT_FAILED);
		PERROR("fork() failed");
		close(fd1[0]);
		close(fd1[1]);
		close(fd2[0]);
		close(fd2[1]);
		status = -1;
	    }

	}
	if (target != NULL) {
	    (*target->isa->_free) (target);
	}
    }
    FREE(path_info);
    FREE(pgm);
    FREE(orig_pgm);
#else /* VMS */
    HTStream *target;
    char *buf = 0;

    target = HTStreamStack(WWW_HTML,
			   format_out,
			   sink, anAnchor);

    HTSprintf0(&buf, "<html>\n<head>\n<title>%s</title>\n</head>\n<body>\n",
	       gettext("Good Advice"));
    PUTS(buf);

    HTSprintf0(&buf, "<h1>%s</h1>\n", gettext("Good Advice"));
    PUTS(buf);

    HTSprintf0(&buf, "%s <a\n",
	       gettext("An excellent http server for VMS is available via"));
    PUTS(buf);

    HTSprintf0(&buf,
	       "href=\"http://www.ecr6.ohio-state.edu/www/doc/serverinfo.html\"\n");
    PUTS(buf);

    HTSprintf0(&buf, ">%s</a>.\n", gettext("this link"));
    PUTS(buf);

    HTSprintf0(&buf, "<p>%s\n",
	       gettext("It provides state of the art CGI script support.\n"));
    PUTS(buf);

    HTSprintf0(&buf, "</body>\n</html>\n");
    PUTS(buf);

    (*target->isa->_free) (target);
    FREE(buf);
    status = HT_LOADED;
#endif /* VMS */
#else /* LYNXCGI_LINKS */
    HTUserMsg(CGI_NOT_COMPILED);
    status = HT_NOT_LOADED;
#endif /* LYNXCGI_LINKS */

    (void) arg;
    (void) anAnchor;
    (void) format_out;
    (void) sink;

    return (status);
}
static void send_file_to_file(DocInfo *newdoc,
			      char *content_base,
			      char *sug_filename)
{
    BOOLEAN FirstRecall = TRUE;
    BOOLEAN use_cte;
    const char *disp_charset;
    FILE *outfile_fp;
    bstring *buffer = NULL;
    bstring *filename = NULL;
    int FnameNum = -1;
    int FnameTotal;
    int c = 0;

    _statusline(FILENAME_PROMPT);

  retry:
    SetupFilename(&filename, sug_filename);
    if (lynx_save_space) {
	BStrCopy0(buffer, lynx_save_space);
	BStrCat(buffer, filename);
	BStrCopy(filename, buffer);
    } else {
	BStrCopy0(buffer, "");
    }

  check_recall:
    switch (RecallFilename(&filename, &FirstRecall, &FnameNum,
			   &FnameTotal, PRINT_FLAG)) {
    case FN_INIT:
	goto retry;
    case FN_READ:
	goto check_recall;
    case FN_QUIT:
	goto done;
    default:
	break;
    }

    if (!LYValidateFilename(&buffer, &filename)) {
	CancelPrint(SAVE_REQUEST_CANCELLED);
    }

    /*
     * See if it already exists.
     */
    switch (c = LYValidateOutput(buffer->str)) {
    case 'Y':
	break;
    case 'N':
	_statusline(NEW_FILENAME_PROMPT);
	FirstRecall = TRUE;
	FnameNum = FnameTotal;
	goto retry;
    default:
	goto done;
    }

    /*
     * See if we can write to it.
     */
    CTRACE((tfp, "LYPrint: filename is %s, action is `%c'\n", buffer->str, c));

#ifdef HAVE_POPEN
    if (buffer->str[0] == '|') {
	if (no_shell) {
	    HTUserMsg(SPAWNING_DISABLED);
	    FirstRecall = TRUE;
	    FnameNum = FnameTotal;
	    goto retry;
	} else if ((outfile_fp = popen(buffer->str + 1, "w")) == NULL) {
	    CTRACE((tfp, "LYPrint: errno is %d\n", errno));
	    HTAlert(CANNOT_WRITE_TO_FILE);
	    _statusline(NEW_FILENAME_PROMPT);
	    FirstRecall = TRUE;
	    FnameNum = FnameTotal;
	    goto retry;
	}
    } else
#endif
	if ((outfile_fp = (TOUPPER(c) == 'A'
			   ? LYAppendToTxtFile(buffer->str)
			   : LYNewTxtFile(buffer->str))) == NULL) {
	CTRACE((tfp, "LYPrint: errno is %d\n", errno));
	HTAlert(CANNOT_WRITE_TO_FILE);
	_statusline(NEW_FILENAME_PROMPT);
	FirstRecall = TRUE;
	FnameNum = FnameTotal;
	goto retry;
    }

    if (LYPrependBaseToSource && HTisDocumentSource()) {
	/*
	 * Added the document's base as a BASE tag to the top of the file.  May
	 * create technically invalid HTML, but will help get any partial or
	 * relative URLs resolved properly if no BASE tag is present to replace
	 * it.  - FM
	 *
	 * Add timestamp (last reload).
	 */

	fprintf(outfile_fp,
		"<!-- X-URL: %s -->\n", newdoc->address);
	if (HText_getDate() != NULL) {
	    fprintf(outfile_fp,
		    "<!-- Date: %s -->\n", HText_getDate());
	    if (HText_getLastModified() != NULL
		&& strcmp(HText_getLastModified(), HText_getDate())
		&& strcmp(HText_getLastModified(),
			  "Thu, 01 Jan 1970 00:00:01 GMT")) {
		fprintf(outfile_fp,
			"<!-- Last-Modified: %s -->\n", HText_getLastModified());
	    }
	}

	fprintf(outfile_fp,
		"<BASE HREF=\"%s\">\n", content_base);
    }

    if (LYPrependCharsetToSource && HTisDocumentSource()) {
	/*
	 * Added the document's charset as a META CHARSET tag to the top of the
	 * file.  May create technically invalid HTML, but will help to resolve
	 * properly the document converted via chartrans:  printed document
	 * correspond to a display charset and we *should* override both
	 * assume_local_charset and original document's META CHARSET (if any).
	 *
	 * Currently, if several META CHARSETs are found Lynx uses the first
	 * only, and it is opposite to BASE where the original BASE in the
	 * <HEAD> overrides ones from the top.
	 *
	 * As in print-to-email we write charset only if the document has 8-bit
	 * characters, and we have no CJK or an unofficial "x-" charset.
	 */
	use_cte = HTLoadedDocumentEightbit();
	disp_charset = LYCharSet_UC[current_char_set].MIMEname;
	if (!use_cte || LYHaveCJKCharacterSet ||
	    strncasecomp(disp_charset, "x-", 2) == 0) {
	} else {
	    fprintf(outfile_fp,
		    "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=%s\">\n\n",
		    disp_charset);
	}
    }

    print_wwwfile_to_fd(outfile_fp, FALSE, FALSE);	/* FILE */
    if (keypad_mode)
	printlist(outfile_fp, FALSE);

#ifdef HAVE_POPEN
    if (LYIsPipeCommand(buffer->str))
	pclose(outfile_fp);
    else
#endif
	LYCloseOutput(outfile_fp);

#ifdef VMS
    if (0 == strncasecomp(buffer->str, "sys$disk:", 9)) {
	if (0 == StrNCmp((buffer->str + 9), "[]", 2)) {
	    HTAddSugFilename(buffer->str + 11);
	} else {
	    HTAddSugFilename(buffer->str + 9);
	}
    } else {
	HTAddSugFilename(buffer->str);
    }
#else
    HTAddSugFilename(buffer->str);
#endif /* VMS */

  done:
    BStrFree(buffer);
    BStrFree(filename);
    return;
}
Esempio n. 5
0
int showlist(DocInfo *newdoc, BOOLEAN titles)
{
    int cnt;
    int refs, hidden_links;
    static char tempfile[LY_MAXPATH];
    static BOOLEAN last_titles = TRUE;
    FILE *fp0;
    char *Address = NULL, *Title = NULL, *cp = NULL;
    char *LinkTitle = NULL;	/* Rel stored as property of link, not of dest */
    BOOLEAN intern_w_post = FALSE;
    const char *desc = "unknown field or link";
    void *helper;

    refs = HText_sourceAnchors(HTMainText);
    hidden_links = HText_HiddenLinkCount(HTMainText);
    if (refs <= 0 && hidden_links > 0 &&
	LYHiddenLinks != HIDDENLINKS_SEPARATE) {
	HTUserMsg(NO_VISIBLE_REFS_FROM_DOC);
	return (-1);
    }
    if (refs <= 0 && hidden_links <= 0) {
	HTUserMsg(NO_REFS_FROM_DOC);
	return (-1);
    }

    if ((fp0 = InternalPageFP(tempfile, titles == last_titles)) == 0)
	return (-1);

    LYLocalFileToURL(&(newdoc->address), tempfile);

    LYRegisterUIPage(newdoc->address,
		     titles ? UIP_LIST_PAGE : UIP_ADDRLIST_PAGE);
    last_titles = titles;
    LYforce_HTML_mode = TRUE;	/* force this file to be HTML */
    LYforce_no_cache = TRUE;	/* force this file to be new */

#ifdef EXP_ADDRLIST_PAGE
    if (titles != TRUE)
	BeginInternalPage(fp0, ADDRLIST_PAGE_TITLE, LIST_PAGE_HELP);
    else
#endif
	BeginInternalPage(fp0, LIST_PAGE_TITLE, LIST_PAGE_HELP);

    StrAllocCopy(Address, HTLoadedDocumentURL());
    LYEntify(&Address, FALSE);
    fprintf(fp0, "%s%s<p>\n", gettext("References in "),
	    (non_empty(Address)
	     ? Address
	     : gettext("this document:")));
    FREE(Address);
    if (refs > 0) {
	fprintf(fp0, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
					"ol" : "ul"));
	if (hidden_links > 0)
	    fprintf(fp0, "<lh><em>%s</em>\n", gettext("Visible links:"));
    }
    if (hidden_links > 0) {
	if (LYHiddenLinks == HIDDENLINKS_IGNORE)
	    hidden_links = 0;
    }
    helper = NULL;		/* init */
    for (cnt = 1; cnt <= refs; cnt++) {
	HTChildAnchor *child = HText_childNextNumber(cnt, &helper);
	HTAnchor *dest_intl = NULL;
	HTAnchor *dest;
	HTParentAnchor *parent;
	char *address;
	const char *title;

	if (child == 0) {
	    /*
	     * child should not be 0 unless form field numbering is on and cnt
	     * is the number of a form input field.  HText_FormDescNumber()
	     * will set desc to a description of what type of input field this
	     * is.  We'll list it to ensure that the link numbers on the list
	     * page match the numbering in the original document, but won't
	     * create a forward link to the form.  - FM && LE
	     *
	     * Changed to create a fake hidden link, to get the numbering right
	     * in connection with always treating this file as
	     * HIDDENLINKS_MERGE in GridText.c - kw
	     */
	    if (fields_are_numbered()) {
		HText_FormDescNumber(cnt, &desc);
		fprintf(fp0,
			"<li><a id=%d href=\"#%d\">form field</a> = <em>%s</em>\n",
			cnt, cnt, desc);
	    }
	    continue;
	}
#ifndef DONT_TRACK_INTERNAL_LINKS
	dest_intl = HTAnchor_followTypedLink(child, HTInternalLink);
#endif
	dest = dest_intl ?
	    dest_intl : HTAnchor_followLink(child);
	parent = HTAnchor_parent(dest);
	if (!intern_w_post && dest_intl &&
	    HTMainAnchor &&
	    HTMainAnchor->post_data &&
	    parent->post_data &&
	    BINEQ(HTMainAnchor->post_data, parent->post_data)) {
	    /*
	     * Set flag to note that we had at least one internal link, if the
	     * document from which we are generating the list has associated
	     * POST data; after an extra check that the link destination really
	     * has the same POST data so that we can believe it is an internal
	     * link.
	     */
	    intern_w_post = TRUE;
	}
	address = HTAnchor_address(dest);
	title = titles ? HTAnchor_title(parent) : NULL;
	if (dest_intl) {
	    HTSprintf0(&LinkTitle, "(internal)");
	} else if (titles && child->type &&
		   dest == child->dest &&
		   !strncmp(HTAtom_name(child->type),
			    "RelTitle: ", 10)) {
	    HTSprintf0(&LinkTitle, "(%s)", HTAtom_name(child->type) + 10);
	} else {
	    FREE(LinkTitle);
	}
	StrAllocCopy(Address, address);
	FREE(address);
	LYEntify(&Address, TRUE);
	if (non_empty(title)) {
	    LYformTitle(&Title, title);
	    LYEntify(&Title, TRUE);
	    if (*Title) {
		cp = findPoundSelector(Address);
	    } else {
		FREE(Title);
	    }
	}

	fprintf(fp0, "<li><a href=\"%s\"%s>%s%s%s%s%s</a>\n", Address,
		dest_intl ? " TYPE=\"internal link\"" : "",
		NonNull(LinkTitle),
		((HTAnchor *) parent != dest) && Title ? "in " : "",
		(char *) (Title ? Title : Address),
		(Title && cp) ? " - " : "",
		(Title && cp) ? (cp + 1) : "");

	FREE(Address);
	FREE(Title);
    }
    FREE(LinkTitle);

    if (hidden_links > 0) {
	if (refs > 0)
	    fprintf(fp0, "\n</%s>\n\n<p>\n",
		    ((keypad_mode == NUMBERS_AS_ARROWS) ?
		     "ol" : "ul"));
	fprintf(fp0, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
					"ol continue" : "ul"));
	fprintf(fp0, "<lh><em>%s</em>\n", gettext("Hidden links:"));
    }

    for (cnt = 0; cnt < hidden_links; cnt++) {
	StrAllocCopy(Address, HText_HiddenLinkAt(HTMainText, cnt));
	LYEntify(&Address, FALSE);
	if (isEmpty(Address)) {
	    FREE(Address);
	    continue;
	}
	fprintf(fp0, "<li><a href=\"%s\">%s</a>\n", Address, Address);

	FREE(Address);
    }

    fprintf(fp0, "\n</%s>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
			       "ol" : "ul"));
    EndInternalPage(fp0);
    LYCloseTempFP(fp0);

    /*
     * Make necessary changes to newdoc before returning to caller.  If the
     * intern_w_post flag is set, we keep the POST data in newdoc that have
     * been passed in.  They should be the same as in the loaded document for
     * which we generated the list.  In that case the file we have written will
     * be associated with the same POST data when it is loaded after we are
     * done here, so that following one of the links we have marked as
     * "internal link" can lead back to the underlying document with the right
     * address+post_data combination.  - kw
     */
    if (intern_w_post) {
	newdoc->internal_link = TRUE;
    } else {
	LYFreePostData(newdoc);
	newdoc->internal_link = FALSE;
    }
    newdoc->isHEAD = FALSE;
    newdoc->safe = FALSE;
    return (0);
}