File: proxy.lua

package info (click to toggle)
luakit 1%3A2.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,844 kB
  • sloc: ansic: 12,519; makefile: 140; ruby: 79; sh: 48
file content (288 lines) | stat: -rw-r--r-- 9,015 bytes parent folder | download | duplicates (2)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
--- Dynamic proxy settings.
--
-- This module offers a simple and convenient user interface for using a proxy
-- while browsing the web. Users can add entries for specific proxy addresses,
-- and easily switch between using any of these proxies to redirect traffic. It
-- is also possible to use the system proxy, or disable proxy use altogether.
--
-- # Adding a new proxy entry
--
-- To add a new proxy entry, use the `:proxy` command, with the name of the
-- proxy and the web address of the proxy as arguments:`:proxy <name> <address>`.
--
-- ## Example
--
-- To add a proxy entry for a local proxy running on port 8000, run the
-- following:
--
--     :proxy proxy-name socks://localhost:8000
--
-- # Viewing and changing the current proxy
--
-- It is currently easiest to view the current proxy by opening the proxy menu
-- with the `:proxy` command. The current proxy will be shown in black text, while any
-- inactive proxies will be shown in light gray text.
--
-- @module proxy
-- @copyright Piotr HusiatyƄski <phusiatynski@gmail.com>

local lousy = require("lousy")
local theme = lousy.theme.get()
local window = require("window")
local binds, modes = require("binds"), require("modes")
local new_mode = require("modes").new_mode
local add_binds, add_cmds = modes.add_binds, modes.add_cmds
local menu_binds = binds.menu_binds

local _, minor = luakit.webkit_version:match("^(%d+)%.(%d+)%.")
if tonumber(minor) < 16 then
    msg.error("proxy support in luakit requires WebKit2GTK 2.16 or later")
    msg.error("this version: %s", luakit.webkit_version)
    return {}
end

local _M = {}

--- Module global variables
local proxies_file = luakit.data_dir .. '/proxymenu'

local proxies = {}
local noproxy = { address = '' }
local active = noproxy

-- Helper function to update text in proxy indicator
local update_proxy_indicator = function (w)
    local name = _M.get_active().name
    local proxyi = w.sbar.r.proxyi
    if name and name ~= "None" then
        local text = string.format("[%s]", name)
        if proxyi.text ~= text then proxyi.text = text end
        proxyi:show()
    else
        proxyi:hide()
    end
end

local update_proxy_indicators = function ()
    for _, w in pairs(window.bywidget) do
        update_proxy_indicator(w)
    end
end

--- Get an ordered list of proxy names.
-- @treturn table List of proxy names.
function _M.get_names()
    return lousy.util.table.keys(proxies)
end

--- Get the address of proxy given by name.
-- @tparam string name The name of a proxy.
-- @treturn string The address of the proxy.
function _M.get(name)
    return proxies[name]
end

--- Get the active proxy configuration.
-- @treturn table The active proxy configuration. Two fields are present:
-- `name` and `address`.
function _M.get_active()
    return active
end

--- Load the proxies list from a file.
-- @tparam string fd_name Custom proxy storage or `nil` to use default.
function _M.load(fd_name)

    -- always add default entries
    -- they will be overwritten when loaded from the file
    proxies["None"]   = "no_proxy"
    proxies["System"] = "default"

    -- load file, if it exists
    fd_name = fd_name or proxies_file
    if not os.exists(fd_name) then return end
    local strip = lousy.util.string.strip

    for line in io.lines(fd_name) do
        local status, name, address = string.match(line, "^(.)%s(.+)%s(.+)$")
        if address then
            name, address = strip(name), strip(address)
            if status == '*' then
                active = { address = address, name = name }
            end
            proxies[name] = address
        end
    end

    if active and active.address ~= '' then
        soup.proxy_uri = active.address
        update_proxy_indicators()
    end
end

--- Save the proxies list to a file.
-- @tparam string fd_name Custom proxy storage or `nil` to use default.
function _M.save(fd_name)
    local fd = io.open(fd_name or proxies_file, "w")
    for name, address in pairs(proxies) do
        if address ~= "" then
            local status = (active.name == name and '*') or ' '
            fd:write(string.format("%s %s %s\n", status, name, address))
        end
    end
    io.close(fd)
end

--- Add a new proxy server to current list.
-- @tparam string name Proxy configuration name.
-- @tparam string address Proxy server address.
-- @tparam boolean save_file Do not save configuration if `false`.
function _M.set(name, address, save_file)
    name = lousy.util.string.strip(name)
    if not string.match(name, "^([%w%p]+)$") then
        error("Invalid proxy name: " .. name)
    end
    proxies[name] = lousy.util.string.strip(address)
    if save_file ~= false then _M.save() end
end

--- Delete a proxy from the proxy list.
-- @tparam string name Proxy server name.
function _M.del(name)
    name = lousy.util.string.strip(name)
    if proxies[name] then
        -- if deleted proxy was the active one, turn proxy off
        if name == active.name then
            active = noproxy
        end
        proxies[name] = nil
        _M.save()
    end
end

--- Set given proxy to active. Return true on success, else false.
-- @tparam string name Proxy configuration name or `nil` to unset proxy.
function _M.set_active(name)
    if name then
        name = lousy.util.string.strip(name)
        if not proxies[name] then
            error("Unknown proxy: " .. name)
        end
        active = { name = name, address = proxies[name] }
    else
        active = noproxy
    end
    soup.proxy_uri = active.address
    _M.save()
    return true
end

-- Create a proxy indicator widget and add it to the status bar
window.add_signal("init", function (w)
    local r = w.sbar.r
    r.proxyi = widget{type="label"}
    r.layout:pack(r.proxyi)
    r.layout:reorder(r.proxyi, 2)

    r.proxyi.fg = theme.proxyi_sbar_fg
    r.proxyi.font = theme.proxyi_sbar_font
    update_proxy_indicators()
end)

new_mode("proxymenu", {
    enter = function (w)
        local rows = {{ "Proxy Name", " Server address", title = true }}
        for _, name in ipairs(_M.get_names()) do
            local address = _M.get(name)
            table.insert(rows, {
                "  " .. name, " " .. address,
                name = name, address = lousy.util.escape(address),
            })
        end
        -- Color menu rows according to the currently used proxy
        local current_proxy = soup.proxy_uri
        local afg, ifg = theme.proxy_active_menu_fg, theme.proxy_inactive_menu_fg
        local abg, ibg = theme.proxy_active_menu_bg, theme.proxy_inactive_menu_bg
        for i=2,#rows do
            rows[i].fg = (rows[i].address == current_proxy) and afg or ifg
            rows[i].bg = (rows[i].address == current_proxy) and abg or ibg
        end

        w.menu:build(rows)
        w:notify("Use j/k to move, d delete, e edit, a add, Return activate.", false)
    end,

    leave = function (w)
        w.menu:hide()
    end,
})

add_cmds({
    { ":proxy", "Change the current proxy or add a new proxy entry.",
        function (w, o)
            local a = o.arg
            local params = lousy.util.string.split(a or '')
            if not a then
                w:set_mode("proxymenu")
            elseif #params == 2 then
                local name, address = unpack(params)
                _M.set(name, address)
            else
                w:error("Bad usage. Correct format :proxy or :proxy <name> <address>")
            end
        end },
})

add_binds("proxymenu", lousy.util.table.join({
    -- Select proxy
    { "<Return>", "Use the currently highlighted proxy.",
        function (w)
            local row = w.menu:get()
            if row and row.address then
                if row.name then
                    _M.set_active(row.name)
                else
                    soup.proxy_uri = row.address
                end
                w:set_mode()
                update_proxy_indicators()
                if row.name then
                    w:notify(string.format("Using proxy: %s (%s)", row.name, row.address))
                elseif row.address == "default" then
                    w:notify("Using system default proxy.")
                else
                    w:notify("Unset proxy.")
                end
            end
        end },

    -- Delete proxy
    { "d", "Delete the currently highlighted proxy entry.",
        function (w)
            local row = w.menu:get()
            if row and row.name then
                _M.del(row.name)
                w.menu:del()
            end
        end },

    -- Edit proxy
    { "e", "Edit the currently highlighted proxy entry.",
        function (w)
            local row = w.menu:get()
            if row and row.name then
                w:enter_cmd(string.format(":proxy %s %s", row.name, row.address))
            end
        end },

    -- New proxy
    { "a", "Begin adding a new proxy entry.",
    function (w) w:enter_cmd(":proxy ") end },
}, menu_binds))

-- Initialize module
_M.load()

return _M

-- vim: et:sw=4:ts=8:sts=4:tw=80