libcli: Avoid a talloc/free
[Samba.git] / source3 / registry / reg_parse_internal.c
blob1a5b112642ff196bf4d6d0e85da330f47f2d3b29
1 /*
2 * Unix SMB/CIFS implementation.
4 * Registry helper routines
6 * Copyright (C) Gregor Beck 2010
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.
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.
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/>.
21 /**
22 * @file reg_parse_internal.h
23 * @author Gregor Beck <gb@sernet.de>
24 * @date Sep 2010
25 * @brief
28 #include "reg_parse_internal.h"
29 #include "cbuf.h"
30 #include "srprs.h"
31 #include "registry.h"
33 size_t iconvert_talloc(const void* ctx,
34 smb_iconv_t cd,
35 const char* src, size_t srclen,
36 char** pdst)
38 size_t dstlen, ret;
39 size_t obytes, ibytes;
40 char *optr, *dst, *tmp;
41 const char* iptr;
43 if (cd == NULL || cd == ((smb_iconv_t)-1)) {
44 return -1;
47 dst = *pdst;
49 if (dst == NULL) {
51 * Allocate an extra two bytes for the
52 * terminating zero.
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;
60 } else {
61 dstlen = talloc_get_size(dst);
63 convert:
64 iptr = src;
65 ibytes = srclen;
66 optr = dst;
67 obytes = dstlen-2;
69 ret = smb_iconv(cd, &iptr, &ibytes, &optr, &obytes);
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;
84 dst = tmp;
85 goto convert;
86 case EILSEQ:
87 reason="Illegal multibyte sequence";
88 break;
90 DEBUG(0,("Conversion error: %s(%.80s) %li\n", reason, iptr,
91 (long int)(iptr-src)));
92 talloc_free(dst);
93 return -1;
96 dstlen = (dstlen-2) - obytes;
98 SSVAL(dst, dstlen, 0);
100 *pdst = dst;
101 return dstlen;
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
117 #define HIVE_INFO_ENTRY(SHORT,LONG) \
118 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, \
126 HIVE_INFO_ENTRY(HKLM, HKEY_LOCAL_MACHINE);
127 HIVE_INFO_ENTRY(HKCU, HKEY_CURRENT_USER);
128 HIVE_INFO_ENTRY(HKCR, HKEY_CLASSES_ROOT);
129 HIVE_INFO_ENTRY(HKU , HKEY_USERS);
130 HIVE_INFO_ENTRY(HKCC, HKEY_CURRENT_CONFIG);
131 HIVE_INFO_ENTRY(HKDD, HKEY_DYN_DATA);
132 HIVE_INFO_ENTRY(HKPD, HKEY_PERFORMANCE_DATA);
133 HIVE_INFO_ENTRY(HKPT, HKEY_PERFORMANCE_TEXT);
134 HIVE_INFO_ENTRY(HKPN, HKEY_PERFORMANCE_NLSTEXT);
135 #undef HIVE_INFO_ENTRY
137 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
143 #define TOINT(A,B) ((int)(A) << 8) + (int)(B)
145 bool srprs_hive(const char** ptr, const struct hive_info** result)
147 const char* str = *ptr;
148 const struct hive_info* info = NULL;
149 bool long_hive = false;
151 if ((toupper(str[0]) != 'H') || (toupper(str[1]) != 'K')
152 || (str[2] == '\0') )
154 return false;
157 switch ( TOINT(toupper(str[2]), toupper(str[3])) ) {
158 case TOINT('E', 'Y'):
159 if (str[4] == '_') {
160 int i;
161 for (i=0; (info = HIVE_INFO[i]); i++) {
162 if (strncmp(&str[5], &info->long_name[5],
163 info->long_name_len-5) == 0)
165 long_hive = true;
166 break;
170 break;
171 case TOINT('L', 'M'):
172 info = &HIVE_INFO_HKLM;
173 break;
174 case TOINT('C', 'U'):
175 info = &HIVE_INFO_HKCU;
176 break;
177 case TOINT('C', 'R'):
178 info = &HIVE_INFO_HKCR;
179 break;
180 case TOINT('C', 'C'):
181 info = &HIVE_INFO_HKCC;
182 break;
183 case TOINT('D', 'D'):
184 info = &HIVE_INFO_HKDD;
185 break;
186 case TOINT('P', 'D'):
187 info = &HIVE_INFO_HKPD;
188 break;
189 case TOINT('P', 'T'):
190 info = &HIVE_INFO_HKPT;
191 break;
192 case TOINT('P', 'N'):
193 info = &HIVE_INFO_HKPN;
194 break;
195 default:
196 if (toupper(str[2]) == 'U') {
197 info = &HIVE_INFO_HKU;
199 break;
201 if (info != NULL) {
202 if (result != NULL) {
203 *result = info;
205 *ptr += long_hive ? info->long_name_len : info->short_name_len;
206 return true;
208 return false;
211 const struct hive_info* hive_info(const char* name)
213 const struct hive_info* info = NULL;
214 srprs_hive(&name, &info);
215 return info;
218 const char* get_charset(const char* c)
220 if (strcmp(c, "dos") == 0) {
221 return lp_dos_charset();
222 } else if (strcmp(c, "unix") == 0) {
223 return lp_unix_charset();
224 } else {
225 return c;
229 bool set_iconv(smb_iconv_t* t, const char* to, const char* from)
231 smb_iconv_t cd = (smb_iconv_t)-1;
233 if (to && from) {
234 to = get_charset(to);
235 from = get_charset(from);
236 cd = smb_iconv_open(to, from);
237 if (cd == ((smb_iconv_t)-1)) {
238 return false;
241 if ((*t != (smb_iconv_t)NULL) && (*t != (smb_iconv_t)-1)) {
242 smb_iconv_close(*t);
244 *t = cd;
245 return true;
249 * Parse option string
250 * @param[in,out] ptr parse position
251 * @param[in] mem_ctx talloc context
252 * @param[out] name ptr 2 value
253 * @param[out] value ptr 2 value
254 * @return true on success
256 bool srprs_option(const char** ptr, const void* mem_ctx, char** name, char** value)
258 const char* pos = *ptr;
259 void* ctx = talloc_new(mem_ctx);
261 cbuf* key = cbuf_new(ctx);
262 cbuf* val = NULL;
264 while(srprs_charsetinv(&pos, ",= \t\n\r", key))
266 if (pos == *ptr) {
267 talloc_free(ctx);
268 return false;
271 if (name != NULL) {
272 *name = talloc_steal(mem_ctx, cbuf_gets(key, 0));
275 if (*pos == '=') {
276 val = cbuf_new(ctx);
277 pos++;
278 if (!srprs_quoted_string(ptr, val, NULL)) {
279 while(srprs_charsetinv(&pos, ", \t\n\r", val))
282 if (value != NULL) {
283 *value = talloc_steal(mem_ctx, cbuf_gets(val, 0));
285 } else {
286 if (value != NULL) {
287 *value = NULL;
291 while(srprs_char(&pos, ','))
294 *ptr = pos;
295 return true;
298 #define CH_INVALID ((charset_t)-1)
299 static const struct {
300 const char* const name;
301 charset_t ctype;
302 int len;
303 uint8_t seq[4];
304 } BOM[] = {
305 {"UTF-8", CH_UTF8, 3, {0xEF, 0xBB, 0xBF}},
306 {"UTF-32LE", CH_INVALID, 4, {0xFF, 0xFE, 0x00, 0x00}},
307 {"UTF-16LE", CH_UTF16LE, 2, {0xFF, 0xFE}},
308 {"UTF-16BE", CH_UTF16BE, 2, {0xFE, 0xFF}},
309 {"UTF-32BE", CH_INVALID, 4, {0x00, 0x00, 0xFE, 0xFF}},
310 {NULL, CH_INVALID, 0}
313 bool srprs_bom(const char** ptr, const char** name, charset_t* ctype)
315 int i;
316 for (i=0; BOM[i].name; i++) {
317 if (memcmp(*ptr, BOM[i].seq, BOM[i].len) == 0) {
318 break;
322 if (BOM[i].name != NULL) {
323 DEBUG(0, ("Found Byte Order Mark for : %s\n", BOM[i].name));
325 if (name != NULL) {
326 *name = BOM[i].name;
329 if (ctype != NULL) {
330 *ctype = BOM[i].ctype;
333 *ptr += BOM[i].len;
335 return true;
337 return false;
340 int write_bom(FILE* file, const char* charset, charset_t ctype)
342 int i;
343 if ( charset == NULL ) {
344 for (i=0; BOM[i].name; i++) {
345 if (BOM[i].ctype == ctype) {
346 return fwrite(BOM[i].seq, 1, BOM[i].len, file);
349 DEBUG(0, ("No Byte Order Mark for charset_t: %u\n", (unsigned)ctype));
350 } else {
351 for (i=0; BOM[i].name; i++) {
352 if (strcasecmp_m(BOM[i].name, charset) == 0) {
353 return fwrite(BOM[i].seq, 1, BOM[i].len, file);
356 DEBUG(0, ("No Byte Order Mark for charset_t: %s\n", charset));
358 return 0;
362 int cbuf_puts_case(cbuf* s, const char* str, size_t len, enum fmt_case fmt)
364 size_t pos = cbuf_getpos(s);
365 int ret = cbuf_puts(s, str, len);
366 char* ptr = cbuf_gets(s,pos);
368 if (ret <= 0) {
369 return ret;
372 switch (fmt) {
373 case FMT_CASE_PRESERVE:
374 break;
375 case FMT_CASE_UPPER:
376 while(*ptr != '\0') {
377 *ptr = toupper(*ptr);
378 ptr++;
380 break;
381 case FMT_CASE_TITLE:
382 *ptr = toupper(*ptr);
383 ptr++;
384 case FMT_CASE_LOWER:
385 while(*ptr != '\0') {
386 *ptr = tolower(*ptr);
387 ptr++;
390 return ret;