config: Access OPT_MUST_SAVE in the real option, not alias.
[elinks/elinks-j605.git] / src / scripting / lua / hooks.c
blobd79ad80e5f2fbc8fe32d1e1177dcd78a5a2099a6
1 /* Lua scripting hooks */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include "elinks.h"
9 #include "cache/cache.h"
10 #include "main/event.h"
11 #include "protocol/uri.h"
12 #include "scripting/lua/core.h"
13 #include "scripting/lua/hooks.h"
14 #include "session/location.h"
15 #include "session/session.h"
16 #include "util/string.h"
19 /* The events that will trigger the functions below and what they are expected
20 * to do is explained in doc/events.txt */
22 static enum evhook_status
23 script_hook_goto_url(va_list ap, void *data)
25 lua_State *L = lua_state;
26 unsigned char **url = va_arg(ap, unsigned char **);
27 struct session *ses = va_arg(ap, struct session *);
28 int err;
30 if (*url == NULL) return EVENT_HOOK_STATUS_NEXT;
32 lua_getglobal(L, "goto_url_hook");
33 if (lua_isnil(L, -1)) {
34 /* The function is not defined */
35 lua_pop(L, 1);
36 return EVENT_HOOK_STATUS_NEXT;
39 lua_pushstring(L, *url);
41 if (!ses || !have_location(ses)) {
42 lua_pushnil(L);
43 } else {
44 lua_pushstring(L, struri(cur_loc(ses)->vs.uri));
47 if (prepare_lua(ses)) return EVENT_HOOK_STATUS_NEXT;
49 err = lua_pcall(L, 2, 1, 0);
50 finish_lua();
51 if (err) return EVENT_HOOK_STATUS_NEXT;
53 if (lua_isstring(L, -1)) {
54 unsigned char *new_url;
56 new_url = stracpy((unsigned char *) lua_tostring(L, -1));
57 if (new_url) {
58 mem_free_set(url, new_url);
60 } else if (lua_isnil(L, -1)) {
61 (*url)[0] = 0;
62 } else {
63 alert_lua_error("goto_url_hook must return a string or nil");
66 lua_pop(L, 1);
68 return EVENT_HOOK_STATUS_NEXT;
71 static enum evhook_status
72 script_hook_follow_url(va_list ap, void *data)
74 lua_State *L = lua_state;
75 unsigned char **url = va_arg(ap, unsigned char **);
76 struct session *ses = va_arg(ap, struct session *);
77 int err;
79 if (*url == NULL) return EVENT_HOOK_STATUS_NEXT;
81 lua_getglobal(L, "follow_url_hook");
82 if (lua_isnil(L, -1)) {
83 /* The function is not defined */
84 lua_pop(L, 1);
85 return EVENT_HOOK_STATUS_NEXT;
88 lua_pushstring(L, *url);
90 if (prepare_lua(ses)) return EVENT_HOOK_STATUS_NEXT;
92 err = lua_pcall(L, 1, 1, 0);
93 finish_lua();
94 if (err) return EVENT_HOOK_STATUS_NEXT;
96 if (lua_isstring(L, -1)) {
97 unsigned char *new_url;
99 new_url = stracpy((unsigned char *) lua_tostring(L, -1));
100 if (new_url) {
101 mem_free_set(url, new_url);
103 } else if (lua_isnil(L, -1)) {
104 (*url)[0] = 0;
105 } else {
106 alert_lua_error("follow_url_hook must return a string or nil");
109 lua_pop(L, 1);
111 return EVENT_HOOK_STATUS_NEXT;
114 static enum evhook_status
115 script_hook_pre_format_html(va_list ap, void *data)
117 lua_State *L = lua_state;
118 struct session *ses = va_arg(ap, struct session *);
119 struct cache_entry *cached = va_arg(ap, struct cache_entry *);
120 struct fragment *fragment = get_cache_fragment(cached);
121 unsigned char *url = struri(cached->uri);
122 int err;
124 if (!cached->length || !*fragment->data) return EVENT_HOOK_STATUS_NEXT;
126 lua_getglobal(L, "pre_format_html_hook");
127 if (lua_isnil(L, -1)) {
128 /* The function is not defined */
129 lua_pop(L, 1);
130 return EVENT_HOOK_STATUS_NEXT;
133 lua_pushstring(L, url);
134 lua_pushlstring(L, fragment->data, fragment->length);
136 if (prepare_lua(ses)) return EVENT_HOOK_STATUS_NEXT;
138 err = lua_pcall(L, 2, 1, 0);
139 finish_lua();
140 if (err) return EVENT_HOOK_STATUS_NEXT;
142 if (lua_isstring(L, -1)) {
143 int len = lua_strlen(L, -1);
145 add_fragment(cached, 0, (unsigned char *) lua_tostring(L, -1), len);
146 normalize_cache_entry(cached, len);
147 } else if (!lua_isnil(L, -1)) {
148 alert_lua_error("pre_format_html_hook must return a string or nil");
151 lua_pop(L, 1);
153 return EVENT_HOOK_STATUS_NEXT;
156 /* The Lua function can return:
157 * - "PROXY:PORT" to use the specified proxy
158 * - "" to not use any proxy
159 * - nil to use the default proxies */
160 static enum evhook_status
161 script_hook_get_proxy(va_list ap, void *data)
163 lua_State *L = lua_state;
164 unsigned char **new_proxy_url = va_arg(ap, unsigned char **);
165 unsigned char *url = va_arg(ap, unsigned char *);
166 int err;
168 if (!new_proxy_url || !url)
169 return EVENT_HOOK_STATUS_NEXT;
171 lua_getglobal(L, "proxy_for_hook");
172 if (lua_isnil(L, -1)) {
173 /* The function is not defined */
174 lua_pop(L, 1);
175 return EVENT_HOOK_STATUS_NEXT;
178 lua_pushstring(L, url);
179 if (prepare_lua(NULL)) return EVENT_HOOK_STATUS_NEXT;
181 err = lua_pcall(L, 1, 1, 0);
182 finish_lua();
183 if (err) return EVENT_HOOK_STATUS_NEXT;
185 if (lua_isstring(L, -1)) {
186 mem_free_set(new_proxy_url,
187 stracpy((unsigned char *) lua_tostring(L, -1)));
188 } else if (lua_isnil(L, -1)) {
189 mem_free_set(new_proxy_url, NULL);
190 } else {
191 alert_lua_error("proxy_hook must return a string or nil");
194 lua_pop(L, 1);
196 return EVENT_HOOK_STATUS_NEXT;
199 static enum evhook_status
200 script_hook_quit(va_list ap, void *data)
202 if (!prepare_lua(NULL)) {
203 lua_dostring(lua_state, "if quit_hook then quit_hook() end");
204 finish_lua();
207 return EVENT_HOOK_STATUS_NEXT;
210 struct event_hook_info lua_scripting_hooks[] = {
211 { "goto-url", 0, script_hook_goto_url, NULL },
212 { "follow-url", 0, script_hook_follow_url, NULL },
213 { "pre-format-html", 0, script_hook_pre_format_html, NULL },
214 { "get-proxy", 0, script_hook_get_proxy, NULL },
215 { "quit", 0, script_hook_quit, NULL },
216 { "dialog-lua-console", 0, dialog_lua_console, NULL },
217 { "free-history", 0, free_lua_console_history, NULL },
218 NULL_EVENT_HOOK_INFO,