From 8ff33b3814224de4a1081249c899707d57628335 Mon Sep 17 00:00:00 2001 From: RomkaZVO Date: Fri, 24 Jul 2026 02:42:54 +0800 Subject: [PATCH] =?UTF-8?q?=D0=B7=D0=B0=D0=B1=D1=8B=D0=BB=20=D1=85=D0=BB?= =?UTF-8?q?=D0=B0=D0=BC=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B8=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.sh | 16 - index.c | 1061 ---------------------------------------------------- index.cgi | Bin 35424 -> 0 bytes status.c | 55 --- status.cgi | Bin 16392 -> 0 bytes style.c | 38 -- style.cgi | Bin 16248 -> 0 bytes 7 files changed, 1170 deletions(-) delete mode 100755 build.sh delete mode 100644 index.c delete mode 100755 index.cgi delete mode 100755 status.c delete mode 100755 status.cgi delete mode 100755 style.c delete mode 100755 style.cgi diff --git a/build.sh b/build.sh deleted file mode 100755 index 6774901..0000000 --- a/build.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -echo "Building Trashbox CGI scripts..." - -echo "Building index.cgi..." -gcc -Wall -O2 -o index.cgi index.c -DBASE_WWW_PATH='"/home/romkazvo/www"' -DTEMPLATE_PATH='"/home/romkazvo/www/cgi-bin/template.html"' - -echo "Building style.cgi..." -gcc -Wall -O2 -o style.cgi style.c -DCSS_PATH='"/home/romkazvo/www/cgi-bin/style.css"' - -echo "Building status.cgi..." -gcc -Wall -O2 -o status.cgi status.c - -echo "Setting permissions..." -chmod +x *.cgi - -echo "Build complete" diff --git a/index.c b/index.c deleted file mode 100644 index 529f996..0000000 --- a/index.c +++ /dev/null @@ -1,1061 +0,0 @@ -// /home/romkazvo/www/cgi-bin/index.c -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// === ПРОТОТИПЫ === -void url_encode(const char *src, char *dst, size_t dst_size); -void url_decode_enhanced(const char *src, char *dst, size_t dst_size); -void format_size(long long size, char* buffer); -void format_date(time_t mtime, char* buffer, size_t size); -void html_escape(const char *src, char *dst, size_t dst_size); - -// === КОНФИГ === -typedef struct { - char base_path[1024]; - char template_path[1024]; - char passwd_file[1024]; - int max_entries; - char hidden_dirs[10][256]; - int hidden_dirs_count; - char hidden_files[10][256]; - int hidden_files_count; - char preview_image[512]; - char preview_text[512]; - char preview_audio[512]; - char preview_video[512]; - char preview_pdf[512]; -} config_t; - -config_t g_config; - -// === ПАРАМЕТРЫ === -typedef struct { - char sort_by[16]; - int sort_order; - char search[256]; - int recursive; -} query_params_t; - -query_params_t g_params; - -// === УТИЛИТЫ === -char* my_strcasestr(const char *haystack, const char *needle) { - if (!haystack || !needle || *needle == '\0') return (char*)haystack; - size_t needle_len = strlen(needle); - while (*haystack) { - if (strncasecmp(haystack, needle, needle_len) == 0) return (char*)haystack; - haystack++; - } - return NULL; -} - -void html_escape(const char *src, char *dst, size_t dst_size) { - if (!src || !dst || dst_size == 0) return; - char *p = dst; - size_t i = 0; - while (*src && i < dst_size - 6) { - switch (*src) { - case '<': strcpy(p, "<"); p += 4; i += 4; break; - case '>': strcpy(p, ">"); p += 4; i += 4; break; - case '"': strcpy(p, """); p += 6; i += 6; break; - case '&': strcpy(p, "&"); p += 5; i += 5; break; - default: *p++ = *src; i++; break; - } - src++; - } - *p = '\0'; -} - -// === ПАРСЕР INI === -int load_config(const char *path, config_t *cfg) { - FILE *f = fopen(path, "r"); - if (!f) return -1; - char line[512]; - char current_section[64] = ""; - while (fgets(line, sizeof(line), f)) { - char *p = line; - while (*p == ' ' || *p == '\t') p++; - if (*p == '\0' || *p == '#' || *p == ';') continue; - if (*p == '[') { - p++; - char *end = strchr(p, ']'); - if (end) { - *end = '\0'; - strncpy(current_section, p, sizeof(current_section) - 1); - current_section[sizeof(current_section) - 1] = '\0'; - } - continue; - } - char *eq = strchr(p, '='); - if (!eq) continue; - *eq = '\0'; - char *key = p; - char *value = eq + 1; - char *end_key = key + strlen(key) - 1; - while (end_key > key && (*end_key == ' ' || *end_key == '\t')) { - *end_key = '\0'; - end_key--; - } - while (*value == ' ' || *value == '\t') value++; - char *end_val = value + strlen(value) - 1; - while (end_val > value && (*end_val == ' ' || *end_val == '\t' || *end_val == '\r' || *end_val == '\n')) { - *end_val = '\0'; - end_val--; - } - if (strcmp(current_section, "paths") == 0) { - if (strcmp(key, "base_path") == 0) strncpy(cfg->base_path, value, sizeof(cfg->base_path) - 1); - else if (strcmp(key, "template_path") == 0) strncpy(cfg->template_path, value, sizeof(cfg->template_path) - 1); - else if (strcmp(key, "passwd_file") == 0) strncpy(cfg->passwd_file, value, sizeof(cfg->passwd_file) - 1); - } else if (strcmp(current_section, "limits") == 0) { - if (strcmp(key, "max_entries") == 0) cfg->max_entries = atoi(value); - } else if (strcmp(current_section, "hidden") == 0) { - if (strcmp(key, "dirs") == 0) { - char *token = strtok(value, ","); - cfg->hidden_dirs_count = 0; - while (token && cfg->hidden_dirs_count < 10) { - while (*token == ' ') token++; - strncpy(cfg->hidden_dirs[cfg->hidden_dirs_count], token, 255); - cfg->hidden_dirs[cfg->hidden_dirs_count][255] = '\0'; - cfg->hidden_dirs_count++; - token = strtok(NULL, ","); - } - } else if (strcmp(key, "files") == 0) { - char *token = strtok(value, ","); - cfg->hidden_files_count = 0; - while (token && cfg->hidden_files_count < 10) { - while (*token == ' ') token++; - strncpy(cfg->hidden_files[cfg->hidden_files_count], token, 255); - cfg->hidden_files[cfg->hidden_files_count][255] = '\0'; - cfg->hidden_files_count++; - token = strtok(NULL, ","); - } - } - } else if (strcmp(current_section, "preview") == 0) { - if (strcmp(key, "image") == 0) strncpy(cfg->preview_image, value, sizeof(cfg->preview_image) - 1); - else if (strcmp(key, "text") == 0) strncpy(cfg->preview_text, value, sizeof(cfg->preview_text) - 1); - else if (strcmp(key, "audio") == 0) strncpy(cfg->preview_audio, value, sizeof(cfg->preview_audio) - 1); - else if (strcmp(key, "video") == 0) strncpy(cfg->preview_video, value, sizeof(cfg->preview_video) - 1); - else if (strcmp(key, "pdf") == 0) strncpy(cfg->preview_pdf, value, sizeof(cfg->preview_pdf) - 1); - } - } - fclose(f); - return 0; -} - -void set_default_config(config_t *cfg) { - strcpy(cfg->base_path, "/home/romkazvo/www"); - strcpy(cfg->template_path, "/home/romkazvo/www/cgi-bin/template.html"); - strcpy(cfg->passwd_file, "/home/romkazvo/www/cgi-bin/.htpasswd"); - cfg->max_entries = 1000; - cfg->hidden_dirs_count = 0; - cfg->hidden_files_count = 0; - strcpy(cfg->preview_image, "jpg,jpeg,png,gif,webp,bmp,svg,ico"); - strcpy(cfg->preview_text, "txt,md,html,htm,css,js,json,xml,csv"); - strcpy(cfg->preview_audio, "mp3,wav,ogg,flac,m4a,aac"); - strcpy(cfg->preview_video, "mp4,webm,ogv,mov,avi,mkv"); - strcpy(cfg->preview_pdf, "pdf"); -} - -int is_string_in_list(const char *str, const char *list) { - if (!list || !*list) return 0; - char temp[512]; - strncpy(temp, list, sizeof(temp) - 1); - temp[sizeof(temp) - 1] = '\0'; - char *token = strtok(temp, ","); - while (token) { - while (*token == ' ') token++; - if (strcasecmp(token, str) == 0) return 1; - token = strtok(NULL, ","); - } - return 0; -} - -// === ОСНОВНЫЕ СТРУКТУРЫ === -typedef struct { - char name[256]; - int is_dir; - long size; - char icon[8]; - char encoded_path[1024]; - char file_url[1024]; - int is_protected; - time_t mtime; - int file_count; - long long dir_size; -} entry_t; - -typedef struct { - char *data; - size_t size; - size_t capacity; -} buffer_t; - -void buffer_init(buffer_t *buf) { - buf->capacity = 65536; - buf->data = malloc(buf->capacity); - buf->size = 0; -} - -void buffer_append(buffer_t *buf, const char *str) { - size_t len = strlen(str); - if (buf->size + len >= buf->capacity) { - buf->capacity *= 2; - buf->data = realloc(buf->data, buf->capacity); - } - memcpy(buf->data + buf->size, str, len); - buf->size += len; -} - -void buffer_free(buffer_t *buf) { free(buf->data); } - -// === БЕЗОПАСНОСТЬ === -int is_safe_path(const char *path) { - if (!path) return 0; - if (strstr(path, "..")) return 0; - if (strstr(path, "./")) return 0; - if (path[0] == '/') return 0; - if (strstr(path, "//")) return 0; - return 1; -} - -void safe_path_join(char *result, size_t result_size, const char *base, const char *path) { - if (!is_safe_path(path)) { - snprintf(result, result_size, "%s", base); - return; - } - snprintf(result, result_size, "%s/%s", base, path); -} - -// === ПАРОЛИ === -int check_folder_password(const char *folder_name, const char *password) { - if (!password || !folder_name || password[0] == '\0') return 0; - FILE *f = fopen(g_config.passwd_file, "r"); - if (!f) return 1; - char line[512]; - while (fgets(line, sizeof(line), f)) { - line[strcspn(line, "\r\n")] = 0; - char *colon = strchr(line, ':'); - if (!colon) continue; - *colon = '\0'; - char *folder = line; - char *pass = colon + 1; - const char *last_slash = strrchr(folder_name, '/'); - const char *base_name = last_slash ? last_slash + 1 : folder_name; - if (strcmp(folder, folder_name) == 0 || strcmp(folder, base_name) == 0) { - fclose(f); - return strcmp(pass, password) == 0; - } - } - fclose(f); - return 1; -} - -int is_folder_protected(const char *folder_path) { - if (!folder_path || folder_path[0] == '\0') return 0; - FILE *f = fopen(g_config.passwd_file, "r"); - if (!f) return 0; - char line[512]; - while (fgets(line, sizeof(line), f)) { - line[strcspn(line, "\r\n")] = 0; - char *colon = strchr(line, ':'); - if (!colon) continue; - *colon = '\0'; - const char *last_slash = strrchr(folder_path, '/'); - const char *folder_name = last_slash ? last_slash + 1 : folder_path; - if (strcmp(line, folder_path) == 0 || strcmp(line, folder_name) == 0) { - fclose(f); - return 1; - } - } - fclose(f); - return 0; -} - -// === ФС === -int count_files_in_dir(const char *path) { - DIR *dir = opendir(path); - if (!dir) return 0; - struct dirent *entry; - int count = 0; - while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; - if (entry->d_name[0] == '.') continue; - int hidden = 0; - for (int i = 0; i < g_config.hidden_files_count; i++) { - if (strcmp(entry->d_name, g_config.hidden_files[i]) == 0) { hidden = 1; break; } - } - if (hidden) continue; - count++; - } - closedir(dir); - return count; -} - -long long get_dir_size(const char *path) { - DIR *dir = opendir(path); - if (!dir) return 0; - struct dirent *entry; - struct stat statbuf; - char fullpath[1024]; - long long size = 0; - while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; - snprintf(fullpath, sizeof(fullpath), "%s/%s", path, entry->d_name); - if (stat(fullpath, &statbuf) == 0) { - if (S_ISDIR(statbuf.st_mode)) size += get_dir_size(fullpath); - else if (S_ISREG(statbuf.st_mode)) size += statbuf.st_size; - } - } - closedir(dir); - return size; -} - -const char* get_file_icon(const char* filename) { - const char *ext = strrchr(filename, '.'); - if (!ext) return "📄"; - ext++; - if (is_string_in_list(ext, g_config.preview_image)) return "🖼️"; - if (is_string_in_list(ext, g_config.preview_audio)) return "🎵"; - if (is_string_in_list(ext, g_config.preview_video)) return "🎬"; - if (strcasecmp(ext, "zip") == 0 || strcasecmp(ext, "rar") == 0 || - strcasecmp(ext, "7z") == 0 || strcasecmp(ext, "tar") == 0 || - strcasecmp(ext, "gz") == 0) return "📦"; - if (strcasecmp(ext, "pdf") == 0) return "📕"; - if (strcasecmp(ext, "doc") == 0 || strcasecmp(ext, "docx") == 0) return "📘"; - if (strcasecmp(ext, "xls") == 0 || strcasecmp(ext, "xlsx") == 0) return "📗"; - if (strcasecmp(ext, "txt") == 0) return "📝"; - return "📄"; -} - -int is_previewable(const char* filename) { - const char *ext = strrchr(filename, '.'); - if (!ext) return 0; - ext++; - return (is_string_in_list(ext, g_config.preview_image) || - is_string_in_list(ext, g_config.preview_text) || - is_string_in_list(ext, g_config.preview_audio) || - is_string_in_list(ext, g_config.preview_video) || - is_string_in_list(ext, g_config.preview_pdf)); -} - -// === РЕКУРСИВНЫЙ ПОИСК === -void search_recursive(const char *base_path, const char *display_path, const char *search_term, entry_t *results, int *count, int max_results) { - DIR *dir = opendir(base_path); - if (!dir) return; - struct dirent *entry; - struct stat file_stat; - char full_path[1024]; - char display_subpath[1024]; - while ((entry = readdir(dir)) != NULL && *count < max_results) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; - if (entry->d_name[0] == '.') continue; - int hidden = 0; - for (int i = 0; i < g_config.hidden_dirs_count; i++) { - if (strcmp(entry->d_name, g_config.hidden_dirs[i]) == 0) { hidden = 1; break; } - } - for (int i = 0; i < g_config.hidden_files_count; i++) { - if (strcmp(entry->d_name, g_config.hidden_files[i]) == 0) { hidden = 1; break; } - } - if (hidden) continue; - snprintf(full_path, sizeof(full_path), "%s/%s", base_path, entry->d_name); - if (display_path[0] == '\0') { - snprintf(display_subpath, sizeof(display_subpath), "%s", entry->d_name); - } else { - snprintf(display_subpath, sizeof(display_subpath), "%s/%s", display_path, entry->d_name); - } - if (is_folder_protected(display_subpath) || is_folder_protected(entry->d_name)) { - continue; - } - if (stat(full_path, &file_stat) == 0) { - if (my_strcasestr(entry->d_name, search_term) != NULL) { - entry_t *result = &results[*count]; - strncpy(result->name, entry->d_name, sizeof(result->name) - 1); - result->name[sizeof(result->name) - 1] = '\0'; - if (S_ISDIR(file_stat.st_mode)) { - result->is_dir = 1; - result->size = 0; - result->dir_size = get_dir_size(full_path); - result->file_count = count_files_in_dir(full_path); - result->mtime = file_stat.st_mtime; - strcpy(result->icon, "📁"); - result->is_protected = 0; - url_encode(display_subpath, result->encoded_path, sizeof(result->encoded_path)); - strncpy(result->file_url, display_subpath, sizeof(result->file_url) - 1); - (*count)++; - } else if (S_ISREG(file_stat.st_mode)) { - result->is_dir = 0; - result->size = file_stat.st_size; - result->dir_size = 0; - result->file_count = 0; - result->mtime = file_stat.st_mtime; - strcpy(result->icon, get_file_icon(entry->d_name)); - result->is_protected = 0; - url_encode(display_subpath, result->encoded_path, sizeof(result->encoded_path)); - strncpy(result->file_url, display_subpath, sizeof(result->file_url) - 1); - (*count)++; - } - } - if (S_ISDIR(file_stat.st_mode)) { - search_recursive(full_path, display_subpath, search_term, results, count, max_results); - } - } - } - closedir(dir); -} - -// === СОРТИРОВКА === -int compare_entries_sorted(const void *a, const void *b) { - const entry_t *entryA = (const entry_t *)a; - const entry_t *entryB = (const entry_t *)b; - if (entryA->is_dir && !entryB->is_dir) return -1; - if (!entryA->is_dir && entryB->is_dir) return 1; - int result = 0; - if (strcmp(g_params.sort_by, "size") == 0) { - long long sizeA = entryA->is_dir ? entryA->dir_size : entryA->size; - long long sizeB = entryB->is_dir ? entryB->dir_size : entryB->size; - result = (sizeA > sizeB) - (sizeA < sizeB); - } else if (strcmp(g_params.sort_by, "date") == 0) { - result = (entryA->mtime > entryB->mtime) - (entryA->mtime < entryB->mtime); - } else { - result = strcasecmp(entryA->name, entryB->name); - } - return result * g_params.sort_order; -} - -// === ФОРМАТИРОВАНИЕ === -void format_size(long long size, char* buffer) { - if (size < 1024) snprintf(buffer, 32, "%lld B", size); - else if (size < 1024 * 1024) snprintf(buffer, 32, "%.1f KB", size / 1024.0); - else if (size < 1024 * 1024 * 1024) snprintf(buffer, 32, "%.1f MB", size / (1024.0 * 1024.0)); - else snprintf(buffer, 32, "%.1f GB", size / (1024.0 * 1024.0 * 1024.0)); -} - -void format_date(time_t mtime, char* buffer, size_t size) { - struct tm *tm_info = localtime(&mtime); - strftime(buffer, size, "%d.%m.%Y", tm_info); -} - -void url_encode(const char *src, char *dst, size_t dst_size) { - static const char *hex = "0123456789ABCDEF"; - char *p = dst; - size_t i = 0; - while (*src && i < dst_size - 3) { - unsigned char c = (unsigned char)*src; - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || strchr("-_.~", c)) { - *p++ = c; i++; - } else if (c == ' ') { - *p++ = '%'; *p++ = '2'; *p++ = '0'; i += 3; - } else { - *p++ = '%'; *p++ = hex[(c >> 4) & 0xF]; *p++ = hex[c & 0xF]; i += 3; - } - src++; - } - *p = '\0'; -} - -void url_decode_enhanced(const char *src, char *dst, size_t dst_size) { - char *p = dst; - size_t decoded_len = 0; - while (*src && decoded_len < dst_size - 1) { - if (*src == '%') { - if (src[1] && src[2] && isxdigit(src[1]) && isxdigit(src[2])) { - char hex[3] = {src[1], src[2], '\0'}; - unsigned char c = (unsigned char)strtol(hex, NULL, 16); - if (c >= 0x80 || c >= 0x20 || c == 0x0A || c == 0x0D) { - *p++ = c; - decoded_len++; - } else { - *p++ = '_'; - decoded_len++; - } - src += 3; - } else { - src++; - } - } else if (*src == '+') { - *p++ = ' '; - decoded_len++; - src++; - } else { - *p++ = *src++; - decoded_len++; - } - } - *p = '\0'; -} - -// === ОТРИСОВКА === -void print_breadcrumb(buffer_t *buf, const char *display_path) { - buffer_append(buf, "
\n"); - buffer_append(buf, " 🏠 Главная"); - if (display_path && display_path[0]) { - char temp_path[1024] = ""; - char encoded[2048]; - char *path_copy = strdup(display_path); - char *token = strtok(path_copy, "/"); - while (token) { - buffer_append(buf, " / "); - if (temp_path[0]) strcat(temp_path, "/"); - strcat(temp_path, token); - url_encode(temp_path, encoded, sizeof(encoded)); - char safe_token[512]; - html_escape(token, safe_token, sizeof(safe_token)); - char link[4096]; - snprintf(link, sizeof(link), "%s", encoded, safe_token); - buffer_append(buf, link); - token = strtok(NULL, "/"); - } - free(path_copy); - } - buffer_append(buf, "\n
\n"); -} - -void print_password_form(buffer_t *buf, const char *folder_name) { - buffer_append(buf, "
\n"); - buffer_append(buf, "
\n"); - buffer_append(buf, "
🔒
\n"); - buffer_append(buf, "

Папка защищена паролем

\n"); - buffer_append(buf, "

Введите пароль для доступа к папке "); - char safe_name[512]; - html_escape(folder_name, safe_name, sizeof(safe_name)); - buffer_append(buf, safe_name); - buffer_append(buf, "

\n"); - buffer_append(buf, "
\n"); - buffer_append(buf, " \n"); - buffer_append(buf, " \n"); - buffer_append(buf, " \n"); - buffer_append(buf, "
\n"); - buffer_append(buf, "

"); - char *query_string = getenv("QUERY_STRING"); - if (query_string && strstr(query_string, "error=1")) { - buffer_append(buf, "❌ Неверный пароль! Попробуйте снова."); - } - buffer_append(buf, "

\n"); - buffer_append(buf, " ← Вернуться на главную\n"); - buffer_append(buf, "
\n"); - buffer_append(buf, "
\n"); -} - -void print_content(buffer_t *buf, const char *base_path, const char *display_path) { - DIR *dir; - struct dirent *entry; - struct stat file_stat; - char full_path[1024]; - entry_t *entries = malloc(sizeof(entry_t) * g_config.max_entries); - if (!entries) { - buffer_append(buf, "
Ошибка выделения памяти
"); - return; - } - int entry_count = 0, dir_count = 0, file_count = 0; - long long total_size = 0; - int is_recursive_search = 0; - char folder_name[256] = ""; - if (display_path && display_path[0]) { - char *last_slash = strrchr(display_path, '/'); - if (last_slash) strcpy(folder_name, last_slash + 1); - else strcpy(folder_name, display_path); - char *query_string = getenv("QUERY_STRING"); - char *password = NULL; - if (query_string) { - char *pass_start = strstr(query_string, "password="); - if (pass_start) { - pass_start += 9; - char *pass_end = strchr(pass_start, '&'); - int pass_len = pass_end ? pass_end - pass_start : strlen(pass_start); - if (pass_len > 0 && pass_len < 256) { - char pass_buf[256]; - strncpy(pass_buf, pass_start, pass_len); - pass_buf[pass_len] = '\0'; - char decoded_pass[256]; - url_decode_enhanced(pass_buf, decoded_pass, sizeof(decoded_pass)); - password = decoded_pass; - } - } - } - if (is_folder_protected(folder_name)) { - if (!password || !check_folder_password(folder_name, password)) { - print_password_form(buf, folder_name); - free(entries); - return; - } - } - } - if (g_params.search[0] != '\0') { - int result_count = 0; - search_recursive(g_config.base_path, "", g_params.search, entries, &result_count, g_config.max_entries); - if (result_count == 0) { - buffer_append(buf, "
\n"); - buffer_append(buf, "
🔍
\n"); - buffer_append(buf, "

Ничего не найдено

\n"); - buffer_append(buf, "

По запросу \""); - char safe_search[512]; - html_escape(g_params.search, safe_search, sizeof(safe_search)); - buffer_append(buf, safe_search); - buffer_append(buf, "\" ничего не найдено

\n"); - buffer_append(buf, "
\n"); - free(entries); - return; - } - entry_count = result_count; - is_recursive_search = 1; - for (int i = 0; i < entry_count; i++) { - if (entries[i].is_dir) { - dir_count++; - total_size += entries[i].dir_size; - } else { - file_count++; - total_size += entries[i].size; - } - } - } else { - dir = opendir(base_path); - if (!dir) { - char alt_path[1024]; - snprintf(alt_path, sizeof(alt_path), "%s", g_config.base_path); - if (display_path[0]) { - char *encoded = strdup(display_path); - url_decode_enhanced(encoded, alt_path + strlen(alt_path), sizeof(alt_path) - strlen(alt_path)); - free(encoded); - } - dir = opendir(alt_path); - if (!dir) { - buffer_append(buf, "
\n"); - buffer_append(buf, "
📁
\n"); - buffer_append(buf, "

Ошибка открытия директории

\n"); - char error_msg[512]; - snprintf(error_msg, sizeof(error_msg), "

Путь: %s

\n", base_path); - buffer_append(buf, error_msg); - snprintf(error_msg, sizeof(error_msg), "

Ошибка: %s

\n", strerror(errno)); - buffer_append(buf, error_msg); - buffer_append(buf, "

← Вернуться на главную

\n"); - buffer_append(buf, "
\n"); - free(entries); - return; - } - } - while ((entry = readdir(dir)) != NULL && entry_count < g_config.max_entries) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; - int hidden = 0; - for (int i = 0; i < g_config.hidden_dirs_count; i++) { - if (strcmp(entry->d_name, g_config.hidden_dirs[i]) == 0) { hidden = 1; break; } - } - for (int i = 0; i < g_config.hidden_files_count; i++) { - if (strcmp(entry->d_name, g_config.hidden_files[i]) == 0) { hidden = 1; break; } - } - if (entry->d_name[0] == '.') hidden = 1; - if (hidden) continue; - snprintf(full_path, sizeof(full_path), "%s/%s", base_path, entry->d_name); - if (stat(full_path, &file_stat) == 0) { - strncpy(entries[entry_count].name, entry->d_name, sizeof(entries[0].name) - 1); - entries[entry_count].name[sizeof(entries[0].name) - 1] = '\0'; - if (S_ISDIR(file_stat.st_mode)) { - entries[entry_count].is_dir = 1; - entries[entry_count].size = 0; - entries[entry_count].mtime = file_stat.st_mtime; - entries[entry_count].file_count = count_files_in_dir(full_path); - entries[entry_count].dir_size = get_dir_size(full_path); - total_size += entries[entry_count].dir_size; - if (is_folder_protected(entry->d_name)) { - strcpy(entries[entry_count].icon, "🔒"); - entries[entry_count].is_protected = 1; - } else { - strcpy(entries[entry_count].icon, "📁"); - entries[entry_count].is_protected = 0; - } - char new_path[2048]; - snprintf(new_path, sizeof(new_path), "%s%s%s", display_path, display_path[0] ? "/" : "", entries[entry_count].name); - url_encode(new_path, entries[entry_count].encoded_path, sizeof(entries[0].encoded_path)); - dir_count++; - } else if (S_ISREG(file_stat.st_mode)) { - entries[entry_count].is_dir = 0; - entries[entry_count].size = file_stat.st_size; - entries[entry_count].mtime = file_stat.st_mtime; - entries[entry_count].file_count = 0; - entries[entry_count].dir_size = 0; - strcpy(entries[entry_count].icon, get_file_icon(entry->d_name)); - entries[entry_count].is_protected = 0; - char encoded_filename[1024]; - url_encode(entry->d_name, encoded_filename, sizeof(encoded_filename)); - snprintf(entries[entry_count].file_url, sizeof(entries[0].file_url), "%s%s%s", display_path, display_path[0] ? "/" : "", encoded_filename); - total_size += file_stat.st_size; - file_count++; - } else { - continue; - } - entry_count++; - } - } - closedir(dir); - if (entry_count == 0) { - buffer_append(buf, "
\n"); - buffer_append(buf, "
📄
\n"); - buffer_append(buf, "

Здесь пусто

\n"); - buffer_append(buf, "

В этой директории нет файлов или папок

\n"); - buffer_append(buf, "
\n"); - free(entries); - return; - } - } - qsort(entries, entry_count, sizeof(entry_t), compare_entries_sorted); - char encoded_path[1024]; - url_encode(display_path, encoded_path, sizeof(encoded_path)); - char safe_search[512]; - html_escape(g_params.search, safe_search, sizeof(safe_search)); - buffer_append(buf, "
\n"); - buffer_append(buf, "
\n"); - buffer_append(buf, "
\n"); - buffer_append(buf, " \n"); - buffer_append(buf, " \n"); - buffer_append(buf, " \n"); - buffer_append(buf, "
\n"); - buffer_append(buf, "
\n"); - buffer_append(buf, "
\n"); - buffer_append(buf, " Сортировка:\n"); - buffer_append(buf, " 📝 Имя\n"); - buffer_append(buf, " 📊 Размер\n"); - buffer_append(buf, " 📅 Дата\n"); - buffer_append(buf, "
\n"); - buffer_append(buf, "
\n"); - if (is_recursive_search) { - buffer_append(buf, "
"); - buffer_append(buf, "🔍 Результаты поиска по всему сайту: "); - char tmp[32]; - snprintf(tmp, sizeof(tmp), "%d", entry_count); - buffer_append(buf, tmp); - buffer_append(buf, " файлов/папок найдено
\n"); - } - buffer_append(buf, "\n"); - if (is_recursive_search) { - char stats[256]; - snprintf(stats, sizeof(stats), - "
\n Найдено: папок %d | файлов %d\n
\n", - dir_count, file_count); - buffer_append(buf, stats); - } else { - char total_size_str[32]; - format_size(total_size, total_size_str); - char stats[256]; - snprintf(stats, sizeof(stats), - "
\n Папки: %d | Файлы: %d | Общий размер: %s\n
\n", - dir_count, file_count, total_size_str); - buffer_append(buf, stats); - } - free(entries); -} - -void print_template(const char *base_path, const char *display_path) { - FILE *file = fopen(g_config.template_path, "r"); - if (!file) { - printf("Error: Cannot read template\n"); - return; - } - buffer_t output; - buffer_init(&output); - char line[4096]; - while (fgets(line, sizeof(line), file)) { - if (strstr(line, "")) { - print_breadcrumb(&output, display_path); - } else if (strstr(line, "")) { - print_content(&output, base_path, display_path); - } else { - buffer_append(&output, line); - } - } - fclose(file); - fwrite(output.data, 1, output.size, stdout); - buffer_free(&output); -} - -int main() { - setlocale(LC_ALL, "en_US.UTF-8"); - setlocale(LC_CTYPE, "en_US.UTF-8"); - if (load_config("/home/romkazvo/www/cgi-bin/config.ini", &g_config) != 0) { - set_default_config(&g_config); - } - strcpy(g_params.sort_by, "name"); - g_params.sort_order = 1; - g_params.search[0] = '\0'; - g_params.recursive = 0; - char *query_string = getenv("QUERY_STRING"); - char display_path[1024] = ""; - char safe_display_path[1024] = ""; - char base_path[1024]; - strcpy(base_path, g_config.base_path); - if (query_string) { - char *path_start = strstr(query_string, "path="); - if (path_start) { - path_start += 5; - char *path_end = strchr(path_start, '&'); - int path_len = path_end ? path_end - path_start : strlen(path_start); - if (path_len > 0 && path_len < sizeof(display_path) - 1) { - char encoded_path[1024]; - strncpy(encoded_path, path_start, path_len); - encoded_path[path_len] = '\0'; - url_decode_enhanced(encoded_path, display_path, sizeof(display_path)); - if (!is_safe_path(display_path)) { - display_path[0] = '\0'; - strcpy(base_path, g_config.base_path); - } else { - strncpy(safe_display_path, display_path, sizeof(safe_display_path) - 1); - safe_display_path[sizeof(safe_display_path) - 1] = '\0'; - safe_path_join(base_path, sizeof(base_path), g_config.base_path, safe_display_path); - } - } - } - char *sort_start = strstr(query_string, "sort="); - if (sort_start) { - sort_start += 5; - char *sort_end = strchr(sort_start, '&'); - int sort_len = sort_end ? sort_end - sort_start : strlen(sort_start); - if (sort_len > 0 && sort_len < sizeof(g_params.sort_by)) { - strncpy(g_params.sort_by, sort_start, sort_len); - g_params.sort_by[sort_len] = '\0'; - } - } - char *search_start = strstr(query_string, "search="); - if (search_start) { - search_start += 7; - char *search_end = strchr(search_start, '&'); - int search_len = search_end ? search_end - search_start : strlen(search_start); - if (search_len > 0 && search_len < sizeof(g_params.search) - 1) { - char encoded_search[256]; - strncpy(encoded_search, search_start, search_len); - encoded_search[search_len] = '\0'; - url_decode_enhanced(encoded_search, g_params.search, sizeof(g_params.search)); - if (g_params.search[0] != '\0') { - g_params.recursive = 1; - } - } - } - if (strstr(query_string, "password=")) { - char *error = strstr(query_string, "error=1"); - if (!error) { - char folder_name[256] = ""; - if (display_path[0]) { - char *last_slash = strrchr(display_path, '/'); - if (last_slash) strcpy(folder_name, last_slash + 1); - else strcpy(folder_name, display_path); - if (is_folder_protected(folder_name)) { - char *pass_start = strstr(query_string, "password="); - if (pass_start) { - pass_start += 9; - char *pass_end = strchr(pass_start, '&'); - int pass_len = pass_end ? pass_end - pass_start : strlen(pass_start); - if (pass_len > 0 && pass_len < 256) { - char pass_buf[256]; - strncpy(pass_buf, pass_start, pass_len); - pass_buf[pass_len] = '\0'; - char decoded_pass[256]; - url_decode_enhanced(pass_buf, decoded_pass, sizeof(decoded_pass)); - if (decoded_pass[0] == '\0') { - char encoded_path[1024]; - url_encode(display_path, encoded_path, sizeof(encoded_path)); - printf("Status: 302 Found\r\n"); - printf("Location: /cgi-bin/index.cgi?path=%s&error=1\r\n\r\n", encoded_path); - return 0; - } - if (!check_folder_password(folder_name, decoded_pass)) { - char encoded_path[1024]; - url_encode(display_path, encoded_path, sizeof(encoded_path)); - printf("Status: 302 Found\r\n"); - printf("Location: /cgi-bin/index.cgi?path=%s&error=1\r\n\r\n", encoded_path); - return 0; - } - } else { - char encoded_path[1024]; - url_encode(display_path, encoded_path, sizeof(encoded_path)); - printf("Status: 302 Found\r\n"); - printf("Location: /cgi-bin/index.cgi?path=%s&error=1\r\n\r\n", encoded_path); - return 0; - } - } - } - } - } - } - } - printf("Content-type: text/html; charset=utf-8\n\n"); - print_template(base_path, display_path); - return 0; -} diff --git a/index.cgi b/index.cgi deleted file mode 100755 index 5a429eeaa7bdd5504606bdad40ca38bca2092c2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35424 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 ii-P(?EtorX$0@w7SCdV~%}C`tJ0!)aaRuT) -#include -#include -#include - -long get_nginx_memory() { - long total_kb = 0; - char command[] = "ps -o rss= -C nginx 2>/dev/null"; - - FILE *ps = popen(command, "r"); - if (!ps) return 0; - - char line[64]; - while (fgets(line, sizeof(line), ps)) { - long kb; - if (sscanf(line, "%ld", &kb) == 1) { - total_kb += kb; - } - } - pclose(ps); - - return total_kb; -} - -int get_process_memory(const char *process_name, long *memory_kb) { - char command[256]; - snprintf(command, sizeof(command), "ps -o rss= -C %s 2>/dev/null | head -1", process_name); - - FILE *ps = popen(command, "r"); - if (!ps) return 0; - - int result = fscanf(ps, "%ld", memory_kb); - pclose(ps); - - return result == 1; -} - -int main() { - printf("Content-type: text/plain; charset=utf-8\n\n"); - - // Получаем память процессов - long busybox_kb = 0, nginx_kb = 0; - - get_process_memory("busybox", &busybox_kb); - nginx_kb = get_nginx_memory(); - - // Выводим в одну строку - printf("BusyBox: %ld KB | Nginx: %ld MB | Всего: %.1f MB", - busybox_kb, - nginx_kb / 1024, - (busybox_kb + nginx_kb) / 1024.0); - - return 0; -} \ No newline at end of file diff --git a/status.cgi b/status.cgi deleted file mode 100755 index 09ddee7a394d9f431e5b5f8f9412e5eb835b49b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16392 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 gZZj8;ZZ)|{N8{|5b#Yo>&Aw@esj -#include -#include -#include - -int main() { - // Проверяем, существует ли файл стилей - char css_path[1024] = "/home/romkazvo/www/cgi-bin/style.css"; - struct stat st; - - if (stat(css_path, &st) != 0) { - printf("Status: 404 Not Found\n"); - printf("Content-type: text/plain\n\n"); - printf("CSS file not found\n"); - return 1; - } - - // Отдаем CSS с правильными заголовками - printf("Content-type: text/css\n"); - printf("Cache-Control: public, max-age=3600\n\n"); // Кэшируем на 1 час - - FILE *css_file = fopen(css_path, "r"); - if (!css_file) { - printf("Status: 500 Internal Server Error\n"); - printf("Content-type: text/plain\n\n"); - printf("Cannot open CSS file\n"); - return 1; - } - - char buffer[4096]; - size_t bytes_read; - while ((bytes_read = fread(buffer, 1, sizeof(buffer), css_file)) > 0) { - fwrite(buffer, 1, bytes_read, stdout); - } - - fclose(css_file); - return 0; -} \ No newline at end of file diff --git a/style.cgi b/style.cgi deleted file mode 100755 index 833b3aefa0b5dfd86eed4af833517d8667530fa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16248 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 YBUCuo%f3w@)QbORhw@k#3J9s<-;RF#K>z>%