Branch data Line data Source code
1 : : // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #include <Python.h>
16 : :
17 : : #include <util/buffer.h>
18 : : #include <util/python/pycppwrapper_util.h>
19 : :
20 : : #include <dns/exceptions.h>
21 : : #include <dns/messagerenderer.h>
22 : : #include <dns/name.h>
23 : :
24 : : #include "pydnspp_common.h"
25 : : #include "messagerenderer_python.h"
26 : : #include "name_python.h"
27 : :
28 : : #include <iostream>
29 : :
30 : : using namespace isc::dns;
31 : : using namespace isc::dns::python;
32 : : using namespace isc::util;
33 : : using namespace isc::util::python;
34 : :
35 : : namespace {
36 : : // The s_* Class simply covers one instantiation of the object.
37 : : class s_NameComparisonResult : public PyObject {
38 : : public:
39 : : s_NameComparisonResult() : cppobj(NULL) {}
40 : : NameComparisonResult* cppobj;
41 : : };
42 : :
43 : : class s_Name : public PyObject {
44 : : public:
45 : : s_Name() : cppobj(NULL), position(0) {}
46 : : Name* cppobj;
47 : : size_t position;
48 : : };
49 : :
50 : : int NameComparisonResult_init(s_NameComparisonResult*, PyObject*);
51 : : void NameComparisonResult_destroy(s_NameComparisonResult* self);
52 : : PyObject* NameComparisonResult_getOrder(s_NameComparisonResult* self);
53 : : PyObject* NameComparisonResult_getCommonLabels(s_NameComparisonResult* self);
54 : : PyObject* NameComparisonResult_getRelation(s_NameComparisonResult* self);
55 : :
56 : : PyMethodDef NameComparisonResult_methods[] = {
57 : : { "get_order", reinterpret_cast<PyCFunction>(NameComparisonResult_getOrder), METH_NOARGS,
58 : : "Returns the order" },
59 : : { "get_common_labels", reinterpret_cast<PyCFunction>(NameComparisonResult_getCommonLabels), METH_NOARGS,
60 : : "Returns the number of common labels" },
61 : : { "get_relation", reinterpret_cast<PyCFunction>(NameComparisonResult_getRelation), METH_NOARGS,
62 : : "Returns the relation" },
63 : : { NULL, NULL, 0, NULL }
64 : : };
65 : :
66 : : int
67 : 1 : NameComparisonResult_init(s_NameComparisonResult*, PyObject*) {
68 : : PyErr_SetString(PyExc_NotImplementedError,
69 : 1 : "NameComparisonResult can't be built directly");
70 : 1 : return (-1);
71 : : }
72 : :
73 : : void
74 : 36 : NameComparisonResult_destroy(s_NameComparisonResult* self) {
75 : 36 : delete self->cppobj;
76 : 36 : self->cppobj = NULL;
77 : 36 : Py_TYPE(self)->tp_free(self);
78 : 36 : }
79 : :
80 : : PyObject*
81 : 7 : NameComparisonResult_getOrder(s_NameComparisonResult* self) {
82 : 7 : return (Py_BuildValue("i", self->cppobj->getOrder()));
83 : : }
84 : :
85 : : PyObject*
86 : 2 : NameComparisonResult_getCommonLabels(s_NameComparisonResult* self) {
87 : 2 : return (Py_BuildValue("I", self->cppobj->getCommonLabels()));
88 : : }
89 : :
90 : : PyObject*
91 : 5 : NameComparisonResult_getRelation(s_NameComparisonResult* self) {
92 : 5 : return (Py_BuildValue("I", self->cppobj->getRelation()));
93 : : }
94 : :
95 : : // Shortcut type which would be convenient for adding class variables safely.
96 : : typedef CPPPyObjectContainer<s_Name, Name> NameContainer;
97 : :
98 : : int Name_init(s_Name* self, PyObject* args);
99 : : void Name_destroy(s_Name* self);
100 : :
101 : : PyObject* Name_toWire(s_Name* self, PyObject* args);
102 : : PyObject* Name_toText(s_Name* self, PyObject* args);
103 : : PyObject* Name_str(PyObject* self);
104 : : PyObject* Name_getLabelCount(s_Name* self);
105 : : PyObject* Name_at(s_Name* self, PyObject* args);
106 : : PyObject* Name_getLength(s_Name* self);
107 : :
108 : : PyObject* Name_compare(s_Name* self, PyObject* args);
109 : : PyObject* Name_equals(s_Name* self, PyObject* args);
110 : :
111 : : PyObject* Name_richcmp(s_Name* self, s_Name* other, int op);
112 : : PyObject* Name_split(s_Name* self, PyObject* args);
113 : : PyObject* Name_reverse(s_Name* self);
114 : : PyObject* Name_concatenate(s_Name* self, PyObject* args);
115 : : PyObject* Name_downcase(s_Name* self);
116 : : PyObject* Name_isWildCard(s_Name* self);
117 : :
118 : : PyMethodDef Name_methods[] = {
119 : : { "at", reinterpret_cast<PyCFunction>(Name_at), METH_VARARGS,
120 : : "Returns the integer value of the name data at the specified position" },
121 : : { "get_length", reinterpret_cast<PyCFunction>(Name_getLength), METH_NOARGS,
122 : : "Returns the length" },
123 : : { "get_labelcount", reinterpret_cast<PyCFunction>(Name_getLabelCount), METH_NOARGS,
124 : : "Returns the number of labels" },
125 : : { "to_text", reinterpret_cast<PyCFunction>(Name_toText), METH_VARARGS,
126 : : "Returns the string representation. The optional argument must be either"
127 : : "True of False. If True, the final dot will be omitted." },
128 : : { "to_wire", reinterpret_cast<PyCFunction>(Name_toWire), METH_VARARGS,
129 : : "Converts the Name object to wire format.\n"
130 : : "The argument can be either a MessageRenderer or an object that "
131 : : "implements the sequence interface. If the object is mutable "
132 : : "(for instance a bytearray()), the wire data is added in-place.\n"
133 : : "If it is not (for instance a bytes() object), a new object is "
134 : : "returned" },
135 : : { "compare", reinterpret_cast<PyCFunction>(Name_compare), METH_VARARGS,
136 : : "Returns a NameComparisonResult object. The argument must be another Name object" },
137 : : { "equals", reinterpret_cast<PyCFunction>(Name_equals), METH_VARARGS,
138 : : "Returns true if the given Name object is equal to this one" },
139 : : { "split", reinterpret_cast<PyCFunction>(Name_split), METH_VARARGS,
140 : : "Splits the name, takes two arguments, the first is an integer "
141 : : "specifying the first label to place in the result. The second "
142 : : "is an integer specifying the number of labels to put in the "
143 : : "result. Returns a new Name object" },
144 : : { "reverse", reinterpret_cast<PyCFunction>(Name_reverse), METH_NOARGS,
145 : : "Returns a new Name object that is the reverse of this one" },
146 : : { "concatenate", reinterpret_cast<PyCFunction>(Name_concatenate), METH_VARARGS,
147 : : "Concatenates the given Name object to this one and returns the "
148 : : "result as a new Name object" },
149 : : { "downcase", reinterpret_cast<PyCFunction>(Name_downcase), METH_NOARGS,
150 : : "Downcases this name object (in-place). Returns a new reference to the Name." },
151 : : { "is_wildcard", reinterpret_cast<PyCFunction>(Name_isWildCard), METH_NOARGS,
152 : : "Returns True if the Name object represents a wildcard name." },
153 : : { NULL, NULL, 0, NULL }
154 : : };
155 : :
156 : : int
157 : 1684 : Name_init(s_Name* self, PyObject* args) {
158 : : const char* s;
159 : 1684 : PyObject* downcase = Py_False;
160 : :
161 : : // Depending on the arguments in *args, we decide which of the
162 : : // constructors is meant. If the first argument is of type string,
163 : : // we use the string-based constructor. If it is a bytes object,
164 : : // we use the wire-based one.
165 [ + + ]: 1684 : if (PyArg_ParseTuple(args, "s|O!", &s, &PyBool_Type, &downcase)) {
166 : : try {
167 [ + - ]: 3356 : const std::string n(s);
168 : :
169 [ + - ][ + + ]: 1678 : self->cppobj = new Name(n, downcase == Py_True);
170 : 1666 : self->position = 0;
171 : 10 : } catch (const EmptyLabel&) {
172 [ - + ]: 5 : PyErr_SetString(po_EmptyLabel, "EmptyLabel");
173 : : return (-1);
174 : 2 : } catch (const TooLongLabel&) {
175 [ - + ]: 1 : PyErr_SetString(po_TooLongLabel, "TooLongLabel");
176 : : return (-1);
177 : 2 : } catch (const BadLabelType&) {
178 [ - + ]: 1 : PyErr_SetString(po_BadLabelType, "BadLabelType");
179 : : return (-1);
180 : 2 : } catch (const BadEscape&) {
181 [ - + ]: 1 : PyErr_SetString(po_BadEscape, "BadEscape");
182 : : return (-1);
183 : 2 : } catch (const TooLongName&) {
184 [ - + ]: 1 : PyErr_SetString(po_TooLongName, "TooLongName");
185 : : return (-1);
186 : 6 : } catch (const IncompleteName&) {
187 [ - + ]: 3 : PyErr_SetString(po_IncompleteName, "IncompleteName");
188 : : return (-1);
189 : : #ifdef CATCHMEMERR
190 : : } catch (const std::bad_alloc&) {
191 : : PyErr_NoMemory();
192 : : return (-1);
193 : : #endif
194 [ + + + + : 12 : } catch (...) {
+ + - ]
195 [ # # ]: 0 : PyErr_SetString(po_IscException, "Unexpected?!");
196 : : return (-1);
197 : : }
198 : 1666 : return (0);
199 : : }
200 : 6 : PyErr_Clear();
201 : :
202 : : PyObject* bytes_obj;
203 : : const char* bytes;
204 : : Py_ssize_t len;
205 : 6 : long position = 0;
206 : :
207 : : // It was not a string (see comment above), so try bytes, and
208 : : // create with buffer object
209 [ + - + + ]: 12 : if (PyArg_ParseTuple(args, "O|lO!", &bytes_obj, &position,
[ + + ]
210 : 6 : &PyBool_Type, &downcase) &&
211 : 6 : PyObject_AsCharBuffer(bytes_obj, &bytes, &len) != -1) {
212 : : try {
213 [ + + ]: 5 : if (position < 0) {
214 : : // Throw IndexError here since name index should be unsigned
215 : : PyErr_SetString(PyExc_IndexError,
216 [ + - ]: 1 : "Name index shouldn't be negative");
217 : : return (-1);
218 : : }
219 : 4 : InputBuffer buffer(bytes, len);
220 : :
221 : 4 : buffer.setPosition(position);
222 [ + - ][ + + ]: 3 : self->cppobj = new Name(buffer, downcase == Py_True);
223 : 2 : self->position = buffer.getPosition();
224 : 2 : } catch (const InvalidBufferPosition&) {
225 : : PyErr_SetString(po_InvalidBufferPosition,
226 [ - + ]: 1 : "InvalidBufferPosition");
227 : : return (-1);
228 : 2 : } catch (const DNSMessageFORMERR&) {
229 [ - + ]: 1 : PyErr_SetString(po_DNSMessageFORMERR, "DNSMessageFORMERR");
230 : : return (-1);
231 [ + + - ]: 2 : } catch (...) {
232 [ # # ]: 0 : PyErr_SetString(po_IscException, "Unexpected?!");
233 : : return (-1);
234 : : }
235 : 2 : return (0);
236 : : }
237 : :
238 : 1 : PyErr_Clear();
239 : : PyErr_SetString(PyExc_TypeError,
240 : 1 : "No valid types in Name constructor (should be string or sequence and offset");
241 : 1684 : return (-1);
242 : : }
243 : :
244 : : void
245 : 2909 : Name_destroy(s_Name* self) {
246 [ + + ]: 5797 : delete self->cppobj;
247 : 2909 : self->cppobj = NULL;
248 : 2909 : Py_TYPE(self)->tp_free(self);
249 : 2909 : }
250 : :
251 : : PyObject*
252 : 6 : Name_at(s_Name* self, PyObject* args) {
253 : : int pos;
254 [ + + ]: 6 : if (!PyArg_ParseTuple(args, "i", &pos)) {
255 : : return (NULL);
256 : : }
257 [ + + ]: 5 : if (pos < 0) {
258 : : // Throw IndexError here since name index should be unsigned
259 : : PyErr_SetString(PyExc_IndexError,
260 : 1 : "name index shouldn't be negative");
261 : 1 : return (NULL);
262 : : }
263 : :
264 : : try {
265 [ + + ][ + - ]: 8 : return (Py_BuildValue("I", self->cppobj->at(pos)));
266 [ - + ]: 4 : } catch (const isc::OutOfRange&) {
267 : : PyErr_SetString(PyExc_IndexError,
268 [ - + ]: 2 : "name index out of range");
269 : : return (NULL);
270 : : }
271 : : }
272 : :
273 : : PyObject*
274 : 19 : Name_getLength(s_Name* self) {
275 : 19 : return (Py_BuildValue("i", self->cppobj->getLength()));
276 : : }
277 : :
278 : : PyObject*
279 : 3 : Name_getLabelCount(s_Name* self) {
280 : 3 : return (Py_BuildValue("i", self->cppobj->getLabelCount()));
281 : : }
282 : :
283 : : PyObject*
284 : 494 : Name_toText(s_Name* self, PyObject* args) {
285 : 494 : PyObject* omit_final_dot_obj = NULL;
286 [ + + ]: 494 : if (PyArg_ParseTuple(args, "|O", &omit_final_dot_obj)) {
287 : 493 : bool omit_final_dot = false;
288 [ + + ]: 493 : if (omit_final_dot_obj != NULL) {
289 [ + + ][ + + ]: 164 : if (PyBool_Check(omit_final_dot_obj) != 0) {
290 : 161 : omit_final_dot = (omit_final_dot_obj == Py_True);
291 : : } else {
292 : : PyErr_SetString(PyExc_TypeError,
293 : 3 : "Optional argument 1 of to_text() should be True of False");
294 : 3 : return (NULL);
295 : : }
296 : : }
297 : : return (Py_BuildValue("s",
298 [ + - ]: 494 : self->cppobj->toText(omit_final_dot).c_str()));
299 : : } else {
300 : : return (NULL);
301 : : }
302 : : }
303 : :
304 : : PyObject*
305 : 10 : Name_str(PyObject* self) {
306 : : // Simply call the to_text method we already defined
307 : : // str() is not defined in the c++ version, only to_text
308 : : // and we already have a wrapper for that one.
309 : : return (PyObject_CallMethod(self,
310 : : const_cast<char*>("to_text"),
311 : 10 : const_cast<char*>("")));
312 : : }
313 : :
314 : : PyObject*
315 : 6 : Name_toWire(s_Name* self, PyObject* args) {
316 : : PyObject* bytes;
317 : : PyObject* mr;
318 : :
319 [ + - ][ + + ]: 6 : if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
[ + + ]
320 : 4 : PyObject* bytes_o = bytes;
321 : :
322 : 4 : OutputBuffer buffer(Name::MAX_WIRE);
323 [ + - ]: 4 : self->cppobj->toWire(buffer);
324 [ + - ]: 4 : PyObject* name_bytes = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
325 [ + - ]: 4 : PyObject* result = PySequence_InPlaceConcat(bytes_o, name_bytes);
326 : : // We need to release the object we temporarily created here
327 : : // to prevent memory leak
328 [ + + ][ + - ]: 4 : Py_DECREF(name_bytes);
329 : : return (result);
330 [ + + ]: 2 : } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
331 : 1 : self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
332 : : // If we return NULL it is seen as an error, so use this for
333 : : // None returns
334 : 1 : Py_RETURN_NONE;
335 : : }
336 : 1 : PyErr_Clear();
337 : : PyErr_SetString(PyExc_TypeError,
338 : 1 : "toWire argument must be a sequence object or a MessageRenderer");
339 : 6 : return (NULL);
340 : : }
341 : :
342 : : PyObject*
343 : 35 : Name_compare(s_Name* self, PyObject* args) {
344 : : s_Name* other;
345 : :
346 [ + - ]: 35 : if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
347 : : return (NULL);
348 : :
349 : 35 : s_NameComparisonResult* ret = PyObject_New(s_NameComparisonResult, &name_comparison_result_type);
350 [ + - ]: 35 : if (ret != NULL) {
351 : : ret->cppobj = new NameComparisonResult(
352 [ + - ]: 35 : self->cppobj->compare(*other->cppobj));
353 : : }
354 : : return (ret);
355 : : }
356 : :
357 : : PyObject*
358 : 3 : Name_equals(s_Name* self, PyObject* args) {
359 : : s_Name* other;
360 : :
361 [ + - ]: 3 : if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
362 : : return (NULL);
363 : :
364 [ + + ]: 3 : if (self->cppobj->equals(*other->cppobj))
365 : 1 : Py_RETURN_TRUE;
366 : : else
367 : 3 : Py_RETURN_FALSE;
368 : : }
369 : :
370 : : PyObject*
371 : 17 : Name_split(s_Name* self, PyObject* args) {
372 : : int first, n;
373 : 17 : s_Name* ret = NULL;
374 : :
375 [ + + ]: 17 : if (PyArg_ParseTuple(args, "ii", &first, &n)) {
376 [ + + ][ + + ]: 9 : if (first < 0 || n < 0) {
377 : : // Throw IndexError here since name index should be unsigned
378 : : PyErr_SetString(PyExc_IndexError,
379 : 3 : "name index shouldn't be negative");
380 : 3 : return (NULL);
381 : : }
382 : 6 : ret = PyObject_New(s_Name, &name_type);
383 [ + - ]: 6 : if (ret != NULL) {
384 : 6 : ret->cppobj = NULL;
385 : : try {
386 [ + - ][ + + ]: 6 : ret->cppobj = new Name(self->cppobj->split(first, n));
387 [ - + ]: 6 : } catch(const isc::OutOfRange& oor) {
388 [ - + ]: 3 : PyErr_SetString(PyExc_IndexError, oor.what());
389 : 3 : ret->cppobj = NULL;
390 : : }
391 [ + + ]: 6 : if (ret->cppobj == NULL) {
392 [ + - ]: 3 : Py_DECREF(ret);
393 : : return (NULL);
394 : : }
395 : : }
396 [ + + ]: 8 : } else if (PyArg_ParseTuple(args, "i", &n)) {
397 : 5 : PyErr_Clear();
398 [ + + ]: 5 : if (n < 0) {
399 : : // Throw IndexError here since name index should be unsigned
400 : : PyErr_SetString(PyExc_IndexError,
401 : 1 : "name index shouldn't be negative");
402 : 1 : return (NULL);
403 : : }
404 : 4 : ret = PyObject_New(s_Name, &name_type);
405 [ + - ]: 4 : if (ret != NULL) {
406 : 4 : ret->cppobj = NULL;
407 : : try {
408 [ + - ][ + + ]: 4 : ret->cppobj = new Name(self->cppobj->split(n));
409 [ - + ]: 4 : } catch(const isc::OutOfRange& oor) {
410 [ - + ]: 2 : PyErr_SetString(PyExc_IndexError, oor.what());
411 : 2 : ret->cppobj = NULL;
412 : : }
413 [ + + ]: 4 : if (ret->cppobj == NULL) {
414 [ + - ]: 2 : Py_DECREF(ret);
415 : : return (NULL);
416 : : }
417 : : }
418 : : }
419 : :
420 : 8 : PyErr_Clear();
421 : : PyErr_SetString(PyExc_TypeError,
422 : 8 : "No valid type in split argument");
423 : 17 : return (ret);
424 : : }
425 : :
426 : : //
427 : : // richcmp defines the ==, !=, >, <, >= and <= operators in python
428 : : // It is translated to a function that gets 3 arguments, an object,
429 : : // an object to compare to, and an operator.
430 : : //
431 : : PyObject*
432 : 1104 : Name_richcmp(s_Name* self, s_Name* other, int op) {
433 : : bool c;
434 : :
435 : : // Check for null and if the types match. If different type,
436 : : // simply return False
437 [ + - ][ + + ]: 1104 : if (!other || (self->ob_type != other->ob_type)) {
438 : 1 : Py_RETURN_FALSE;
439 : : }
440 : :
441 [ + + + + : 1103 : switch (op) {
+ + - ]
442 : : case Py_LT:
443 : 2 : c = *self->cppobj < *other->cppobj;
444 : 2 : break;
445 : : case Py_LE:
446 : 3 : c = *self->cppobj <= *other->cppobj;
447 : 3 : break;
448 : : case Py_EQ:
449 : 904 : c = *self->cppobj == *other->cppobj;
450 : 904 : break;
451 : : case Py_NE:
452 : 378 : c = *self->cppobj != *other->cppobj;
453 : 189 : break;
454 : : case Py_GT:
455 : 2 : c = *self->cppobj > *other->cppobj;
456 : 2 : break;
457 : : case Py_GE:
458 : 3 : c = *self->cppobj >= *other->cppobj;
459 : 3 : break;
460 : : default:
461 : : PyErr_SetString(PyExc_IndexError,
462 : 0 : "Unhandled rich comparison operator");
463 : 0 : return (NULL);
464 : : }
465 [ + + ]: 1103 : if (c) {
466 : 717 : Py_RETURN_TRUE;
467 : : } else {
468 : 1104 : Py_RETURN_FALSE;
469 : : }
470 : : }
471 : :
472 : : PyObject*
473 : 2 : Name_reverse(s_Name* self) {
474 : 2 : s_Name* ret = PyObject_New(s_Name, &name_type);
475 : :
476 [ + - ]: 2 : if (ret != NULL) {
477 [ + - ]: 2 : ret->cppobj = new Name(self->cppobj->reverse());
478 [ - + ]: 2 : if (ret->cppobj == NULL) {
479 [ # # ]: 2 : Py_DECREF(ret);
480 : : return (NULL);
481 : : }
482 : : }
483 : : return (ret);
484 : : }
485 : :
486 : : PyObject*
487 : 4 : Name_concatenate(s_Name* self, PyObject* args) {
488 : : s_Name* other;
489 : :
490 [ + + ]: 4 : if (!PyArg_ParseTuple(args, "O!", &name_type, &other))
491 : : return (NULL);
492 : :
493 : 3 : s_Name* ret = PyObject_New(s_Name, &name_type);
494 [ + - ]: 3 : if (ret != NULL) {
495 : : try {
496 [ + - ][ + + ]: 5 : ret->cppobj = new Name(self->cppobj->concatenate(*other->cppobj));
497 [ - + ]: 2 : } catch (const TooLongName& tln) {
498 [ - + ]: 1 : PyErr_SetString(po_TooLongName, tln.what());
499 : : return (NULL);
500 : : }
501 : : }
502 : : return (ret);
503 : : }
504 : :
505 : : PyObject*
506 : 1 : Name_downcase(s_Name* self) {
507 : 1 : self->cppobj->downcase();
508 : 1 : Py_INCREF(self);
509 : 1 : return (self);
510 : : }
511 : :
512 : : PyObject*
513 : 2 : Name_isWildCard(s_Name* self) {
514 [ + + ]: 2 : if (self->cppobj->isWildcard()) {
515 : 1 : Py_RETURN_TRUE;
516 : : } else {
517 : 2 : Py_RETURN_FALSE;
518 : : }
519 : : }
520 : :
521 : : } // end of unnamed namespace
522 : :
523 : : namespace isc {
524 : : namespace dns {
525 : : namespace python {
526 : :
527 : : //
528 : : // Definition of the custom exceptions
529 : : // Initialization and addition of these go in the module init at the
530 : : // end
531 : : //
532 : : PyObject* po_EmptyLabel;
533 : : PyObject* po_TooLongName;
534 : : PyObject* po_TooLongLabel;
535 : : PyObject* po_BadLabelType;
536 : : PyObject* po_BadEscape;
537 : : PyObject* po_IncompleteName;
538 : : PyObject* po_InvalidBufferPosition;
539 : : PyObject* po_DNSMessageFORMERR;
540 : :
541 : : //
542 : : // Definition of enums
543 : : // Initialization and addition of these go in the module init at the
544 : : // end
545 : : //
546 : : PyObject* po_NameRelation;
547 : :
548 : : PyTypeObject name_comparison_result_type = {
549 : : PyVarObject_HEAD_INIT(NULL, 0)
550 : : "pydnspp.NameComparisonResult",
551 : : sizeof(s_NameComparisonResult), // tp_basicsize
552 : : 0, // tp_itemsize
553 : : (destructor)NameComparisonResult_destroy, // tp_dealloc
554 : : NULL, // tp_print
555 : : NULL, // tp_getattr
556 : : NULL, // tp_setattr
557 : : NULL, // tp_reserved
558 : : NULL, // tp_repr
559 : : NULL, // tp_as_number
560 : : NULL, // tp_as_sequence
561 : : NULL, // tp_as_mapping
562 : : NULL, // tp_hash
563 : : NULL, // tp_call
564 : : NULL, // tp_str
565 : : NULL, // tp_getattro
566 : : NULL, // tp_setattro
567 : : NULL, // tp_as_buffer
568 : : Py_TPFLAGS_DEFAULT, // tp_flags
569 : : "This is a supplemental class used only as a return value of Name.compare(). "
570 : : "It encapsulate a tuple of the comparison: ordering, number of common labels, "
571 : : "and relationship as follows:\n"
572 : : "- ordering: relative ordering under the DNSSEC order relation\n"
573 : : "- labels: the number of common significant labels of the two names being"
574 : : " compared\n"
575 : : "- relationship: see NameComparisonResult.NameRelation\n",
576 : : NULL, // tp_traverse
577 : : NULL, // tp_clear
578 : : NULL, // tp_richcompare
579 : : 0, // tp_weaklistoffset
580 : : NULL, // tp_iter
581 : : NULL, // tp_iternext
582 : : NameComparisonResult_methods, // tp_methods
583 : : NULL, // tp_members
584 : : NULL, // tp_getset
585 : : NULL, // tp_base
586 : : NULL, // tp_dict
587 : : NULL, // tp_descr_get
588 : : NULL, // tp_descr_set
589 : : 0, // tp_dictoffset
590 : : (initproc)NameComparisonResult_init, // tp_init
591 : : NULL, // tp_alloc
592 : : PyType_GenericNew, // tp_new
593 : : NULL, // tp_free
594 : : NULL, // tp_is_gc
595 : : NULL, // tp_bases
596 : : NULL, // tp_mro
597 : : NULL, // tp_cache
598 : : NULL, // tp_subclasses
599 : : NULL, // tp_weaklist
600 : : NULL, // tp_del
601 : : 0 // tp_version_tag
602 : : };
603 : :
604 : : PyTypeObject name_type = {
605 : : PyVarObject_HEAD_INIT(NULL, 0)
606 : : "pydnspp.Name",
607 : : sizeof(s_Name), // tp_basicsize
608 : : 0, // tp_itemsize
609 : : (destructor)Name_destroy, // tp_dealloc
610 : : NULL, // tp_print
611 : : NULL, // tp_getattr
612 : : NULL, // tp_setattr
613 : : NULL, // tp_reserved
614 : : NULL, // tp_repr
615 : : NULL, // tp_as_number
616 : : NULL, // tp_as_sequence
617 : : NULL, // tp_as_mapping
618 : : NULL, // tp_hash
619 : : NULL, // tp_call
620 : : Name_str, // tp_str
621 : : NULL, // tp_getattro
622 : : NULL, // tp_setattro
623 : : NULL, // tp_as_buffer
624 : : Py_TPFLAGS_DEFAULT, // tp_flags
625 : : "The Name class encapsulates DNS names.\n"
626 : : "It provides interfaces to construct a name from string or wire-format data, "
627 : : "transform a name into a string or wire-format data, compare two names, get "
628 : : "access to various properties of a name, etc.",
629 : : NULL, // tp_traverse
630 : : NULL, // tp_clear
631 : : (richcmpfunc)Name_richcmp, // tp_richcompare
632 : : 0, // tp_weaklistoffset
633 : : NULL, // tp_iter
634 : : NULL, // tp_iternext
635 : : Name_methods, // tp_methods
636 : : NULL, // tp_members
637 : : NULL, // tp_getset
638 : : NULL, // tp_base
639 : : NULL, // tp_dict
640 : : NULL, // tp_descr_get
641 : : NULL, // tp_descr_set
642 : : 0, // tp_dictoffset
643 : : (initproc)Name_init, // tp_init
644 : : NULL, // tp_alloc
645 : : PyType_GenericNew, // tp_new
646 : : NULL, // tp_free
647 : : NULL, // tp_is_gc
648 : : NULL, // tp_bases
649 : : NULL, // tp_mro
650 : : NULL, // tp_cache
651 : : NULL, // tp_subclasses
652 : : NULL, // tp_weaklist
653 : : // Note: not sure if the following are correct. Added them just to
654 : : // make the compiler happy.
655 : : NULL, // tp_del
656 : : 0 // tp_version_tag
657 : : };
658 : :
659 : : PyObject*
660 : 1414 : createNameObject(const Name& source) {
661 : 1414 : NameContainer container(PyObject_New(s_Name, &name_type));
662 [ + - ][ + - ]: 2828 : container.set(new Name(source));
663 : 1414 : return (container.release());
664 : : }
665 : :
666 : : bool
667 : 9 : PyName_Check(PyObject* obj) {
668 [ - + ]: 9 : if (obj == NULL) {
669 [ # # ]: 0 : isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
670 : : }
671 [ + + ][ + - ]: 9 : return (PyObject_TypeCheck(obj, &name_type));
672 : : }
673 : :
674 : : const Name&
675 : 2161 : PyName_ToName(const PyObject* name_obj) {
676 [ - + ]: 2161 : if (name_obj == NULL) {
677 [ # # ]: 0 : isc_throw(PyCPPWrapperException,
678 : : "obj argument NULL in Name PyObject conversion");
679 : : }
680 : 2161 : const s_Name* name = static_cast<const s_Name*>(name_obj);
681 : 2161 : return (*name->cppobj);
682 : : }
683 : :
684 : :
685 : : } // namespace python
686 : : } // namespace dns
687 : 123 : } // namespace isc
|