#include <HTUtils.h>
#include <HTFile.h>
#include <HTParse.h>
#include <HTAlert.h>
#include <HTTP.h>
#include <LYCurses.h>
#include <LYUtils.h>
#include <LYStructs.h>
#include <LYGlobalDefs.h>
#include <LYShowInfo.h>
#include <LYCharUtils.h>
#include <GridText.h>
#include <LYReadCFG.h>
#include <LYCharSets.h>
#include <LYStrings.h>

#include <LYLeaks.h>

#ifdef DIRED_SUPPORT
#include <HTAAProt.h>
#include <time.h>
#include <LYLocal.h>
#endif /* DIRED_SUPPORT */

#define ADVANCED_INFO 1		/* to get more info in advanced mode */

/*
 * LYNX_VERSION and LYNX_DATE are automatically generated by PRCS, the tool
 * which we use to archive versions of Lynx.  We use a convention for naming
 * the successive versions:
 *	{release}{status}{patch}
 * where
 *	{release} is the release that we are working on, e.g., 2.8.4
 *	{status} is one of "dev", "pre" or "rel", and
 *	{patch} is a number assigned by PRCS.
 */
PUBLIC BOOL LYVersionIsRelease NOARGS
{
    return (BOOL)(strstr(LYNX_VERSION, "rel") != 0);
}

PUBLIC char *LYVersionStatus NOARGS
{
    if (LYVersionIsRelease())
	return REL_VERSION;
    else if (strstr(LYNX_VERSION, "pre") != 0)
	return PRE_VERSION;
    return DEV_VERSION;
}

PUBLIC char *LYVersionDate NOARGS
{
    static char temp[LYNX_DATE_LEN+1];
    LYstrncpy(temp, &LYNX_DATE[LYNX_DATE_OFF], LYNX_DATE_LEN);
    return temp;
}

/*
 *  LYShowInfo prints a page of info about the current file and the link
 *  that the cursor is on.
 */

PUBLIC int LYShowInfo ARGS4(
	DocInfo *,	doc,
	int,		size_of_file,
	DocInfo *,	newdoc,
	char *, 	owner_address)
{
    static char tempfile[LY_MAXPATH] = "\0";
    int url_type;
    FILE *fp0;
    char *Address = NULL, *Title = NULL;
    char *name;
    CONST char *cp;
#ifdef ADVANCED_INFO
    BOOLEAN LYInfoAdvanced = (BOOL) (user_mode == ADVANCED_MODE);
#endif
#ifdef DIRED_SUPPORT
    struct stat dir_info;
#endif /* DIRED_SUPPORT */

    if (LYReuseTempfiles) {
	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
    } else {
	LYRemoveTemp(tempfile);
	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
    }
    if (fp0 == NULL) {
	HTAlert(CANNOT_OPEN_TEMP);
	return(-1);
    }

    /*
     *	Point the address pointer at this Url
     */
    LYLocalFileToURL(&newdoc->address, tempfile);

    if (nlinks > 0 && links[doc->link].lname != NULL &&
	(url_type = is_url(links[doc->link].lname)) != 0 &&
	(url_type == LYNXEXEC_URL_TYPE ||
	 url_type == LYNXPROG_URL_TYPE)) {
	char *last_slash = strrchr(links[doc->link].lname,'/');
	int next_to_last = strlen(links[doc->link].lname) - 1;

	if ((last_slash - links[doc->link].lname) == next_to_last) {
	    links[doc->link].lname[next_to_last] = '\0';
	}
    }

    fprintf(fp0, "<html>\n<head>\n");
    LYAddMETAcharsetToFD(fp0, -1);
    fprintf(fp0, "<title>%s</title>\n</head>\n<body>\n",
		 SHOWINFO_TITLE);

    fprintf(fp0, "<h1>%s %s (%s) (<a href=\"%s\">%s</a>)",
		 LYNX_NAME, LYNX_VERSION,
		 LYVersionDate(),
		 (LYVersionIsRelease() ? LYNX_WWW_HOME     : LYNX_WWW_DIST),
		 LYVersionStatus());

    fprintf(fp0, "</h1>\n");  /* don't forget to close <h1> */


#ifdef DIRED_SUPPORT
    if (lynx_edit_mode && nlinks > 0) {
	char *temp;

	fprintf(fp0, "<pre>\n");
	fprintf(fp0, "\n%s\n\n", gettext("Directory that you are currently viewing"));

	temp = HTfullURL_toFile(doc->address);
	fprintf(fp0, "   <em>%4s</em>  %s\n", gettext("Name:"), temp);
	FREE(temp);

	fprintf(fp0, "   <em>%4s</em>  %s\n", gettext("URL:"), doc->address);

	temp = HTfullURL_toFile(links[doc->link].lname);

	if (lstat(temp, &dir_info) == -1) {
	    CTRACE((tfp, "lstat(%s) failed, errno=%d\n", temp, errno));
	    HTAlert(CURRENT_LINK_STATUS_FAILED);
	} else {
	    char modes[80];
	    if (S_ISDIR(dir_info.st_mode)) {
		fprintf(fp0, "\n%s\n\n",
			gettext("Directory that you have currently selected"));
	    } else if (S_ISREG(dir_info.st_mode)) {
		fprintf(fp0, "\n%s\n\n",
			gettext("File that you have currently selected"));
#ifdef S_IFLNK
	    } else if (S_ISLNK(dir_info.st_mode)) {
		fprintf(fp0, "\n%s\n\n",
			gettext("Symbolic link that you have currently selected"));
#endif
	    } else {
		fprintf(fp0, "\n%s\n\n",
			gettext("Item that you have currently selected"));
	    }
	    fprintf(fp0, "       <em>%s</em>  %s\n", gettext("Full name:"), temp);
#ifdef S_IFLNK
	    if (S_ISLNK(dir_info.st_mode)) {
		char buf[1025];
		int buf_size;

		if ((buf_size = readlink(temp, buf, sizeof(buf)-1)) != -1) {
		    buf[buf_size] = '\0';
		} else {
		    sprintf(buf, "%.1024s", gettext("Unable to follow link"));
		}
		fprintf(fp0, "  <em>%s</em>  %s\n", gettext("Points to file:"), buf);
	    }
#endif
	    name = HTAA_UidToName(dir_info.st_uid);
	    if (*name)
		fprintf(fp0, "   <em>%s</em>  %s\n", gettext("Name of owner:"), name);
	    name = HTAA_GidToName (dir_info.st_gid);
	    if (*name)
		fprintf(fp0, "      <em>%s</em>  %s\n", gettext("Group name:"), name);
	    if (S_ISREG(dir_info.st_mode)) {
		fprintf(fp0, "       <em>%s</em>  %ld (bytes)\n",
			gettext("File size:"), (long)dir_info.st_size);
	    }
	    /*
	     *	Include date and time information.
	     */
	    cp = ctime(&dir_info.st_ctime);
	    fprintf(fp0, "   <em>%s</em>  %s", gettext("Creation date:"), cp);

	    cp = ctime(&dir_info.st_mtime);
	    fprintf(fp0, "   <em>%s</em>  %s", gettext("Last modified:"), cp);

	    cp = ctime(&dir_info.st_atime);
	    fprintf(fp0, "   <em>%s</em>  %s\n", gettext("Last accessed:"), cp);

	    fprintf(fp0, "   %s\n", gettext("Access Permissions"));
	    fprintf(fp0, "      <em>%s</em>  ", gettext("Owner:"));
	    modes[0] = '\0';
	    modes[1] = '\0';   /* In case there are no permissions */
	    modes[2] = '\0';
	    if ((dir_info.st_mode & S_IRUSR))
		strcat(modes, ", read");
	    if ((dir_info.st_mode & S_IWUSR))
		strcat(modes, ", write");
	    if ((dir_info.st_mode & S_IXUSR)) {
		if (S_ISDIR(dir_info.st_mode))
		    strcat(modes, ", search");
		else {
		    strcat(modes, ", execute");
		    if ((dir_info.st_mode & S_ISUID))
			strcat(modes, ", setuid");
		}
	    }
	    fprintf(fp0, "%s\n", (char *)&modes[2]); /* Skip leading ', ' */

	    fprintf(fp0, "      <em>Group:</em>  ");
	    modes[0] = '\0';
	    modes[1] = '\0';   /* In case there are no permissions */
	    modes[2] = '\0';
	    if ((dir_info.st_mode & S_IRGRP))
		strcat(modes, ", read");
	    if ((dir_info.st_mode & S_IWGRP))
		strcat(modes, ", write");
	    if ((dir_info.st_mode & S_IXGRP)) {
		if (S_ISDIR(dir_info.st_mode))
		    strcat(modes, ", search");
		else {
		    strcat(modes, ", execute");
		    if ((dir_info.st_mode & S_ISGID))
			strcat(modes, ", setgid");
		}
	    }
	    fprintf(fp0, "%s\n", (char *)&modes[2]);  /* Skip leading ', ' */

	    fprintf(fp0, "      <em>World:</em>  ");
	    modes[0] = '\0';
	    modes[1] = '\0';   /* In case there are no permissions */
	    modes[2] = '\0';
	    if ((dir_info.st_mode & S_IROTH))
		strcat(modes, ", read");
	    if ((dir_info.st_mode & S_IWOTH))
		strcat(modes, ", write");
	    if ((dir_info.st_mode & S_IXOTH)) {
		if (S_ISDIR(dir_info.st_mode))
		    strcat(modes, ", search");
		else {
		    strcat(modes, ", execute");
#ifdef S_ISVTX
		    if ((dir_info.st_mode & S_ISVTX))
			strcat(modes, ", sticky");
#endif
		}
	    }
	    fprintf(fp0, "%s\n", (char *)&modes[2]);  /* Skip leading ', ' */
	}
	FREE(temp);
	fprintf(fp0,"</pre>\n");
    } else {
#endif /* DIRED_SUPPORT */

    fprintf(fp0, "<h2>%s</h2>\n<dl compact>",
	    gettext("File that you are currently viewing"));

    LYformTitle(&Title, doc->title);
    LYEntify(&Title, TRUE);
    fprintf(fp0, "<dt><em>%s</em> %s%s\n",
		 gettext("Linkname:"),
		 Title,
		 ((doc->isHEAD &&
		   !strstr(Title, " (HEAD)") &&
		   !strstr(Title, " - HEAD")) ? " (HEAD)" : ""));

    StrAllocCopy(Address, doc->address);
    LYEntify(&Address, TRUE);
    fprintf(fp0,
	    "<dt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>URL:</em> %s\n", Address);

    if (HTLoadedDocumentCharset()) {
	fprintf(fp0, "<dt><em>&nbsp;%s</em> %s\n",
		     gettext("Charset:"),
		     HTLoadedDocumentCharset());
    } else {
      LYUCcharset * p_in = HTAnchor_getUCInfoStage(HTMainAnchor,
							     UCT_STAGE_PARSER);
      if (!p_in || isEmpty(p_in->MIMEname) ||
	   HTAnchor_getUCLYhndl(HTMainAnchor, UCT_STAGE_PARSER) < 0) {
	   p_in = HTAnchor_getUCInfoStage(HTMainAnchor, UCT_STAGE_MIME);
      }
      if (p_in && p_in->MIMEname && *(p_in->MIMEname) &&
	  HTAnchor_getUCLYhndl(HTMainAnchor, UCT_STAGE_MIME) >= 0) {
	fprintf(fp0, "<dt><em>&nbsp;%s</em> %s (assumed)\n",
		     gettext("Charset:"),
		     p_in->MIMEname);
      }
    }

    if ((cp = HText_getServer()) != NULL && *cp != '\0')
	fprintf(fp0, "<dt><em>&nbsp;&nbsp;%s</em> %s\n", gettext("Server:"), cp);

    if ((cp = HText_getDate()) != NULL && *cp != '\0')
	fprintf(fp0, "<dt><em>&nbsp;&nbsp;&nbsp;&nbsp;%s</em> %s\n", gettext("Date:"), cp);

    if ((cp = HText_getLastModified()) != NULL && *cp != '\0')
	fprintf(fp0, "<dt><em>%s</em> %s\n", gettext("Last Mod:"), cp);

#ifdef ADVANCED_INFO
    if (LYInfoAdvanced) {
	if (HTMainAnchor && HTMainAnchor->expires) {
	    fprintf(fp0, "<dt><em>%s</em> %s\n",
		    gettext("&nbsp;Expires:"), HTMainAnchor->expires);
	}
	if (HTMainAnchor && HTMainAnchor->cache_control) {
	    fprintf(fp0, "<dt><em>%s</em> %s\n",
		    gettext("Cache-Control:"), HTMainAnchor->cache_control);
	}
	if (HTMainAnchor && HTMainAnchor->content_length > 0) {
	    fprintf(fp0, "<dt><em>%s</em> %d %s\n",
		    gettext("Content-Length:"),
		    HTMainAnchor->content_length, gettext("bytes"));
	}
	if (HTMainAnchor && HTMainAnchor->content_language) {
	    fprintf(fp0, "<dt><em>%s</em> %s\n",
		    gettext("Language:"), HTMainAnchor->content_language);
	}
    }
#endif /* ADVANCED_INFO */

    if (doc->post_data) {
	fprintf(fp0, "<dt><em>%s</em> <xmp>%.*s</xmp>\n",
		gettext("Post Data:"),
		BStrLen(doc->post_data),
		BStrData(doc->post_data));
	fprintf(fp0, "<dt><em>%s</em> %s\n",
		gettext("Post Content Type:"), doc->post_content_type);
    }

    if (owner_address) {
	StrAllocCopy(Address, owner_address);
	LYEntify(&Address, TRUE);
    } else {
	StrAllocCopy(Address, NO_NOTHING);
    }
    fprintf(fp0, "<dt><em>%s</em> %s\n", gettext("Owner(s):"), Address);

    fprintf(fp0, "<dt>&nbsp;&nbsp;&nbsp;&nbsp;<em>%s</em> %d %s\n",
	    gettext("size:"), size_of_file, gettext("lines"));

    fprintf(fp0, "<dt>&nbsp;&nbsp;&nbsp;&nbsp;<em>%s</em> %s%s%s",
		 gettext("mode:"),
		 (lynx_mode == FORMS_LYNX_MODE ?
				  gettext("forms mode") :
		  HTisDocumentSource() ?
				  gettext("source") : gettext("normal")),
		 (doc->safe ? gettext(", safe") : ""),
		 (doc->internal_link ? gettext(", via internal link") : "")
	    );
#ifdef ADVANCED_INFO
    if (LYInfoAdvanced) {
	fprintf(fp0, "%s%s%s\n",
		(HText_hasNoCacheSet(HTMainText) ?
				  gettext(", no-cache") : ""),
		(HTAnchor_isISMAPScript((HTAnchor *)HTMainAnchor) ?
				  gettext(", ISMAP script") : ""),
		(doc->bookmark ?
				  gettext(", bookmark file") : "")
	    );
    }
#endif /* ADVANCED_INFO */

    fprintf(fp0, "\n</dl>\n");  /* end of list */

    if (nlinks > 0) {
	fprintf(fp0, "<h2>%s</h2>\n<dl compact>",
		gettext("Link that you currently have selected"));
	StrAllocCopy(Title, LYGetHiliteStr(doc->link, 0));
	LYEntify(&Title, TRUE);
	fprintf(fp0, "<dt><em>%s</em> %s\n",
		gettext("Linkname:"),
		Title);
	if (lynx_mode == FORMS_LYNX_MODE &&
	    links[doc->link].type == WWW_FORM_LINK_TYPE) {
	    if (links[doc->link].l_form->submit_method) {
		int method = links[doc->link].l_form->submit_method;
		char *enctype = links[doc->link].l_form->submit_enctype;

		fprintf(fp0, "<dt>&nbsp;&nbsp;<em>%s</em> %s\n",
			     gettext("Method:"),
			     (method == URL_POST_METHOD) ? "POST" :
			     (method == URL_MAIL_METHOD) ? "(email)" :
							   "GET");
		fprintf(fp0, "<dt>&nbsp;<em>%s</em> %s\n",
			     gettext("Enctype:"),
			     (enctype &&
			      *enctype ?
			       enctype : "application/x-www-form-urlencoded"));
	    }
	    if (links[doc->link].l_form->submit_action) {
		StrAllocCopy(Address, links[doc->link].l_form->submit_action);
		LYEntify(&Address, TRUE);
		fprintf(fp0, "<dt>&nbsp;&nbsp;<em>Action:</em> %s\n", Address);
	    }
	    if (!(links[doc->link].l_form->submit_method &&
		  links[doc->link].l_form->submit_action)) {
		fprintf(fp0, "<dt>&nbsp;%s\n", gettext("(Form field)"));
	    }
	} else {
	    if (links[doc->link].lname) {
		StrAllocCopy(Title, links[doc->link].lname);
		LYEntify(&Title, TRUE);
	    } else {
		StrAllocCopy(Title, "");
	    }
	    fprintf(fp0,
	       "<dt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>URL:</em> %s\n", Title);
	}
	fprintf(fp0, "</dl>\n");  /* end of list */

    } else
	fprintf(fp0, "<h2>%s</h2>", gettext("No Links on the current page"));

#ifdef DIRED_SUPPORT
    }
#endif /* DIRED_SUPPORT */
    EndInternalPage(fp0);

    LYrefresh();

    LYCloseTemp(tempfile);
    FREE(Address);
    FREE(Title);

    return(0);
}
