/* $LynxId: LYShowInfo.c,v 1.82 2018/05/11 20:43:26 tom Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DIRED_SUPPORT #include #include #include #endif /* DIRED_SUPPORT */ #define BEGIN_DL(text) fprintf(fp0, "

%s

\n
", LYEntifyTitle(&buffer, text)) #define END_DL() fprintf(fp0, "\n
\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 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. */ BOOL LYVersionIsRelease(void) { return (BOOL) (strstr(LYNX_VERSION, "rel") != 0); } const char *LYVersionStatus(void) { if (LYVersionIsRelease()) return REL_VERSION; else if (strstr(LYNX_VERSION, "pre") != 0) return PRE_VERSION; return DEV_VERSION; } const char *LYVersionDate(void) { static char temp[LYNX_DATE_LEN + 1]; LYStrNCpy(temp, &LYNX_DATE[LYNX_DATE_OFF], LYNX_DATE_LEN); return temp; } 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, "
"); while (need++ < label_columns) fprintf(fp, " "); if (LYwideLines && allow_wide) fprintf(fp, "%s
%s
\n", the_label, the_value); else fprintf(fp, "%s%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
%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, "

%s %s (%s) (%s)", LYNX_NAME, LYNX_VERSION, LYVersionDate(), (LYVersionIsRelease()? LYNX_WWW_HOME : LYNX_WWW_DIST), LYVersionStatus()); fprintf(fp0, "

\n"); /* don't forget to close

*/ #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, "
%s %.*s\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, "
 %s\n", LYEntifyTitle(&buffer, gettext("(Form field)"))); } } else { dt_URL(fp0, NonNull(links[doc->link].lname)); } END_DL(); } else { fprintf(fp0, "

%s

", LYEntifyTitle(&buffer, gettext("No Links on the current page"))); } if ((cp = HText_getHttpHeaders()) != 0) { fprintf(fp0, "

%s

", LYEntifyTitle(&buffer, gettext("Server Headers:"))); fprintf(fp0, "
%s
", LYEntifyTitle(&buffer, cp)); } #ifdef DIRED_SUPPORT } #endif /* DIRED_SUPPORT */ EndInternalPage(fp0); LYrefresh(); LYCloseTemp(tempfile); FREE(Title); FREE(buffer); return (0); }