]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-signature.c
bus: add API calls to escape string components of objects paths
[thirdparty/systemd.git] / src / libsystemd-bus / bus-signature.c
CommitLineData
de1c301e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <util.h>
23
24#include "bus-signature.h"
25#include "bus-type.h"
26
27static int signature_element_length_internal(
28 const char *s,
29 bool allow_dict_entry,
813a4f93
LP
30 unsigned array_depth,
31 unsigned struct_depth,
de1c301e
LP
32 size_t *l) {
33
34 int r;
35
718db961
LP
36 if (!s)
37 return -EINVAL;
38
39 assert(l);
de1c301e
LP
40
41 if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
42 *l = 1;
43 return 0;
44 }
45
46 if (*s == SD_BUS_TYPE_ARRAY) {
47 size_t t;
48
813a4f93
LP
49 if (array_depth >= 32)
50 return -EINVAL;
51
52 r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
de1c301e
LP
53 if (r < 0)
54 return r;
55
56 *l = t + 1;
57 return 0;
58 }
59
60 if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
61 const char *p = s + 1;
62
813a4f93
LP
63 if (struct_depth >= 32)
64 return -EINVAL;
65
de1c301e
LP
66 while (*p != SD_BUS_TYPE_STRUCT_END) {
67 size_t t;
68
813a4f93 69 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
de1c301e
LP
70 if (r < 0)
71 return r;
72
73 p += t;
74 }
75
76 *l = p - s + 1;
77 return 0;
78 }
79
80 if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
81 const char *p = s + 1;
82 unsigned n = 0;
83
813a4f93
LP
84 if (struct_depth >= 32)
85 return -EINVAL;
86
de1c301e
LP
87 while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
88 size_t t;
89
90 if (n == 0 && !bus_type_is_basic(*p))
91 return -EINVAL;
92
813a4f93 93 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
de1c301e
LP
94 if (r < 0)
95 return r;
96
97 p += t;
98 n++;
99 }
100
101 if (n != 2)
102 return -EINVAL;
103
104 *l = p - s + 1;
105 return 0;
106 }
107
108 return -EINVAL;
109}
110
813a4f93
LP
111
112int signature_element_length(const char *s, size_t *l) {
113 return signature_element_length_internal(s, true, 0, 0, l);
114}
115
29ddb38f 116bool signature_is_single(const char *s, bool allow_dict_entry) {
de1c301e
LP
117 int r;
118 size_t t;
119
718db961
LP
120 if (!s)
121 return false;
de1c301e 122
29ddb38f 123 r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
de1c301e
LP
124 if (r < 0)
125 return false;
126
127 return s[t] == 0;
128}
129
130bool signature_is_pair(const char *s) {
718db961
LP
131
132 if (!s)
133 return false;
de1c301e
LP
134
135 if (!bus_type_is_basic(*s))
136 return false;
137
29ddb38f 138 return signature_is_single(s + 1, false);
de1c301e
LP
139}
140
141bool signature_is_valid(const char *s, bool allow_dict_entry) {
142 const char *p;
143 int r;
144
718db961
LP
145 if (!s)
146 return false;
de1c301e
LP
147
148 p = s;
149 while (*p) {
150 size_t t;
151
813a4f93 152 r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
de1c301e
LP
153 if (r < 0)
154 return false;
155
156 p += t;
157 }
158
159 return p - s <= 255;
160}