221 lines
4.5 KiB
C
221 lines
4.5 KiB
C
/* full of jank */
|
|
#include <string.h>
|
|
#include <skalibs/env.h>
|
|
#include <skalibs/allreadwrite.h>
|
|
#include <skalibs/unix-transactional.h>
|
|
#include <skalibs/stralloc.h>
|
|
#include <skalibs/bytestr.h>
|
|
#include <skalibs/buffer.h>
|
|
#include <skalibs/skamisc.h>
|
|
#include <skalibs/strerr.h>
|
|
#include <skalibs/djbunix.h>
|
|
#include <skalibs/exec.h>
|
|
|
|
#include "pdjson.h"
|
|
|
|
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
|
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
|
|
|
#define USAGE "mvwtc id"
|
|
#define HTTPOK "HTTP/1.1 200 OK"
|
|
|
|
void
|
|
url_hpn(stralloc *url, stralloc *host, stralloc *path, stralloc *name)
|
|
{
|
|
char *afterscheme;
|
|
size_t urli, eohost, lastslash;
|
|
|
|
urli = byte_chr(url->s, url->len, '/');
|
|
urli += 2;
|
|
|
|
afterscheme = url->s + urli;
|
|
eohost = byte_chr(url->s + urli, url->len - urli, '/');
|
|
stralloc_catb(host, url->s + urli, eohost);
|
|
stralloc_0(host);
|
|
|
|
stralloc_cats(path, url->s + urli + eohost);
|
|
stralloc_0(host);
|
|
|
|
lastslash = byte_rchr(url->s, url->len, '/');
|
|
stralloc_cats(name, url->s + lastslash + 1);
|
|
stralloc_0(host);
|
|
}
|
|
|
|
/* '\n' → '\0' */
|
|
void
|
|
sa_nltoz(stralloc *sa)
|
|
{
|
|
size_t idx;
|
|
|
|
idx = byte_chr(sa->s, sa->len, '\n');
|
|
if (idx < sa->len) {
|
|
sa->s[idx] = '\0';
|
|
sa->len = idx;
|
|
}
|
|
}
|
|
|
|
/* '\0' → '\n' */
|
|
void
|
|
sa_ztonl(stralloc *sa)
|
|
{
|
|
size_t idx;
|
|
|
|
idx = byte_chr(sa->s, sa->len, '\0');
|
|
if (idx < sa->len) {
|
|
sa->s[idx] = '\n';
|
|
sa->len = idx + 1;
|
|
}
|
|
}
|
|
|
|
/* img url in sa → url */
|
|
int
|
|
imgpath(stralloc *url, stralloc *sa)
|
|
{
|
|
json_stream j;
|
|
enum json_type t;
|
|
const char *key, *val;
|
|
|
|
json_open_buffer(&j, sa->s, sa->len);
|
|
json_set_streaming(&j, 0);
|
|
|
|
t = json_next(&j);
|
|
if (t != JSON_OBJECT) {
|
|
json_close(&j);
|
|
return -1;
|
|
}
|
|
|
|
while ((t = json_next(&j)) != JSON_DONE) {
|
|
switch (t) {
|
|
case JSON_STRING:
|
|
key = json_get_string(&j, NULL);
|
|
if (!strncmp(key, "post_url", MIN(strlen(key),
|
|
strlen("post_url")))) {
|
|
/* i'm not sure why there need to be two of these */
|
|
t = json_next(&j);
|
|
t = json_next(&j);
|
|
val = json_get_string(&j, NULL);
|
|
url->len = 0;
|
|
stralloc_cats(url, val);
|
|
stralloc_0(url);
|
|
return 0;
|
|
}
|
|
break;
|
|
case JSON_OBJECT_END:
|
|
goto done;
|
|
break;
|
|
}
|
|
}
|
|
done:
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
http_recv(int fd, stralloc *sa)
|
|
{
|
|
char obuf[BUFFER_INSIZE];
|
|
buffer outb = BUFFER_INIT(&buffer_read, fd, obuf, BUFFER_INSIZE);
|
|
if (skagetln(&outb, sa, '\n') < 0)
|
|
return -1;
|
|
if (sa->len < sizeof(HTTPOK) || !strncmp(sa->s, HTTPOK, sizeof(HTTPOK)))
|
|
return -1;
|
|
sa->len = 0;
|
|
|
|
/* skip to the end of the header */
|
|
for (;;) {
|
|
if (skagetln(&outb, sa, '\n') < 0)
|
|
return -1;
|
|
if (!strncmp(sa->s, "\r\n", 2)) {
|
|
break;
|
|
}
|
|
sa->len = 0;
|
|
}
|
|
|
|
sa->len = 0;
|
|
skagetln(&outb, sa, '\n');
|
|
// todo handle fuckery here
|
|
stralloc_0(sa);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
http_send(int fd, char *id)
|
|
{
|
|
char buf[BUFFER_OUTSIZE];
|
|
|
|
buffer b = BUFFER_INIT(&buffer_write, fd, buf, BUFFER_OUTSIZE);
|
|
|
|
buffer_putsnoflush(&b, "GET /api/links/");
|
|
buffer_putsnoflush(&b, id);
|
|
buffer_putsnoflush(&b, ".json HTTP/1.0\r\n");
|
|
buffer_putsnoflush(&b, "Host: walltaker.joi.how\r\n");
|
|
buffer_putsnoflush(&b, "Connection: close\r\n");
|
|
buffer_putsnoflush(&b, "User-Agent: mvwt\r\n\r\n");
|
|
buffer_flush(&b);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
stralloc resp = STRALLOC_ZERO;
|
|
stralloc img = STRALLOC_ZERO;
|
|
stralloc currentimg = STRALLOC_ZERO;
|
|
stralloc tmp = STRALLOC_ZERO;
|
|
stralloc imhost = STRALLOC_ZERO;
|
|
stralloc impath = STRALLOC_ZERO;
|
|
stralloc imfile = STRALLOC_ZERO;
|
|
PROG = "mvwtc";
|
|
|
|
if (argc != 2)
|
|
strerr_dieusage(100, USAGE);
|
|
|
|
if (http_send(7, argv[1]) < 0)
|
|
strerr_diefu(111, "send http request");
|
|
if (http_recv(6, &resp) < 0) {
|
|
stralloc_free(&resp);
|
|
strerr_diefu(111, "recieve http response");
|
|
}
|
|
fd_shutdown(7, 1);
|
|
fd_close(7);
|
|
fd_shutdown(6, 0);
|
|
fd_close(6);
|
|
|
|
if (imgpath(&img, &resp) < 0) {
|
|
stralloc_free(&img);
|
|
stralloc_free(&resp);
|
|
strerr_dief(111, "json seems mangled");
|
|
}
|
|
stralloc_free(&resp);
|
|
|
|
if (opengetlnclose("current", ¤timg, '\n') >= 0) {
|
|
sa_nltoz(¤timg);
|
|
if (!strncmp(currentimg.s, img.s,
|
|
MIN(currentimg.len, img.len))) {
|
|
/* we don't need to do anything, just exit */
|
|
stralloc_free(¤timg);
|
|
stralloc_free(&img);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
stralloc_copy(&tmp, &img);
|
|
sa_ztonl(&tmp);
|
|
if (!openwritenclose_suffix6("current", tmp.s, tmp.len, NULL, 0, "~")) {
|
|
stralloc_free(&tmp);
|
|
stralloc_free(¤timg);
|
|
stralloc_free(&img);
|
|
strerr_diefu(111, "write to current");
|
|
}
|
|
stralloc_free(&tmp);
|
|
|
|
url_hpn(&img, &imhost, &impath, &imfile);
|
|
|
|
char const *wtimg_argv[] = { "s6-tlsclient", "-N", "--",
|
|
imhost.s, "443", "mvwtimg", imhost.s, impath.s, imfile.s, 0 };
|
|
|
|
xexec(wtimg_argv);
|
|
|
|
return 111;
|
|
}
|