+char *bus_path_escape(const char *s) {
+ char *r, *t;
+ const char *f;
+
+ assert(s);
+
+ /* Escapes all chars that D-Bus' object path cannot deal
+ * with. Can be reverse with bus_path_unescape() */
+
+ if (!(r = new(char, strlen(s)*3+1)))
+ return NULL;
+
+ for (f = s, t = r; *f; f++) {
+
+ if (!(*f >= 'A' && *f <= 'Z') &&
+ !(*f >= 'a' && *f <= 'z') &&
+ !(*f >= '0' && *f <= '9')) {
+ *(t++) = '_';
+ *(t++) = hexchar(*f >> 4);
+ *(t++) = hexchar(*f);
+ } else
+ *(t++) = *f;
+ }
+
+ *t = 0;
+
+ return r;
+}
+
+char *bus_path_unescape(const char *s) {
+ char *r, *t;
+ const char *f;
+
+ assert(s);
+
+ if (!(r = new(char, strlen(s)+1)))
+ return NULL;
+
+ for (f = s, t = r; *f; f++) {
+
+ if (*f == '_') {
+ int a, b;
+
+ if ((a = unhexchar(f[1])) < 0 ||
+ (b = unhexchar(f[2])) < 0) {
+ /* Invalid escape code, let's take it literal then */
+ *(t++) = '_';
+ } else {
+ *(t++) = (char) ((a << 4) | b);
+ f += 2;
+ }
+ } else
+ *(t++) = *f;
+ }
+
+ *t = 0;
+
+ return r;
+}
+