diff --git a/src/app/api/fever/route.ts b/src/app/api/fever/route.ts index 3c45bc3..09d6ced 100644 --- a/src/app/api/fever/route.ts +++ b/src/app/api/fever/route.ts @@ -16,6 +16,7 @@ const secs = (d: Date | null | undefined) => (d ? Math.floor(d.getTime() / 1000) async function params(request: Request) { const url = new URL(request.url); const all = new URLSearchParams(url.search); + for (const key of [...all.keys()]) if (key.toLowerCase() === "api_key") all.delete(key); if (request.method === "POST") { const type = request.headers.get("content-type") ?? ""; const body = type.includes("multipart/form-data") @@ -144,7 +145,7 @@ async function handle(request: Request) { if (!user) return Response.json(base); await ensureMissingRefs(user.id); - if (p.has("mark")) await mark(user, p); + if (request.method === "POST" && p.has("mark")) await mark(user, p); const subs = await subscriptionsOf(user.id); const body: Record = { diff --git a/src/lib/api/greader.ts b/src/lib/api/greader.ts index 825c113..8314296 100644 --- a/src/lib/api/greader.ts +++ b/src/lib/api/greader.ts @@ -37,8 +37,23 @@ export function parseItemId(raw: string): number | null { return Number.isSafeInteger(n) && n > 0 ? n : null; } +function stripKey(params: URLSearchParams, name: string) { + for (const key of [...params.keys()]) if (key.toLowerCase() === name) params.delete(key); +} + +async function readPostBody(request: Request) { + if (request.method !== "POST") return new URLSearchParams(); + const type = request.headers.get("content-type") ?? ""; + const entries = type.includes("multipart/form-data") + ? [...(await request.formData()).entries()].map(([k, v]) => [k, String(v)] as [string, string]) + : [...new URLSearchParams(await request.text())]; + return new URLSearchParams(entries); +} + async function readParams(request: Request) { const params = new URLSearchParams(new URL(request.url).search); + // A senha de aplicativo não pode ir na query: ela cai em log, histórico e Referer. + stripKey(params, "passwd"); if (request.method === "POST") { const type = request.headers.get("content-type") ?? ""; const body = type.includes("multipart/form-data") @@ -324,7 +339,8 @@ async function streamContents(user: ApiUser, p: URLSearchParams, stream: string) export async function handleGReader(request: Request, path: string): Promise { if (path === "accounts/ClientLogin") { - const p = await readParams(request); + if (request.method !== "POST") return unauthorized(); + const p = await readPostBody(request); const password = p.get("Passwd"); const user = await userFromAppPassword(password); if (!user || user.email.toLowerCase() !== (p.get("Email") ?? "").trim().toLowerCase()) return unauthorized();