Predicate the SpiderMonkey scripting backend on CONFIG_SPIDERMONKEY
[elinks.git] / src / scripting / see / hooks.c
blobee4d9ee17491358f59ef6d30082235d45058cfbc
1 /* Ruby scripting hooks */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <see/see.h>
9 #include "elinks.h"
11 #include "cache/cache.h"
12 #include "main/event.h"
13 #include "protocol/uri.h"
14 #include "scripting/see/core.h"
15 #include "scripting/see/hooks.h"
16 #include "session/location.h"
17 #include "session/session.h"
18 #include "util/string.h"
21 /* The events that will trigger the functions below and what they are expected
22 * to do is explained in doc/events.txt */
24 static struct SEE_value *
25 call_see_hook(struct SEE_interpreter *see, struct session *ses,
26 unsigned char *name,
27 struct SEE_value *args[], int argc,
28 struct SEE_value *result)
30 struct SEE_string *hook_name = SEE_string_sprintf(see, name);
31 struct SEE_value hook;
32 SEE_try_context_t try_context;
33 struct SEE_value *exception;
35 SEE_OBJECT_GET(see, see->Global, hook_name, &hook);
37 if (SEE_VALUE_GET_TYPE(&hook) != SEE_OBJECT
38 || !SEE_OBJECT_HAS_CALL(hook.u.object))
39 return NULL;
41 see_ses = ses;
43 SEE_TRY(see, try_context) {
44 SEE_OBJECT_CALL(see, hook.u.object, NULL, argc, args, result);
47 exception = SEE_CAUGHT(try_context);
48 if (exception) {
49 SEE_try_context_t try_context2;
50 struct SEE_value value;
52 SEE_TRY(see, try_context2) {
53 struct string error_msg;
55 SEE_ToString(see, exception, &value);
57 if (init_string(&error_msg)) {
58 convert_see_string(&error_msg, value.u.string);
59 alert_see_error(ses, error_msg.source);
60 done_string(&error_msg);
64 if (SEE_CAUGHT(try_context2)) {
65 alert_see_error(ses, "exception thrown while printing exception");
68 see_ses = NULL;
69 return NULL;
72 see_ses = NULL;
73 return result;
77 static enum evhook_status
78 script_hook_goto_url(va_list ap, void *data)
80 unsigned char **url = va_arg(ap, unsigned char **);
81 struct session *ses = va_arg(ap, struct session *);
82 struct SEE_interpreter *see = &see_interpreter;
83 struct SEE_value args_[2], *args[2] = { &args_[0], &args_[1] };
84 struct SEE_value result;
86 if (*url == NULL)
87 return EVENT_HOOK_STATUS_NEXT;
89 see_ses = ses;
90 SEE_SET_STRING(args[0], SEE_string_sprintf(see, "%s", *url));
92 if (!ses || !have_location(ses)) {
93 SEE_SET_UNDEFINED(args[1]);
94 } else {
95 SEE_SET_STRING(args[1],
96 SEE_string_sprintf(see, "%s", struri(cur_loc(ses)->vs.uri)));
99 if (!call_see_hook(see, ses, "goto_url", args, sizeof_array(args), &result))
100 return EVENT_HOOK_STATUS_NEXT;
102 switch (SEE_VALUE_GET_TYPE(&result)) {
103 case SEE_STRING:
105 struct string new_url;
107 if (convert_see_string(&new_url, result.u.string))
108 mem_free_set(url, new_url.source);
109 break;
111 case SEE_NULL:
112 break;
114 default:
115 alert_see_error(ses, "goto_url_hook must return a string or null");
118 return EVENT_HOOK_STATUS_NEXT;
121 static enum evhook_status
122 script_hook_follow_url(va_list ap, void *data)
124 unsigned char **url = va_arg(ap, unsigned char **);
125 struct session *ses = va_arg(ap, struct session *);
126 struct SEE_interpreter *see = &see_interpreter;
127 struct SEE_value args_[1], *args[1] = { &args_[0] };
128 struct SEE_value result;
130 if (*url == NULL)
131 return EVENT_HOOK_STATUS_NEXT;
133 SEE_SET_STRING(args[0], SEE_string_sprintf(see, "%s", *url));
135 if (!call_see_hook(see, ses, "follow_url", args, sizeof_array(args), &result))
136 return EVENT_HOOK_STATUS_NEXT;
138 switch (SEE_VALUE_GET_TYPE(&result)) {
139 case SEE_STRING:
141 struct string new_url;
143 if (convert_see_string(&new_url, result.u.string))
144 mem_free_set(url, new_url.source);
145 break;
147 case SEE_NULL:
148 break;
150 default:
151 alert_see_error(ses, "follow_url_hook must return a string or null");
154 return EVENT_HOOK_STATUS_NEXT;
157 static enum evhook_status
158 script_hook_pre_format_html(va_list ap, void *data)
160 struct session *ses = va_arg(ap, struct session *);
161 struct cache_entry *cached = va_arg(ap, struct cache_entry *);
162 struct fragment *fragment = get_cache_fragment(cached);
163 unsigned char *url = struri(cached->uri);
164 struct SEE_interpreter *see = &see_interpreter;
165 struct SEE_value args_[2], *args[2] = { &args_[0], &args_[1] };
166 struct SEE_value result;
168 evhook_use_params(ses && cached);
170 if (!cached->length || !*fragment->data)
171 return EVENT_HOOK_STATUS_NEXT;
173 SEE_SET_STRING(args[0], SEE_string_sprintf(see, "%s", url));
174 SEE_SET_STRING(args[1], SEE_string_sprintf(see, "%.*s", fragment->length,
175 fragment->data));
177 if (!call_see_hook(see, ses, "pre_format_html", args, sizeof_array(args), &result))
178 return EVENT_HOOK_STATUS_NEXT;
180 switch (SEE_VALUE_GET_TYPE(&result)) {
181 case SEE_STRING:
183 struct string new_html;
185 if (convert_see_string(&new_html, result.u.string)) {
186 add_fragment(cached, 0, new_html.source, new_html.length);
187 normalize_cache_entry(cached, new_html.length);
189 break;
191 case SEE_NULL:
192 break;
194 default:
195 alert_see_error(ses, "pre_format_hook must return a string or null");
198 return EVENT_HOOK_STATUS_NEXT;
201 /* The function can return:
202 * - "PROXY:PORT" to use the specified proxy
203 * - "" to not use any proxy
204 * - nil to use the default proxies */
205 static enum evhook_status
206 script_hook_get_proxy(va_list ap, void *data)
208 unsigned char **new_proxy_url = va_arg(ap, unsigned char **);
209 unsigned char *url = va_arg(ap, unsigned char *);
210 struct SEE_interpreter *see = &see_interpreter;
211 struct SEE_value result, args_[1], *args[1] = { &args_[0] };
213 if (!new_proxy_url || !url)
214 return EVENT_HOOK_STATUS_NEXT;
216 SEE_SET_STRING(args[0], SEE_string_sprintf(see, "%s", url));
218 if (!call_see_hook(see, NULL, "get_proxy", args, sizeof_array(args), &result))
219 return EVENT_HOOK_STATUS_NEXT;
221 switch (SEE_VALUE_GET_TYPE(&result)) {
222 case SEE_STRING:
224 struct string proxy;
226 if (convert_see_string(&proxy, result.u.string))
227 mem_free_set(new_proxy_url, proxy.source);
228 break;
230 case SEE_NULL:
231 break;
233 default:
234 alert_see_error(NULL, "proxy_hook must return a string, undefined or null");
237 return EVENT_HOOK_STATUS_NEXT;
240 static enum evhook_status
241 script_hook_quit(va_list ap, void *data)
243 struct SEE_interpreter *see = &see_interpreter;
244 struct SEE_value result;
246 call_see_hook(see, NULL, "quit", NULL, 0, &result);
248 return EVENT_HOOK_STATUS_NEXT;
251 struct event_hook_info see_scripting_hooks[] = {
252 { "goto-url", 0, script_hook_goto_url, NULL },
253 { "follow-url", 0, script_hook_follow_url, NULL },
254 { "pre-format-html", 0, script_hook_pre_format_html, NULL },
255 { "get-proxy", 0, script_hook_get_proxy, NULL },
256 { "quit", 0, script_hook_quit, NULL },
258 NULL_EVENT_HOOK_INFO,