Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */ 2 : 3 : #include <stdlib.h> 4 : 5 : #include "alloc-util.h" 6 : #include "bus-label.h" 7 : #include "hexdecoct.h" 8 : #include "macro.h" 9 : 10 14 : char *bus_label_escape(const char *s) { 11 : char *r, *t; 12 : const char *f; 13 : 14 14 : assert_return(s, NULL); 15 : 16 : /* Escapes all chars that D-Bus' object path cannot deal 17 : * with. Can be reversed with bus_path_unescape(). We special 18 : * case the empty string. */ 19 : 20 14 : if (*s == 0) 21 2 : return strdup("_"); 22 : 23 12 : r = new(char, strlen(s)*3 + 1); 24 12 : if (!r) 25 0 : return NULL; 26 : 27 78 : for (f = s, t = r; *f; f++) { 28 : 29 : /* Escape everything that is not a-zA-Z0-9. We also 30 : * escape 0-9 if it's the first character */ 31 : 32 66 : if (!(*f >= 'A' && *f <= 'Z') && 33 66 : !(*f >= 'a' && *f <= 'z') && 34 10 : !(f > s && *f >= '0' && *f <= '9')) { 35 8 : *(t++) = '_'; 36 8 : *(t++) = hexchar(*f >> 4); 37 8 : *(t++) = hexchar(*f); 38 : } else 39 58 : *(t++) = *f; 40 : } 41 : 42 12 : *t = 0; 43 : 44 12 : return r; 45 : } 46 : 47 330 : char *bus_label_unescape_n(const char *f, size_t l) { 48 : char *r, *t; 49 : size_t i; 50 : 51 330 : assert_return(f, NULL); 52 : 53 : /* Special case for the empty string */ 54 330 : if (l == 1 && *f == '_') 55 5 : return strdup(""); 56 : 57 325 : r = new(char, l + 1); 58 325 : if (!r) 59 0 : return NULL; 60 : 61 9194 : for (i = 0, t = r; i < l; ++i) { 62 8869 : if (f[i] == '_') { 63 : int a, b; 64 : 65 1153 : if (l - i < 3 || 66 1153 : (a = unhexchar(f[i + 1])) < 0 || 67 1153 : (b = unhexchar(f[i + 2])) < 0) { 68 : /* Invalid escape code, let's take it literal then */ 69 0 : *(t++) = '_'; 70 : } else { 71 1153 : *(t++) = (char) ((a << 4) | b); 72 1153 : i += 2; 73 : } 74 : } else 75 7716 : *(t++) = f[i]; 76 : } 77 : 78 325 : *t = 0; 79 : 80 325 : return r; 81 : }