Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2008 Stefan Walter
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see
18 : * <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include "gkd-secret-util.h"
24 :
25 : #include "pkcs11/pkcs11i.h"
26 :
27 : #include <string.h>
28 :
29 : /* -----------------------------------------------------------------------------
30 : * INTERNAL
31 : */
32 :
33 : static gchar*
34 122 : decode_object_identifier (const gchar* enc, gssize length)
35 : {
36 : GString *result;
37 :
38 122 : g_assert (enc);
39 :
40 122 : if (length < 0)
41 114 : length = strlen (enc);
42 :
43 122 : result = g_string_sized_new (length);
44 680 : while (length > 0) {
45 558 : char ch = *(enc++);
46 558 : --length;
47 :
48 : /* Underscores get special handling */
49 558 : if (G_UNLIKELY (ch == '_' &&
50 : g_ascii_isxdigit(enc[0]) &&
51 : g_ascii_isxdigit (enc[1]))) {
52 2 : ch = (g_ascii_xdigit_value (enc[0]) * 16) +
53 2 : (g_ascii_xdigit_value (enc[1]));
54 2 : enc += 2;
55 2 : length -= 2;
56 : }
57 :
58 558 : g_string_append_c (result, ch);
59 : }
60 :
61 122 : return g_string_free (result, FALSE);
62 : }
63 :
64 : gboolean
65 114 : gkd_secret_util_parse_path (const gchar *path, gchar **collection, gchar **item)
66 : {
67 : const gchar *pos;
68 :
69 114 : g_return_val_if_fail (path, FALSE);
70 :
71 : /* Make sure it starts with our prefix */
72 114 : if (g_str_has_prefix (path, SECRET_COLLECTION_PREFIX))
73 114 : path += strlen (SECRET_COLLECTION_PREFIX);
74 0 : else if (g_str_has_prefix (path, SECRET_ALIAS_PREFIX))
75 0 : path += strlen (SECRET_ALIAS_PREFIX);
76 : else
77 0 : return FALSE;
78 :
79 : /* Skip the path separator */
80 114 : if (path[0] != '/')
81 0 : return FALSE;
82 114 : ++path;
83 :
84 : /* Make sure we have something */
85 114 : if (path[0] == '\0')
86 0 : return FALSE;
87 :
88 114 : pos = strchr (path, '/');
89 :
90 : /* No item, just a collection */
91 114 : if (pos == NULL) {
92 106 : if (collection)
93 106 : *collection = decode_object_identifier (path, -1);
94 106 : if (item)
95 7 : *item = NULL;
96 106 : return TRUE;
97 : }
98 :
99 : /* Make sure we have an item, and no further path bits */
100 8 : if (pos[1] == '\0' || strchr (pos + 1, '/'))
101 0 : return FALSE;
102 :
103 8 : if (collection)
104 8 : *collection = decode_object_identifier (path, pos - path);
105 8 : if (item)
106 8 : *item = decode_object_identifier (pos + 1, -1);
107 8 : return TRUE;
108 : }
109 :
110 : gchar*
111 180 : gkd_secret_util_build_path (const gchar *base, gconstpointer identifier, gssize n_identifier)
112 : {
113 : GString *result;
114 : const gchar *name;
115 : gsize length;
116 :
117 180 : g_assert (base);
118 180 : g_assert (base[0] == '/');
119 180 : g_assert (identifier);
120 :
121 180 : name = identifier;
122 180 : if (n_identifier < 0)
123 0 : length = strlen (name);
124 : else
125 180 : length = n_identifier;
126 :
127 180 : result = g_string_new (base);
128 180 : if (!g_str_has_suffix (base, "/"))
129 : g_string_append_c (result, '/');
130 :
131 810 : while (length > 0) {
132 630 : char ch = *(name++);
133 630 : --length;
134 :
135 : /* Normal characters can go right through */
136 630 : if (G_LIKELY ((ch >= 'A' && ch <= 'Z') ||
137 : (ch >= 'a' && ch <= 'z') ||
138 : (ch >= '0' && ch <= '9'))) {
139 623 : g_string_append_c (result, ch);
140 :
141 : /* Special characters are encoded with a _ */
142 : } else {
143 7 : g_string_append_printf (result, "_%02x", (unsigned int)(unsigned char)ch);
144 : }
145 : }
146 :
147 180 : return g_string_free (result, FALSE);
148 : }
|