diff options
-rw-r--r-- | modules/luci-base/luasrc/dispatcher.lua | 12 | ||||
-rw-r--r-- | modules/luci-base/luasrc/view/error404.htm | 2 | ||||
-rw-r--r-- | modules/luci-base/src/template_lualib.c | 49 | ||||
-rw-r--r-- | modules/luci-base/src/template_utils.c | 124 | ||||
-rw-r--r-- | modules/luci-base/src/template_utils.h | 6 |
5 files changed, 186 insertions, 7 deletions
diff --git a/modules/luci-base/luasrc/dispatcher.lua b/modules/luci-base/luasrc/dispatcher.lua index 91b86679fd..5fc2b80e71 100644 --- a/modules/luci-base/luasrc/dispatcher.lua +++ b/modules/luci-base/luasrc/dispatcher.lua @@ -75,11 +75,16 @@ function error404(message) http.status(404, "Not Found") message = message or "Not Found" - require("luci.template") - if not util.copcall(luci.template.render, "error404") then + local function render() + local template = require "luci.template" + template.render("error404") + end + + if not util.copcall(render) then http.prepare_content("text/plain") http.write(message) end + return false end @@ -113,7 +118,8 @@ function httpdispatch(request, prefix) end end - for node in pathinfo:gmatch("[^/]+") do + local node + for node in pathinfo:gmatch("[^/%z]+") do r[#r+1] = node end diff --git a/modules/luci-base/luasrc/view/error404.htm b/modules/luci-base/luasrc/view/error404.htm index bc74226830..a762f6038b 100644 --- a/modules/luci-base/luasrc/view/error404.htm +++ b/modules/luci-base/luasrc/view/error404.htm @@ -7,5 +7,5 @@ <%+header%> <h2 name="content">404 <%:Not Found%></h2> <p><%:Sorry, the object you requested was not found.%></p> -<tt><%:Unable to dispatch%>: <%=luci.http.request.env.PATH_INFO%></tt> +<tt><%:Unable to dispatch%>: <%=url(unpack(luci.dispatcher.context.request))%></tt> <%+footer%> diff --git a/modules/luci-base/src/template_lualib.c b/modules/luci-base/src/template_lualib.c index d5c8dd6b4c..45e23966e9 100644 --- a/modules/luci-base/src/template_lualib.c +++ b/modules/luci-base/src/template_lualib.c @@ -1,7 +1,7 @@ /* * LuCI Template - Lua binding * - * Copyright (C) 2009 Jo-Philipp Wich <jow@openwrt.org> + * Copyright (C) 2009-2018 Jo-Philipp Wich <jo@mein.io> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -110,6 +110,51 @@ int template_L_striptags(lua_State *L) return 0; } +int template_L_urlencode(lua_State *L) +{ + size_t len = 0; + const char *str = luaL_checkstring(L, 1); + char *res = urlencode(str, &len); + + if (res != NULL) + { + lua_pushlstring(L, res, len); + free(res); + + return 1; + } + else if (len == 0) + { + lua_pushvalue(L, 1); + return 1; + } + + return 0; +} + +int template_L_urldecode(lua_State *L) +{ + size_t len = 0; + const char *str = luaL_checkstring(L, 1); + int keep_plus = lua_toboolean(L, 2); + char *res = urldecode(str, &len, keep_plus == 1); + + if (res != NULL) + { + lua_pushlstring(L, res, len); + free(res); + + return 1; + } + else if (len == 0) + { + lua_pushvalue(L, 1); + return 1; + } + + return 0; +} + static int template_L_load_catalog(lua_State *L) { const char *lang = luaL_optstring(L, 1, "en"); const char *dir = luaL_optstring(L, 2, NULL); @@ -165,6 +210,8 @@ static const luaL_reg R[] = { { "utf8", template_L_utf8 }, { "pcdata", template_L_pcdata }, { "striptags", template_L_striptags }, + { "urlencode", template_L_urlencode }, + { "urldecode", template_L_urldecode }, { "load_catalog", template_L_load_catalog }, { "close_catalog", template_L_close_catalog }, { "change_catalog", template_L_change_catalog }, diff --git a/modules/luci-base/src/template_utils.c b/modules/luci-base/src/template_utils.c index 3979487f12..eefdd17008 100644 --- a/modules/luci-base/src/template_utils.c +++ b/modules/luci-base/src/template_utils.c @@ -1,7 +1,7 @@ /* * LuCI Template - Utility functions * - * Copyright (C) 2010 Jo-Philipp Wich <jow@openwrt.org> + * Copyright (C) 2010-2018 Jo-Philipp Wich <jo@mein.io> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -428,6 +428,128 @@ char * striptags(const char *s, unsigned int l) return buf_destroy(buf); } + +static inline bool is_urlencode_char(char c) +{ + return !((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + (c == '$') || (c == '_') || + (c == '-') || (c == '.') || + (c == '~')); +} + +/* + * URL-encode all special characters in given string and return + * encoded copy. + * + * If no encoding was required, returns NULL. If an encoded_len + * pointer is passed, it is set to the length of the encoded string. + * + * Sets encoded_len and returns NULL if memory allocation failed. + */ +char *urlencode(const char *s, size_t *encoded_len) +{ + size_t i, enc_len; + char *enc, *ptr; + + for (i = 0, enc_len = 0; s[i]; i++) + if (is_urlencode_char(s[i])) + enc_len += 3; + else + enc_len++; + + if (i != enc_len) + { + if (encoded_len) + *encoded_len = enc_len; + + enc = calloc(1, enc_len + 1); + + if (!enc) + return NULL; + + for (i = 0, ptr = enc; s[i]; i++) + if (is_urlencode_char(s[i])) + ptr += snprintf(ptr, 4, "%%%02x", (unsigned char)s[i]); + else + *ptr++ = s[i]; + + return enc; + } + + return NULL; +} + +/* + * URL-decode given string and return decoded copy. + * + * If no decoding was required, returns NULL. If an decoded_len + * pointer is passed, it is set to the length of the decoded string. + * + * When keep_plus is true, skip decoding of plus ("+") signs into + * space (0x20) characters. + * + * Sets decoded_len and returns NULL if memory allocation failed. + */ + +#define hex(x) \ + (((x) <= '9') ? ((x) - '0') : \ + (((x) <= 'F') ? ((x) - 'A' + 10) : \ + ((x) - 'a' + 10))) + +char *urldecode(const char *s, size_t *decoded_len, bool keep_plus) +{ + bool changed = false; + size_t i, dec_len; + char *dec, *ptr; + + for (i = 0, dec_len = 0; s[i]; i++, dec_len++) + { + if (s[i] == '%' && isxdigit(s[i+1]) && isxdigit(s[i+2])) + { + changed = true; + i += 2; + } + else if (!keep_plus && s[i] == '+') + { + changed = true; + } + } + + if (changed) + { + if (decoded_len) + *decoded_len = dec_len; + + dec = calloc(1, dec_len + 1); + + if (!dec) + return NULL; + + for (i = 0, ptr = dec; s[i]; i++) + { + if (s[i] == '%' && isxdigit(s[i+1]) && isxdigit(s[i+2])) + { + *ptr++ = (char)(16 * hex(s[i+1]) + hex(s[i+2])); + i += 2; + } + else if (!keep_plus && s[i] == '+') + { + *ptr++ = ' '; + } + else + { + *ptr++ = s[i]; + } + } + + return dec; + } + + return NULL; +} + void luastr_escape(struct template_buffer *out, const char *s, unsigned int l, int escape_xml) { diff --git a/modules/luci-base/src/template_utils.h b/modules/luci-base/src/template_utils.h index 32a79f93bc..872ecb072f 100644 --- a/modules/luci-base/src/template_utils.h +++ b/modules/luci-base/src/template_utils.h @@ -1,7 +1,7 @@ /* * LuCI Template - Utility header * - * Copyright (C) 2010-2012 Jo-Philipp Wich <jow@openwrt.org> + * Copyright (C) 2010-2018 Jo-Philipp Wich <jo@mein.io> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,8 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <stdbool.h> +#include <ctype.h> /* buffer object */ @@ -42,6 +44,8 @@ char * buf_destroy(struct template_buffer *buf); char * utf8(const char *s, unsigned int l); char * pcdata(const char *s, unsigned int l); char * striptags(const char *s, unsigned int l); +char * urlencode(const char *s, size_t *encoded_len); +char * urldecode(const char *s, size_t *decoded_len, bool keep_plus); void luastr_escape(struct template_buffer *out, const char *s, unsigned int l, int escape_xml); void luastr_translate(struct template_buffer *out, const char *s, unsigned int l, int escape_xml); |