Python.h must be included as last to satisfy tcc, but Python redefines
[elinks/kon.git] / src / scripting / python / hooks.c
blob9f3d0952744308cb2a1cde090a02c930048ac74c
1 /* Python scripting hooks */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
8 #include "elinks.h"
10 #include "cache/cache.h"
11 #include "main/event.h"
12 #include "protocol/uri.h"
13 #include "scripting/python/core.h"
14 #include "scripting/python/hooks.h"
15 #include "session/location.h"
16 #include "session/session.h"
17 #include "util/string.h"
19 #undef _POSIX_C_SOURCE
20 #include <Python.h>
22 /* The events that will trigger the functions below and what they are expected
23 * to do is explained in doc/events.txt */
25 extern PyObject *pDict;
26 extern PyObject *pModule;
28 static void
29 do_script_hook_goto_url(struct session *ses, unsigned char **url)
31 PyObject *pFunc = PyDict_GetItemString(pDict, "goto_url_hook");
33 if (pFunc && PyCallable_Check(pFunc)) {
34 PyObject *pValue;
35 unsigned char *str;
37 if (!ses || !have_location(ses)) {
38 str = NULL;
39 } else {
40 str = struri(cur_loc(ses)->vs.uri);
43 pValue = PyObject_CallFunction(pFunc, "ss", *url, str);
44 if (pValue && (pValue != Py_None)) {
45 const unsigned char *res = PyString_AsString(pValue);
47 if (res) {
48 unsigned char *new_url = stracpy((unsigned char *)res);
50 if (new_url) mem_free_set(url, new_url);
52 Py_DECREF(pValue);
53 } else {
54 if (PyErr_Occurred()) {
55 PyErr_Print();
56 PyErr_Clear();
62 static enum evhook_status
63 script_hook_goto_url(va_list ap, void *data)
65 unsigned char **url = va_arg(ap, unsigned char **);
66 struct session *ses = va_arg(ap, struct session *);
68 if (pDict && *url)
69 do_script_hook_goto_url(ses, url);
71 return EVENT_HOOK_STATUS_NEXT;
74 static void
75 do_script_hook_follow_url(unsigned char **url)
77 PyObject *pFunc = PyDict_GetItemString(pDict, "follow_url_hook");
79 if (pFunc && PyCallable_Check(pFunc)) {
80 PyObject *pValue = PyObject_CallFunction(pFunc, "s", *url);
81 if (pValue && (pValue != Py_None)) {
82 const unsigned char *str = PyString_AsString(pValue);
83 unsigned char *new_url;
85 if (str) {
86 new_url = stracpy((unsigned char *)str);
87 if (new_url) mem_free_set(url, new_url);
89 Py_DECREF(pValue);
90 } else {
91 if (PyErr_Occurred()) {
92 PyErr_Print();
93 PyErr_Clear();
99 static enum evhook_status
100 script_hook_follow_url(va_list ap, void *data)
102 unsigned char **url = va_arg(ap, unsigned char **);
104 if (pDict && *url)
105 do_script_hook_follow_url(url);
107 return EVENT_HOOK_STATUS_NEXT;
110 static void
111 do_script_hook_pre_format_html(unsigned char *url, struct cache_entry *cached,
112 struct fragment *fragment)
114 PyObject *pFunc = PyDict_GetItemString(pDict, "pre_format_html_hook");
116 if (pFunc && PyCallable_Check(pFunc)) {
117 PyObject *pValue = PyObject_CallFunction(pFunc, "ss#", url,
118 fragment->data,
119 fragment->length);
121 if (pValue && (pValue != Py_None)) {
122 const unsigned char *str = PyString_AsString(pValue);
124 if (str) {
125 int len = PyString_Size(pValue); /* strlen(str); */
127 add_fragment(cached, 0, str, len);
128 normalize_cache_entry(cached, len);
130 Py_DECREF(pValue);
131 } else {
132 if (PyErr_Occurred()) {
133 PyErr_Print();
134 PyErr_Clear();
140 static enum evhook_status
141 script_hook_pre_format_html(va_list ap, void *data)
143 struct session *ses = va_arg(ap, struct session *);
144 struct cache_entry *cached = va_arg(ap, struct cache_entry *);
145 struct fragment *fragment = get_cache_fragment(cached);
146 unsigned char *url = struri(cached->uri);
148 if (pDict && ses && url && cached->length && *fragment->data)
149 do_script_hook_pre_format_html(url, cached, fragment);
151 return EVENT_HOOK_STATUS_NEXT;
154 static inline void
155 do_script_hook_get_proxy(unsigned char **new_proxy_url, unsigned char *url)
157 PyObject *pFunc = PyDict_GetItemString(pDict, "proxy_for_hook");
159 if (pFunc && PyCallable_Check(pFunc)) {
160 PyObject *pValue = PyObject_CallFunction(pFunc, "s", url);
162 if (pValue && (pValue != Py_None)) {
163 const unsigned char *str = PyString_AsString(pValue);
165 if (str) {
166 unsigned char *new_url = stracpy((unsigned char *)str);
168 if (new_url) mem_free_set(new_proxy_url, new_url);
170 Py_DECREF(pValue);
171 } else {
172 if (PyErr_Occurred()) {
173 PyErr_Print();
174 PyErr_Clear();
180 static enum evhook_status
181 script_hook_get_proxy(va_list ap, void *data)
183 unsigned char **new_proxy_url = va_arg(ap, unsigned char **);
184 unsigned char *url = va_arg(ap, unsigned char *);
186 if (pDict && new_proxy_url && url)
187 do_script_hook_get_proxy(new_proxy_url, url);
189 return EVENT_HOOK_STATUS_NEXT;
192 static void
193 do_script_hook_quit(void)
195 PyObject *pFunc = PyDict_GetItemString(pDict, "quit_hook");
197 if (pFunc && PyCallable_Check(pFunc)) {
198 PyObject *pValue = PyObject_CallFunction(pFunc, NULL);
200 if (pValue) {
201 if (pValue != Py_None) {
202 Py_DECREF(pValue);
204 } else {
205 if (PyErr_Occurred()) {
206 PyErr_Print();
207 PyErr_Clear();
213 static enum evhook_status
214 script_hook_quit(va_list ap, void *data)
216 if (pDict) do_script_hook_quit();
217 return EVENT_HOOK_STATUS_NEXT;
220 struct event_hook_info python_scripting_hooks[] = {
221 { "goto-url", 0, script_hook_goto_url, NULL },
222 { "follow-url", 0, script_hook_follow_url, NULL },
223 { "pre-format-html", 0, script_hook_pre_format_html, NULL },
224 { "get-proxy", 0, script_hook_get_proxy, NULL },
225 { "quit", 0, script_hook_quit, NULL },
226 NULL_EVENT_HOOK_INFO,