aboutsummaryrefslogtreecommitdiff
path: root/server.lua
blob: efdce3227be9b23dfe69890398c54481bd20056b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
local lfs = require "lfs"
local data_dir = "/home/gemini/data"

local function handle_gopher()
    local sock = ngx.req.socket(true)
    if not sock then return end
    
    sock:settimeout(4000)
    local line, err = sock:receive("*l")
    if not line then line = "" end

    -- Очищаем запрос от перевода строки
    local selector = line:gsub("%s+", "")
    local out = {}

    -- =========================================================================
    -- ГЛАВНОЕ МЕНЮ 
    -- =========================================================================
    if selector == "" or selector == "/" then
        table.insert(out, "i[  GOPHER-АРХИВ ]\t\tlocalhost\t70")
        table.insert(out, "i=========================================================\t\tlocalhost\t70")
        table.insert(out, "iАвтономный листингдокументации.\t\tlocalhost\t70\n")

        -- Сканируем папки проектов в data
        for dir in lfs.dir(data_dir) do
            if dir ~= "." and dir ~= ".." and dir ~= "README.md" then
                local attr = lfs.attributes(data_dir .. "/" .. dir)
                if attr and attr.mode == "directory" then
                    -- Тип 1 означает директорию (папку) в протоколе Gopher
                    table.insert(out, string.format("1// %s\t/%s\tasustem.ru\t70", dir, dir))
                end
            end
        end
        
        table.insert(out, "\n1[ ВЕРНУТЬСЯ В КОРЕНЬ ]\t/\tasustem.ru\t70")
        table.insert(out, "i---------------------------------------------------------\t\tlocalhost\t70")
        table.insert(out, "iGopher-сервер на базе OpenResty/LuaJIT. Ссылка на капсулу:\t\tlocalhost\t70")
        table.insert(out, ".") -- Точка на отдельной строке — маркер конца передачи в Gopher

        sock:send(table.concat(out, "\r\n") .. "\r\n")
        return
    end

    -- =========================================================================
    -- СЛУЖЕБНЫЙ ЛИСТИНГ КОНКРЕТНОЙ ПАПКИ ИЛИ ОТДАЧА ФАЙЛА
    -- =========================================================================
    local local_path = data_dir .. selector
    local attr = lfs.attributes(local_path)

    if not attr then
        sock:send("Файл или папка не найдены на сервере.\t\tlocalhost\t70\r\n.\r\n")
        return
    end

    -- Если это папка проекта — выводим список её файлов
    if attr.mode == "directory" then
        table.insert(out, string.format("i[ СОДЕРЖИМОЕ ПРОЕКТА: %s ]\t\tlocalhost\t70", selector:sub(2)))
        table.insert(out, "i=========================================================\t\tlocalhost\t70")
        
        for file in lfs.dir(local_path) do
            if file ~= "." and file ~= ".." then
                local f_path = selector .. "/" .. file
                local g_type = "0" -- По умолчанию тип 0 (текст/документ)
                
                if file:match("%.jpg$") or file:match("%.png$") then
                    g_type = "I" -- Тип I означает графический файл (image)
                elseif file:match("%.qet$") or file:match("%.pdf$") then
                    g_type = "9" -- Тип 9 означает бинарный файл (binary)
                end
                
                table.insert(out, string.format("%s%s\t%s\t\t70", g_type, file, f_path))
            end
        end
        
        table.insert(out, "\n1[ НАЗАД В ГЛАВНОЕ МЕНЮ ]\t/\\t70")
        table.insert(out, ".")
        sock:send(table.concat(out, "\r\n") .. "\r\n")

    -- Если это файл — стримим его бинарное содержимое в сокет напрямую
    elseif attr.mode == "file" then
        local f = io.open(local_path, "rb")
        if f then
            local content = f:read("*all")
            f:close()
            sock:send(content) -- В Gopher файлы отдаются без заголовков, чистым потоком
        end
    end
end

handle_gopher()