luci-base: add urldecode() and urlencode() C implementations
[project/luci.git] / modules / luci-base / src / template_lualib.c
1 /*
2  * LuCI Template - Lua binding
3  *
4  *   Copyright (C) 2009-2018 Jo-Philipp Wich <jo@mein.io>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */
18
19 #include "template_lualib.h"
20
21 static int template_L_do_parse(lua_State *L, struct template_parser *parser, const char *chunkname)
22 {
23         int lua_status, rv;
24
25         if (!parser)
26         {
27                 lua_pushnil(L);
28                 lua_pushinteger(L, errno);
29                 lua_pushstring(L, strerror(errno));
30                 return 3;
31         }
32
33         lua_status = lua_load(L, template_reader, parser, chunkname);
34
35         if (lua_status == 0)
36                 rv = 1;
37         else
38                 rv = template_error(L, parser);
39
40         template_close(parser);
41
42         return rv;
43 }
44
45 int template_L_parse(lua_State *L)
46 {
47         const char *file = luaL_checkstring(L, 1);
48         struct template_parser *parser = template_open(file);
49
50         return template_L_do_parse(L, parser, file);
51 }
52
53 int template_L_parse_string(lua_State *L)
54 {
55         size_t len;
56         const char *str = luaL_checklstring(L, 1, &len);
57         struct template_parser *parser = template_string(str, len);
58
59         return template_L_do_parse(L, parser, "[string]");
60 }
61
62 int template_L_utf8(lua_State *L)
63 {
64         size_t len = 0;
65         const char *str = luaL_checklstring(L, 1, &len);
66         char *res = utf8(str, len);
67
68         if (res != NULL)
69         {
70                 lua_pushstring(L, res);
71                 free(res);
72
73                 return 1;
74         }
75
76         return 0;
77 }
78
79 int template_L_pcdata(lua_State *L)
80 {
81         size_t len = 0;
82         const char *str = luaL_checklstring(L, 1, &len);
83         char *res = pcdata(str, len);
84
85         if (res != NULL)
86         {
87                 lua_pushstring(L, res);
88                 free(res);
89
90                 return 1;
91         }
92
93         return 0;
94 }
95
96 int template_L_striptags(lua_State *L)
97 {
98         size_t len = 0;
99         const char *str = luaL_checklstring(L, 1, &len);
100         char *res = striptags(str, len);
101
102         if (res != NULL)
103         {
104                 lua_pushstring(L, res);
105                 free(res);
106
107                 return 1;
108         }
109
110         return 0;
111 }
112
113 int template_L_urlencode(lua_State *L)
114 {
115         size_t len = 0;
116         const char *str = luaL_checkstring(L, 1);
117         char *res = urlencode(str, &len);
118
119         if (res != NULL)
120         {
121                 lua_pushlstring(L, res, len);
122                 free(res);
123
124                 return 1;
125         }
126         else if (len == 0)
127         {
128                 lua_pushvalue(L, 1);
129                 return 1;
130         }
131
132         return 0;
133 }
134
135 int template_L_urldecode(lua_State *L)
136 {
137         size_t len = 0;
138         const char *str = luaL_checkstring(L, 1);
139         int keep_plus = lua_toboolean(L, 2);
140         char *res = urldecode(str, &len, keep_plus == 1);
141
142         if (res != NULL)
143         {
144                 lua_pushlstring(L, res, len);
145                 free(res);
146
147                 return 1;
148         }
149         else if (len == 0)
150         {
151                 lua_pushvalue(L, 1);
152                 return 1;
153         }
154
155         return 0;
156 }
157
158 static int template_L_load_catalog(lua_State *L) {
159         const char *lang = luaL_optstring(L, 1, "en");
160         const char *dir  = luaL_optstring(L, 2, NULL);
161         lua_pushboolean(L, !lmo_load_catalog(lang, dir));
162         return 1;
163 }
164
165 static int template_L_close_catalog(lua_State *L) {
166         const char *lang = luaL_optstring(L, 1, "en");
167         lmo_close_catalog(lang);
168         return 0;
169 }
170
171 static int template_L_change_catalog(lua_State *L) {
172         const char *lang = luaL_optstring(L, 1, "en");
173         lua_pushboolean(L, !lmo_change_catalog(lang));
174         return 1;
175 }
176
177 static int template_L_translate(lua_State *L) {
178         size_t len;
179         char *tr;
180         int trlen;
181         const char *key = luaL_checklstring(L, 1, &len);
182
183         switch (lmo_translate(key, len, &tr, &trlen))
184         {
185                 case 0:
186                         lua_pushlstring(L, tr, trlen);
187                         return 1;
188
189                 case -1:
190                         return 0;
191         }
192
193         lua_pushnil(L);
194         lua_pushstring(L, "no catalog loaded");
195         return 2;
196 }
197
198 static int template_L_hash(lua_State *L) {
199         size_t len;
200         const char *key = luaL_checklstring(L, 1, &len);
201         lua_pushinteger(L, sfh_hash(key, len));
202         return 1;
203 }
204
205
206 /* module table */
207 static const luaL_reg R[] = {
208         { "parse",                              template_L_parse },
209         { "parse_string",               template_L_parse_string },
210         { "utf8",                               template_L_utf8 },
211         { "pcdata",                             template_L_pcdata },
212         { "striptags",                  template_L_striptags },
213         { "urlencode",                  template_L_urlencode },
214         { "urldecode",                  template_L_urldecode },
215         { "load_catalog",               template_L_load_catalog },
216         { "close_catalog",              template_L_close_catalog },
217         { "change_catalog",             template_L_change_catalog },
218         { "translate",                  template_L_translate },
219         { "hash",                               template_L_hash },
220         { NULL,                                 NULL }
221 };
222
223 LUALIB_API int luaopen_luci_template_parser(lua_State *L) {
224         luaL_register(L, TEMPLATE_LUALIB_META, R);
225         return 1;
226 }