]> git.ipfire.org Git - people/ms/libloc.git/blob - src/python/writer.c
f708417369aa58b621bd52de80343dd73ad28fbd
[people/ms/libloc.git] / src / python / writer.c
1 /*
2 libloc - A library to determine the location of someone on the Internet
3
4 Copyright (C) 2017 IPFire Development Team <info@ipfire.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15 */
16
17 #include <Python.h>
18
19 #include <loc/libloc.h>
20 #include <loc/writer.h>
21
22 #include "locationmodule.h"
23 #include "as.h"
24 #include "country.h"
25 #include "network.h"
26 #include "writer.h"
27
28 static PyObject* Writer_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
29 WriterObject* self = (WriterObject*)type->tp_alloc(type, 0);
30
31 return (PyObject*)self;
32 }
33
34 static void Writer_dealloc(WriterObject* self) {
35 if (self->writer)
36 loc_writer_unref(self->writer);
37
38 Py_TYPE(self)->tp_free((PyObject* )self);
39 }
40
41 static int Writer_init(WriterObject* self, PyObject* args, PyObject* kwargs) {
42 PyObject* private_key = NULL;
43 FILE* f = NULL;
44
45 // Parse arguments
46 if (!PyArg_ParseTuple(args, "|O", &private_key))
47 return -1;
48
49 // Convert into FILE*
50 if (private_key && private_key != Py_None) {
51 int fd = PyObject_AsFileDescriptor(private_key);
52 if (fd < 0)
53 return -1;
54
55 // Re-open file descriptor
56 f = fdopen(fd, "r");
57 if (!f) {
58 PyErr_SetFromErrno(PyExc_IOError);
59 return -1;
60 }
61 }
62
63 // Create the writer object
64 int r = loc_writer_new(loc_ctx, &self->writer, f);
65
66 return r;
67 }
68
69 static PyObject* Writer_get_vendor(WriterObject* self) {
70 const char* vendor = loc_writer_get_vendor(self->writer);
71
72 return PyUnicode_FromString(vendor);
73 }
74
75 static int Writer_set_vendor(WriterObject* self, PyObject* value) {
76 const char* vendor = PyUnicode_AsUTF8(value);
77
78 int r = loc_writer_set_vendor(self->writer, vendor);
79 if (r) {
80 PyErr_Format(PyExc_ValueError, "Could not set vendor: %s", vendor);
81 return r;
82 }
83
84 return 0;
85 }
86
87 static PyObject* Writer_get_description(WriterObject* self) {
88 const char* description = loc_writer_get_description(self->writer);
89
90 return PyUnicode_FromString(description);
91 }
92
93 static int Writer_set_description(WriterObject* self, PyObject* value) {
94 const char* description = PyUnicode_AsUTF8(value);
95
96 int r = loc_writer_set_description(self->writer, description);
97 if (r) {
98 PyErr_Format(PyExc_ValueError, "Could not set description: %s", description);
99 return r;
100 }
101
102 return 0;
103 }
104
105 static PyObject* Writer_get_license(WriterObject* self) {
106 const char* license = loc_writer_get_license(self->writer);
107
108 return PyUnicode_FromString(license);
109 }
110
111 static int Writer_set_license(WriterObject* self, PyObject* value) {
112 const char* license = PyUnicode_AsUTF8(value);
113
114 int r = loc_writer_set_license(self->writer, license);
115 if (r) {
116 PyErr_Format(PyExc_ValueError, "Could not set license: %s", license);
117 return r;
118 }
119
120 return 0;
121 }
122
123 static PyObject* Writer_add_as(WriterObject* self, PyObject* args) {
124 struct loc_as* as;
125 uint32_t number = 0;
126
127 if (!PyArg_ParseTuple(args, "i", &number))
128 return NULL;
129
130 // Create AS object
131 int r = loc_writer_add_as(self->writer, &as, number);
132 if (r)
133 return NULL;
134
135 PyObject* obj = new_as(&ASType, as);
136 loc_as_unref(as);
137
138 return obj;
139 }
140
141 static PyObject* Writer_add_country(WriterObject* self, PyObject* args) {
142 struct loc_country* country;
143 const char* country_code;
144
145 if (!PyArg_ParseTuple(args, "s", &country_code))
146 return NULL;
147
148 // Create country object
149 int r = loc_writer_add_country(self->writer, &country, country_code);
150 if (r) {
151 switch (r) {
152 case -EINVAL:
153 PyErr_SetString(PyExc_ValueError, "Invalid network");
154 break;
155
156 default:
157 return NULL;
158 }
159 }
160
161 PyObject* obj = new_country(&CountryType, country);
162 loc_country_unref(country);
163
164 return obj;
165 }
166
167 static PyObject* Writer_add_network(WriterObject* self, PyObject* args) {
168 struct loc_network* network;
169 const char* string = NULL;
170
171 if (!PyArg_ParseTuple(args, "s", &string))
172 return NULL;
173
174 // Create network object
175 int r = loc_writer_add_network(self->writer, &network, string);
176 if (r) {
177 switch (r) {
178 case -EINVAL:
179 PyErr_SetString(PyExc_ValueError, "Invalid network");
180 break;
181
182 case -EBUSY:
183 PyErr_SetString(PyExc_IndexError, "A network already exists here");
184 break;
185 }
186
187 return NULL;
188 }
189
190 PyObject* obj = new_network(&NetworkType, network);
191 loc_network_unref(network);
192
193 return obj;
194 }
195
196 static PyObject* Writer_write(WriterObject* self, PyObject* args) {
197 const char* path = NULL;
198
199 if (!PyArg_ParseTuple(args, "s", &path))
200 return NULL;
201
202 FILE* f = fopen(path, "w+");
203 if (!f) {
204 PyErr_Format(PyExc_IOError, strerror(errno));
205 return NULL;
206 }
207
208 int r = loc_writer_write(self->writer, f);
209 fclose(f);
210
211 // Raise any errors
212 if (r) {
213 PyErr_Format(PyExc_IOError, strerror(errno));
214 return NULL;
215 }
216
217 Py_RETURN_NONE;
218 }
219
220 static struct PyMethodDef Writer_methods[] = {
221 {
222 "add_as",
223 (PyCFunction)Writer_add_as,
224 METH_VARARGS,
225 NULL,
226 },
227 {
228 "add_country",
229 (PyCFunction)Writer_add_country,
230 METH_VARARGS,
231 NULL,
232 },
233 {
234 "add_network",
235 (PyCFunction)Writer_add_network,
236 METH_VARARGS,
237 NULL,
238 },
239 {
240 "write",
241 (PyCFunction)Writer_write,
242 METH_VARARGS,
243 NULL,
244 },
245 { NULL },
246 };
247
248 static struct PyGetSetDef Writer_getsetters[] = {
249 {
250 "description",
251 (getter)Writer_get_description,
252 (setter)Writer_set_description,
253 NULL,
254 NULL,
255 },
256 {
257 "license",
258 (getter)Writer_get_license,
259 (setter)Writer_set_license,
260 NULL,
261 NULL,
262 },
263 {
264 "vendor",
265 (getter)Writer_get_vendor,
266 (setter)Writer_set_vendor,
267 NULL,
268 NULL,
269 },
270 { NULL },
271 };
272
273 PyTypeObject WriterType = {
274 PyVarObject_HEAD_INIT(NULL, 0)
275 .tp_name = "location.Writer",
276 .tp_basicsize = sizeof(WriterObject),
277 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
278 .tp_new = Writer_new,
279 .tp_dealloc = (destructor)Writer_dealloc,
280 .tp_init = (initproc)Writer_init,
281 .tp_doc = "Writer object",
282 .tp_methods = Writer_methods,
283 .tp_getset = Writer_getsetters,
284 };