refactored nginx.conf
This commit is contained in:
BIN
Trash/ginxsom.db
Normal file
BIN
Trash/ginxsom.db
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T10:34:57-04:00
|
||||
Random data: 52bea9fe68b05eeeee258ae97cdcf8d9e7abbc13e67d61f681927250daef6e56
|
||||
Timestamp: 2025-09-02T15:17:47-04:00
|
||||
Random data: 4e8fefec3104b88408f0c71a73e97ba176846747e5577334d42be314839a9bba
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
@@ -1 +0,0 @@
|
||||
This is a set file to test. Don't edit.
|
||||
@@ -1 +0,0 @@
|
||||
test data for debug
|
||||
@@ -1,6 +1,6 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T09:58:19-04:00
|
||||
Random data: faafb490d178139a95368b519dd836ef835b488da9324ab5387299654f294826
|
||||
Timestamp: 2025-09-02T14:22:55-04:00
|
||||
Random data: 952a584d8f3fc6b5e49b1dfabbf68d76385d6d51142aa07170c71897ea861c03
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T10:34:52-04:00
|
||||
Random data: 340fc3549683d7c208ffa373d5932551f9b2e53cc1a5713b55c934403d9640a2
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-09-02T12:45:42-04:00
|
||||
Random data: d29860f9b375c2f964dd3bcb4466fa018fe70ac6335b4ee79cec000c4f7de1e9
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 199 KiB |
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T10:10:05-04:00
|
||||
Random data: 0dbb5e8f50695faa4f8bc3a5369d21fca51c98fda6be69520a6bfe6160bd55ca
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-09-02T12:45:28-04:00
|
||||
Random data: 8d599bd3356624fcb782f832b8f03d9a53972b8472a1bdcac83eae353e722621
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-09-02T12:46:50-04:00
|
||||
Random data: 4f03071e8de671359cc9f2d4c868825c597601a3224c924c16ac63d31222595e
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T09:49:32-04:00
|
||||
Random data: 5fc993875e7b145b161463e2250f7b7d4be0428fca7a91a40a843b25d594eb2d
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T10:34:56-04:00
|
||||
Random data: 52e5fee5b2f73c73ed388c9df9f74c58117b5f93982c5e6202951fd9fd90b626
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T10:07:52-04:00
|
||||
Random data: f1690ecb249bb7499e997e47b515e0f067dc0fffa13f4265f497b87166799187
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1 +0,0 @@
|
||||
test
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-09-02T12:45:33-04:00
|
||||
Random data: 0d4dce455f8a7bdfb8bd1cc8e90c2546fcb71f0689c3774530adfa718014c905
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T10:11:22-04:00
|
||||
Random data: 97e6573bd31c5dd5dc1f3fd7ed6e7d94898959af435556879a648f83b62267e7
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T10:44:56-04:00
|
||||
Random data: 162b8c0930df1f600ddd936e99ecce0866ab82a436f545d2187ba56726f0df4f
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T09:23:37-04:00
|
||||
Random data: 91175d5c0a2465bb69dabfa79d822054cbc8c00cc05cc551b1ed69b5f619631a
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,7 +0,0 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T09:53:53-04:00
|
||||
Random data: e4170eb6a32ff51102a2e154ec96dd4c769b3033f92b2bdb68fe4b835ec42d8f
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
@@ -1,6 +1,6 @@
|
||||
Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-08-19T10:06:44-04:00
|
||||
Random data: a0100362b9eb683a4bf49f49b8b6597490142d2a2d2543e7d500f371f0a1f052
|
||||
Timestamp: 2025-09-02T13:59:11-04:00
|
||||
Random data: 77050ac92e48c47746e1d90541d99079e811c59fdd109491165b6d310ef8da76
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
Binary file not shown.
BIN
build/main.o
BIN
build/main.o
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
# Local Ginxsom Development Server Configuration
|
||||
# This configuration serves files directly from the local repo directory
|
||||
# Comprehensive Blossom Protocol Implementation
|
||||
|
||||
# Main context - specify error log here to override system default
|
||||
error_log logs/error.log debug;
|
||||
@@ -41,47 +41,206 @@ http {
|
||||
# Maximum upload size (adjust as needed)
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Security headers
|
||||
# Security headers (applied to all responses)
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
|
||||
# Delete blob endpoint - DELETE /<sha256> (must come first)
|
||||
location ~ "^/([a-f0-9]{64}).*$" {
|
||||
# Only handle DELETE method for this pattern
|
||||
if ($request_method != DELETE) {
|
||||
# Let other patterns handle non-DELETE requests for this path
|
||||
return 404;
|
||||
# 1. SPECIFIC ENDPOINTS (most specific first)
|
||||
|
||||
# PUT /upload (BUD-02) - File uploads
|
||||
location = /upload {
|
||||
if ($request_method !~ ^(PUT|HEAD)$) {
|
||||
return 405;
|
||||
}
|
||||
|
||||
# Pass to FastCGI application for processing
|
||||
include fastcgi_params;
|
||||
fastcgi_param QUERY_STRING $query_string;
|
||||
fastcgi_param REQUEST_METHOD $request_method;
|
||||
fastcgi_param CONTENT_TYPE $content_type;
|
||||
fastcgi_param CONTENT_LENGTH $content_length;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_param REQUEST_URI $request_uri;
|
||||
fastcgi_param DOCUMENT_URI $document_uri;
|
||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||
fastcgi_param REQUEST_SCHEME $scheme;
|
||||
fastcgi_param HTTPS $https if_not_empty;
|
||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||
fastcgi_param REMOTE_PORT $remote_port;
|
||||
fastcgi_param SERVER_ADDR $server_addr;
|
||||
fastcgi_param SERVER_PORT $server_port;
|
||||
fastcgi_param SERVER_NAME $server_name;
|
||||
fastcgi_param REDIRECT_STATUS 200;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
|
||||
fastcgi_pass fastcgi_backend;
|
||||
}
|
||||
|
||||
# Old working regex pattern - testing rollback
|
||||
# GET /list/<pubkey> (BUD-02) - List user's blobs
|
||||
location ~ "^/list/([a-f0-9]{64})$" {
|
||||
if ($request_method !~ ^(GET)$) {
|
||||
return 405;
|
||||
}
|
||||
fastcgi_param QUERY_STRING $query_string;
|
||||
fastcgi_param REQUEST_METHOD $request_method;
|
||||
fastcgi_param CONTENT_TYPE $content_type;
|
||||
fastcgi_param CONTENT_LENGTH $content_length;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_param REQUEST_URI $request_uri;
|
||||
fastcgi_param DOCUMENT_URI $document_uri;
|
||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||
fastcgi_param REQUEST_SCHEME $scheme;
|
||||
fastcgi_param HTTPS $https if_not_empty;
|
||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||
fastcgi_param REMOTE_PORT $remote_port;
|
||||
fastcgi_param SERVER_ADDR $server_addr;
|
||||
fastcgi_param SERVER_PORT $server_port;
|
||||
fastcgi_param SERVER_NAME $server_name;
|
||||
fastcgi_param REDIRECT_STATUS 200;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
|
||||
fastcgi_pass fastcgi_backend;
|
||||
}
|
||||
|
||||
# PUT /mirror (BUD-04) - Mirror content
|
||||
location = /mirror {
|
||||
if ($request_method !~ ^(PUT)$) {
|
||||
return 405;
|
||||
}
|
||||
fastcgi_param QUERY_STRING $query_string;
|
||||
fastcgi_param REQUEST_METHOD $request_method;
|
||||
fastcgi_param CONTENT_TYPE $content_type;
|
||||
fastcgi_param CONTENT_LENGTH $content_length;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_param REQUEST_URI $request_uri;
|
||||
fastcgi_param DOCUMENT_URI $document_uri;
|
||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||
fastcgi_param REQUEST_SCHEME $scheme;
|
||||
fastcgi_param HTTPS $https if_not_empty;
|
||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||
fastcgi_param REMOTE_PORT $remote_port;
|
||||
fastcgi_param SERVER_ADDR $server_addr;
|
||||
fastcgi_param SERVER_PORT $server_port;
|
||||
fastcgi_param SERVER_NAME $server_name;
|
||||
fastcgi_param REDIRECT_STATUS 200;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
|
||||
fastcgi_pass fastcgi_backend;
|
||||
}
|
||||
|
||||
# HEAD/PUT /media (BUD-05) - Media operations
|
||||
location = /media {
|
||||
if ($request_method !~ ^(HEAD|PUT)$) {
|
||||
return 405;
|
||||
}
|
||||
fastcgi_param QUERY_STRING $query_string;
|
||||
fastcgi_param REQUEST_METHOD $request_method;
|
||||
fastcgi_param CONTENT_TYPE $content_type;
|
||||
fastcgi_param CONTENT_LENGTH $content_length;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_param REQUEST_URI $request_uri;
|
||||
fastcgi_param DOCUMENT_URI $document_uri;
|
||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||
fastcgi_param REQUEST_SCHEME $scheme;
|
||||
fastcgi_param HTTPS $https if_not_empty;
|
||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||
fastcgi_param REMOTE_PORT $remote_port;
|
||||
fastcgi_param SERVER_ADDR $server_addr;
|
||||
fastcgi_param SERVER_PORT $server_port;
|
||||
fastcgi_param SERVER_NAME $server_name;
|
||||
fastcgi_param REDIRECT_STATUS 200;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
|
||||
fastcgi_pass fastcgi_backend;
|
||||
}
|
||||
|
||||
# PUT /report (BUD-09) - Report content
|
||||
location = /report {
|
||||
if ($request_method !~ ^(PUT)$) {
|
||||
return 405;
|
||||
}
|
||||
fastcgi_param QUERY_STRING $query_string;
|
||||
fastcgi_param REQUEST_METHOD $request_method;
|
||||
fastcgi_param CONTENT_TYPE $content_type;
|
||||
fastcgi_param CONTENT_LENGTH $content_length;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_param REQUEST_URI $request_uri;
|
||||
fastcgi_param DOCUMENT_URI $document_uri;
|
||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||
fastcgi_param REQUEST_SCHEME $scheme;
|
||||
fastcgi_param HTTPS $https if_not_empty;
|
||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||
fastcgi_param REMOTE_PORT $remote_port;
|
||||
fastcgi_param SERVER_ADDR $server_addr;
|
||||
fastcgi_param SERVER_PORT $server_port;
|
||||
fastcgi_param SERVER_NAME $server_name;
|
||||
fastcgi_param REDIRECT_STATUS 200;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
|
||||
fastcgi_pass fastcgi_backend;
|
||||
}
|
||||
|
||||
# 2. BLOB OPERATIONS (SHA256 patterns)
|
||||
|
||||
# GET/HEAD/DELETE /<sha256> (BUD-01) - Blob operations with optional file extensions
|
||||
location ~ "^/([a-f0-9]{64})(\.[a-zA-Z0-9]+)?$" {
|
||||
limit_except HEAD GET {
|
||||
deny all;
|
||||
# Handle DELETE method via rewrite to avoid fastcgi_param in if block
|
||||
if ($request_method = DELETE) {
|
||||
rewrite ^/(.*)$ /fcgi-delete/$1 last;
|
||||
}
|
||||
|
||||
# Route HEAD requests to FastCGI via rewrite
|
||||
# Route HEAD requests to FastCGI for metadata
|
||||
if ($request_method = HEAD) {
|
||||
rewrite ^/(.*)$ /fcgi-head/$1 last;
|
||||
}
|
||||
|
||||
# GET requests served directly with explicit file extensions
|
||||
# Potentially in the future look at a LUA extension
|
||||
try_files /$1.jpg /$1.jpeg /$1.png /$1.webp /$1.gif /$1.pdf /$1.mp4 /$1.mp3 /$1.txt /$1.md=404;
|
||||
|
||||
# Set appropriate headers for blobs
|
||||
# Only allow GET for file serving at this point
|
||||
if ($request_method != GET) {
|
||||
return 405;
|
||||
}
|
||||
|
||||
# GET requests - serve files directly with extension fallback
|
||||
try_files /$1.txt /$1.jpg /$1.jpeg /$1.png /$1.webp /$1.gif /$1.pdf /$1.mp4 /$1.mp3 /$1.md =404;
|
||||
|
||||
# Cache headers for blob content
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
}
|
||||
|
||||
|
||||
# Internal handler for DELETE operations
|
||||
location ~ "^/fcgi-delete/([a-f0-9]{64}).*$" {
|
||||
internal;
|
||||
fastcgi_pass fastcgi_backend;
|
||||
fastcgi_param QUERY_STRING $query_string;
|
||||
fastcgi_param REQUEST_METHOD DELETE;
|
||||
fastcgi_param CONTENT_TYPE $content_type;
|
||||
fastcgi_param CONTENT_LENGTH $content_length;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_param REQUEST_URI /$1;
|
||||
fastcgi_param DOCUMENT_URI /$1;
|
||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||
fastcgi_param REQUEST_SCHEME $scheme;
|
||||
fastcgi_param HTTPS $https if_not_empty;
|
||||
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||
fastcgi_param REMOTE_PORT $remote_port;
|
||||
fastcgi_param SERVER_ADDR $server_addr;
|
||||
fastcgi_param SERVER_PORT $server_port;
|
||||
fastcgi_param SERVER_NAME $server_name;
|
||||
fastcgi_param REDIRECT_STATUS 200;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
|
||||
}
|
||||
|
||||
# 3. INTERNAL HANDLERS
|
||||
|
||||
# FastCGI handler for HEAD requests
|
||||
location ~ "^/fcgi-head/([a-f0-9]{64}).*$" {
|
||||
@@ -102,32 +261,7 @@ http {
|
||||
fastcgi_param SERVER_NAME $server_name;
|
||||
}
|
||||
|
||||
|
||||
# Upload endpoint - requires authentication
|
||||
location /upload {
|
||||
# Pass to FastCGI application for processing
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
|
||||
fastcgi_pass fastcgi_backend;
|
||||
|
||||
# Only allow PUT method for uploads
|
||||
if ($request_method !~ ^(PUT)$ ) {
|
||||
return 405;
|
||||
}
|
||||
}
|
||||
|
||||
# List blobs endpoint - GET /list/<pubkey>
|
||||
location ~ "^/list/([a-f0-9]{64}).*$" {
|
||||
# Pass to FastCGI application for processing
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
|
||||
fastcgi_pass fastcgi_backend;
|
||||
|
||||
# Only allow GET method for list requests
|
||||
if ($request_method !~ ^(GET)$ ) {
|
||||
return 405;
|
||||
}
|
||||
}
|
||||
# 4. UTILITY ENDPOINTS
|
||||
|
||||
# Health check endpoint
|
||||
location /health {
|
||||
@@ -144,7 +278,7 @@ http {
|
||||
|
||||
# Root redirect
|
||||
location = / {
|
||||
return 200 "Ginxsom Local Development Server\nTry: GET /<sha256>\nHealth: GET /health\n";
|
||||
return 200 "Ginxsom Blossom Server\nEndpoints: GET /<sha256>, PUT /upload, GET /list/<pubkey>\nHealth: GET /health\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
db/ginxsom.db
BIN
db/ginxsom.db
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
190
db/schema.sql
190
db/schema.sql
@@ -29,17 +29,13 @@ CREATE TABLE IF NOT EXISTS server_config (
|
||||
CREATE INDEX IF NOT EXISTS idx_blobs_uploaded_at ON blobs(uploaded_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_blobs_uploader_pubkey ON blobs(uploader_pubkey);
|
||||
CREATE INDEX IF NOT EXISTS idx_blobs_type ON blobs(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_blobs_size ON blobs(size);
|
||||
|
||||
-- Insert default server configuration
|
||||
-- Insert basic server configuration
|
||||
INSERT OR IGNORE INTO server_config (key, value, description) VALUES
|
||||
('max_file_size', '104857600', 'Maximum file size in bytes (100MB)'),
|
||||
('require_auth', 'false', 'Whether authentication is required for uploads'),
|
||||
('allowed_types', '*', 'Allowed MIME types (* for all)'),
|
||||
('server_name', 'ginxsom', 'Server name for responses'),
|
||||
('storage_quota', '10737418240', 'Total storage quota in bytes (10GB)'),
|
||||
('cleanup_interval', '86400', 'Cleanup interval in seconds (daily)'),
|
||||
('max_upload_rate', '1048576', 'Max upload rate per client in bytes/sec (1MB/s)');
|
||||
('server_name', 'ginxsom', 'Server name for responses');
|
||||
|
||||
-- View for storage statistics
|
||||
CREATE VIEW IF NOT EXISTS storage_stats AS
|
||||
@@ -52,186 +48,4 @@ SELECT
|
||||
COUNT(DISTINCT uploader_pubkey) as unique_uploaders
|
||||
FROM blobs;
|
||||
|
||||
-- View for recent uploads (last 24 hours)
|
||||
CREATE VIEW IF NOT EXISTS recent_uploads AS
|
||||
SELECT
|
||||
sha256,
|
||||
size,
|
||||
type,
|
||||
uploaded_at,
|
||||
uploader_pubkey,
|
||||
filename,
|
||||
datetime(uploaded_at, 'unixepoch') as uploaded_datetime
|
||||
FROM blobs
|
||||
WHERE uploaded_at > (strftime('%s', 'now') - 86400)
|
||||
ORDER BY uploaded_at DESC;
|
||||
|
||||
-- ============================================================================
|
||||
-- AUTHENTICATION RULES SYSTEM
|
||||
-- ============================================================================
|
||||
|
||||
-- Authentication rules table for flexible access control
|
||||
CREATE TABLE IF NOT EXISTS auth_rules (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
rule_type TEXT NOT NULL, -- 'whitelist', 'blacklist', 'hash_blacklist', 'rate_limit', etc.
|
||||
rule_target TEXT NOT NULL, -- pubkey, hash, IP, MIME type, etc.
|
||||
rule_value TEXT, -- JSON for complex rules (optional)
|
||||
operation TEXT NOT NULL DEFAULT '*', -- 'upload', 'delete', 'list', '*' (all operations)
|
||||
enabled INTEGER NOT NULL DEFAULT 1, -- 0 = disabled, 1 = enabled
|
||||
priority INTEGER NOT NULL DEFAULT 100, -- Lower numbers = higher priority (for conflict resolution)
|
||||
expires_at INTEGER, -- Optional expiration timestamp
|
||||
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
created_by TEXT, -- Admin pubkey who created this rule (optional)
|
||||
description TEXT, -- Human-readable rule description
|
||||
CHECK (enabled IN (0, 1)), -- Boolean constraint
|
||||
CHECK (priority >= 0), -- Priority must be non-negative
|
||||
CHECK (expires_at IS NULL OR expires_at > created_at) -- Expiration must be in future
|
||||
);
|
||||
|
||||
-- Rule evaluation cache for performance optimization
|
||||
CREATE TABLE IF NOT EXISTS auth_cache (
|
||||
cache_key TEXT PRIMARY KEY, -- SHA-256 hash of request parameters
|
||||
allowed INTEGER NOT NULL, -- 0 = denied, 1 = allowed
|
||||
rule_id INTEGER, -- Which rule made the decision (optional)
|
||||
rule_reason TEXT, -- Human-readable reason for decision
|
||||
expires_at INTEGER NOT NULL, -- Cache entry expiration
|
||||
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
CHECK (allowed IN (0, 1)), -- Boolean constraint
|
||||
FOREIGN KEY (rule_id) REFERENCES auth_rules(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- Indexes for authentication system performance
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_type_target ON auth_rules(rule_type, rule_target);
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_operation ON auth_rules(operation);
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_enabled ON auth_rules(enabled);
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_priority ON auth_rules(priority);
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_expires ON auth_rules(expires_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_cache_expires ON auth_cache(expires_at);
|
||||
|
||||
-- ============================================================================
|
||||
-- ADMINISTRATIVE SYSTEM
|
||||
-- ============================================================================
|
||||
|
||||
-- Administrators table for nostr-based server administration
|
||||
CREATE TABLE IF NOT EXISTS administrators (
|
||||
pubkey TEXT PRIMARY KEY NOT NULL, -- Nostr public key (64 hex chars)
|
||||
permissions TEXT NOT NULL DEFAULT '[]', -- JSON array of permissions
|
||||
added_by TEXT, -- Pubkey of admin who added this admin
|
||||
added_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
expires_at INTEGER, -- Optional expiration timestamp
|
||||
enabled INTEGER NOT NULL DEFAULT 1, -- 0 = disabled, 1 = enabled
|
||||
description TEXT, -- Human-readable description
|
||||
last_seen INTEGER, -- Last administrative action timestamp
|
||||
CHECK (length(pubkey) = 64), -- Ensure valid pubkey length
|
||||
CHECK (enabled IN (0, 1)), -- Boolean constraint
|
||||
CHECK (expires_at IS NULL OR expires_at > added_at), -- Expiration must be in future
|
||||
FOREIGN KEY (added_by) REFERENCES administrators(pubkey) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- Administrative actions audit log
|
||||
CREATE TABLE IF NOT EXISTS admin_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
admin_pubkey TEXT NOT NULL, -- Which admin performed the action
|
||||
command TEXT NOT NULL, -- Administrative command executed
|
||||
parameters TEXT, -- JSON command parameters
|
||||
result TEXT, -- Success/failure result and details
|
||||
timestamp INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
event_id TEXT, -- Reference to nostr event (optional)
|
||||
target_table TEXT, -- Which table was affected (optional)
|
||||
target_id TEXT, -- Which record was affected (optional)
|
||||
ip_address TEXT, -- Client IP address (optional)
|
||||
user_agent TEXT, -- Client user agent (optional)
|
||||
FOREIGN KEY (admin_pubkey) REFERENCES administrators(pubkey) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Server identity and administrative configuration
|
||||
INSERT OR IGNORE INTO server_config (key, value, description) VALUES
|
||||
('server_pubkey', '', 'Server nostr public key (generated on first run)'),
|
||||
('server_privkey_file', 'keys/server.key', 'Path to encrypted server private key file'),
|
||||
('admin_relays', '[]', 'JSON array of relay URLs for administrative events'),
|
||||
('admin_event_processing', 'true', 'Enable nostr-based administrative event processing'),
|
||||
('require_admin_auth', 'true', 'Require admin authorization for sensitive operations'),
|
||||
('auth_rules_enabled', 'true', 'Enable flexible authentication rules system'),
|
||||
('auth_cache_ttl', '300', 'Authentication cache TTL in seconds (5 minutes)'),
|
||||
('admin_session_timeout', '3600', 'Administrative session timeout in seconds (1 hour)'),
|
||||
('max_admin_log_entries', '10000', 'Maximum administrative log entries to retain');
|
||||
|
||||
-- Indexes for administrative system performance
|
||||
CREATE INDEX IF NOT EXISTS idx_administrators_enabled ON administrators(enabled);
|
||||
CREATE INDEX IF NOT EXISTS idx_administrators_expires ON administrators(expires_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_admin_log_timestamp ON admin_log(timestamp);
|
||||
CREATE INDEX IF NOT EXISTS idx_admin_log_admin_pubkey ON admin_log(admin_pubkey);
|
||||
CREATE INDEX IF NOT EXISTS idx_admin_log_command ON admin_log(command);
|
||||
|
||||
-- ============================================================================
|
||||
-- VIEWS FOR ADMINISTRATIVE QUERIES
|
||||
-- ============================================================================
|
||||
|
||||
-- View for active authentication rules
|
||||
CREATE VIEW IF NOT EXISTS active_auth_rules AS
|
||||
SELECT
|
||||
id,
|
||||
rule_type,
|
||||
rule_target,
|
||||
rule_value,
|
||||
operation,
|
||||
priority,
|
||||
expires_at,
|
||||
created_at,
|
||||
created_by,
|
||||
description,
|
||||
CASE
|
||||
WHEN expires_at IS NULL THEN 'never'
|
||||
WHEN expires_at > strftime('%s', 'now') THEN 'active'
|
||||
ELSE 'expired'
|
||||
END as status
|
||||
FROM auth_rules
|
||||
WHERE enabled = 1
|
||||
ORDER BY priority ASC, created_at ASC;
|
||||
|
||||
-- View for active administrators
|
||||
CREATE VIEW IF NOT EXISTS active_administrators AS
|
||||
SELECT
|
||||
pubkey,
|
||||
permissions,
|
||||
added_by,
|
||||
added_at,
|
||||
expires_at,
|
||||
description,
|
||||
last_seen,
|
||||
CASE
|
||||
WHEN expires_at IS NULL THEN 'never'
|
||||
WHEN expires_at > strftime('%s', 'now') THEN 'active'
|
||||
ELSE 'expired'
|
||||
END as status,
|
||||
datetime(added_at, 'unixepoch') as added_datetime,
|
||||
datetime(last_seen, 'unixepoch') as last_seen_datetime
|
||||
FROM administrators
|
||||
WHERE enabled = 1;
|
||||
|
||||
-- View for recent administrative actions (last 7 days)
|
||||
CREATE VIEW IF NOT EXISTS recent_admin_actions AS
|
||||
SELECT
|
||||
id,
|
||||
admin_pubkey,
|
||||
command,
|
||||
parameters,
|
||||
result,
|
||||
timestamp,
|
||||
event_id,
|
||||
target_table,
|
||||
target_id,
|
||||
datetime(timestamp, 'unixepoch') as action_datetime
|
||||
FROM admin_log
|
||||
WHERE timestamp > (strftime('%s', 'now') - 604800) -- 7 days
|
||||
ORDER BY timestamp DESC;
|
||||
|
||||
-- View for authentication statistics
|
||||
CREATE VIEW IF NOT EXISTS auth_stats AS
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM auth_rules WHERE enabled = 1) as active_rules,
|
||||
(SELECT COUNT(*) FROM auth_rules WHERE enabled = 1 AND expires_at > strftime('%s', 'now')) as non_expired_rules,
|
||||
(SELECT COUNT(*) FROM auth_cache WHERE expires_at > strftime('%s', 'now')) as cached_decisions,
|
||||
(SELECT COUNT(*) FROM administrators WHERE enabled = 1) as active_admins,
|
||||
(SELECT COUNT(*) FROM admin_log WHERE timestamp > (strftime('%s', 'now') - 86400)) as daily_admin_actions;
|
||||
|
||||
42
debug_hash_data.log
Normal file
42
debug_hash_data.log
Normal file
@@ -0,0 +1,42 @@
|
||||
=== HASH DEBUG SESSION ===
|
||||
Content length: 296
|
||||
File data to hash: 5465737420626c6f6220636f6e74656e7420666f722047696e78736f6d20426c6f73736f6d207365727665720a54696d657374616d703a20323032352d30392d30325431333a35393a31312d30343a30300a52616e646f6d20646174613a20373730353061633932653438633437373436653164393035343164393930373965383131633539666464313039343931313635623664333130656638646137360a54657374206d6573736167653a2048656c6c6f2066726f6d207075745f746573742e7368210a0a546869732066696c65206973207573656420746f2074657374207468652075706c6f61642066756e6374696f6e616c6974790a6f66207468652047696e78736f6d20426c6f73736f6d2073657276657220696d706c656d656e746174696f6e2e0a
|
||||
File data as string: Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-09-02T13:59:11-04:00
|
||||
Random data: 77050ac92e48c47746e1d90541d99079e811c59fdd109491165b6d310ef8da76
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
|
||||
Calculated SHA-256: e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4
|
||||
=== END DEBUG SESSION ===
|
||||
|
||||
=== HASH DEBUG SESSION ===
|
||||
Content length: 296
|
||||
File data to hash: 5465737420626c6f6220636f6e74656e7420666f722047696e78736f6d20426c6f73736f6d207365727665720a54696d657374616d703a20323032352d30392d30325431343a32323a35352d30343a30300a52616e646f6d20646174613a20393532613538346438663366633662356534396231646661626266363864373633383564366435313134326161303731373063373138393765613836316330330a54657374206d6573736167653a2048656c6c6f2066726f6d207075745f746573742e7368210a0a546869732066696c65206973207573656420746f2074657374207468652075706c6f61642066756e6374696f6e616c6974790a6f66207468652047696e78736f6d20426c6f73736f6d2073657276657220696d706c656d656e746174696f6e2e0a
|
||||
File data as string: Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-09-02T14:22:55-04:00
|
||||
Random data: 952a584d8f3fc6b5e49b1dfabbf68d76385d6d51142aa07170c71897ea861c03
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
|
||||
Calculated SHA-256: 52d7920725bbbd86d54a7802a45c0c39fa8158705436fc57d7c4fb4be1ce75f1
|
||||
=== END DEBUG SESSION ===
|
||||
|
||||
=== HASH DEBUG SESSION ===
|
||||
Content length: 296
|
||||
File data to hash: 5465737420626c6f6220636f6e74656e7420666f722047696e78736f6d20426c6f73736f6d207365727665720a54696d657374616d703a20323032352d30392d30325431353a31373a34372d30343a30300a52616e646f6d20646174613a20346538666566656333313034623838343038663063373161373365393762613137363834363734376535353737333334643432626533313438333961396262610a54657374206d6573736167653a2048656c6c6f2066726f6d207075745f746573742e7368210a0a546869732066696c65206973207573656420746f2074657374207468652075706c6f61642066756e6374696f6e616c6974790a6f66207468652047696e78736f6d20426c6f73736f6d2073657276657220696d706c656d656e746174696f6e2e0a
|
||||
File data as string: Test blob content for Ginxsom Blossom server
|
||||
Timestamp: 2025-09-02T15:17:47-04:00
|
||||
Random data: 4e8fefec3104b88408f0c71a73e97ba176846747e5577334d42be314839a9bba
|
||||
Test message: Hello from put_test.sh!
|
||||
|
||||
This file is used to test the upload functionality
|
||||
of the Ginxsom Blossom server implementation.
|
||||
|
||||
Calculated SHA-256: 115c440bf5b69015f8b844d325ae33458a555b463d5d53e4dfe2d24cd740c5bc
|
||||
=== END DEBUG SESSION ===
|
||||
|
||||
36
debug_validation.log
Normal file
36
debug_validation.log
Normal file
@@ -0,0 +1,36 @@
|
||||
=== STRUCTURE VALIDATION DEBUG ===
|
||||
nostr_validate_event_structure result: 0 (Success)
|
||||
=== END STRUCTURE DEBUG ===
|
||||
|
||||
=== CRYPTO VALIDATION DEBUG ===
|
||||
nostr_verify_event_signature result: 0 (Success)
|
||||
=== END CRYPTO DEBUG ===
|
||||
|
||||
=== COMPLETE VALIDATION DEBUG ===
|
||||
nostr_validate_event result: 0 (Success)
|
||||
=== END COMPLETE DEBUG ===
|
||||
|
||||
=== STRUCTURE VALIDATION DEBUG ===
|
||||
nostr_validate_event_structure result: 0 (Success)
|
||||
=== END STRUCTURE DEBUG ===
|
||||
|
||||
=== CRYPTO VALIDATION DEBUG ===
|
||||
nostr_verify_event_signature result: 0 (Success)
|
||||
=== END CRYPTO DEBUG ===
|
||||
|
||||
=== COMPLETE VALIDATION DEBUG ===
|
||||
nostr_validate_event result: 0 (Success)
|
||||
=== END COMPLETE DEBUG ===
|
||||
|
||||
=== STRUCTURE VALIDATION DEBUG ===
|
||||
nostr_validate_event_structure result: 0 (Success)
|
||||
=== END STRUCTURE DEBUG ===
|
||||
|
||||
=== CRYPTO VALIDATION DEBUG ===
|
||||
nostr_verify_event_signature result: 0 (Success)
|
||||
=== END CRYPTO DEBUG ===
|
||||
|
||||
=== COMPLETE VALIDATION DEBUG ===
|
||||
nostr_validate_event result: 0 (Success)
|
||||
=== END COMPLETE DEBUG ===
|
||||
|
||||
@@ -12,3 +12,17 @@
|
||||
127.0.0.1 - - [02/Sep/2025:12:45:42 -0400] "PUT /upload HTTP/1.1" 200 262 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:12:46:50 -0400] "PUT /upload HTTP/1.1" 200 262 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:12:49:20 -0400] "GET /list/79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 HTTP/1.1" 200 1520 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:13:59:11 -0400] "PUT /upload HTTP/1.1" 200 262 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:13:59:38 -0400] "GET /e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4.txt HTTP/1.1" 404 162 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:14:03:38 -0400] "GET /e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4.txt HTTP/1.1" 404 162 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:14:05:11 -0400] "GET /e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4.txt HTTP/1.1" 404 162 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:14:22:56 -0400] "PUT /upload HTTP/1.1" 200 262 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:14:23:24 -0400] "GET /e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4.txt HTTP/1.1" 404 162 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:14:24:38 -0400] "GET /list/79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 HTTP/1.1" 200 635 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:14:25:06 -0400] "GET /e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4 HTTP/1.1" 404 162 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:14:25:10 -0400] "GET /e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4.txt HTTP/1.1" 404 162 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:15:17:32 -0400] "GET /list/79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 HTTP/1.1" 200 635 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:15:17:47 -0400] "PUT /upload HTTP/1.1" 200 262 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:15:18:08 -0400] "GET /e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4.txt HTTP/1.1" 404 162 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:15:20:15 -0400] "GET /e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4.txt HTTP/1.1" 200 296 "-" "curl/8.15.0"
|
||||
127.0.0.1 - - [02/Sep/2025:15:20:49 -0400] "GET /e6bdc6b5336072dc05e1a6eea68c75110cbd6c1994f5dbfe75c5880a8b43dcf4 HTTP/1.1" 200 296 "-" "curl/8.15.0"
|
||||
|
||||
4776
logs/error.log
4776
logs/error.log
File diff suppressed because it is too large
Load Diff
1002
logs/fcgi-stderr.log
1002
logs/fcgi-stderr.log
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
176726
|
||||
189132
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
spawn-fcgi: child exited with: 127
|
||||
|
||||
@@ -141,8 +141,10 @@ if ! command -v spawn-fcgi &> /dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start FastCGI application with stderr logging using wrapper
|
||||
spawn-fcgi -s "$SOCKET_PATH" -M 666 -u "$USER" -g "$USER" -f "./fcgi-wrapper.sh" -P "$PID_FILE" 2>logs/spawn-fcgi.log
|
||||
# Start FastCGI application with stderr logging (no wrapper needed)
|
||||
# Create stderr log with timestamp
|
||||
echo "FastCGI starting at $(date)" > logs/fcgi-stderr.log
|
||||
spawn-fcgi -s "$SOCKET_PATH" -M 666 -u "$USER" -g "$USER" -f "$FCGI_BINARY" -P "$PID_FILE" 2>>logs/fcgi-stderr.log
|
||||
|
||||
if [ $? -eq 0 ] && [ -f "$PID_FILE" ]; then
|
||||
PID=$(cat "$PID_FILE")
|
||||
|
||||
@@ -2489,6 +2489,14 @@ void handle_upload_request(void) {
|
||||
|
||||
size_t bytes_written = fwrite(file_data, 1, content_length, outfile);
|
||||
fclose(outfile);
|
||||
|
||||
// Set file permissions to 644 (owner read/write, group/others read) - standard for web files
|
||||
if (chmod(filepath, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0) {
|
||||
fprintf(stderr, "WARNING: Failed to set file permissions for %s\r\n", filepath);
|
||||
// Continue anyway - this is not a fatal error
|
||||
} else {
|
||||
fprintf(stderr, "DEBUG: File permissions set to 644 for %s\r\n", filepath);
|
||||
}
|
||||
free(file_data);
|
||||
|
||||
if (bytes_written != (size_t)content_length) {
|
||||
|
||||
Reference in New Issue
Block a user