Cast to (const char *) in strrchr calls
[elinks.git] / src / scripting / lua / hooks.c
blobb94745a2d6fe12cda7791618b1f595365dd9a3b4
1 /* Lua scripting hooks */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <lauxlib.h>
8 #include <lua.h>
9 #include <lualib.h>
11 #include "elinks.h"
13 #include "cache/cache.h"
14 #include "main/event.h"
15 #include "protocol/uri.h"
16 #include "scripting/lua/core.h"
17 #include "scripting/lua/hooks.h"
18 #include "session/location.h"
19 #include "session/session.h"
20 #include "util/string.h"
23 /* The events that will trigger the functions below and what they are expected
24 * to do is explained in doc/events.txt */
26 static enum evhook_status
27 script_hook_goto_url(va_list ap, void *data)
29 lua_State *L = lua_state;
30 unsigned char **url = va_arg(ap, unsigned char **);
31 struct session *ses = va_arg(ap, struct session *);
32 int err;
34 if (*url == NULL) return EVENT_HOOK_STATUS_NEXT;
36 lua_getglobal(L, "goto_url_hook");
37 if (lua_isnil(L, -1)) {
38 /* The function is not defined */
39 lua_pop(L, 1);
40 return EVENT_HOOK_STATUS_NEXT;
43 lua_pushstring(L, *url);
45 if (!ses || !have_location(ses)) {
46 lua_pushnil(L);
47 } else {
48 lua_pushstring(L, struri(cur_loc(ses)->vs.uri));
51 if (prepare_lua(ses)) return EVENT_HOOK_STATUS_NEXT;
53 err = lua_pcall(L, 2, 1, 0);
54 finish_lua();
55 if (err) return EVENT_HOOK_STATUS_NEXT;
57 if (lua_isstring(L, -1)) {
58 unsigned char *new_url;
60 new_url = stracpy((unsigned char *) lua_tostring(L, -1));
61 if (new_url) {
62 mem_free_set(url, new_url);
64 } else if (lua_isnil(L, -1)) {
65 (*url)[0] = 0;
66 } else {
67 alert_lua_error("goto_url_hook must return a string or nil");
70 lua_pop(L, 1);
72 return EVENT_HOOK_STATUS_NEXT;
75 static enum evhook_status
76 script_hook_follow_url(va_list ap, void *data)
78 lua_State *L = lua_state;
79 unsigned char **url = va_arg(ap, unsigned char **);
80 struct session *ses = va_arg(ap, struct session *);
81 int err;
83 if (*url == NULL) return EVENT_HOOK_STATUS_NEXT;
85 lua_getglobal(L, "follow_url_hook");
86 if (lua_isnil(L, -1)) {
87 /* The function is not defined */
88 lua_pop(L, 1);
89 return EVENT_HOOK_STATUS_NEXT;
92 lua_pushstring(L, *url);
94 if (prepare_lua(ses)) return EVENT_HOOK_STATUS_NEXT;
96 err = lua_pcall(L, 1, 1, 0);
97 finish_lua();
98 if (err) return EVENT_HOOK_STATUS_NEXT;
100 if (lua_isstring(L, -1)) {
101 unsigned char *new_url;
103 new_url = stracpy((unsigned char *) lua_tostring(L, -1));
104 if (new_url) {
105 mem_free_set(url, new_url);
107 } else if (lua_isnil(L, -1)) {
108 (*url)[0] = 0;
109 } else {
110 alert_lua_error("follow_url_hook must return a string or nil");
113 lua_pop(L, 1);
115 return EVENT_HOOK_STATUS_NEXT;
118 static enum evhook_status
119 script_hook_pre_format_html(va_list ap, void *data)
121 lua_State *L = lua_state;
122 struct session *ses = va_arg(ap, struct session *);
123 struct cache_entry *cached = va_arg(ap, struct cache_entry *);
124 struct fragment *fragment = get_cache_fragment(cached);
125 unsigned char *url = struri(cached->uri);
126 int err;
128 if (!cached->length || !*fragment->data) return EVENT_HOOK_STATUS_NEXT;
130 lua_getglobal(L, "pre_format_html_hook");
131 if (lua_isnil(L, -1)) {
132 /* The function is not defined */
133 lua_pop(L, 1);
134 return EVENT_HOOK_STATUS_NEXT;
137 lua_pushstring(L, url);
138 lua_pushlstring(L, fragment->data, fragment->length);
140 if (prepare_lua(ses)) return EVENT_HOOK_STATUS_NEXT;
142 err = lua_pcall(L, 2, 1, 0);
143 finish_lua();
144 if (err) return EVENT_HOOK_STATUS_NEXT;
146 if (lua_isstring(L, -1)) {
147 int len = lua_strlen(L, -1);
149 add_fragment(cached, 0, (unsigned char *) lua_tostring(L, -1), len);
150 normalize_cache_entry(cached, len);
151 } else if (!lua_isnil(L, -1)) {
152 alert_lua_error("pre_format_html_hook must return a string or nil");
155 lua_pop(L, 1);
157 return EVENT_HOOK_STATUS_NEXT;
160 /* The Lua function can return:
161 * - "PROXY:PORT" to use the specified proxy
162 * - "" to not use any proxy
163 * - nil to use the default proxies */
164 static enum evhook_status
165 script_hook_get_proxy(va_list ap, void *data)
167 lua_State *L = lua_state;
168 unsigned char **new_proxy_url = va_arg(ap, unsigned char **);
169 unsigned char *url = va_arg(ap, unsigned char *);
170 int err;
172 if (!new_proxy_url || !url)
173 return EVENT_HOOK_STATUS_NEXT;
175 lua_getglobal(L, "proxy_for_hook");
176 if (lua_isnil(L, -1)) {
177 /* The function is not defined */
178 lua_pop(L, 1);
179 return EVENT_HOOK_STATUS_NEXT;
182 lua_pushstring(L, url);
183 if (prepare_lua(NULL)) return EVENT_HOOK_STATUS_NEXT;
185 err = lua_pcall(L, 1, 1, 0);
186 finish_lua();
187 if (err) return EVENT_HOOK_STATUS_NEXT;
189 if (lua_isstring(L, -1)) {
190 mem_free_set(new_proxy_url,
191 stracpy((unsigned char *) lua_tostring(L, -1)));
192 } else if (lua_isnil(L, -1)) {
193 mem_free_set(new_proxy_url, NULL);
194 } else {
195 alert_lua_error("proxy_hook must return a string or nil");
198 lua_pop(L, 1);
200 return EVENT_HOOK_STATUS_NEXT;
203 static enum evhook_status
204 script_hook_quit(va_list ap, void *data)
206 if (!prepare_lua(NULL)) {
207 (void)luaL_dostring(lua_state, "if quit_hook then quit_hook() end");
208 finish_lua();
211 return EVENT_HOOK_STATUS_NEXT;
214 struct event_hook_info lua_scripting_hooks[] = {
215 { "goto-url", 0, script_hook_goto_url, NULL },
216 { "follow-url", 0, script_hook_follow_url, NULL },
217 { "pre-format-html", 0, script_hook_pre_format_html, NULL },
218 { "get-proxy", 0, script_hook_get_proxy, NULL },
219 { "quit", 0, script_hook_quit, NULL },
220 { "dialog-lua-console", 0, dialog_lua_console, NULL },
221 { "free-history", 0, free_lua_console_history, NULL },
222 NULL_EVENT_HOOK_INFO,