]> git.ipfire.org Git - location/libloc.git/blob - src/python/writer.c
location.in: do not confuse UTC with local time zones
[location/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_key1 = NULL;
43 PyObject* private_key2 = NULL;
44 FILE* f1 = NULL;
45 FILE* f2 = NULL;
46 int fd;
47
48 // Parse arguments
49 if (!PyArg_ParseTuple(args, "|OO", &private_key1, &private_key2))
50 return -1;
51
52 // Ignore None
53 if (private_key1 == Py_None) {
54 Py_DECREF(private_key1);
55 private_key1 = NULL;
56 }
57
58 if (private_key2 == Py_None) {
59 Py_DECREF(private_key2);
60 private_key2 = NULL;
61 }
62
63 // Convert into FILE*
64 if (private_key1) {
65 fd = PyObject_AsFileDescriptor(private_key1);
66 if (fd < 0)
67 return -1;
68
69 // Re-open file descriptor
70 f2 = fdopen(fd, "r");
71 if (!f2) {
72 PyErr_SetFromErrno(PyExc_IOError);
73 return -1;
74 }
75 }
76
77 if (private_key2) {
78 fd = PyObject_AsFileDescriptor(private_key2);
79 if (fd < 0)
80 return -1;
81
82 // Re-open file descriptor
83 f2 = fdopen(fd, "r");
84 if (!f2) {
85 PyErr_SetFromErrno(PyExc_IOError);
86 return -1;
87 }
88 }
89
90 // Create the writer object
91 return loc_writer_new(loc_ctx, &self->writer, f1, f2);
92 }
93
94 static PyObject* Writer_get_vendor(WriterObject* self) {
95 const char* vendor = loc_writer_get_vendor(self->writer);
96
97 return PyUnicode_FromString(vendor);
98 }
99
100 static int Writer_set_vendor(WriterObject* self, PyObject* value) {
101 const char* vendor = PyUnicode_AsUTF8(value);
102
103 int r = loc_writer_set_vendor(self->writer, vendor);
104 if (r) {
105 PyErr_Format(PyExc_ValueError, "Could not set vendor: %s", vendor);
106 return r;
107 }
108
109 return 0;
110 }
111
112 static PyObject* Writer_get_description(WriterObject* self) {
113 const char* description = loc_writer_get_description(self->writer);
114
115 return PyUnicode_FromString(description);
116 }
117
118 static int Writer_set_description(WriterObject* self, PyObject* value) {
119 const char* description = PyUnicode_AsUTF8(value);
120
121 int r = loc_writer_set_description(self->writer, description);
122 if (r) {
123 PyErr_Format(PyExc_ValueError, "Could not set description: %s", description);
124 return r;
125 }
126
127 return 0;
128 }
129
130 static PyObject* Writer_get_license(WriterObject* self) {
131 const char* license = loc_writer_get_license(self->writer);
132
133 return PyUnicode_FromString(license);
134 }
135
136 static int Writer_set_license(WriterObject* self, PyObject* value) {
137 const char* license = PyUnicode_AsUTF8(value);
138
139 int r = loc_writer_set_license(self->writer, license);
140 if (r) {
141 PyErr_Format(PyExc_ValueError, "Could not set license: %s", license);
142 return r;
143 }
144
145 return 0;
146 }
147
148 static PyObject* Writer_add_as(WriterObject* self, PyObject* args) {
149 struct loc_as* as;
150 uint32_t number = 0;
151
152 if (!PyArg_ParseTuple(args, "i", &number))
153 return NULL;
154
155 // Create AS object
156 int r = loc_writer_add_as(self->writer, &as, number);
157 if (r)
158 return NULL;
159
160 PyObject* obj = new_as(&ASType, as);
161 loc_as_unref(as);
162
163 return obj;
164 }
165
166 static PyObject* Writer_add_country(WriterObject* self, PyObject* args) {
167 struct loc_country* country;
168 const char* country_code;
169
170 if (!PyArg_ParseTuple(args, "s", &country_code))
171 return NULL;
172
173 // Create country object
174 int r = loc_writer_add_country(self->writer, &country, country_code);
175 if (r) {
176 switch (r) {
177 case -EINVAL:
178 PyErr_SetString(PyExc_ValueError, "Invalid network");
179 break;
180
181 default:
182 return NULL;
183 }
184 }
185
186 PyObject* obj = new_country(&CountryType, country);
187 loc_country_unref(country);
188
189 return obj;
190 }
191
192 static PyObject* Writer_add_network(WriterObject* self, PyObject* args) {
193 struct loc_network* network;
194 const char* string = NULL;
195
196 if (!PyArg_ParseTuple(args, "s", &string))
197 return NULL;
198
199 // Create network object
200 int r = loc_writer_add_network(self->writer, &network, string);
201 if (r) {
202 switch (r) {
203 case -EINVAL:
204 PyErr_SetString(PyExc_ValueError, "Invalid network");
205 break;
206
207 case -EBUSY:
208 PyErr_SetString(PyExc_IndexError, "A network already exists here");
209 break;
210 }
211
212 return NULL;
213 }
214
215 PyObject* obj = new_network(&NetworkType, network);
216 loc_network_unref(network);
217
218 return obj;
219 }
220
221 static PyObject* Writer_write(WriterObject* self, PyObject* args) {
222 const char* path = NULL;
223 int version = LOC_DATABASE_VERSION_UNSET;
224
225 if (!PyArg_ParseTuple(args, "s|i", &path, &version))
226 return NULL;
227
228 FILE* f = fopen(path, "w+");
229 if (!f) {
230 PyErr_Format(PyExc_IOError, strerror(errno));
231 return NULL;
232 }
233
234 int r = loc_writer_write(self->writer, f, (enum loc_database_version)version);
235 fclose(f);
236
237 // Raise any errors
238 if (r) {
239 PyErr_Format(PyExc_IOError, strerror(errno));
240 return NULL;
241 }
242
243 Py_RETURN_NONE;
244 }
245
246 static struct PyMethodDef Writer_methods[] = {
247 {
248 "add_as",
249 (PyCFunction)Writer_add_as,
250 METH_VARARGS,
251 NULL,
252 },
253 {
254 "add_country",
255 (PyCFunction)Writer_add_country,
256 METH_VARARGS,
257 NULL,
258 },
259 {
260 "add_network",
261 (PyCFunction)Writer_add_network,
262 METH_VARARGS,
263 NULL,
264 },
265 {
266 "write",
267 (PyCFunction)Writer_write,
268 METH_VARARGS,
269 NULL,
270 },
271 { NULL },
272 };
273
274 static struct PyGetSetDef Writer_getsetters[] = {
275 {
276 "description",
277 (getter)Writer_get_description,
278 (setter)Writer_set_description,
279 NULL,
280 NULL,
281 },
282 {
283 "license",
284 (getter)Writer_get_license,
285 (setter)Writer_set_license,
286 NULL,
287 NULL,
288 },
289 {
290 "vendor",
291 (getter)Writer_get_vendor,
292 (setter)Writer_set_vendor,
293 NULL,
294 NULL,
295 },
296 { NULL },
297 };
298
299 PyTypeObject WriterType = {
300 PyVarObject_HEAD_INIT(NULL, 0)
301 .tp_name = "location.Writer",
302 .tp_basicsize = sizeof(WriterObject),
303 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
304 .tp_new = Writer_new,
305 .tp_dealloc = (destructor)Writer_dealloc,
306 .tp_init = (initproc)Writer_init,
307 .tp_doc = "Writer object",
308 .tp_methods = Writer_methods,
309 .tp_getset = Writer_getsetters,
310 };