mvwt/mvwtc.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", &currentimg, '\n') >= 0) {
sa_nltoz(&currentimg);
if (!strncmp(currentimg.s, img.s,
MIN(currentimg.len, img.len))) {
/* we don't need to do anything, just exit */
stralloc_free(&currentimg);
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(&currentimg);
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;
}