1
0
Fork 0
mirror of https://git.sr.ht/~sircmpwn/gmni synced 2024-04-16 13:13:46 +02:00

Add 'd' to download page

This commit is contained in:
Eyal Sawady 2020-10-20 12:55:39 -04:00 committed by Drew DeVault
parent 9ddd5c16da
commit fa78663748
6 changed files with 87 additions and 2 deletions

View File

@ -68,3 +68,7 @@ performed with the user's input supplied to the server.
Suppress the input prompt if the server requests an input, and instead
print a diagnostic message and exit with a zero (successful) status
code.
*-o* _path_
Write output to _path_. If _path_ ends with a '/', the basename of the URL
will be appended. If _path_ is the empty string, "./" will be presumed.

View File

@ -8,5 +8,7 @@ struct pathspec {
char *getpath(const struct pathspec *paths, size_t npaths);
int mkdirs(char *path, mode_t mode);
int download_resp(FILE *out, struct gemini_response resp, const char *path,
char *url);
#endif

View File

@ -14,6 +14,7 @@
#include <unistd.h>
#include "gmni.h"
#include "tofu.h"
#include "util.h"
static void
usage(const char *argv_0)
@ -125,6 +126,8 @@ main(int argc, char *argv[])
enum input_mode input_mode = INPUT_READ;
FILE *input_source = stdin;
char *output_file = NULL;
bool follow_redirects = false, linefeed = true;
int max_redirect = 5;
@ -136,7 +139,7 @@ main(int argc, char *argv[])
cfg.action = TOFU_ASK;
int c;
while ((c = getopt(argc, argv, "46d:D:E:hj:lLiINR:")) != -1) {
while ((c = getopt(argc, argv, "46d:D:E:hj:lLiINR:o:")) != -1) {
switch (c) {
case '4':
hints.ai_family = AF_INET;
@ -204,6 +207,9 @@ main(int argc, char *argv[])
return 1;
}
break;
case 'o':
output_file = optarg;
break;
default:
fprintf(stderr, "fatal: unknown flag %c\n", c);
return 1;
@ -304,6 +310,11 @@ main(int argc, char *argv[])
break;
}
if (output_file != NULL) {
ret = download_resp(stderr, resp, output_file, url);
break;
}
char last;
char buf[BUFSIZ];
for (int n = 1; n > 0;) {

View File

@ -78,6 +78,7 @@ const char *help_msg =
"m\tSave bookmark\n"
"M\tBrowse bookmarks\n"
"r\tReload the page\n"
"d <path>\tDownload page to <path>\n"
"\n"
"Other commands include:\n\n"
"<Enter>\tread more lines\n"
@ -553,6 +554,24 @@ do_prompts(const char *prompt, struct browser *browser)
? strchr(browser->meta, ';') : NULL);
result = PROMPT_AGAIN;
goto exit;
case 'd':
if (in[1] != '\0' && !isspace(in[1])) break;
struct gemini_response resp;
char url[1024] = {0};
strncpy(&url[0], browser->plain_url, sizeof(url));
// XXX: may affect history, do we care?
enum gemini_result res = do_requests(browser, &resp);
if (res != GEMINI_OK) {
fprintf(stderr, "Error: %s\n",
gemini_strerr(res, &resp));
result = PROMPT_AGAIN;
goto exit;
}
set_url(browser, url, NULL);
download_resp(browser->tty, resp, trim_ws(&in[1]), url);
gemini_response_finish(&resp);
result = PROMPT_AGAIN;
goto exit;
case '?':
if (in[1]) break;
fprintf(browser->tty, "%s", help_msg);
@ -849,7 +868,9 @@ display_response(struct browser *browser, struct gemini_response *resp)
if (strncmp(resp->meta, "text/", 5) == 0) {
return display_plaintext(browser, resp);
}
assert(0); // TODO: Deal with other mimetypes
fprintf(stderr, "Media type %s is unsupported, use \"d <path>\" to download this page\n",
resp->meta);
return false;
}
static enum tofu_action

View File

@ -10,6 +10,7 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "gmni.h"
#include "tofu.h"
#include "util.h"

View File

@ -2,9 +2,12 @@
#include <errno.h>
#include <libgen.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "gmni.h"
#include "util.h"
static void
@ -60,3 +63,46 @@ getpath(const struct pathspec *paths, size_t npaths) {
}
return NULL;
}
int
download_resp(FILE *out, struct gemini_response resp, const char *path,
char *url)
{
char buf[PATH_MAX];
assert(path);
if (path[0] == '\0') {
path = "./";
}
if (path[strlen(path)-1] == '/') {
strncat(strncpy(&buf[0], path, sizeof(buf)), basename(url),
sizeof(buf));
path = &buf[0];
}
FILE *f = fopen(path, "w");
if (f == NULL) {
fprintf(stderr, "Could not open %s for writing: %s\n",
path, strerror(errno));
return 1;
}
fprintf(out, "Downloading %s to %s\n", url, path);
for (int n = 1; n > 0;) {
n = BIO_read(resp.bio, buf, BUFSIZ);
if (n == -1) {
fprintf(stderr, "Error: read\n");
return 1;
}
ssize_t w = 0;
while (w < (ssize_t)n) {
ssize_t x = fwrite(&buf[w], 1, n - w, f);
if (ferror(f)) {
fprintf(stderr, "Error: write: %s\n",
strerror(errno));
return 1;
}
w += x;
}
}
fprintf(out, "Finished download\n");
fclose(f);
return 0;
}