Correct argument parsing in validate_bus_name
[dbus-python-phuang.git] / _dbus_bindings / validation-impl.h
blob0ca42a3cab7153f011280c62217e0a9a245c1ef8
1 /* Implementation of various validation functions for use in dbus-python.
3 * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
5 * Licensed under the Academic Free License version 2.1
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 static dbus_bool_t _validate_bus_name(const char *name,
26 dbus_bool_t may_be_unique,
27 dbus_bool_t may_be_not_unique)
29 dbus_bool_t dot = FALSE;
30 dbus_bool_t unique;
31 char last;
32 const char *ptr;
34 if (name[0] == '\0') {
35 PyErr_SetString(PyExc_ValueError, "Invalid bus name: "
36 "may not be empty");
37 return FALSE;
39 unique = (name[0] == ':');
40 if (unique && !may_be_unique) {
41 PyErr_Format(PyExc_ValueError, "Invalid well-known bus name '%s':"
42 "only unique names may start with ':'", name);
43 return FALSE;
45 if (!unique && !may_be_not_unique) {
46 PyErr_Format(PyExc_ValueError, "Invalid unique bus name '%s': "
47 "unique names must start with ':'", name);
48 return FALSE;
50 if (strlen(name) > 255) {
51 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
52 "too long (> 255 characters)", name);
53 return FALSE;
55 last = '\0';
56 for (ptr = name + (unique ? 1 : 0); *ptr; ptr++) {
57 if (*ptr == '.') {
58 dot = TRUE;
59 if (last == '.') {
60 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
61 "contains substring '..'", name);
62 return FALSE;
64 else if (last == '\0') {
65 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
66 "must not start with '.'", name);
67 return FALSE;
70 else if (*ptr >= '0' && *ptr <= '9') {
71 if (!unique) {
72 if (last == '.') {
73 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
74 "a digit may not follow '.' except in a "
75 "unique name starting with ':'", name);
76 return FALSE;
78 else if (last == '\0') {
79 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
80 "must not start with a digit", name);
81 return FALSE;
85 else if ((*ptr < 'a' || *ptr > 'z') &&
86 (*ptr < 'A' || *ptr > 'Z') && *ptr != '_' && *ptr != '-') {
87 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
88 "contains invalid character '%c'", name, *ptr);
89 return FALSE;
91 last = *ptr;
93 if (last == '.') {
94 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': must "
95 "not end with '.'", name);
96 return FALSE;
98 if (!dot) {
99 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': must "
100 "contain '.'", name);
101 return FALSE;
103 return TRUE;
106 PyDoc_STRVAR(validate_bus_name__doc__,
107 "validate_bus_name(name: str[, allow_unique: bool[, allow_well_known: "
108 "bool]])\n\n"
109 "Raise ValueError if the argument is not a valid bus name.\n\n"
110 "By default both unique and well-known names are accepted.\n"
111 "The keyword arguments allow_unique and/or allow_well_known allow\n"
112 "either type of bus name to be rejected.\n"
115 static PyObject *
116 validate_bus_name(PyObject *unused, PyObject *args, PyObject *kwargs)
118 const char *name;
119 int allow_unique = 1;
120 int allow_well_known = 1;
121 static char *argnames[] = { "name", "allow_unique", "allow_well_known",
122 NULL };
124 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
125 "s|ii:validate_bus_name", argnames,
126 &name, &allow_unique,
127 &allow_well_known)) {
128 return NULL;
130 if (!_validate_bus_name(name, !!allow_unique, !!allow_well_known)) {
131 return NULL;
133 Py_RETURN_NONE;
136 static dbus_bool_t _validate_member_name(const char *name)
138 const char *ptr;
140 if (name[0] == '\0') {
141 PyErr_SetString(PyExc_ValueError, "Invalid member name: may not "
142 "be empty");
143 return FALSE;
145 if (strlen(name) > 255) {
146 PyErr_Format(PyExc_ValueError, "Invalid member name '%s': "
147 "too long (> 255 characters)", name);
148 return FALSE;
150 for (ptr = name; *ptr; ptr++) {
151 if (*ptr >= '0' && *ptr <= '9') {
152 if (ptr == name) {
153 PyErr_Format(PyExc_ValueError, "Invalid member name '%s': "
154 "must not start with a digit", name);
155 return FALSE;
158 else if ((*ptr < 'a' || *ptr > 'z') &&
159 (*ptr < 'A' || *ptr > 'Z') && *ptr != '_') {
160 PyErr_Format(PyExc_ValueError, "Invalid member name '%s': "
161 "contains invalid character '%c'", name, *ptr);
162 return FALSE;
165 return TRUE;
168 PyDoc_STRVAR(validate_member_name__doc__,
169 "validate_member_name(name: str)\n\n"
170 "Raise ValueError if the argument is not a valid member (signal or method) "
171 "name.\n"
174 static PyObject *
175 validate_member_name(PyObject *unused, PyObject *args)
177 const char *name;
179 if (!PyArg_ParseTuple(args, "s:validate_member_name", &name)) {
180 return NULL;
182 if (!_validate_member_name(name)) {
183 return NULL;
185 Py_RETURN_NONE;
188 static dbus_bool_t _validate_interface_name(const char *name)
190 dbus_bool_t dot = FALSE;
191 char last;
192 const char *ptr;
194 if (name[0] == '\0') {
195 PyErr_SetString(PyExc_ValueError, "Invalid interface or error name: "
196 "may not be empty");
197 return FALSE;
199 if (strlen(name) > 255) {
200 PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': "
201 "too long (> 255 characters)", name);
202 return FALSE;
204 last = '\0';
205 for (ptr = name; *ptr; ptr++) {
206 if (*ptr == '.') {
207 dot = TRUE;
208 if (last == '.') {
209 PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': "
210 "contains substring '..'", name);
211 return FALSE;
213 else if (last == '\0') {
214 PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': "
215 "must not start with '.'", name);
216 return FALSE;
219 else if (*ptr >= '0' && *ptr <= '9') {
220 if (last == '.') {
221 PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': "
222 "a digit may not follow '.'", name);
223 return FALSE;
225 else if (last == '\0') {
226 PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': "
227 "must not start with a digit", name);
228 return FALSE;
231 else if ((*ptr < 'a' || *ptr > 'z') &&
232 (*ptr < 'A' || *ptr > 'Z') && *ptr != '_') {
233 PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': "
234 "contains invalid character '%c'", name, *ptr);
235 return FALSE;
237 last = *ptr;
239 if (last == '.') {
240 PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': must "
241 "not end with '.'", name);
242 return FALSE;
244 if (!dot) {
245 PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': must "
246 "contain '.'", name);
247 return FALSE;
249 return TRUE;
252 PyDoc_STRVAR(validate_interface_name__doc__,
253 "validate_interface_name(name: str)\n\n"
254 "Raise ValueError if the argument is not a valid interface name.\n"
257 PyDoc_STRVAR(validate_error_name__doc__,
258 "validate_error_name(name: str)\n\n"
259 "Raise ValueError if the argument is not a valid error name.\n"
262 static PyObject *
263 validate_interface_name(PyObject *unused, PyObject *args)
265 const char *name;
267 if (!PyArg_ParseTuple(args, "s:validate_interface_name", &name)) {
268 return NULL;
270 if (!_validate_interface_name(name)) {
271 return NULL;
273 Py_RETURN_NONE;
276 static inline dbus_bool_t _validate_error_name(const char *name)
278 return _validate_interface_name(name);
281 static dbus_bool_t _validate_object_path(const char *path)
283 const char *ptr;
285 if (path[0] != '/') {
286 PyErr_Format(PyExc_ValueError, "Invalid object path '%s': does not "
287 "start with '/'", path);
288 return FALSE;
290 if (path[1] == '\0') return TRUE;
291 for (ptr = path + 1; *ptr; ptr++) {
292 if (*ptr == '/') {
293 if (ptr[-1] == '/') {
294 PyErr_Format(PyExc_ValueError, "Invalid object path '%s': "
295 "contains substring '//'", path);
296 return FALSE;
299 else if ((*ptr < 'a' || *ptr > 'z') &&
300 (*ptr < 'A' || *ptr > 'Z') &&
301 (*ptr < '0' || *ptr > '9') && *ptr != '_') {
302 PyErr_Format(PyExc_ValueError, "Invalid object path '%s': "
303 "contains invalid character '%c'", path, *ptr);
304 return FALSE;
307 if (ptr[-1] == '/') {
308 PyErr_Format(PyExc_ValueError, "Invalid object path '%s': ends "
309 "with '/' and is not just '/'", path);
310 return FALSE;
312 return TRUE;
315 PyDoc_STRVAR(validate_object_path__doc__,
316 "validate_object_path(name: str)\n\n"
317 "Raise ValueError if the argument is not a valid object path.\n"
320 static PyObject *
321 validate_object_path(PyObject *unused, PyObject *args)
323 const char *name;
325 if (!PyArg_ParseTuple(args, "s:validate_object_path", &name)) {
326 return NULL;
328 if (!_validate_object_path(name)) {
329 return NULL;
331 Py_RETURN_NONE;
334 /* vim:set ft=c cino< sw=4 sts=4 et: */