File: _util.lua

package info (click to toggle)
lua-uri 0.1%2B20130926%2Bgit14fa255d-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 404 kB
  • sloc: makefile: 53
file content (130 lines) | stat: -rw-r--r-- 3,877 bytes parent folder | download | duplicates (3)
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
local M = { _NAME = "uri._util" }

local string_char, string_format = string.char, string.format

-- Build a char->hex map
local escapes = {}
for i = 0, 255 do
    escapes[string_char(i)] = string_format("%%%02X", i)
end
local function _encode_char (chr) return escapes[chr] end

function M.uri_encode (text, patn)
    if not text then return end
    if not patn then
        -- Default unsafe characters.  RFC 2732 ^(uric - reserved)
        -- TODO - this should be updated to the latest RFC.
        patn = "^A-Za-z0-9%-_.!~*'()"
    end
    return (text:gsub("([" .. patn .. "])", _encode_char))
end

function M.uri_decode (str, patn)
    -- Note from RFC1630:  "Sequences which start with a percent sign
    -- but are not followed by two hexadecimal characters are reserved
    -- for future extension"
    if not str then return end
    if patn then patn = "[" .. patn .. "]" end
    return (str:gsub("%%(%x%x)", function (hex)
        local char = string_char(tonumber(hex, 16))
        return (patn and not char:find(patn)) and "%" .. hex or char
    end))
end

-- This is the remove_dot_segments algorithm from RFC 3986 section 5.2.4.
-- The input buffer is 's', the output buffer 'path'.
function M.remove_dot_segments (s)
    local path = ""

    while s ~= "" do
        if s:find("^%.%.?/") then                       -- A
            s = s:gsub("^%.%.?/", "", 1)
        elseif s:find("^/%./") or s == "/." then        -- B
            s = s:gsub("^/%./?", "/", 1)
        elseif s:find("^/%.%./") or s == "/.." then     -- C
            s = s:gsub("^/%.%./?", "/", 1)
            if path:find("/") then
                path = path:gsub("/[^/]*$", "", 1)
            else
                path = ""
            end
        elseif s == "." or s == ".." then               -- D
            s = ""
        else                                            -- E
            local _, p, seg = s:find("^(/?[^/]*)")
            s = s:sub(p + 1)
            path = path .. seg
        end
    end

    return path
end

-- TODO - wouldn't this be better as a method on string?  s:split(patn)
function M.split (patn, s, max)
    if s == "" then return {} end

    local i, j = 1, string.find(s, patn)
    if not j then return { s } end

    local list = {}
    while true do
        if #list + 1 == max then list[max] = s:sub(i); return list end
        list[#list + 1] = s:sub(i, j - 1)
        i = j + 1
        j = string.find(s, patn, i)
        if not j then
            list[#list + 1] = s:sub(i)
            break
        end
    end
    return list
end

function M.attempt_require (modname)
    local ok, result = pcall(require, modname)
    if ok then
        return result
    elseif type(result) == "string" and
           result:find("module '.*' not found") then
        return nil
    else
        error(result)
    end
end

function M.subclass_of (class, baseclass)
    class.__index = class
    class.__tostring = baseclass.__tostring
    class._SUPER = baseclass
    setmetatable(class, baseclass)
end

function M.do_class_changing_change (uri, baseclass, changedesc, newvalue,
                                     changefunc)
    local tmpuri = {}
    setmetatable(tmpuri, baseclass)
    for k, v in pairs(uri) do tmpuri[k] = v end
    changefunc(tmpuri, newvalue)
    tmpuri._uri = nil

    local foo, err = tmpuri:init()
    if not foo then
        error("URI not valid after " .. changedesc .. " changed to '" ..
              newvalue .. "': " .. err, 3)
    end

    setmetatable(uri, getmetatable(tmpuri))
    for k in pairs(uri) do uri[k] = nil end
    for k, v in pairs(tmpuri) do uri[k] = v end
end

function M.uri_part_not_allowed (class, method)
    class[method] = function (self, new)
        if new then error(method .. " not allowed on this kind of URI") end
        return self["_" .. method]
    end
end

return M
-- vi:ts=4 sw=4 expandtab