1 /* Ruby scripting hooks */
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
,
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
))
43 SEE_TRY(see
, try_context
) {
44 SEE_OBJECT_CALL(see
, hook
.u
.object
, NULL
, argc
, args
, result
);
47 exception
= SEE_CAUGHT(try_context
);
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");
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
;
87 return EVENT_HOOK_STATUS_NEXT
;
90 SEE_SET_STRING(args
[0], SEE_string_sprintf(see
, "%s", *url
));
92 if (!ses
|| !have_location(ses
)) {
93 SEE_SET_UNDEFINED(args
[1]);
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
)) {
105 struct string new_url
;
107 if (convert_see_string(&new_url
, result
.u
.string
))
108 mem_free_set(url
, new_url
.source
);
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
;
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
)) {
141 struct string new_url
;
143 if (convert_see_string(&new_url
, result
.u
.string
))
144 mem_free_set(url
, new_url
.source
);
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
,
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
)) {
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
);
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
)) {
226 if (convert_see_string(&proxy
, result
.u
.string
))
227 mem_free_set(new_proxy_url
, proxy
.source
);
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
,