Mention relicensing in NEWS
[dbus-python-phuang.git] / _dbus_bindings / validation.c
blobabec0a9bbaadfb20e052e94146697e55d5bf7aa8
1 /* Implementation of various validation functions for use in dbus-python.
3 * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use, copy,
9 * modify, merge, publish, distribute, sublicense, and/or sell copies
10 * of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 #include "dbus_bindings-internal.h"
28 dbus_bool_t
29 dbus_py_validate_bus_name(const char *name,
30 dbus_bool_t may_be_unique,
31 dbus_bool_t may_be_not_unique)
33 dbus_bool_t dot = FALSE;
34 dbus_bool_t unique;
35 char last;
36 const char *ptr;
38 if (name[0] == '\0') {
39 PyErr_SetString(PyExc_ValueError, "Invalid bus name: "
40 "may not be empty");
41 return FALSE;
43 unique = (name[0] == ':');
44 if (unique && !may_be_unique) {
45 PyErr_Format(PyExc_ValueError, "Invalid well-known bus name '%s':"
46 "only unique names may start with ':'", name);
47 return FALSE;
49 if (!unique && !may_be_not_unique) {
50 PyErr_Format(PyExc_ValueError, "Invalid unique bus name '%s': "
51 "unique names must start with ':'", name);
52 return FALSE;
54 if (strlen(name) > 255) {
55 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
56 "too long (> 255 characters)", name);
57 return FALSE;
59 last = '\0';
60 for (ptr = name + (unique ? 1 : 0); *ptr; ptr++) {
61 if (*ptr == '.') {
62 dot = TRUE;
63 if (last == '.') {
64 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
65 "contains substring '..'", name);
66 return FALSE;
68 else if (last == '\0') {
69 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
70 "must not start with '.'", name);
71 return FALSE;
74 else if (*ptr >= '0' && *ptr <= '9') {
75 if (!unique) {
76 if (last == '.') {
77 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
78 "a digit may not follow '.' except in a "
79 "unique name starting with ':'", name);
80 return FALSE;
82 else if (last == '\0') {
83 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
84 "must not start with a digit", name);
85 return FALSE;
89 else if ((*ptr < 'a' || *ptr > 'z') &&
90 (*ptr < 'A' || *ptr > 'Z') && *ptr != '_' && *ptr != '-') {
91 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': "
92 "contains invalid character '%c'", name, *ptr);
93 return FALSE;
95 last = *ptr;
97 if (last == '.') {
98 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': must "
99 "not end with '.'", name);
100 return FALSE;
102 if (!dot) {
103 PyErr_Format(PyExc_ValueError, "Invalid bus name '%s': must "
104 "contain '.'", name);
105 return FALSE;
107 return TRUE;
110 dbus_bool_t
111 dbus_py_validate_member_name(const char *name)
113 const char *ptr;
115 if (name[0] == '\0') {
116 PyErr_SetString(PyExc_ValueError, "Invalid member name: may not "
117 "be empty");
118 return FALSE;
120 if (strlen(name) > 255) {
121 PyErr_Format(PyExc_ValueError, "Invalid member name '%s': "
122 "too long (> 255 characters)", name);
123 return FALSE;
125 for (ptr = name; *ptr; ptr++) {
126 if (*ptr >= '0' && *ptr <= '9') {
127 if (ptr == name) {
128 PyErr_Format(PyExc_ValueError, "Invalid member name '%s': "
129 "must not start with a digit", name);
130 return FALSE;
133 else if ((*ptr < 'a' || *ptr > 'z') &&
134 (*ptr < 'A' || *ptr > 'Z') && *ptr != '_') {
135 PyErr_Format(PyExc_ValueError, "Invalid member name '%s': "
136 "contains invalid character '%c'", name, *ptr);
137 return FALSE;
140 return TRUE;
143 dbus_bool_t
144 dbus_py_validate_interface_name(const char *name)
146 dbus_bool_t dot = FALSE;
147 char last;
148 const char *ptr;
150 if (name[0] == '\0') {
151 PyErr_SetString(PyExc_ValueError, "Invalid interface or error name: "
152 "may not be empty");
153 return FALSE;
155 if (strlen(name) > 255) {
156 PyErr_Format(PyExc_ValueError, "Invalid interface or error name '%s': "
157 "too long (> 255 characters)", name);
158 return FALSE;
160 last = '\0';
161 for (ptr = name; *ptr; ptr++) {
162 if (*ptr == '.') {
163 dot = TRUE;
164 if (last == '.') {
165 PyErr_Format(PyExc_ValueError, "Invalid interface or "
166 "error name '%s': contains substring '..'", name);
167 return FALSE;
169 else if (last == '\0') {
170 PyErr_Format(PyExc_ValueError, "Invalid interface or error "
171 "name '%s': must not start with '.'", name);
172 return FALSE;
175 else if (*ptr >= '0' && *ptr <= '9') {
176 if (last == '.') {
177 PyErr_Format(PyExc_ValueError, "Invalid interface or error "
178 "name '%s': a digit may not follow '.'", name);
179 return FALSE;
181 else if (last == '\0') {
182 PyErr_Format(PyExc_ValueError, "Invalid interface or error "
183 "name '%s': must not start with a digit", name);
184 return FALSE;
187 else if ((*ptr < 'a' || *ptr > 'z') &&
188 (*ptr < 'A' || *ptr > 'Z') && *ptr != '_') {
189 PyErr_Format(PyExc_ValueError, "Invalid interface or error "
190 "name '%s': contains invalid character '%c'",
191 name, *ptr);
192 return FALSE;
194 last = *ptr;
196 if (last == '.') {
197 PyErr_Format(PyExc_ValueError, "Invalid interface or error name "
198 "'%s': must not end with '.'", name);
199 return FALSE;
201 if (!dot) {
202 PyErr_Format(PyExc_ValueError, "Invalid interface or error name "
203 "'%s': must contain '.'", name);
204 return FALSE;
206 return TRUE;
210 dbus_bool_t
211 dbus_py_validate_object_path(const char *path)
213 const char *ptr;
215 if (path[0] != '/') {
216 PyErr_Format(PyExc_ValueError, "Invalid object path '%s': does not "
217 "start with '/'", path);
218 return FALSE;
220 if (path[1] == '\0') return TRUE;
221 for (ptr = path + 1; *ptr; ptr++) {
222 if (*ptr == '/') {
223 if (ptr[-1] == '/') {
224 PyErr_Format(PyExc_ValueError, "Invalid object path '%s': "
225 "contains substring '//'", path);
226 return FALSE;
229 else if ((*ptr < 'a' || *ptr > 'z') &&
230 (*ptr < 'A' || *ptr > 'Z') &&
231 (*ptr < '0' || *ptr > '9') && *ptr != '_') {
232 PyErr_Format(PyExc_ValueError, "Invalid object path '%s': "
233 "contains invalid character '%c'", path, *ptr);
234 return FALSE;
237 if (ptr[-1] == '/') {
238 PyErr_Format(PyExc_ValueError, "Invalid object path '%s': ends "
239 "with '/' and is not just '/'", path);
240 return FALSE;
242 return TRUE;
245 /* vim:set ft=c cino< sw=4 sts=4 et: */