1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00
elinks/src/dialogs/document.c
2022-01-16 19:09:27 +01:00

349 lines
7.9 KiB
C

/* Information about current document and current link */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "elinks.h"
#include "bfu/dialog.h"
#include "cache/cache.h"
#include "dialogs/document.h"
#include "document/document.h"
#include "document/view.h"
#include "globhist/globhist.h"
#include "intl/libintl.h"
#include "protocol/header.h"
#include "protocol/uri.h"
#include "session/location.h"
#include "session/session.h"
#include "terminal/terminal.h"
#include "terminal/window.h"
#include "util/conv.h"
#include "util/memory.h"
#include "util/string.h"
#include "viewer/text/link.h"
#include "viewer/text/view.h"
void
nowhere_box(struct terminal *term, char *title)
{
assert(term);
if_assert_failed return;
if (!title || !*title)
title = N_("Info");
info_box(term, 0, title, ALIGN_CENTER,
N_("You are nowhere!"));
}
static void
add_link_info_to_string(struct string *msg, struct session *ses)
{
struct document_view *doc_view = current_frame(ses);
struct terminal *term = ses->tab->term;
char *a;
struct link *link;
if (!doc_view) return;
add_char_to_string(msg, '\n');
a = get_current_link_info(ses, doc_view);
if (a) {
add_format_to_string(msg, "\n%s: %s",
_("Link", term), a);
mem_free(a);
}
a = get_current_link_title(doc_view);
if (a) {
add_format_to_string(msg, "\n%s: %s",
_("Link title", term), a);
mem_free(a);
}
link = get_current_link_in_view(doc_view);
if (link) {
struct string img;
#ifdef CONFIG_GLOBHIST
struct global_history_item *historyitem;
#endif
if (link->where_img && init_string(&img)) {
add_string_uri_to_string(&img, link->where_img,
URI_PUBLIC);
decode_uri_string_for_display(&img);
add_format_to_string(msg, "\n%s: %s",
_("Link image", term),
img.source);
done_string(&img);
}
#ifdef CONFIG_GLOBHIST
historyitem = get_global_history_item(link->where);
if (historyitem) {
char *last_visit;
last_visit = ctime(&historyitem->last_visit);
if (last_visit)
add_format_to_string(msg,
"\n%s: %.24s",
_("Link last visit time",
term),
last_visit);
if (*historyitem->title)
add_format_to_string(msg, "\n%s: %s",
_("Link title (from history)",
term),
historyitem->title);
}
#endif
}
}
/* Link info message box. */
void
link_info_dialog(struct session *ses)
{
struct terminal *term = ses->tab->term;
struct location *location = cur_loc(ses);
struct string msg;
if (!location) {
nowhere_box(term, NULL);
return;
}
if (!init_string(&msg)) return;
add_link_info_to_string(&msg, ses);
info_box(term, MSGBOX_FREE_TEXT | MSGBOX_SCROLLABLE,
N_("Info"), ALIGN_LEFT, msg.source);
}
/* Location info. message box. */
void
document_info_dialog(struct session *ses)
{
struct terminal *term = ses->tab->term;
struct location *location = cur_loc(ses);
struct document_view *doc_view;
struct string msg;
if (!location) {
nowhere_box(term, NULL);
return;
}
doc_view = current_frame(ses);
if (!init_string(&msg)) return;
add_to_string(&msg, _("URL", term));
add_to_string(&msg, ": ");
/* Add the uri with password and post info stripped */
add_uri_to_string(&msg, location->vs.uri, URI_PUBLIC);
add_char_to_string(&msg, '\n');
if (doc_view && doc_view->document->title) {
add_format_to_string(&msg, "%s: %s", _("Title", term),
doc_view->document->title);
}
add_char_to_string(&msg, '\n');
if (doc_view && doc_view->document->cached) {
struct cache_entry *cached = doc_view->document->cached;
char *a;
add_format_to_string(&msg, "\n%s: %" OFF_PRINT_FORMAT,
_("Size", term),
(off_print_T) cached->length);
if (cached->incomplete) {
add_format_to_string(&msg, " (%s)", _("incomplete", term));
}
if (doc_view) {
add_format_to_string(&msg, "\n%s: %s", _("Codepage", term),
get_cp_name(doc_view->document->cp));
if (doc_view->document->cp_status == CP_STATUS_ASSUMED) {
add_format_to_string(&msg, " (%s)", _("assumed", term));
} else if (doc_view->document->cp_status == CP_STATUS_IGNORED) {
add_format_to_string(&msg, " (%s)",
_("ignoring server setting", term));
}
}
a = parse_header(cached->head, "Server", NULL);
if (a) {
add_format_to_string(&msg, "\n%s: %s",
_("Server", term), a);
mem_free(a);
}
if (cached->ssl_info) {
add_format_to_string(&msg, "\n%s: %s",
_("SSL Cipher", term),
cached->ssl_info);
}
if (cached->encoding_info) {
add_format_to_string(&msg, "\n%s: %s",
_("Encoding", term),
cached->encoding_info);
}
a = parse_header(cached->head, "Date", NULL);
if (a) {
add_format_to_string(&msg, "\n%s: %s",
_("Date", term), a);
mem_free(a);
}
if (cached->last_modified) {
add_format_to_string(&msg, "\n%s: %s",
_("Last modified", term),
cached->last_modified);
}
if (!cached->incomplete) {
add_format_to_string(&msg, "\n%s: ",
_("Time since loading", term));
add_duration_to_string(&msg,
time(NULL) - cached->seconds);
}
}
#ifdef CONFIG_GLOBHIST
{
char *last_visit = NULL;
struct global_history_item *historyitem;
add_format_to_string(&msg, "\n%s: ",
_("Last visit time", term));
historyitem = get_global_history_item(struri(location->vs.uri));
if (historyitem) last_visit = ctime(&historyitem->last_visit);
/* GNU's documentation says that ctime() can return NULL.
* The Open Group Base Specifications Issue 6 implies
* otherwise, but is ambiguous. Let's be safe. -- Miciah
*/
if (last_visit) {
/* The string returned by ctime() includes a newline,
* and we don't want that, so we use add_bytes_to_str.
* The string always has exactly 25 characters, so add
* 24 bytes: The length of the string, minus one for
* the newline. -- Miciah
*/
add_bytes_to_string(&msg, last_visit, 24);
} else {
add_to_string(&msg, _("Unknown", term));
}
}
#endif
add_link_info_to_string(&msg, ses);
info_box(term, MSGBOX_FREE_TEXT | MSGBOX_SCROLLABLE,
N_("Info"), ALIGN_LEFT, msg.source);
}
void
cached_header_dialog(struct session *ses, struct cache_entry *cached)
{
int msgbox_flags = 0;
char *title = N_("Header info");
char *headers = NULL;
int i = 0, j = 0;
if (!cached || !cached->head || !*cached->head)
goto display_headers;
#ifdef CONFIG_DEBUG
/* If |cached->head| starts with a newline, it has been
* internally generated, usually to give ELinks-generated
* documents (e.g., file:// directory listings) a MIME type
* of text/html. */
if (*cached->head == '\r')
title = N_("Internal header info");
#endif
headers = (char *)mem_alloc(strlen(cached->head) + 1);
if (!headers) return;
/* Sanitize headers string. */
/* XXX: Do we need to check length and limit
* it to something reasonable? */
while (cached->head[i]) {
/* Check for control chars. */
if ((unsigned char)cached->head[i] < ' '
&& cached->head[i] != '\n') {
/* Ignore '\r' but replace
* other control chars with
* a visible char. */
if (cached->head[i] != '\r') {
headers[j] = '*';
j++;
}
} else {
headers[j] = cached->head[i];
j++;
}
i++;
}
/* Ensure null termination. */
headers[j] = '\0';
/* Remove any trailing newlines. */
while (j && headers[--j] == '\n')
headers[j] = '\0';
if (!*headers)
mem_free_set(&headers, NULL);
display_headers:
if (!headers) {
headers = N_("No header info.");
} else {
msgbox_flags = MSGBOX_FREE_TEXT | MSGBOX_SCROLLABLE;
}
/* Headers info message box. */
info_box(ses->tab->term, msgbox_flags,
title, ALIGN_LEFT, headers);
}
/* Headers info. message box. */
void
protocol_header_dialog(struct session *ses)
{
if (!have_location(ses)) {
nowhere_box(ses->tab->term, N_("Header info"));
return;
}
if (ses->doc_view && ses->doc_view->document)
cached_header_dialog(ses, ses->doc_view->document->cached);
}