#include "log.h" #include "arena.h" #include "net.h" #include "sha1.h" #include "vector.h" #include #include #include #include /* for setlocale */ #include #include int main(void) { setlocale(LC_ALL, ""); /* TODO: make sure I don't regret this */ vl_log_setlevel(LOG_TRACE); vl_arena *arena = vl_arena_new(8192); vl_net_ensure_cached(arena, "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json", "manifest.json"); vl_arena_reset(arena); vl_net_ensure_cached(arena, "https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json", "runtime-manifest.json"); vl_arena_reset(arena); json_error_t err; json_t *manifest = json_load_file("manifest.json", 0, &err), *ver; size_t idx; if (!manifest) { vl_error("bad: %s", err.text); exit(EXIT_FAILURE); } json_t *versions = json_object_get(manifest, "versions"); json_array_foreach(versions, idx, ver) { const char *verid; const char *url; const char *sha1_hex; json_unpack(ver, "{s:s,s:s,s:s}", "id", &verid, "url", &url, "sha1", &sha1_hex); if (!strcmp(verid, "1.8.9") && url) { vl_sha1 hash; vl_sha1_decode(hash, sha1_hex); vl_net_ensure_verified(url, "1.8.9.json", VERIFY_SHA1, hash); } } json_decref(manifest); json_t *oneeightnine = json_load_file("1.8.9.json", 0, &err); if (!oneeightnine) { vl_error("bad ver: %s", err.text); exit(EXIT_FAILURE); } json_t *libs = json_object_get(oneeightnine, "libraries"), *lib; vl_vector *vec = vl_newvec(struct vl_download_job); json_array_foreach(libs, idx, lib) { const char *url; const char *path; json_int_t sz; const char *sha1hex; size_t sha1hexlen; struct vl_download_job tjob; if (json_unpack(lib, "{s:{s:{s:s,s:s,s:I,s:s%}}}", "downloads", "artifact", "url", &url, "path", &path, "size", &sz, "sha1", &sha1hex, &sha1hexlen) < 0) { continue; } path = basename(vl_arena_strdup(arena, path)); tjob.url = url; tjob.opath = path; tjob.expect_len = (size_t)sz; if (sha1hexlen != VL_SHA1_DIGEST_HEX_STRLEN || vl_sha1_decode(tjob.expect_hash, sha1hex) < 0) { vl_error("bad expect hash %s", sha1hex); continue; } tjob.verify_flags = VERIFY_SIZE | VERIFY_SHA1; if (vl_net_verify(tjob.opath, VERIFY_SIZE | VERIFY_SHA1, tjob.expect_len, tjob.expect_hash) == NET_OK) { vl_trace("fine %s", tjob.opath); continue; } if (vl_vector_push(vec, &tjob) < 0) { abort(); } } size_t njobs; struct vl_download_job *jobs = vl_vector_values(vec, &njobs); printf("%d\n", vl_net_download_all(jobs, njobs, 8)); for (size_t n = 0; n < njobs; ++n) { printf("job %s status: %u\n", jobs[n].url, jobs[n].status); } json_decref(oneeightnine); vl_vector_free(vec); vl_arena_free(arena); return 0; }