blob: a243507243ae31c0cb3d694082ca16dfe7e095a1 [file] [log] [blame]
Radek Krejci0f3499a2017-10-13 13:39:36 +02001/**
2 * @file err.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief NETCONF reply errors
5 *
6 * Copyright (c) 2017 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15/* Python API header */
16#include <Python.h>
17#include <structmember.h>
18
19/* standard headers */
20#include <string.h>
21
22#include "netconf.h"
Radek Krejcic2074282017-11-06 15:57:22 +010023#include "../src/messages_p.h"
Radek Krejci0f3499a2017-10-13 13:39:36 +020024
25static void
26ncErrFree(ncErrObject *self)
27{
28 nc_client_err_clean(self->err, self->ctx);
29
30 Py_TYPE(self)->tp_free((PyObject*)self);
31}
32
Radek Krejci06542e42018-02-08 14:22:48 +010033static char *
34escape_quotes(char *strbuf, size_t strbuf_size, const char *text)
35{
36 size_t i, o;
37 for (i = o = 0; i < strbuf_size; i++) {
38 if (text[i] == '"') {
39 strbuf[o++] = '\\';
40 }
41 strbuf[o++] = text[i];
42 if (!text[i]) {
43 /* end of the text */
44 break;
45 }
46 }
47 return strbuf;
48}
49
Radek Krejci0f3499a2017-10-13 13:39:36 +020050static PyObject *
51ncErrStr(ncErrObject *self)
52{
Radek Krejcib5ac0602017-10-17 10:35:03 +020053 uint16_t u, f = 0;
54 char *str = NULL;
Radek Krejci06542e42018-02-08 14:22:48 +010055#define BUFSIZE 4096
56 char buf[BUFSIZE];
Radek Krejcib5ac0602017-10-17 10:35:03 +020057
58 if (self->err->type) {
59 asprintf(&str, "\"type\":\"%s\"", self->err->type);
60 }
61 if (self->err->tag) {
62 asprintf(&str, "%s%s\"tag\":\"%s\"", str ? str : "", str ? "," : "", self->err->tag);
63 }
64 if (self->err->severity) {
65 asprintf(&str, "%s%s\"severity\":\"%s\"", str ? str : "", str ? "," : "", self->err->severity);
66 }
67 if (self->err->apptag) {
Radek Krejci06542e42018-02-08 14:22:48 +010068 asprintf(&str, "%s%s\"app-tag\":\"%s\"", str ? str : "", str ? "," : "", escape_quotes(buf, BUFSIZE, self->err->apptag));
Radek Krejcib5ac0602017-10-17 10:35:03 +020069 }
70 if (self->err->path) {
Radek Krejci06542e42018-02-08 14:22:48 +010071 asprintf(&str, "%s%s\"path\":\"%s\"", str ? str : "", str ? "," : "", escape_quotes(buf, BUFSIZE, self->err->path));
Radek Krejcib5ac0602017-10-17 10:35:03 +020072 }
73 if (self->err->message) {
Radek Krejci06542e42018-02-08 14:22:48 +010074 asprintf(&str, "%s%s\"message\":\"%s", str ? str : "", str ? "," : "", escape_quotes(buf, BUFSIZE, self->err->message));
Radek Krejcib5ac0602017-10-17 10:35:03 +020075 if (self->err->message_lang) {
76 asprintf(&str, "%s (%s)\"", str, self->err->message_lang);
77 } else {
78 asprintf(&str, "%s\"", str);
79 }
80 }
81 if (self->err->sid || self->err->attr || self->err->elem || self->err->ns || self->err->other) {
82 asprintf(&str, "%s%s\"info\":{", str ? str : "", str ? "," : "");
83
84 if (self->err->sid) {
85 asprintf(&str, "%s%s\"session-id\":\"%s\"", str, f ? "," : "", self->err->sid);
86 f = 1;
87 }
88 if (self->err->attr_count) {
89 asprintf(&str, "%s%s\"bad-attr\":[", str, f ? "," : "");
90 for (u = 0; u < self->err->attr_count; u++) {
91 asprintf(&str, "%s%s\"%s\"", str, u ? "," : "", self->err->attr[u]);
92 }
93 asprintf(&str, "%s]", str);
94 f = 1;
95 }
96 if (self->err->elem_count) {
97 asprintf(&str, "%s%s\"bad-element\":[", str, f ? "," : "");
98 for (u = 0; u < self->err->elem_count; u++) {
99 asprintf(&str, "%s%s\"%s\"", str, u ? "," : "", self->err->elem[u]);
100 }
101 asprintf(&str, "%s]", str);
102 f = 1;
103 }
104 if (self->err->ns_count) {
105 asprintf(&str, "%s%s\"bad-namespace\":[", str, f ? "," : "");
106 for (u = 0; u < self->err->ns_count; u++) {
107 asprintf(&str, "%s%s\"%s\"", str, u ? "," : "", self->err->ns[u]);
108 }
109 asprintf(&str, "%s]", str);
110 f = 1;
111 }
112 if (self->err->other_count) {
113 for (u = 0; u < self->err->other_count; u++) {
Radek Krejci06542e42018-02-08 14:22:48 +0100114 asprintf(&str, "%s%s\"%s\":\"%s\"", str, f ? "," : "", self->err->other[u]->name,
115 escape_quotes(buf, BUFSIZE, self->err->other[u]->content));
Radek Krejcib5ac0602017-10-17 10:35:03 +0200116 }
117 f = 1;
118 }
119
120 asprintf(&str, "%s}", str);
121 }
122 return PyUnicode_FromFormat("{%s}", str);
Radek Krejci0f3499a2017-10-13 13:39:36 +0200123}
124
125/*
126 * tp_getset callbacs held by ncErrGetSetters[]
127 */
128
129static PyObject *
130ncErrGetType(ncErrObject *self, void *closure)
131{
132 if (!self->err->type) {
133 Py_RETURN_NONE;
134 }
135 return PyUnicode_FromString(self->err->type);
136}
137
138static PyObject *
139ncErrGetTag(ncErrObject *self, void *closure)
140{
141 if (!self->err->tag) {
142 Py_RETURN_NONE;
143 }
144 return PyUnicode_FromString(self->err->tag);
145}
146
147static PyObject *
Radek Krejcib5ac0602017-10-17 10:35:03 +0200148ncErrGetSeverity(ncErrObject *self, void *closure)
149{
150 if (!self->err->severity) {
151 Py_RETURN_NONE;
152 }
153 return PyUnicode_FromString(self->err->severity);
154}
155
156static PyObject *
157ncErrGetAppTag(ncErrObject *self, void *closure)
158{
159 if (!self->err->apptag) {
160 Py_RETURN_NONE;
161 }
162 return PyUnicode_FromString(self->err->apptag);
163}
164
165static PyObject *
166ncErrGetPath(ncErrObject *self, void *closure)
167{
168 if (!self->err->path) {
169 Py_RETURN_NONE;
170 }
171 return PyUnicode_FromString(self->err->path);
172}
173
174static PyObject *
Radek Krejci0f3499a2017-10-13 13:39:36 +0200175ncErrGetMessage(ncErrObject *self, void *closure)
176{
177 if (!self->err->message) {
178 Py_RETURN_NONE;
179 }
180 return PyUnicode_FromString(self->err->message);
181}
182
Radek Krejcib5ac0602017-10-17 10:35:03 +0200183static PyObject *
184ncErrGetMessageLang(ncErrObject *self, void *closure)
185{
186 if (!self->err->message_lang) {
187 Py_RETURN_NONE;
188 }
189 return PyUnicode_FromString(self->err->message_lang);
190}
191
192static PyObject *
193ncErrGetSID(ncErrObject *self, void *closure)
194{
195 if (!self->err->sid) {
196 Py_RETURN_NONE;
197 }
198 return PyUnicode_FromString(self->err->sid);
199}
200
201static PyObject *
202ncErrGetBadAttr(ncErrObject *self, void *closure)
203{
204 PyObject *list;
205 uint16_t u;
206
207 if (!self->err->attr_count) {
208 Py_RETURN_NONE;
209 }
210
211 list = PyList_New(self->err->attr_count);
212 if (!list) {
213 return NULL;
214 }
215 for (u = 0; u < self->err->attr_count; u++) {
216 PyList_SET_ITEM(list, u, PyUnicode_FromString(self->err->attr[u]));
217 }
218
219 return list;
220}
221
222static PyObject *
223ncErrGetBadElem(ncErrObject *self, void *closure)
224{
225 PyObject *list;
226 uint16_t u;
227
228 if (!self->err->elem_count) {
229 Py_RETURN_NONE;
230 }
231
232 list = PyList_New(self->err->elem_count);
233 if (!list) {
234 return NULL;
235 }
236 for (u = 0; u < self->err->elem_count; u++) {
237 PyList_SET_ITEM(list, u, PyUnicode_FromString(self->err->elem[u]));
238 }
239
240 return list;
241}
242
243static PyObject *
244ncErrGetBadNS(ncErrObject *self, void *closure)
245{
246 PyObject *list;
247 uint16_t u;
248
249 if (!self->err->ns_count) {
250 Py_RETURN_NONE;
251 }
252
253 list = PyList_New(self->err->ns_count);
254 if (!list) {
255 return NULL;
256 }
257 for (u = 0; u < self->err->ns_count; u++) {
258 PyList_SET_ITEM(list, u, PyUnicode_FromString(self->err->ns[u]));
259 }
260
261 return list;
262}
263
Radek Krejci0f3499a2017-10-13 13:39:36 +0200264/*
265 * Callback structures
266 */
267
268static PyGetSetDef ncErrGetSetters[] = {
269 {"type", (getter)ncErrGetType, NULL, "<error-type>", NULL},
270 {"tag", (getter)ncErrGetTag, NULL, "<error-tag>", NULL},
Radek Krejcib5ac0602017-10-17 10:35:03 +0200271 {"severity", (getter)ncErrGetSeverity, NULL, "<error-severity>", NULL},
272 {"app-tag", (getter)ncErrGetAppTag, NULL, "<error-app-tag>", NULL},
273 {"path", (getter)ncErrGetPath, NULL, "<error-path>", NULL},
Radek Krejci0f3499a2017-10-13 13:39:36 +0200274 {"message", (getter)ncErrGetMessage, NULL, "<error-message>", NULL},
Radek Krejcib5ac0602017-10-17 10:35:03 +0200275 {"lang", (getter)ncErrGetMessageLang, NULL, "<error-message xml:lang=\" \">", NULL},
276 {"session-id", (getter)ncErrGetSID, NULL, "<error-info><session-id/></error-info>", NULL},
277 {"bad-attr", (getter)ncErrGetBadAttr, NULL, "<error-info><bad-attr/></error-info>", NULL},
278 {"bad-elem", (getter)ncErrGetBadElem, NULL, "<error-info><bad-element/></error-info>", NULL},
279 {"bad-namespace", (getter)ncErrGetBadNS, NULL, "<error-info><bad-namespace/></error-info>", NULL},
Radek Krejci0f3499a2017-10-13 13:39:36 +0200280 {NULL} /* Sentinel */
281};
282
283PyDoc_STRVAR(ncErrDoc,
284 "NETCONF Error Reply information.\n\n");
285
286PyTypeObject ncErrType = {
287 PyVarObject_HEAD_INIT(NULL, 0)
288 "netconf2.Err", /* tp_name */
289 sizeof(ncErrObject), /* tp_basicsize */
290 0, /* tp_itemsize */
291 (destructor)ncErrFree, /* tp_dealloc */
292 0, /* tp_print */
293 0, /* tp_getattr */
294 0, /* tp_setattr */
295 0, /* tp_reserved */
296 (reprfunc)ncErrStr, /* tp_repr */
297 0, /* tp_as_number */
298 0, /* tp_as_sequence */
299 0, /* tp_as_mapping */
300 0, /* tp_hash */
301 0, /* tp_call */
302 (reprfunc)ncErrStr, /* tp_str */
303 0, /* tp_getattro */
304 0, /* tp_setattro */
305 0, /* tp_as_buffer */
306 Py_TPFLAGS_DEFAULT, /* tp_flags */
307 ncErrDoc, /* tp_doc */
308 0, /* tp_traverse */
309 0, /* tp_clear */
310 0, /* tp_richcompare */
311 0, /* tp_weaklistoffset */
312 0, /* tp_iter */
313 0, /* tp_iternext */
314 0, /* tp_methods */
315 0, /* tp_members */
316 ncErrGetSetters, /* tp_getset */
317 0, /* tp_base */
318 0, /* tp_dict */
319 0, /* tp_descr_get */
320 0, /* tp_descr_set */
321 0, /* tp_dictoffset */
322 0, /* tp_init */
323 0, /* tp_alloc */
324 0, /* tp_new */
325};
326