Skip to content

Commit

Permalink
check hash before saving
Browse files Browse the repository at this point in the history
  • Loading branch information
hzrd149 committed Feb 20, 2024
1 parent ea33d99 commit 931acae
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 44 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Blossom-server
# 🌸 Blossom-server

Generic blob storage and retrieval for nostr
Blobs stored simply on mediaservers
4 changes: 2 additions & 2 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<title>Blossom-server</title>
</head>
<body>
<h1>Blossom-server</h1>
<p>Generic blob storage and retrieval for nostr</p>
<h1>🌸 Blossom-server</h1>
<p>Blobs stored simply on mediaservers</p>

<h2>Get:</h2>
<code>GET /b91dfd7565edb9382a5537b80bd5f24c6cbe9aee693abcdb7448098f1e8c608b.png</code>
Expand Down
10 changes: 6 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ async function handlePointers(ctx: Koa.ParameterizedContext, pointers: BlobPoint
const pass = (ctx.body = new PassThrough());
stream.pipe(pass);

fileStorage.saveFile(pointer.hash, stream, pointer.metadata);
fileStorage.saveFile(pointer.hash, stream, pointer.metadata).catch((e) => {});
return true;
}
} catch (e) {}
Expand Down Expand Up @@ -238,9 +238,11 @@ router.get("/:hash", async (ctx, next) => {
if (search.ext) ctx.type = search.ext;
const pass = (ctx.body = new PassThrough());
cdnSource.pipe(pass);
fileStorage.saveFile(hash, cdnSource, {
mimeType: ext ? mime.getType(ext) ?? undefined : undefined,
});
fileStorage
.saveFile(hash, cdnSource, {
mimeType: ext ? mime.getType(ext) ?? undefined : undefined,
})
.catch((e) => {});
}
}

Expand Down
85 changes: 49 additions & 36 deletions src/storage/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import path from "node:path";
import { tmpdir } from "node:os";
import dayjs from "dayjs";
import { Readable } from "node:stream";
import { createHash } from "node:crypto";
import mime from "mime";

import { BlobSearch, FilePointer, PointerMetadata } from "../types.js";
Expand Down Expand Up @@ -33,46 +34,58 @@ export async function readFilePointer(pointer: FilePointer) {
}

const saving = new Set();
export async function saveFile(hash: string, stream: Readable, metadata?: PointerMetadata) {
if (files.some((f) => f.startsWith(hash))) return;
if (saving.has(hash)) return;
log("Saving file", hash);
saving.add(hash);

const tmpFile = path.join(tmpDir, hash);
stream.pipe(fs.createWriteStream(tmpFile));
stream.on("end", async () => {
log("Downloaded", hash);
const size = (await pfs.stat(tmpFile)).size;
let mimeType = metadata?.mimeType;
const type = await fileTypeFromFile(tmpFile);
if (type) {
log("Detected type", type.mime);
mimeType = type.mime;
}
export function saveFile(hash: string, stream: Readable, metadata?: PointerMetadata) {
return new Promise<void>((resolve, reject) => {
if (files.some((f) => f.startsWith(hash))) return;
if (saving.has(hash)) return;
log("Downloading file", hash);
saving.add(hash);

const rule = getFileRule(
{
mimeType,
pubkey: metadata?.pubkey,
},
config.cache.rules,
);
if (!rule) {
await pfs.rm(tmpFile);
return;
}
const sha256 = createHash("sha256");
stream.pipe(sha256);

const tmpFile = path.join(tmpDir, hash);
stream.pipe(fs.createWriteStream(tmpFile));
stream.on("end", async () => {
const digest = sha256.digest("hex");
if (digest !== hash) {
log("Expected", hash, "got", digest);
return reject(new Error("Hash mismatch"));
}

log("Downloaded", hash);
const size = (await pfs.stat(tmpFile)).size;
let mimeType = metadata?.mimeType;
const type = await fileTypeFromFile(tmpFile);
if (type) {
log("Detected type", type.mime);
mimeType = type.mime;
}

const rule = getFileRule(
{
mimeType,
pubkey: metadata?.pubkey,
},
config.cache.rules,
);
if (!rule) {
await pfs.rm(tmpFile);
return;
}

log("Found rule:", rule.expiration);

log("Found rule:", rule.expiration);
// TODO: verify hash
const filename = await saveTempFile(hash, tmpFile, mimeType);
saving.delete(hash);
log("Moved file to data dir", path.join(DATA_DIR, filename));

const filename = await saveTempFile(hash, tmpFile, mimeType);
saving.delete(hash);
log("Moved file to data dir", path.join(DATA_DIR, filename));
setBlobExpiration(hash, getExpirationTime(rule));
setBlobSize(hash, size);
if (mimeType) setBlobMimetype(hash, mimeType);

setBlobExpiration(hash, getExpirationTime(rule));
setBlobSize(hash, size);
if (mimeType) setBlobMimetype(hash, mimeType);
resolve();
});
});
}

Expand Down

0 comments on commit 931acae

Please sign in to comment.