1
/* Support for dumping to the file on startup (w/o bfu) */
2
/* $Id: dump.c,v 1.80.2.2 2004/01/17 22:33:02 pasky Exp $ */
11
#include <sys/types.h> /* NetBSD flavour */
12
#ifdef HAVE_SYS_SIGNAL_H
13
#include <sys/signal.h>
16
#include <fcntl.h> /* OS/2 needs this after sys/types.h */
25
#include "config/options.h"
26
#include "cache/cache.h"
27
#include "document/document.h"
28
#include "document/options.h"
29
#include "document/renderer.h"
30
#include "document/view.h"
31
#include "intl/gettext/libintl.h"
32
#include "lowlevel/select.h"
33
#include "osdep/ascii.h"
34
#include "osdep/osdep.h"
35
#include "protocol/protocol.h"
36
#include "protocol/uri.h"
37
#include "sched/error.h"
38
#include "sched/connection.h"
39
#include "terminal/color.h"
40
#include "terminal/hardio.h"
41
#include "terminal/terminal.h"
42
#include "util/memory.h"
43
#include "util/string.h"
44
#include "viewer/dump/dump.h"
45
#include "viewer/text/view.h"
46
#include "viewer/text/vs.h"
50
static struct download dump_download;
51
static int dump_redir_count = 0;
54
/* This dumps the given @ce's source onto @fd nothing more. It returns 0 if it
55
* all went fine and 1 if something isn't quite right and we should terminate
58
dump_source(int fd, struct download *status, struct cache_entry *ce)
60
struct fragment *frag;
65
foreach (frag, ce->frag) {
66
int d = dump_pos - frag->offset;
69
if (d < 0 || frag->length <= d)
73
w = hard_write(fd, frag->data + d, l);
76
detach_connection(status, dump_pos);
79
ERROR(gettext("Can't write to stdout: %s"),
80
(unsigned char *) strerror(errno));
82
ERROR(gettext("Can't write to stdout."));
89
detach_connection(status, dump_pos);
96
/* This dumps the given @ce's formatted output onto @fd. It returns 0 if it all
97
* went fine and 1 if something isn't quite right and we should terminate
100
dump_formatted(int fd, struct download *status, struct cache_entry *ce)
102
struct document_options o;
103
struct document_view formatted;
104
struct view_state *vs;
108
/* No need to add a byte for the \0 to the result of strlen():
109
* struct view_state has an unsigned char url[1]. -- Miciah */
110
vs = mem_alloc(sizeof(struct view_state) + strlen(get_cache_uri(ce)));
113
memset(vs, 0, sizeof(struct view_state));
114
memset(&formatted, 0, sizeof(struct document_view));
116
get_opt_bool("document.browse.links.numbering") =
117
!get_opt_bool_tree(cmdline_options, "no-numbering");
119
init_document_options(&o);
122
o.width = get_opt_int("document.dump.width");
124
o.cp = get_opt_int("document.dump.codepage");
125
o.color_mode = COLOR_MODE_DUMP;
129
init_vs(vs, get_cache_uri(ce), -1);
131
render_document(vs, &formatted, &o);
132
dump_to_file(formatted.document, fd);
134
detach_formatted(&formatted);
142
dump_end(struct download *status, void *p)
144
struct cache_entry *ce = status->ce;
145
int fd = get_output_handle();
147
if (fd == -1) return;
148
if (ce && ce->redirect && dump_redir_count++ < MAX_REDIRECTS) {
151
if (status->state >= 0)
152
change_connection(status, NULL, PRI_CANCEL, 0);
154
u = join_urls(get_cache_uri(ce), ce->redirect);
157
if (!ce->redirect_get
159
&& !get_opt_int("protocol.http.bugs.broken_302_redirect")) {
160
unsigned char *pc = ce->uri.post;
162
if (pc) add_to_strn(&u, pc);
165
load_url(u, get_cache_uri(ce), status, PRI_MAIN, 0, -1);
170
if (status->state >= 0 && status->state < S_TRANS) return;
171
if (status->state >= S_TRANS
172
&& get_opt_int_tree(cmdline_options, "dump"))
175
if (get_opt_int_tree(cmdline_options, "source")) {
176
if (dump_source(fd, status, ce) > 0)
179
if (status->state >= 0)
183
if (dump_formatted(fd, status, ce) > 0)
187
if (status->state != S_OK) {
188
ERROR(get_err_msg(status->state, NULL));
198
dump_start(unsigned char *url)
200
unsigned char *real_url = NULL;
204
ERROR(gettext("URL expected after %s."),
205
get_opt_int_tree(cmdline_options, "source")
206
? "-source" : "-dump");
210
dump_download.end = dump_end;
214
real_url = translate_url(url, wd);
215
if (wd) mem_free(wd);
217
if (!real_url) real_url = stracpy(url);
219
|| known_protocol(real_url, NULL) == PROTOCOL_UNKNOWN
220
|| load_url(real_url, NULL, &dump_download, PRI_MAIN, 0, -1)) {
226
if (real_url) mem_free(real_url);
229
/* Using this function in dump_to_file() is unfortunately slightly slower than
230
* the current code. However having this here instead of in the scripting
231
* backends is better. */
233
add_document_to_string(struct string *string, struct document *document)
237
assert(string && document);
238
if_assert_failed return NULL;
240
for (y = 0; y < document->height; y++) {
241
struct screen_char *pos = document->data[y].chars;
244
for (x = 0; x < document->data[y].length; x++) {
245
unsigned char data = pos->data;
246
unsigned int frame = (pos->attr & SCREEN_ATTR_FRAME);
248
if (data < ' ' || data == ASCII_DEL) {
250
} else if (frame && data >= 176 && data < 224) {
251
data = frame_dumb[data - 176];
254
add_char_to_string(string, data);
257
add_char_to_string(string, '\n');
264
dump_to_file(struct document *document, int fd)
270
unsigned char *buf = mem_alloc(D_BUF);
274
for (y = 0; y < document->height; y++) {
275
for (x = 0; x <= document->data[y].length; x++) {
278
if (x == document->data[y].length) {
281
unsigned char attr = document->data[y].chars[x].attr;
283
c = document->data[y].chars[x].data;
285
if ((attr & SCREEN_ATTR_FRAME)
286
&& c >= 176 && c < 224)
287
c = frame_dumb[c - 176];
292
if (hard_write(fd, buf, bptr) != bptr)
299
if (hard_write(fd, buf, bptr) != bptr) {
305
if (get_opt_bool("document.browse.links.numbering")
306
&& document->nlinks) {
307
char *header = "\nReferences\n\n Visible links\n";
308
int headlen = strlen(header);
310
if (hard_write(fd, header, headlen) != headlen)
313
for (x = 0; x < document->nlinks; x++) {
314
struct link *l = &document->links[x];
315
unsigned char *where = l->where;
317
if (!where) continue;
319
if (strlen(where) > 4 && !memcmp(where, "MAP@", 4))
322
if (l->title && *l->title)
323
snprintf(buf, D_BUF, "%4d. %s\n\t%s\n",
324
x + 1, l->title, where);
326
snprintf(buf, D_BUF, "%4d. %s\n",
329
if (hard_write(fd, buf, bptr) != bptr)