|
|
|
|
@ -5,6 +5,7 @@
|
|
|
|
|
#include "../../lib/u_async.h" |
|
|
|
|
#include <string.h> |
|
|
|
|
#include <stdio.h> |
|
|
|
|
#include <ctype.h> |
|
|
|
|
#include <openssl/rand.h> |
|
|
|
|
#include <openssl/sha.h> |
|
|
|
|
|
|
|
|
|
@ -14,6 +15,13 @@
|
|
|
|
|
#define RECEIPT_TB 1200000ULL |
|
|
|
|
#define STORE_USERS 256 |
|
|
|
|
|
|
|
|
|
// Windows сравнивает имена без регистра; алиас не должен обходить неизменяемость avatars.
|
|
|
|
|
static int store_avatar_namespace(const char* path) { |
|
|
|
|
const char name[] = "avatars"; |
|
|
|
|
for (unsigned i = 0; i < sizeof(name) - 1; i++) if (tolower((unsigned char)path[i]) != name[i]) return 0; |
|
|
|
|
return !path[7] || path[7] == '/'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct store_file { char path[MF_PATH_MAX + 80]; int fd; uint64_t touched; }; |
|
|
|
|
struct store_user { struct store_user* next; uint64_t owner, used, reserved, files, directories; int valid; }; |
|
|
|
|
struct store_upload { |
|
|
|
|
@ -383,8 +391,9 @@ static int store_begin(struct mf_storage* s, uint64_t group, uint64_t peer, cons
|
|
|
|
|
static int store_command(struct mf_storage* s, uint64_t group, uint64_t peer, const struct mf_message* q, struct mf_message* r) { |
|
|
|
|
if (!mf_path_valid(q->path, q->command == MF_LIST || q->command == MF_STAT || q->command == MF_QUOTA) || |
|
|
|
|
(q->command == MF_RENAME && !mf_path_valid(q->target, 0))) return MF_INVALID_PATH; |
|
|
|
|
if (q->command == MF_RENAME && (!strcmp(q->path, "avatars") || !strncmp(q->path, "avatars/", 8) || |
|
|
|
|
!strcmp(q->target, "avatars") || !strncmp(q->target, "avatars/", 8))) return MF_INVALID_PATH; |
|
|
|
|
if (store_avatar_namespace(q->path) && strcmp(q->path, "avatars") && |
|
|
|
|
(strncmp(q->path, "avatars/", 8) || !mf_avatar_file_valid(q->path + 8))) return MF_INVALID_PATH; |
|
|
|
|
if (q->command == MF_RENAME && (store_avatar_namespace(q->path) || store_avatar_namespace(q->target))) return MF_INVALID_PATH; |
|
|
|
|
char path[MF_PATH_MAX + 80]; |
|
|
|
|
snprintf(path, sizeof(path), "%llu/%llu%s%s", (unsigned long long)group, (unsigned long long)q->owner, *q->path ? "/" : "", q->path); |
|
|
|
|
struct mf_disk_info info = {0}; |
|
|
|
|
|