#include #include #include #include #include #include #include #include static HttpClientContext * TryDownload(ParseeData *data, char *server, char *identi) { HttpClientContext *cctx; char *path; server = HttpUrlEncode(server); identi = HttpUrlEncode(identi); path = StrConcat(4, "/_matrix/media/v3/download/", server, "/", identi); cctx = ParseeCreateRequest(data->config, HTTP_GET, path); ASAuthenticateRequest(data->config, cctx); Free(path); HttpRequestSendHeaders(cctx); if (HttpRequestSend(cctx) != HTTP_OK) { Log(LOG_WARNING, "Failing back."); HttpClientContextFree(cctx); path = StrConcat(4, "/_matrix/client/v1/media/download/", server, "/", identi); cctx = ParseeCreateRequest(data->config, HTTP_GET, path); ASAuthenticateRequest(data->config, cctx); Free(path); HttpRequestSendHeaders(cctx); HttpRequestSend(cctx); } Free(server); Free(identi); return cctx; } RouteHead(RouteMedia, arr, argp) { ParseeHttpArg *args = argp; HttpClientContext *cctx; HashMap *reqh, *params; char *server = ArrayGet(arr, 0); char *identi = ArrayGet(arr, 1); char *path, *key, *val; char *hmac, *chkmak = NULL; params = HttpRequestParams(args->ctx); hmac = HashMapGet(params, "hmac"); /* TODO: Make it check the DB for its validicity. "Purging" would be * useful, alongside checking if someone isn't just a little idiotic. */ { char *concat = StrConcat(3, server, "/", identi); chkmak = ParseeHMACS(args->data->id, concat); Free(concat); } if (!server || !identi || !hmac || !StrEquals(hmac, chkmak)) { char *err = hmac && StrEquals(hmac, chkmak) ? "No server/identifier/HMAC code" : "Hah! You _dirty_ little liar! Try a little harder!"; Free(chkmak); HttpResponseStatus(args->ctx, HTTP_BAD_REQUEST); return MatrixCreateError("M_NOT_YET_UPLOADED", err); } Free(chkmak); /* Proxy the media through an authenticated endpoint if the HMAC * is valid. */ cctx = TryDownload(args->data, server, identi); reqh = HttpResponseHeaders(cctx); while (HashMapIterate(reqh, &key, (void **) &val)) { HttpResponseHeader(args->ctx, key, val); } HttpSendHeaders(args->ctx); if (HttpRequestMethodGet(args->ctx) != HTTP_HEAD) { StreamCopy(HttpClientStream(cctx), HttpServerStream(args->ctx)); } HttpClientContextFree(cctx); return NULL; }