Files
ginxsom/include/ginxsom.h
2025-08-18 17:42:51 -04:00

150 lines
4.8 KiB
C

#ifndef GINXSOM_H
#define GINXSOM_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcgi_stdio.h>
#include <sqlite3.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>
/* 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 */