Browse Source

Allow immutable avatar originals and manifests in storage

master
evgeny 6 days ago
parent
commit
50efddd5f0
  1. 12
      src/member_files/protocol.c
  2. 4
      src/member_files/protocol.h
  3. 5
      src/member_files/storage.c

12
src/member_files/protocol.c

@ -4,11 +4,21 @@
#include <ctype.h>
int mf_avatar_file_valid(const char* file) {
if (!file || strlen(file) != 68 || strcmp(file + 64, ".png")) return 0;
if (!file || strlen(file) < 68 || strlen(file) > 69) return 0;
const char* suffix = file + 64;
if (strcmp(suffix, ".png") && strcmp(suffix, ".jpg") && strcmp(suffix, ".webp") && strcmp(suffix, ".json")) return 0;
for (unsigned i = 0; i < 64; i++) if (!((file[i] >= '0' && file[i] <= '9') || (file[i] >= 'a' && file[i] <= 'f'))) return 0;
return 1;
}
int mf_avatar_manifest_valid(const char* file) { return mf_avatar_file_valid(file) && !strcmp(file + 64, ".json"); }
/* Раздельные пределы метаданных и изображений; фактический хеш проверяет COMMIT. */
uint64_t mf_avatar_file_limit(const char* file) {
if (!mf_avatar_file_valid(file)) return 0;
return mf_avatar_manifest_valid(file) ? MF_AVATAR_MANIFEST_MAX_BYTES : MF_AVATAR_ORIGINAL_MAX_BYTES;
}
uint64_t mf_get64(const uint8_t* p) {
uint64_t v = 0;
for (unsigned i = 0; i < 8; i++) v |= (uint64_t)p[i] << (8 * i);

4
src/member_files/protocol.h

@ -23,7 +23,11 @@ extern "C" {
#define MF_ENTRY_HEADER 35
#define MF_QUOTA_BYTES 40 /* used/limit/reserved в байтах, files/directories; пять u64 LE */
#define MF_AVATAR_MAX_BYTES (1024 * 1024)
#define MF_AVATAR_ORIGINAL_MAX_BYTES (32 * 1024 * 1024)
#define MF_AVATAR_MANIFEST_MAX_BYTES 4096
int mf_avatar_file_valid(const char* file);
int mf_avatar_manifest_valid(const char* file);
uint64_t mf_avatar_file_limit(const char* file);
#define MF_IDLE_TB 100000ULL /* 10 секунд */
#define MF_REQUEST 1
#define MF_RESPONSE 2

5
src/member_files/storage.c

@ -326,7 +326,10 @@ static struct store_upload* store_upload_find(struct mf_storage* s, uint64_t gro
static int store_begin(struct mf_storage* s, uint64_t group, uint64_t peer, const char* path, const struct mf_message* q) {
if (q->size > INT64_MAX || mf_zero(q->upload, 16)) return MF_INVALID_RANGE;
if (!strncmp(q->path, "avatars/", 8)) {
if (!mf_avatar_file_valid(q->path + 8) || !q->size || q->size > MF_AVATAR_MAX_BYTES) return MF_INVALID_RANGE;
if (!q->size || q->size > mf_avatar_file_limit(q->path + 8)) {
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "avatar: invalid object path=%s bytes=%llu", q->path, (unsigned long long)q->size);
return MF_INVALID_RANGE;
}
if (!mf_zero(q->version, 16)) return MF_EXISTS;
char hash[65]; for (unsigned i = 0; i < 32; i++) snprintf(hash + i * 2, 3, "%02x", q->hash[i]);
if (strncmp(q->path + 8, hash, 64)) return MF_HASH_MISMATCH;

Loading…
Cancel
Save