source: trunk/server/source3/registry/reg_parse_internal.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 7.7 KB
Line 
1/*
2 * Unix SMB/CIFS implementation.
3 *
4 * Registry helper routines
5 *
6 * Copyright (C) Gregor Beck 2010
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21/**
22 * @file reg_parse_internal.h
23 * @author Gregor Beck <gb@sernet.de>
24 * @date Sep 2010
25 * @brief
26 */
27
28#include "reg_parse_internal.h"
29#include "cbuf.h"
30#include "srprs.h"
31#include "registry.h"
32
33size_t iconvert_talloc(const void* ctx,
34 smb_iconv_t cd,
35 const char* src, size_t srclen,
36 char** pdst)
37{
38 size_t dstlen, ret;
39 size_t obytes, ibytes;
40 char *optr, *dst, *tmp;
41 const char* iptr;
42
43 if (cd == NULL || cd == ((smb_iconv_t)-1)) {
44 return -1;
45 }
46
47 dst = *pdst;
48
49 if (dst == NULL) {
50 /*
51 * Allocate an extra two bytes for the
52 * terminating zero.
53 */
54 dstlen = srclen + 2;
55 dst = (char *)talloc_size(ctx, dstlen);
56 if (dst == NULL) {
57 DEBUG(0,("iconver_talloc no mem\n"));
58 return -1;
59 }
60 } else {
61 dstlen = talloc_get_size(dst);
62 }
63convert:
64 iptr = src;
65 ibytes = srclen;
66 optr = dst;
67 obytes = dstlen-2;
68
69 ret = smb_iconv(cd, &iptr, &ibytes, &optr, &obytes);
70
71 if(ret == -1) {
72 const char *reason="unknown error";
73 switch(errno) {
74 case EINVAL:
75 reason="Incomplete multibyte sequence";
76 break;
77 case E2BIG:
78 dstlen = 2*dstlen + 2;
79 tmp = talloc_realloc(ctx, dst, char, dstlen);
80 if (tmp == NULL) {
81 reason="talloc_realloc failed";
82 break;
83 }
84 dst = tmp;
85 goto convert;
86 case EILSEQ:
87 reason="Illegal multibyte sequence";
88 break;
89 }
90 DEBUG(0,("Conversion error: %s(%.80s) %li\n", reason, iptr,
91 (long int)(iptr-src)));
92 talloc_free(dst);
93 return -1;
94 }
95
96 dstlen = (dstlen-2) - obytes;
97
98 SSVAL(dst, dstlen, 0);
99
100 *pdst = dst;
101 return dstlen;
102}
103
104#ifndef HKEY_CURRENT_CONFIG
105#define HKEY_CURRENT_CONFIG 0x80000005
106#endif
107#ifndef HKEY_DYN_DATA
108#define HKEY_DYN_DATA 0x80000006
109#endif
110#ifndef HKEY_PERFORMANCE_TEXT
111#define HKEY_PERFORMANCE_TEXT 0x80000050
112#endif
113#ifndef HKEY_PERFORMANCE_NLSTEXT
114#define HKEY_PERFORMANCE_NLSTEXT 0x80000060
115#endif
116
117#define HIVE_INFO_ENTRY(SHORT,LONG) \
118static const struct hive_info HIVE_INFO_##SHORT = { \
119 .handle = LONG, \
120 .short_name = #SHORT, \
121 .short_name_len = sizeof(#SHORT)-1, \
122 .long_name = #LONG, \
123 .long_name_len = sizeof(#LONG)-1, \
124}
125
126HIVE_INFO_ENTRY(HKLM, HKEY_LOCAL_MACHINE);
127HIVE_INFO_ENTRY(HKCU, HKEY_CURRENT_USER);
128HIVE_INFO_ENTRY(HKCR, HKEY_CLASSES_ROOT);
129HIVE_INFO_ENTRY(HKU , HKEY_USERS);
130HIVE_INFO_ENTRY(HKCC, HKEY_CURRENT_CONFIG);
131HIVE_INFO_ENTRY(HKDD, HKEY_DYN_DATA);
132HIVE_INFO_ENTRY(HKPD, HKEY_PERFORMANCE_DATA);
133HIVE_INFO_ENTRY(HKPT, HKEY_PERFORMANCE_TEXT);
134HIVE_INFO_ENTRY(HKPN, HKEY_PERFORMANCE_NLSTEXT);
135#undef HIVE_INFO_ENTRY
136
137static const struct hive_info* HIVE_INFO[] = {
138 &HIVE_INFO_HKLM, &HIVE_INFO_HKCU, &HIVE_INFO_HKCR, &HIVE_INFO_HKU,
139 &HIVE_INFO_HKCC, &HIVE_INFO_HKDD, &HIVE_INFO_HKPD, &HIVE_INFO_HKPT,
140 &HIVE_INFO_HKPN, NULL
141};
142
143const struct hive_info* hive_info(const char* name, int nlen)
144{
145 const struct hive_info** info;
146 char buf[32];
147 int s;
148
149 if (nlen >= sizeof(buf)) {
150 return NULL;
151 }
152 for (s=0; s<nlen; s++) {
153 buf[s] = toupper(name[s]);
154 }
155 buf[s] = '\0';
156
157 if ((s < 3) || (strncmp(buf, "HK", 2) != 0)) {
158 return NULL;
159 }
160
161 if (s <= 4) {
162 for(info = HIVE_INFO; *info; info++) {
163 if (strcmp(buf+2, (*info)->short_name+2) == 0) {
164 return *info;
165 }
166 }
167 return NULL;
168 }
169
170 if ((s < 10) || (strncmp(buf, "HKEY_", 5)) != 0) {
171 return NULL;
172 }
173
174 for(info = HIVE_INFO; *info; info++) {
175 if (strcmp(buf+5, (*info)->long_name+5) == 0) {
176 return *info;
177 }
178 }
179 return NULL;
180}
181
182const char* get_charset(const char* c)
183{
184 if (strcmp(c, "dos") == 0) {
185 return lp_dos_charset();
186 } else if (strcmp(c, "unix") == 0) {
187 return lp_unix_charset();
188 } else {
189 return c;
190 }
191}
192
193bool set_iconv(smb_iconv_t* t, const char* to, const char* from)
194{
195 smb_iconv_t cd = (smb_iconv_t)-1;
196
197 if (to && from) {
198 to = get_charset(to);
199 from = get_charset(from);
200 cd = smb_iconv_open(to, from);
201 if (cd == ((smb_iconv_t)-1)) {
202 return false;
203 }
204 }
205 if ((*t != (smb_iconv_t)NULL) && (*t != (smb_iconv_t)-1)) {
206 smb_iconv_close(*t);
207 }
208 *t = cd;
209 return true;
210}
211
212/**
213 * Parse option string
214 * @param[in,out] ptr parse position
215 * @param[in] mem_ctx talloc context
216 * @param[out] name ptr 2 value
217 * @param[out] value ptr 2 value
218 * @return true on success
219 */
220bool srprs_option(const char** ptr, const void* mem_ctx, char** name, char** value)
221{
222 const char* pos = *ptr;
223 void* ctx = talloc_new(mem_ctx);
224
225 cbuf* key = cbuf_new(ctx);
226 cbuf* val = NULL;
227
228 while(srprs_charsetinv(&pos, ",= \t\n\r", key))
229 ;
230 if (pos == *ptr) {
231 talloc_free(ctx);
232 return false;
233 }
234
235 if (name != NULL) {
236 *name = talloc_steal(mem_ctx, cbuf_gets(key, 0));
237 }
238
239 if (*pos == '=') {
240 val = cbuf_new(ctx);
241 pos++;
242 if (!srprs_quoted_string(ptr, val, NULL)) {
243 while(srprs_charsetinv(&pos, ", \t\n\r", val))
244 ;
245 }
246 if (value != NULL) {
247 *value = talloc_steal(mem_ctx, cbuf_gets(val, 0));
248 }
249 } else {
250 if (value != NULL) {
251 *value = NULL;
252 }
253 }
254
255 while(srprs_char(&pos, ','))
256 ;
257
258 *ptr = pos;
259 return true;
260}
261
262#define CH_INVALID ((charset_t)-1)
263static const struct {
264 const char* const name;
265 charset_t ctype;
266 int len;
267 char seq[4];
268} BOM[] = {
269 {"UTF-8", CH_UTF8, 3, {0xEF, 0xBB, 0xBF}},
270 {"UTF-32LE", CH_INVALID, 4, {0xFF, 0xFE, 0x00, 0x00}},
271 {"UTF-16LE", CH_UTF16LE, 2, {0xFF, 0xFE}},
272 {"UTF-16BE", CH_UTF16BE, 2, {0xFE, 0xFF}},
273 {"UTF-32BE", CH_INVALID, 4, {0x00, 0x00, 0xFE, 0xFF}},
274 {NULL, CH_INVALID, 0}
275};
276
277bool srprs_bom(const char** ptr, const char** name, charset_t* ctype)
278{
279 int i;
280 for (i=0; BOM[i].name; i++) {
281 if (memcmp(*ptr, BOM[i].seq, BOM[i].len) == 0) {
282 break;
283 }
284 }
285
286 if (BOM[i].name != NULL) {
287 DEBUG(0, ("Found Byte Order Mark for : %s\n", BOM[i].name));
288
289 if (name != NULL) {
290 *name = BOM[i].name;
291 }
292
293 if (ctype != NULL) {
294 *ctype = BOM[i].ctype;
295 }
296
297 *ptr += BOM[i].len;
298
299 return true;
300 }
301 return false;
302}
303
304int write_bom(FILE* file, const char* charset, charset_t ctype)
305{
306 int i;
307 if ( charset == NULL ) {
308 for (i=0; BOM[i].name; i++) {
309 if (BOM[i].ctype == ctype) {
310 return fwrite(BOM[i].seq, 1, BOM[i].len, file);
311 }
312 }
313 DEBUG(0, ("No Byte Order Mark for charset_t: %u\n", (unsigned)ctype));
314 } else {
315 for (i=0; BOM[i].name; i++) {
316 if (StrCaseCmp(BOM[i].name, charset) == 0) {
317 return fwrite(BOM[i].seq, 1, BOM[i].len, file);
318 }
319 }
320 DEBUG(0, ("No Byte Order Mark for charset_t: %s\n", charset));
321 }
322 return 0;
323}
324
325
326int cbuf_puts_case(cbuf* s, const char* str, size_t len, enum fmt_case fmt)
327{
328 size_t pos = cbuf_getpos(s);
329 int ret = cbuf_puts(s, str, len);
330 char* ptr = cbuf_gets(s,pos);
331
332 if (ret <= 0) {
333 return ret;
334 }
335
336 switch (fmt) {
337 case FMT_CASE_PRESERVE:
338 break;
339 case FMT_CASE_UPPER:
340 while(*ptr != '\0') {
341 *ptr = toupper(*ptr);
342 ptr++;
343 }
344 break;
345 case FMT_CASE_TITLE:
346 *ptr = toupper(*ptr);
347 ptr++;
348 case FMT_CASE_LOWER:
349 while(*ptr != '\0') {
350 *ptr = tolower(*ptr);
351 ptr++;
352 }
353 }
354 return ret;
355}
Note: See TracBrowser for help on using the repository browser.