Annotate

util/jid.lua @ 13265:6ac5ad578565

mod_cron: Load last task run time inside task runner to fix async This ensures that all interactions with storage happen inside an async thread, allowing async waiting to be performed in storage drivers.
author Kim Alvefur <zash@zash.se>
date Sat, 14 Oct 2023 22:32:33 +0200
parent 12975:d10957394a3c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1523
841d61be198f Remove version number from copyright headers
Matthew Wild <mwild1@gmail.com>
parents: 1171
diff changeset
1 -- Prosody IM
2923
b7049746bd29 Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents: 2245
diff changeset
2 -- Copyright (C) 2008-2010 Matthew Wild
b7049746bd29 Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents: 2245
diff changeset
3 -- Copyright (C) 2008-2010 Waqas Hussain
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 4407
diff changeset
4 --
758
b1885732e979 GPL->MIT!
Matthew Wild <mwild1@gmail.com>
parents: 717
diff changeset
5 -- This project is MIT/X11 licensed. Please see the
b1885732e979 GPL->MIT!
Matthew Wild <mwild1@gmail.com>
parents: 717
diff changeset
6 -- COPYING file in the source package for more information.
519
cccd610a0ef9 Insert copyright/license headers
Matthew Wild <mwild1@gmail.com>
parents: 384
diff changeset
7 --
cccd610a0ef9 Insert copyright/license headers
Matthew Wild <mwild1@gmail.com>
parents: 384
diff changeset
8
cccd610a0ef9 Insert copyright/license headers
Matthew Wild <mwild1@gmail.com>
parents: 384
diff changeset
9
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
10
7321
a7199fc8a50e util.jid: Import select() into local (fixes traceback, tests on Lua 5.2)
Kim Alvefur <zash@zash.se>
parents: 7296
diff changeset
11 local select = select;
5944
f3817912e8b2 util.jid: Strip trailing '.' when normalizing hostnames
Matthew Wild <mwild1@gmail.com>
parents: 4407
diff changeset
12 local match, sub = string.match, string.sub;
12975
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12769
diff changeset
13 local nodeprep = require "prosody.util.encodings".stringprep.nodeprep;
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12769
diff changeset
14 local nameprep = require "prosody.util.encodings".stringprep.nameprep;
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12769
diff changeset
15 local resourceprep = require "prosody.util.encodings".stringprep.resourceprep;
367
cc26368294a3 Remove some declarations I added while debugging
Matthew Wild <mwild1@gmail.com>
parents: 366
diff changeset
16
4407
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
17 local escapes = {
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
18 [" "] = "\\20"; ['"'] = "\\22";
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
19 ["&"] = "\\26"; ["'"] = "\\27";
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
20 ["/"] = "\\2f"; [":"] = "\\3a";
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
21 ["<"] = "\\3c"; [">"] = "\\3e";
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
22 ["@"] = "\\40"; ["\\"] = "\\5c";
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
23 };
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
24 local unescapes = {};
11056
0b0a42542456 util.jid: Fix special escaping of '\' per XEP-0106
Kim Alvefur <zash@zash.se>
parents: 10358
diff changeset
25 local backslash_escapes = {};
0b0a42542456 util.jid: Fix special escaping of '\' per XEP-0106
Kim Alvefur <zash@zash.se>
parents: 10358
diff changeset
26 for k,v in pairs(escapes) do
0b0a42542456 util.jid: Fix special escaping of '\' per XEP-0106
Kim Alvefur <zash@zash.se>
parents: 10358
diff changeset
27 unescapes[v] = k;
0b0a42542456 util.jid: Fix special escaping of '\' per XEP-0106
Kim Alvefur <zash@zash.se>
parents: 10358
diff changeset
28 backslash_escapes[v] = v:gsub("\\", escapes)
0b0a42542456 util.jid: Fix special escaping of '\' per XEP-0106
Kim Alvefur <zash@zash.se>
parents: 10358
diff changeset
29 end
4407
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
30
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
31 local _ENV = nil;
8555
4f0f5b49bb03 vairious: Add annotation when an empty environment is set [luacheck]
Kim Alvefur <zash@zash.se>
parents: 7670
diff changeset
32 -- luacheck: std none
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
33
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
34 local function split(jid)
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
35 if jid == nil then return; end
3480
97831dfe7f72 util.jid: Fix parsing of JIDs with no nodepart and an @ in the resourcepart (thanks seth)
Matthew Wild <mwild1@gmail.com>
parents: 3375
diff changeset
36 local node, nodepos = match(jid, "^([^@/]+)@()");
9324
607b262da853 util.jid: Add missing semicolon
Kim Alvefur <zash@zash.se>
parents: 8555
diff changeset
37 local host, hostpos = match(jid, "^([^@/]+)()", nodepos);
12768
6e3aa3995eab util.jid: Remove redundant check from split() (micro-optimization?)
Matthew Wild <mwild1@gmail.com>
parents: 12605
diff changeset
38 local resource = host and match(jid, "^/(.+)$", hostpos);
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
39 if (host == nil) or ((resource == nil) and #jid >= hostpos) then return nil, nil, nil; end
366
5691edc7dd63 Improve jid.split() and jid.bare() to pass new test cases with invalid JIDs
Matthew Wild <mwild1@gmail.com>
parents: 365
diff changeset
40 return node, host, resource;
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
41 end
104
cfbd3b849f9e Fixed: util/jid.lua now returns module object
Waqas Hussain <waqas20@gmail.com>
parents: 29
diff changeset
42
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
43 local function bare(jid)
6891
7f76c77ddcb8 util.jid: Fix backout
Kim Alvefur <zash@zash.se>
parents: 6889
diff changeset
44 local node, host = split(jid);
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
45 if node ~= nil and host ~= nil then
6889
7f7920f2aebf Backout 7e820979fd9b (broke tests)
Kim Alvefur <zash@zash.se>
parents: 6777
diff changeset
46 return node.."@"..host;
7f7920f2aebf Backout 7e820979fd9b (broke tests)
Kim Alvefur <zash@zash.se>
parents: 6777
diff changeset
47 end
7f7920f2aebf Backout 7e820979fd9b (broke tests)
Kim Alvefur <zash@zash.se>
parents: 6777
diff changeset
48 return host;
365
a59300fc22ec Add jid.bare() helper function
Matthew Wild <mwild1@gmail.com>
parents: 109
diff changeset
49 end
a59300fc22ec Add jid.bare() helper function
Matthew Wild <mwild1@gmail.com>
parents: 109
diff changeset
50
10358
a77d9b3885bb util.jid: Add a 'strict' flag for jidprep calls
Kim Alvefur <zash@zash.se>
parents: 9324
diff changeset
51 local function prepped_split(jid, strict)
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
52 local node, host, resource = split(jid);
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
53 if host ~= nil and host ~= "." then
5944
f3817912e8b2 util.jid: Strip trailing '.' when normalizing hostnames
Matthew Wild <mwild1@gmail.com>
parents: 4407
diff changeset
54 if sub(host, -1, -1) == "." then -- Strip empty root label
f3817912e8b2 util.jid: Strip trailing '.' when normalizing hostnames
Matthew Wild <mwild1@gmail.com>
parents: 4407
diff changeset
55 host = sub(host, 1, -2);
f3817912e8b2 util.jid: Strip trailing '.' when normalizing hostnames
Matthew Wild <mwild1@gmail.com>
parents: 4407
diff changeset
56 end
10358
a77d9b3885bb util.jid: Add a 'strict' flag for jidprep calls
Kim Alvefur <zash@zash.se>
parents: 9324
diff changeset
57 host = nameprep(host, strict);
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
58 if host == nil then return; end
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
59 if node ~= nil then
10358
a77d9b3885bb util.jid: Add a 'strict' flag for jidprep calls
Kim Alvefur <zash@zash.se>
parents: 9324
diff changeset
60 node = nodeprep(node, strict);
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
61 if node == nil then return; end
717
ab428c579cbc util/jid: string prepping functions added: prepped_split and prep
Waqas Hussain <waqas20@gmail.com>
parents: 615
diff changeset
62 end
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
63 if resource ~= nil then
10358
a77d9b3885bb util.jid: Add a 'strict' flag for jidprep calls
Kim Alvefur <zash@zash.se>
parents: 9324
diff changeset
64 resource = resourceprep(resource, strict);
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
65 if resource == nil then return; end
717
ab428c579cbc util/jid: string prepping functions added: prepped_split and prep
Waqas Hussain <waqas20@gmail.com>
parents: 615
diff changeset
66 end
ab428c579cbc util/jid: string prepping functions added: prepped_split and prep
Waqas Hussain <waqas20@gmail.com>
parents: 615
diff changeset
67 return node, host, resource;
ab428c579cbc util/jid: string prepping functions added: prepped_split and prep
Waqas Hussain <waqas20@gmail.com>
parents: 615
diff changeset
68 end
ab428c579cbc util/jid: string prepping functions added: prepped_split and prep
Waqas Hussain <waqas20@gmail.com>
parents: 615
diff changeset
69 end
ab428c579cbc util/jid: string prepping functions added: prepped_split and prep
Waqas Hussain <waqas20@gmail.com>
parents: 615
diff changeset
70
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
71 local function join(node, host, resource)
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
72 if host == nil then return end
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
73 if node ~= nil and resource ~= nil then
2245
df9e18f5c808 util.jid: Add join(node, host, resource) function to join the components and return nil if invalid
Matthew Wild <mwild1@gmail.com>
parents: 1523
diff changeset
74 return node.."@"..host.."/"..resource;
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
75 elseif node ~= nil then
2245
df9e18f5c808 util.jid: Add join(node, host, resource) function to join the components and return nil if invalid
Matthew Wild <mwild1@gmail.com>
parents: 1523
diff changeset
76 return node.."@"..host;
12190
3616128cd2e3 util.jid: Explicitly check for nil rather than falsy
Kim Alvefur <zash@zash.se>
parents: 11056
diff changeset
77 elseif resource ~= nil then
2245
df9e18f5c808 util.jid: Add join(node, host, resource) function to join the components and return nil if invalid
Matthew Wild <mwild1@gmail.com>
parents: 1523
diff changeset
78 return host.."/"..resource;
df9e18f5c808 util.jid: Add join(node, host, resource) function to join the components and return nil if invalid
Matthew Wild <mwild1@gmail.com>
parents: 1523
diff changeset
79 end
6338
736c388748fd util.jid: Return early in join on invalid jids
Kim Alvefur <zash@zash.se>
parents: 5945
diff changeset
80 return host;
2245
df9e18f5c808 util.jid: Add join(node, host, resource) function to join the components and return nil if invalid
Matthew Wild <mwild1@gmail.com>
parents: 1523
diff changeset
81 end
6339
1c19464cde77 util.jid: Use existing join function in jid.prep
Kim Alvefur <zash@zash.se>
parents: 6338
diff changeset
82
10358
a77d9b3885bb util.jid: Add a 'strict' flag for jidprep calls
Kim Alvefur <zash@zash.se>
parents: 9324
diff changeset
83 local function prep(jid, strict)
a77d9b3885bb util.jid: Add a 'strict' flag for jidprep calls
Kim Alvefur <zash@zash.se>
parents: 9324
diff changeset
84 local node, host, resource = prepped_split(jid, strict);
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
85 return join(node, host, resource);
6339
1c19464cde77 util.jid: Use existing join function in jid.prep
Kim Alvefur <zash@zash.se>
parents: 6338
diff changeset
86 end
2245
df9e18f5c808 util.jid: Add join(node, host, resource) function to join the components and return nil if invalid
Matthew Wild <mwild1@gmail.com>
parents: 1523
diff changeset
87
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
88 local function compare(jid, acl)
3375
29e51e1c7c3d util.jid: compare() added, with some tests.
Kim Alvefur <zash@zash.se>
parents: 2923
diff changeset
89 -- compare jid to single acl rule
29e51e1c7c3d util.jid: compare() added, with some tests.
Kim Alvefur <zash@zash.se>
parents: 2923
diff changeset
90 -- TODO compare to table of rules?
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
91 local jid_node, jid_host, jid_resource = split(jid);
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
92 local acl_node, acl_host, acl_resource = split(acl);
12769
27e1d4354274 util.jid: Simplify boolean logic in conditionals
Matthew Wild <mwild1@gmail.com>
parents: 12768
diff changeset
93 if (acl_node == nil or acl_node == jid_node) and
27e1d4354274 util.jid: Simplify boolean logic in conditionals
Matthew Wild <mwild1@gmail.com>
parents: 12768
diff changeset
94 (acl_host == nil or acl_host == jid_host) and
27e1d4354274 util.jid: Simplify boolean logic in conditionals
Matthew Wild <mwild1@gmail.com>
parents: 12768
diff changeset
95 (acl_resource == nil or acl_resource == jid_resource) then
3375
29e51e1c7c3d util.jid: compare() added, with some tests.
Kim Alvefur <zash@zash.se>
parents: 2923
diff changeset
96 return true
29e51e1c7c3d util.jid: compare() added, with some tests.
Kim Alvefur <zash@zash.se>
parents: 2923
diff changeset
97 end
29e51e1c7c3d util.jid: compare() added, with some tests.
Kim Alvefur <zash@zash.se>
parents: 2923
diff changeset
98 return false
29e51e1c7c3d util.jid: compare() added, with some tests.
Kim Alvefur <zash@zash.se>
parents: 2923
diff changeset
99 end
29e51e1c7c3d util.jid: compare() added, with some tests.
Kim Alvefur <zash@zash.se>
parents: 2923
diff changeset
100
7296
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
101 local function node(jid)
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
102 return (select(1, split(jid)));
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
103 end
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
104
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
105 local function host(jid)
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
106 return (select(2, split(jid)));
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
107 end
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
108
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
109 local function resource(jid)
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
110 return (select(3, split(jid)));
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
111 end
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
112
12605
053417068957 doap: Update XEP versions for which no code changes appear needed
Kim Alvefur <zash@zash.se>
parents: 12190
diff changeset
113 -- TODO Forbid \20 at start and end of escaped output per XEP-0106 v1.1
11056
0b0a42542456 util.jid: Fix special escaping of '\' per XEP-0106
Kim Alvefur <zash@zash.se>
parents: 10358
diff changeset
114 local function escape(s) return s and (s:gsub("\\%x%x", backslash_escapes):gsub("[\"&'/:<>@ ]", escapes)); end
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
115 local function unescape(s) return s and (s:gsub("\\%x%x", unescapes)); end
4407
f78c6f5fa090 util.jid: Added escape() and unescape().
Waqas Hussain <waqas20@gmail.com>
parents: 3480
diff changeset
116
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
117 return {
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
118 split = split;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
119 bare = bare;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
120 prepped_split = prepped_split;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
121 join = join;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
122 prep = prep;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
123 compare = compare;
7296
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
124 node = node;
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
125 host = host;
1859e07ae082 util.jid+tests: Add simple helpers... node(), host() and resource() for extracting specific parts of a JID
Matthew Wild <mwild1@gmail.com>
parents: 6891
diff changeset
126 resource = resource;
6777
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
127 escape = escape;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
128 unescape = unescape;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6340
diff changeset
129 };