summaryrefslogtreecommitdiffstats
path: root/src/LYShowInfo.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/LYShowInfo.c485
1 files changed, 485 insertions, 0 deletions
diff --git a/src/LYShowInfo.c b/src/LYShowInfo.c
new file mode 100644
index 0000000..129810c
--- /dev/null
+++ b/src/LYShowInfo.c
@@ -0,0 +1,485 @@
+/* $LynxId: LYShowInfo.c,v 1.86 2024/01/15 18:16:29 tom Exp $ */
+#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 BEGIN_DL(text) fprintf(fp0, "<h2>%s</h2>\n<dl compact>", LYEntifyTitle(&buffer, text))
+#define END_DL() fprintf(fp0, "\n</dl>\n")
+
+#define ADD_SS(label,value) dt_String(fp0, label, value, 0)
+#define ADD_WW(label,value) dt_String(fp0, label, value, 1)
+#define ADD_NN(label,value,units) dt_Number(fp0, label, (long) value, units)
+
+static int label_columns;
+
+/*
+ * LYNX_VERSION and LYNX_DATE are generated by the configure script.
+ */
+BOOL LYVersionIsRelease(void)
+{
+ return TRUE;
+}
+
+const char *LYVersionStatus(void)
+{
+ return REL_VERSION;
+}
+
+const char *LYVersionDate(void)
+{
+ return LYNX_DATE;
+}
+
+static void dt_String(FILE *fp,
+ const char *label,
+ const char *value,
+ int allow_wide)
+{
+ int have;
+ int need;
+ char *the_label = NULL;
+ char *the_value = NULL;
+
+ StrAllocCopy(the_label, label);
+ StrAllocCopy(the_value, value);
+
+ have = (int) strlen(the_label);
+ need = LYstrExtent(the_label, have, label_columns);
+
+ LYEntify(&the_label, TRUE);
+ LYEntify(&the_value, TRUE);
+
+ fprintf(fp, "<dt>");
+ while (need++ < label_columns)
+ fprintf(fp, "&nbsp;");
+ if (LYwideLines && allow_wide)
+ fprintf(fp, "<em>%s</em> <pre>%s</pre>\n", the_label, the_value);
+ else
+ fprintf(fp, "<em>%s</em> %s\n", the_label, the_value);
+
+ FREE(the_label);
+ FREE(the_value);
+}
+
+static void dt_Number(FILE *fp0,
+ const char *label,
+ long number,
+ const char *units)
+{
+ char *value = NULL;
+ char *buffer = NULL;
+
+ HTSprintf(&value, "%ld %s", number, LYEntifyTitle(&buffer, units));
+ ADD_SS(label, value);
+ FREE(value);
+ FREE(buffer);
+}
+
+static void dt_URL(FILE *fp0, const char *address)
+{
+ if (address == NULL)
+ address = "";
+ ADD_WW(gettext("URL:"), address);
+
+ /*
+ * If the display handles UTF-8, and if the address uses %xy formatted
+ * characters, show the decoded URL on the next line.
+ */
+ if (LYCharSet_UC[current_char_set].enc == UCT_ENC_UTF8) {
+ char *working = NULL;
+
+ StrAllocCopy(working, address);
+ if (strcmp(HTUnEscape(working), address)) {
+ fprintf(fp0, "\n<br>%s\n", working);
+ }
+ free(working);
+ }
+}
+
+/*
+ * LYShowInfo prints a page of info about the current file and the link that
+ * the cursor is on.
+ */
+int LYShowInfo(DocInfo *doc,
+ DocInfo *newdoc,
+ char *owner_address)
+{
+ static char tempfile[LY_MAXPATH] = "\0";
+
+ int url_type;
+ FILE *fp0;
+ char *Title = NULL;
+ const char *cp;
+ char *temp = NULL;
+ char *buffer = NULL;
+
+ BOOLEAN LYInfoAdvanced = (BOOL) (user_mode == ADVANCED_MODE);
+
+#ifdef DIRED_SUPPORT
+ struct stat dir_info;
+ const char *name;
+#endif /* DIRED_SUPPORT */
+
+ if (LYReuseTempfiles) {
+ fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
+ } else {
+ (void) 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 = (int) strlen(links[doc->link].lname) - 1;
+
+ if ((last_slash - links[doc->link].lname) == next_to_last) {
+ links[doc->link].lname[next_to_last] = '\0';
+ }
+ }
+
+ label_columns = 9;
+
+ WriteInternalTitle(fp0, 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) {
+
+ BEGIN_DL(gettext("Directory that you are currently viewing"));
+
+ temp = HTfullURL_toFile(doc->address);
+ ADD_SS(gettext("Name:"), temp);
+ FREE(temp);
+
+ dt_URL(fp0, doc->address);
+
+ END_DL();
+
+ 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];
+
+ label_columns = 16;
+ if (S_ISDIR(dir_info.st_mode)) {
+ BEGIN_DL(gettext("Directory that you have currently selected"));
+ } else if (S_ISREG(dir_info.st_mode)) {
+ BEGIN_DL(gettext("File that you have currently selected"));
+#ifdef S_IFLNK
+ } else if (S_ISLNK(dir_info.st_mode)) {
+ BEGIN_DL(gettext("Symbolic link that you have currently selected"));
+#endif
+ } else {
+ BEGIN_DL(gettext("Item that you have currently selected"));
+ }
+ ADD_SS(gettext("Full name:"), temp);
+#ifdef S_IFLNK
+ if (S_ISLNK(dir_info.st_mode)) {
+ char buf[MAX_LINE];
+ int buf_size;
+ size_t limit = sizeof(buf) - 1;
+
+ if ((buf_size = (int) readlink(temp, buf, limit)) != -1) {
+ if (buf_size > (int) limit)
+ buf_size = (int) limit;
+ buf[buf_size] = '\0';
+ } else {
+ sprintf(buf, "%.*s", (int) limit,
+ gettext("Unable to follow link"));
+ }
+ ADD_SS(gettext("Points to file:"), buf);
+ }
+#endif
+ name = HTAA_UidToName((int) dir_info.st_uid);
+ if (*name)
+ ADD_SS(gettext("Name of owner:"), name);
+ name = HTAA_GidToName((int) dir_info.st_gid);
+ if (*name)
+ ADD_SS(gettext("Group name:"), name);
+ if (S_ISREG(dir_info.st_mode)) {
+ ADD_NN(gettext("File size:"),
+ (long) dir_info.st_size,
+ gettext("(bytes)"));
+ }
+ /*
+ * Include date and time information.
+ */
+ ADD_SS(gettext("Creation date:"),
+ ctime(&dir_info.st_ctime));
+
+ ADD_SS(gettext("Last modified:"),
+ ctime(&dir_info.st_mtime));
+
+ ADD_SS(gettext("Last accessed:"),
+ ctime(&dir_info.st_atime));
+
+ END_DL();
+
+ label_columns = 9;
+ BEGIN_DL(gettext("Access Permissions"));
+ 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");
+ }
+ }
+ ADD_SS(gettext("Owner:"), &modes[2]);
+
+ 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");
+ }
+ }
+ ADD_SS(gettext("Group:"), &modes[2]);
+
+ 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
+ }
+ }
+ ADD_SS(gettext("World:"), &modes[2]);
+ END_DL();
+ }
+ FREE(temp);
+ } else {
+#endif /* DIRED_SUPPORT */
+
+ BEGIN_DL(gettext("File that you are currently viewing"));
+
+ LYformTitle(&Title, doc->title);
+ HTSprintf(&temp, "%s%s",
+ LYEntifyTitle(&buffer, Title),
+ ((doc->isHEAD &&
+ !strstr(Title, " (HEAD)") &&
+ !strstr(Title, " - HEAD")) ? " (HEAD)" : ""));
+ ADD_SS(gettext("Linkname:"), temp);
+ FREE(temp);
+
+ dt_URL(fp0, doc->address);
+
+ if (HTLoadedDocumentCharset()) {
+ ADD_SS(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 && non_empty(p_in->MIMEname) &&
+ HTAnchor_getUCLYhndl(HTMainAnchor, UCT_STAGE_MIME) >= 0) {
+ HTSprintf(&temp, "%s %s",
+ LYEntifyTitle(&buffer, p_in->MIMEname),
+ gettext("(assumed)"));
+ ADD_SS(gettext("Charset:"), p_in->MIMEname);
+ FREE(temp);
+ }
+ }
+
+ if ((cp = HText_getServer()) != NULL && *cp != '\0')
+ ADD_SS(gettext("Server:"), cp);
+
+ if ((cp = HText_getDate()) != NULL && *cp != '\0')
+ ADD_SS(gettext("Date:"), cp);
+
+ if ((cp = HText_getLastModified()) != NULL && *cp != '\0')
+ ADD_SS(gettext("Last Mod:"), cp);
+
+ if (LYInfoAdvanced) {
+ if (HTMainAnchor && HTMainAnchor->expires) {
+ ADD_SS(gettext("Expires:"), HTMainAnchor->expires);
+ }
+ if (HTMainAnchor && HTMainAnchor->cache_control) {
+ ADD_SS(gettext("Cache-Control:"), HTMainAnchor->cache_control);
+ }
+ if (HTMainAnchor && HTMainAnchor->content_length > 0) {
+ ADD_NN(gettext("Content-Length:"),
+ HTMainAnchor->content_length,
+ gettext("bytes"));
+ } else {
+ ADD_NN(gettext("Length:"),
+ HText_getNumOfBytes(),
+ gettext("bytes"));
+ }
+ if (HTMainAnchor && HTMainAnchor->content_language) {
+ ADD_SS(gettext("Language:"), HTMainAnchor->content_language);
+ }
+ }
+
+ if (doc->post_data) {
+ fprintf(fp0, "<dt><em>%s</em> <xmp>%.*s</xmp>\n",
+ LYEntifyTitle(&buffer, gettext("Post Data:")),
+ BStrLen(doc->post_data),
+ BStrData(doc->post_data));
+ ADD_SS(gettext("Post Content Type:"), doc->post_content_type);
+ }
+
+ ADD_SS(gettext("Owner(s):"),
+ (owner_address
+ ? owner_address
+ : NO_NOTHING));
+
+ ADD_NN(gettext("size:"),
+ HText_getNumOfLines(),
+ gettext("lines"));
+
+ StrAllocCopy(temp,
+ ((lynx_mode == FORMS_LYNX_MODE)
+ ? gettext("forms mode")
+ : (HTisDocumentSource()
+ ? gettext("source")
+ : gettext("normal"))));
+ if (doc->safe)
+ StrAllocCat(temp, gettext(", safe"));
+ if (doc->internal_link)
+ StrAllocCat(temp, gettext(", via internal link"));
+
+ if (LYInfoAdvanced) {
+ if (HText_hasNoCacheSet(HTMainText))
+ StrAllocCat(temp, gettext(", no-cache"));
+ if (HTAnchor_isISMAPScript((HTAnchor *) HTMainAnchor))
+ StrAllocCat(temp, gettext(", ISMAP script"));
+ if (doc->bookmark)
+ StrAllocCat(temp, gettext(", bookmark file"));
+ }
+
+ ADD_SS(gettext("mode:"), temp);
+ FREE(temp);
+
+ END_DL();
+
+ if (nlinks > 0) {
+ BEGIN_DL(gettext("Link that you currently have selected"));
+ ADD_SS(gettext("Linkname:"),
+ LYGetHiliteStr(doc->link, 0));
+ 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;
+
+ ADD_SS(gettext("Method:"),
+ ((method == URL_POST_METHOD) ? "POST" :
+ ((method == URL_MAIL_METHOD) ? "(email)" :
+ "GET")));
+ ADD_SS(gettext("Enctype:"),
+ (non_empty(enctype)
+ ? enctype
+ : "application/x-www-form-urlencoded"));
+ }
+ if (links[doc->link].l_form->submit_action) {
+ ADD_SS(gettext("Action:"),
+ links[doc->link].l_form->submit_action);
+ }
+ if (!(links[doc->link].l_form->submit_method &&
+ links[doc->link].l_form->submit_action)) {
+ fprintf(fp0, "<dt>&nbsp;%s\n",
+ LYEntifyTitle(&buffer, gettext("(Form field)")));
+ }
+ } else {
+ dt_URL(fp0, NonNull(links[doc->link].lname));
+ }
+ END_DL();
+
+ } else {
+ fprintf(fp0, "<h2>%s</h2>",
+ LYEntifyTitle(&buffer,
+ gettext("No Links on the current page")));
+ }
+
+ if ((cp = HText_getHttpHeaders()) != 0) {
+ fprintf(fp0, "<h2>%s</h2>",
+ LYEntifyTitle(&buffer, gettext("Server Headers:")));
+ fprintf(fp0, "<pre>%s</pre>",
+ LYEntifyTitle(&buffer, cp));
+ }
+#ifdef DIRED_SUPPORT
+ }
+#endif /* DIRED_SUPPORT */
+ EndInternalPage(fp0);
+
+ LYrefresh();
+
+ LYCloseTemp(tempfile);
+ FREE(Title);
+ FREE(buffer);
+
+ return (0);
+}