WHATSNEW: Update changes since rc1.
[Samba/gbeck.git] / source3 / registry / reg_parse_internal.c
blobdedbe123d864139a3bc7fa321b2ccc513afb7991
1 /* * Samba Unix/Linux SMB client library
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 /**
17 * @file reg_parse_internal.h
18 * @author Gregor Beck <gb@sernet.de>
19 * @date Sep 2010
20 * @brief
23 #include "reg_parse_internal.h"
24 #include "cbuf.h"
25 #include "srprs.h"
26 #include "registry.h"
28 size_t iconvert_talloc(const void* ctx,
29 smb_iconv_t cd,
30 const char* src, size_t srclen,
31 char** pdst)
33 size_t dstlen, ret;
34 size_t obytes, ibytes;
35 char *optr, *dst, *tmp;
36 const char* iptr;
38 if (cd == NULL || cd == ((smb_iconv_t)-1)) {
39 return -1;
42 dst = *pdst;
44 if (dst == NULL) {
46 * Allocate an extra two bytes for the
47 * terminating zero.
49 dstlen = srclen + 2;
50 dst = (char *)talloc_size(ctx, dstlen);
51 if (dst == NULL) {
52 DEBUG(0,("iconver_talloc no mem\n"));
53 return -1;
55 } else {
56 dstlen = talloc_get_size(dst);
58 convert:
59 iptr = src;
60 ibytes = srclen;
61 optr = dst;
62 obytes = dstlen-2;
64 ret = smb_iconv(cd, &iptr, &ibytes, &optr, &obytes);
66 if(ret == -1) {
67 const char *reason="unknown error";
68 switch(errno) {
69 case EINVAL:
70 reason="Incomplete multibyte sequence";
71 break;
72 case E2BIG:
73 dstlen = 2*dstlen + 2;
74 tmp = talloc_realloc(ctx, dst, char, dstlen);
75 if (tmp == NULL) {
76 reason="talloc_realloc failed";
77 break;
79 dst = tmp;
80 goto convert;
81 case EILSEQ:
82 reason="Illegal multibyte sequence";
83 break;
85 DEBUG(0,("Conversion error: %s(%.80s) %li\n", reason, iptr,
86 (long int)(iptr-src)));
87 talloc_free(dst);
88 return -1;
91 dstlen = (dstlen-2) - obytes;
93 SSVAL(dst, dstlen, 0);
95 *pdst = dst;
96 return dstlen;
99 #ifndef HKEY_CURRENT_CONFIG
100 #define HKEY_CURRENT_CONFIG 0x80000005
101 #endif
102 #ifndef HKEY_DYN_DATA
103 #define HKEY_DYN_DATA 0x80000006
104 #endif
105 #ifndef HKEY_PERFORMANCE_TEXT
106 #define HKEY_PERFORMANCE_TEXT 0x80000050
107 #endif
108 #ifndef HKEY_PERFORMANCE_NLSTEXT
109 #define HKEY_PERFORMANCE_NLSTEXT 0x80000060
110 #endif
112 #define HIVE_INFO_ENTRY(SHORT,LONG) \
113 static const struct hive_info HIVE_INFO_##SHORT = { \
114 .handle = LONG, \
115 .short_name = #SHORT, \
116 .short_name_len = sizeof(#SHORT)-1, \
117 .long_name = #LONG, \
118 .long_name_len = sizeof(#LONG)-1, \
121 HIVE_INFO_ENTRY(HKLM, HKEY_LOCAL_MACHINE);
122 HIVE_INFO_ENTRY(HKCU, HKEY_CURRENT_USER);
123 HIVE_INFO_ENTRY(HKCR, HKEY_CLASSES_ROOT);
124 HIVE_INFO_ENTRY(HKU , HKEY_USERS);
125 HIVE_INFO_ENTRY(HKCC, HKEY_CURRENT_CONFIG);
126 HIVE_INFO_ENTRY(HKDD, HKEY_DYN_DATA);
127 HIVE_INFO_ENTRY(HKPD, HKEY_PERFORMANCE_DATA);
128 HIVE_INFO_ENTRY(HKPT, HKEY_PERFORMANCE_TEXT);
129 HIVE_INFO_ENTRY(HKPN, HKEY_PERFORMANCE_NLSTEXT);
130 #undef HIVE_INFO_ENTRY
132 static const struct hive_info* HIVE_INFO[] = {
133 &HIVE_INFO_HKLM, &HIVE_INFO_HKCU, &HIVE_INFO_HKCR, &HIVE_INFO_HKU,
134 &HIVE_INFO_HKCC, &HIVE_INFO_HKDD, &HIVE_INFO_HKPD, &HIVE_INFO_HKPT,
135 &HIVE_INFO_HKPN, NULL
138 const struct hive_info* hive_info(const char* name, int nlen)
140 const struct hive_info** info;
141 char buf[32];
142 int s;
144 if (nlen >= sizeof(buf)) {
145 return NULL;
147 for (s=0; s<nlen; s++) {
148 buf[s] = toupper(name[s]);
150 buf[s] = '\0';
152 if ((s < 3) || (strncmp(buf, "HK", 2) != 0)) {
153 return NULL;
156 if (s <= 4) {
157 for(info = HIVE_INFO; *info; info++) {
158 if (strcmp(buf+2, (*info)->short_name+2) == 0) {
159 return *info;
162 return NULL;
165 if ((s < 10) || (strncmp(buf, "HKEY_", 5)) != 0) {
166 return NULL;
169 for(info = HIVE_INFO; *info; info++) {
170 if (strcmp(buf+5, (*info)->long_name+5) == 0) {
171 return *info;
174 return NULL;
177 const char* get_charset(const char* c)
179 if (strcmp(c, "dos") == 0) {
180 return lp_dos_charset();
181 } else if (strcmp(c, "unix") == 0) {
182 return lp_unix_charset();
183 } else {
184 return c;
188 bool set_iconv(smb_iconv_t* t, const char* to, const char* from)
190 smb_iconv_t cd = (smb_iconv_t)-1;
192 if (to && from) {
193 to = get_charset(to);
194 from = get_charset(from);
195 cd = smb_iconv_open(to, from);
196 if (cd == ((smb_iconv_t)-1)) {
197 return false;
200 if ((*t != (smb_iconv_t)NULL) && (*t != (smb_iconv_t)-1)) {
201 smb_iconv_close(*t);
203 *t = cd;
204 return true;
208 * Parse option string
209 * @param[in,out] ptr parse position
210 * @param[in] mem_ctx talloc context
211 * @param[out] name ptr 2 value
212 * @param[out] value ptr 2 value
213 * @return true on success
215 bool srprs_option(const char** ptr, const void* mem_ctx, char** name, char** value)
217 const char* pos = *ptr;
218 void* ctx = talloc_new(mem_ctx);
220 cbuf* key = cbuf_new(ctx);
221 cbuf* val = NULL;
223 while(srprs_charsetinv(&pos, ",= \t\n\r", key))
225 if (pos == *ptr) {
226 talloc_free(ctx);
227 return false;
230 if (name != NULL) {
231 *name = talloc_steal(mem_ctx, cbuf_gets(key, 0));
234 if (*pos == '=') {
235 val = cbuf_new(ctx);
236 pos++;
237 if (!srprs_quoted_string(ptr, val, NULL)) {
238 while(srprs_charsetinv(&pos, ", \t\n\r", val))
241 if (value != NULL) {
242 *value = talloc_steal(mem_ctx, cbuf_gets(val, 0));
244 } else {
245 if (value != NULL) {
246 *value = NULL;
250 while(srprs_char(&pos, ','))
253 *ptr = pos;
254 return true;
257 #define CH_INVALID ((charset_t)-1)
258 static const struct {
259 const char* const name;
260 charset_t ctype;
261 int len;
262 char seq[4];
263 } BOM[] = {
264 {"UTF-8", CH_UTF8, 3, {0xEF, 0xBB, 0xBF}},
265 {"UTF-32LE", CH_INVALID, 4, {0xFF, 0xFE, 0x00, 0x00}},
266 {"UTF-16LE", CH_UTF16LE, 2, {0xFF, 0xFE}},
267 {"UTF-16BE", CH_UTF16BE, 2, {0xFE, 0xFF}},
268 {"UTF-32BE", CH_INVALID, 4, {0x00, 0x00, 0xFE, 0xFF}},
269 {NULL, CH_INVALID, 0}
272 bool srprs_bom(const char** ptr, const char** name, charset_t* ctype)
274 int i;
275 for (i=0; BOM[i].name; i++) {
276 if (memcmp(*ptr, BOM[i].seq, BOM[i].len) == 0) {
277 break;
281 if (BOM[i].name != NULL) {
282 DEBUG(0, ("Found Byte Order Mark for : %s\n", BOM[i].name));
284 if (name != NULL) {
285 *name = BOM[i].name;
288 if (ctype != NULL) {
289 *ctype = BOM[i].ctype;
292 *ptr += BOM[i].len;
294 return true;
296 return false;
299 int write_bom(FILE* file, const char* charset, charset_t ctype)
301 int i;
302 if ( charset == NULL ) {
303 for (i=0; BOM[i].name; i++) {
304 if (BOM[i].ctype == ctype) {
305 return fwrite(BOM[i].seq, 1, BOM[i].len, file);
308 DEBUG(0, ("No Byte Order Mark for charset_t: %u\n", (unsigned)ctype));
309 } else {
310 for (i=0; BOM[i].name; i++) {
311 if (StrCaseCmp(BOM[i].name, charset) == 0) {
312 return fwrite(BOM[i].seq, 1, BOM[i].len, file);
315 DEBUG(0, ("No Byte Order Mark for charset_t: %s\n", charset));
317 return 0;
321 int cbuf_puts_case(cbuf* s, const char* str, size_t len, enum fmt_case fmt)
323 size_t pos = cbuf_getpos(s);
324 int ret = cbuf_puts(s, str, len);
325 char* ptr = cbuf_gets(s,pos);
327 if (ret <= 0) {
328 return ret;
331 switch (fmt) {
332 case FMT_CASE_PRESERVE:
333 break;
334 case FMT_CASE_UPPER:
335 while(*ptr != '\0') {
336 *ptr = toupper(*ptr);
337 ptr++;
339 break;
340 case FMT_CASE_TITLE:
341 *ptr = toupper(*ptr);
342 ptr++;
343 case FMT_CASE_LOWER:
344 while(*ptr != '\0') {
345 *ptr = tolower(*ptr);
346 ptr++;
349 return ret;