#ifndef GINXSOM_H #define GINXSOM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Constants */ #define GINXSOM_VERSION "0.1.0" #define MAX_PATH_LEN 4096 #define MAX_CONFIG_LINE 1024 #define SHA256_HEX_LEN 64 #define SHA256_DIGEST_LEN 32 #define MAX_PUBKEY_HEX_LEN 64 #define MAX_MIME_TYPE_LEN 128 #define MAX_FILENAME_LEN 256 #define MAX_CONTENT_LEN 1024 #define DEFAULT_MAX_FILE_SIZE (100 * 1024 * 1024) // 100MB #define DEFAULT_MAX_BLOBS_PER_USER 1000 #define DEFAULT_RATE_LIMIT 10 /* Error codes */ typedef enum { GINXSOM_OK = 0, GINXSOM_ERROR = -1, GINXSOM_ERROR_CONFIG = -2, GINXSOM_ERROR_DB = -3, GINXSOM_ERROR_AUTH = -4, GINXSOM_ERROR_STORAGE = -5, GINXSOM_ERROR_MEMORY = -6, GINXSOM_ERROR_INVALID_REQUEST = -7, GINXSOM_ERROR_FILE_TOO_LARGE = -8, GINXSOM_ERROR_RATE_LIMIT = -9, GINXSOM_ERROR_NOT_FOUND = -10 } ginxsom_error_t; /* Configuration structure */ typedef struct { char socket_path[MAX_PATH_LEN]; size_t max_file_size; char storage_path[MAX_PATH_LEN]; char database_path[MAX_PATH_LEN]; bool require_auth_upload; bool require_auth_get; bool require_auth_list; int max_blobs_per_user; int rate_limit_uploads; } ginxsom_config_t; /* Blob descriptor structure */ typedef struct { char sha256[SHA256_HEX_LEN + 1]; char pubkey[MAX_PUBKEY_HEX_LEN + 1]; size_t size; char mime_type[MAX_MIME_TYPE_LEN]; time_t uploaded; char filename[MAX_FILENAME_LEN]; } ginxsom_blob_t; /* Nostr event structure */ typedef struct { char id[SHA256_HEX_LEN + 1]; char pubkey[MAX_PUBKEY_HEX_LEN + 1]; int kind; char content[MAX_CONTENT_LEN]; time_t created_at; time_t expiration; char verb[16]; // t tag value: get, upload, list, delete char x_hashes[10][SHA256_HEX_LEN + 1]; // x tag values (up to 10) int x_count; char server[MAX_PATH_LEN]; // server tag value char signature[128]; } nostr_event_t; /* FastCGI context structure */ typedef struct { ginxsom_config_t config; sqlite3 *db; char *request_method; char *request_uri; char *content_type; char *content_length_str; size_t content_length; char *authorization; } ginxsom_context_t; /* Function declarations */ /* config.c */ int ginxsom_load_config(const char *config_path, ginxsom_config_t *config); void ginxsom_config_init_defaults(ginxsom_config_t *config); /* database.c */ int ginxsom_db_init(sqlite3 **db, const char *db_path); int ginxsom_db_close(sqlite3 *db); int ginxsom_db_store_blob(sqlite3 *db, const ginxsom_blob_t *blob); int ginxsom_db_delete_blob(sqlite3 *db, const char *sha256, const char *pubkey); int ginxsom_db_list_blobs(sqlite3 *db, const char *pubkey, ginxsom_blob_t **blobs, int *count); int ginxsom_db_blob_exists(sqlite3 *db, const char *sha256); int ginxsom_db_get_user_blob_count(sqlite3 *db, const char *pubkey); /* auth.c */ int ginxsom_parse_auth_header(const char *auth_header, nostr_event_t *event); int ginxsom_verify_nostr_event(const nostr_event_t *event); int ginxsom_validate_auth_for_upload(const nostr_event_t *event, const char *sha256); int ginxsom_validate_auth_for_delete(const nostr_event_t *event, const char *sha256); int ginxsom_validate_auth_for_list(const nostr_event_t *event); /* storage.c */ int ginxsom_store_blob(const char *storage_path, const char *sha256, const char *data, size_t size, const char *mime_type); int ginxsom_delete_blob(const char *storage_path, const char *sha256); char *ginxsom_detect_mime_type(const char *data, size_t size); int ginxsom_calculate_sha256(const char *data, size_t size, char *sha256_hex); /* server.c */ int ginxsom_handle_upload(ginxsom_context_t *ctx); int ginxsom_handle_upload_head(ginxsom_context_t *ctx); int ginxsom_handle_list(ginxsom_context_t *ctx, const char *pubkey); int ginxsom_handle_delete(ginxsom_context_t *ctx, const char *sha256); void ginxsom_send_response(int status, const char *content_type, const char *body, size_t body_len); void ginxsom_send_error(int status, const char *reason); /* utils.c */ char *ginxsom_read_request_body(size_t content_length); int ginxsom_hex_to_bytes(const char *hex, unsigned char *bytes, size_t bytes_len); void ginxsom_bytes_to_hex(const unsigned char *bytes, size_t bytes_len, char *hex); int ginxsom_parse_query_params(const char *query_string, char *params[][2], int max_params); char *ginxsom_url_decode(const char *encoded); int ginxsom_create_directory(const char *path); #endif /* GINXSOM_H */