diff --git a/xtrn/go-for/go-for.js b/xtrn/go-for/go-for.js index 59c44e5a58e44dd05ae8399fbb06b6d857464c87..615f2da7e2641aadb26a9f60dcfe56df5cc941f2 100644 --- a/xtrn/go-for/go-for.js +++ b/xtrn/go-for/go-for.js @@ -10,9 +10,16 @@ load('typeahead.js'); * - Improve address input (brighter, autodelete) (typeahead.js) * - Improve highlight visibility * - Shift-Tab? Would have to store escaped state in input loop (I think) + * - m to search for selector in page (typeahead autocomplete) + * - s to select character encoding? Apparently some servers now do utf8. + * - t to toggle TLS (or perhaps have the user specify this with the address, or attempt to connect with TLS first and fall back) + * - . to display the source */ const cache_ttl = 300; // seconds - make configgy +const max_dir_size = 4096000; +const max_file_size = 1073741824; +const max_text_size = 4096000; const timeout = 30; // seconds - make configgyable const type_map = { @@ -148,8 +155,8 @@ function go_fetch(host, port, selector, type, query) { const socket = new Socket(); if (!socket.connect(host, port)) return null; - const fn = get_cache_fn(host, port, selector); - const f = new File(fn); + var fn = get_cache_fn(host, port, selector); + var f = new File(fn); set_status(format('Requesting %s:%s %s ...', host, port, selector)); if (type != '7') { @@ -157,31 +164,59 @@ function go_fetch(host, port, selector, type, query) { } else { socket.sendline(selector + '\t' + query); } - const dl_start = time(); + set_status(format('Downloading %s:%s %s ...', host, port, selector)); + var line; + var fs = 0; if (type == '1' || type == '7') { // this is a gopher directory - var line; + var parsed; f.open('w'); - while (time() - dl_start < timeout && !js.terminated && socket.is_connected && (line = socket.recvline()) != '.') { - if (line) f.writeln(JSON.stringify(parse_line(line))); + while (!js.terminated && !console.aborted && socket.is_connected && fs <= max_dir_size && (line = socket.recvline()) != '.') { + if (line) { + last_dl = time(); + parsed = JSON.stringify(parse_line(line)); + f.writeln(parsed); + fs += parsed.length; + } } f.close(); } else if (type == '0' || type == '6') { // this is a text file f.open('w'); - while (time() - dl_start < timeout && !js.terminated && socket.is_connected) { - f.writeln(socket.recvline()); + while (!js.terminated && !console.aborted && socket.is_connected && fs <= max_text_size) { + line = socket.recvline(); + f.writeln(line); + last_dl = time(); + fs += line.length; } f.close(); } else if (['4', '5', '9', 'g', 'I'].indexOf(type) > -1) { // this is a binary file f.open('wb'); - while (time() - dl_start < timeout && !js.terminated && socket.is_connected) { + while (!js.terminated && !console.aborted && socket.is_connected && fs <= max_file_size) { f.writeBin(socket.recvBin(1), 1); + last_dl = time(); + fs++; } f.close(); } - set_status(format('Downloaded %s:%s %s', host, port, selector)); + if (console.aborted) { + console.aborted = false; + const msg = format('Aborted download of %s:%s %s.', host, port, selector); + f.remove(); + fn = get_cache_fn(host, port, selector + '_error'); + f = new File(fn); + f.open('w'); + if (type == '1' || type == '7') { + f.writeln(JSON.stringify(parse_line('i' + msg + '\tnull\tnull\t0'))); + } else { + f.writeln(msg); + } + f.close(); + set_status(format('Download of %s:%s %s aborted', host, port, selector)); + } else { + set_status(format('Downloaded %s:%s %s', host, port, selector)); + } return fn; @@ -203,7 +238,6 @@ function go_for(host, port, selector, type, skip_cache, query) { state.port = port; state.selector = selector; set_address(); - set_status(format('%s %s:%s %s', type_map[type], host, port, selector)); return fn; } @@ -213,8 +247,12 @@ function go_history() { print_document(false); if (loc.type != '1' && loc.type != '7') return; lowlight(state.doc[state.item], state.item); - state.item = loc.item; - state.history[state.history_idx].item = loc.item; + if (loc.item < 0) { + next_link(); + } else { + state.item = loc.item; + state.history[state.history_idx].item = loc.item; + } highlight(state.doc[state.item], state.item); scrollbox.scroll_into_view(state.item); } @@ -340,6 +378,7 @@ function print_document(auto_highlight) { } else if (['4', '5', '9', 'g', 'I'].indexOf(state.item_type) > -1) { console.clear(BG_BLACK|LIGHTGRAY); bbs.send_file(state.fn); + file_remove(state.fn); reset_display(); go_back(); } @@ -374,8 +413,13 @@ function main() { break; // Select current item case '\r': - if ((state.item_type == '1' || state.item_type == '7') && ['0', '1', '4', '5', '6', '9', 'g', 'I'].indexOf(state.doc[state.item].type) > -1) { + // Fetch a potentially-cached text file or directory listing + if ((state.item_type == '1' || state.item_type == '7') && ['0', '1', '6'].indexOf(state.doc[state.item].type) > -1) { go_get(state.doc[state.item].host, state.doc[state.item].port, state.doc[state.item].selector, state.doc[state.item].type); + // Fetch a downloadable type, don't bother checking the cache + } else if ((state.item_type == '1' || state.item_type == '7') && ['4', '5', '9', 'g', 'I'].indexOf(state.doc[state.item].type) > -1) { + go_get(state.doc[state.item].host, state.doc[state.item].port, state.doc[state.item].selector, state.doc[state.item].type, false, true); + // Prompt for a query and then submit it to this index-search selector } else if (state.item_type == '1' && state.doc[state.item].type == '7') { var query = get_query(); if (query && query.length) {