summaryrefslogtreecommitdiffstats
path: root/source3/registry/reg_parse_internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/registry/reg_parse_internal.c')
-rw-r--r--source3/registry/reg_parse_internal.c392
1 files changed, 392 insertions, 0 deletions
diff --git a/source3/registry/reg_parse_internal.c b/source3/registry/reg_parse_internal.c
new file mode 100644
index 0000000..d68fee6
--- /dev/null
+++ b/source3/registry/reg_parse_internal.c
@@ -0,0 +1,392 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Registry helper routines
+ *
+ * Copyright (C) Gregor Beck 2010
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * @file reg_parse_internal.h
+ * @author Gregor Beck <gb@sernet.de>
+ * @date Sep 2010
+ * @brief
+ */
+
+#include "reg_parse_internal.h"
+#include "cbuf.h"
+#include "srprs.h"
+#include "registry.h"
+
+size_t iconvert_talloc(const void* ctx,
+ smb_iconv_t cd,
+ const char* src, size_t srclen,
+ char** pdst)
+{
+ size_t dstlen, ret;
+ size_t obytes, ibytes;
+ char *optr, *dst, *tmp;
+ const char* iptr;
+
+ if (cd == NULL || cd == ((smb_iconv_t)-1)) {
+ return -1;
+ }
+
+ dst = *pdst;
+
+ if (dst == NULL) {
+ /*
+ * Allocate an extra two bytes for the
+ * terminating zero.
+ */
+ dstlen = srclen + 2;
+ dst = (char *)talloc_size(ctx, dstlen);
+ if (dst == NULL) {
+ DEBUG(0,("iconver_talloc no mem\n"));
+ return -1;
+ }
+ } else {
+ dstlen = talloc_get_size(dst);
+ }
+convert:
+ iptr = src;
+ ibytes = srclen;
+ optr = dst;
+ obytes = dstlen-2;
+
+ ret = smb_iconv(cd, &iptr, &ibytes, &optr, &obytes);
+
+ if(ret == -1) {
+ const char *reason="unknown error";
+ switch(errno) {
+ case EINVAL:
+ reason="Incomplete multibyte sequence";
+ break;
+ case E2BIG:
+ dstlen = 2*dstlen + 2;
+ tmp = talloc_realloc(ctx, dst, char, dstlen);
+ if (tmp == NULL) {
+ reason="talloc_realloc failed";
+ break;
+ }
+ dst = tmp;
+ goto convert;
+ case EILSEQ:
+ reason="Illegal multibyte sequence";
+ break;
+ }
+ DEBUG(0,("Conversion error: %s(%.80s) %li\n", reason, iptr,
+ (long int)(iptr-src)));
+ talloc_free(dst);
+ return -1;
+ }
+
+ dstlen = (dstlen-2) - obytes;
+
+ SSVAL(dst, dstlen, 0);
+
+ *pdst = dst;
+ return dstlen;
+}
+
+#ifndef HKEY_CURRENT_CONFIG
+#define HKEY_CURRENT_CONFIG 0x80000005
+#endif
+#ifndef HKEY_DYN_DATA
+#define HKEY_DYN_DATA 0x80000006
+#endif
+#ifndef HKEY_PERFORMANCE_TEXT
+#define HKEY_PERFORMANCE_TEXT 0x80000050
+#endif
+#ifndef HKEY_PERFORMANCE_NLSTEXT
+#define HKEY_PERFORMANCE_NLSTEXT 0x80000060
+#endif
+
+#define HIVE_INFO_ENTRY(SHORT,LONG) \
+const struct hive_info HIVE_INFO_##SHORT = { \
+ .handle = LONG, \
+ .short_name = #SHORT, \
+ .short_name_len = sizeof(#SHORT)-1, \
+ .long_name = #LONG, \
+ .long_name_len = sizeof(#LONG)-1, \
+}
+
+HIVE_INFO_ENTRY(HKLM, HKEY_LOCAL_MACHINE);
+HIVE_INFO_ENTRY(HKCU, HKEY_CURRENT_USER);
+HIVE_INFO_ENTRY(HKCR, HKEY_CLASSES_ROOT);
+HIVE_INFO_ENTRY(HKU , HKEY_USERS);
+HIVE_INFO_ENTRY(HKCC, HKEY_CURRENT_CONFIG);
+HIVE_INFO_ENTRY(HKDD, HKEY_DYN_DATA);
+HIVE_INFO_ENTRY(HKPD, HKEY_PERFORMANCE_DATA);
+HIVE_INFO_ENTRY(HKPT, HKEY_PERFORMANCE_TEXT);
+HIVE_INFO_ENTRY(HKPN, HKEY_PERFORMANCE_NLSTEXT);
+#undef HIVE_INFO_ENTRY
+
+const struct hive_info* HIVE_INFO[] = {
+ &HIVE_INFO_HKLM, &HIVE_INFO_HKCU, &HIVE_INFO_HKCR, &HIVE_INFO_HKU,
+ &HIVE_INFO_HKCC, &HIVE_INFO_HKDD, &HIVE_INFO_HKPD, &HIVE_INFO_HKPT,
+ &HIVE_INFO_HKPN, NULL
+};
+
+#define TOINT(A,B) ((int)(A) << 8) + (int)(B)
+
+bool srprs_hive(const char** ptr, const struct hive_info** result)
+{
+ const char* str = *ptr;
+ const struct hive_info* info = NULL;
+ bool long_hive = false;
+
+ if ((toupper(str[0]) != 'H') || (toupper(str[1]) != 'K')
+ || (str[2] == '\0') )
+ {
+ return false;
+ }
+
+ switch ( TOINT(toupper(str[2]), toupper(str[3])) ) {
+ case TOINT('E', 'Y'):
+ if (str[4] == '_') {
+ int i;
+ for (i=0; (info = HIVE_INFO[i]); i++) {
+ if (strncmp(&str[5], &info->long_name[5],
+ info->long_name_len-5) == 0)
+ {
+ long_hive = true;
+ break;
+ }
+ }
+ }
+ break;
+ case TOINT('L', 'M'):
+ info = &HIVE_INFO_HKLM;
+ break;
+ case TOINT('C', 'U'):
+ info = &HIVE_INFO_HKCU;
+ break;
+ case TOINT('C', 'R'):
+ info = &HIVE_INFO_HKCR;
+ break;
+ case TOINT('C', 'C'):
+ info = &HIVE_INFO_HKCC;
+ break;
+ case TOINT('D', 'D'):
+ info = &HIVE_INFO_HKDD;
+ break;
+ case TOINT('P', 'D'):
+ info = &HIVE_INFO_HKPD;
+ break;
+ case TOINT('P', 'T'):
+ info = &HIVE_INFO_HKPT;
+ break;
+ case TOINT('P', 'N'):
+ info = &HIVE_INFO_HKPN;
+ break;
+ default:
+ if (toupper(str[2]) == 'U') {
+ info = &HIVE_INFO_HKU;
+ }
+ break;
+ }
+ if (info != NULL) {
+ if (result != NULL) {
+ *result = info;
+ }
+ *ptr += long_hive ? info->long_name_len : info->short_name_len;
+ return true;
+ }
+ return false;
+}
+
+const struct hive_info* hive_info(const char* name)
+{
+ const struct hive_info* info = NULL;
+ srprs_hive(&name, &info);
+ return info;
+}
+
+const char *smbreg_get_charset(const char *c)
+{
+ if (strcmp(c, "dos") == 0) {
+ return lp_dos_charset();
+ } else if (strcmp(c, "unix") == 0) {
+ return lp_unix_charset();
+ } else {
+ return c;
+ }
+}
+
+bool set_iconv(smb_iconv_t* t, const char* to, const char* from)
+{
+ smb_iconv_t cd = (smb_iconv_t)-1;
+
+ if (to && from) {
+ to = smbreg_get_charset(to);
+ from = smbreg_get_charset(from);
+ cd = smb_iconv_open(to, from);
+ if (cd == ((smb_iconv_t)-1)) {
+ return false;
+ }
+ }
+ if ((*t != (smb_iconv_t)NULL) && (*t != (smb_iconv_t)-1)) {
+ smb_iconv_close(*t);
+ }
+ *t = cd;
+ return true;
+}
+
+/**
+ * Parse option string
+ * @param[in,out] ptr parse position
+ * @param[in] mem_ctx talloc context
+ * @param[out] name ptr 2 value
+ * @param[out] value ptr 2 value
+ * @return true on success
+ */
+bool srprs_option(const char** ptr, const void* mem_ctx, char** name, char** value)
+{
+ const char* pos = *ptr;
+ void* ctx = talloc_new(mem_ctx);
+
+ cbuf* key = cbuf_new(ctx);
+ cbuf* val = NULL;
+
+ while(srprs_charsetinv(&pos, ",= \t\n\r", key))
+ ;
+ if (pos == *ptr) {
+ talloc_free(ctx);
+ return false;
+ }
+
+ if (name != NULL) {
+ *name = talloc_steal(mem_ctx, cbuf_gets(key, 0));
+ }
+
+ if (*pos == '=') {
+ val = cbuf_new(ctx);
+ pos++;
+ if (!srprs_quoted_string(ptr, val, NULL)) {
+ while(srprs_charsetinv(&pos, ", \t\n\r", val))
+ ;
+ }
+ if (value != NULL) {
+ *value = talloc_steal(mem_ctx, cbuf_gets(val, 0));
+ }
+ } else {
+ if (value != NULL) {
+ *value = NULL;
+ }
+ }
+
+ while(srprs_char(&pos, ','))
+ ;
+
+ *ptr = pos;
+ return true;
+}
+
+#define CH_INVALID ((charset_t)-1)
+static const struct {
+ const char* const name;
+ charset_t ctype;
+ int len;
+ uint8_t seq[4];
+} BOM[] = {
+ {"UTF-8", CH_UTF8, 3, {0xEF, 0xBB, 0xBF}},
+ {"UTF-32LE", CH_INVALID, 4, {0xFF, 0xFE, 0x00, 0x00}},
+ {"UTF-16LE", CH_UTF16LE, 2, {0xFF, 0xFE}},
+ {"UTF-16BE", CH_UTF16BE, 2, {0xFE, 0xFF}},
+ {"UTF-32BE", CH_INVALID, 4, {0x00, 0x00, 0xFE, 0xFF}},
+ { .name = NULL }
+};
+
+bool srprs_bom(const char** ptr, const char** name, charset_t* ctype)
+{
+ int i;
+ for (i=0; BOM[i].name; i++) {
+ if (memcmp(*ptr, BOM[i].seq, BOM[i].len) == 0) {
+ break;
+ }
+ }
+
+ if (BOM[i].name != NULL) {
+ DEBUG(0, ("Found Byte Order Mark for : %s\n", BOM[i].name));
+
+ if (name != NULL) {
+ *name = BOM[i].name;
+ }
+
+ if (ctype != NULL) {
+ *ctype = BOM[i].ctype;
+ }
+
+ *ptr += BOM[i].len;
+
+ return true;
+ }
+ return false;
+}
+
+int write_bom(FILE* file, const char* charset, charset_t ctype)
+{
+ int i;
+ if ( charset == NULL ) {
+ for (i=0; BOM[i].name; i++) {
+ if (BOM[i].ctype == ctype) {
+ return fwrite(BOM[i].seq, 1, BOM[i].len, file);
+ }
+ }
+ DEBUG(0, ("No Byte Order Mark for charset_t: %u\n", (unsigned)ctype));
+ } else {
+ for (i=0; BOM[i].name; i++) {
+ if (strcasecmp_m(BOM[i].name, charset) == 0) {
+ return fwrite(BOM[i].seq, 1, BOM[i].len, file);
+ }
+ }
+ DEBUG(0, ("No Byte Order Mark for charset_t: %s\n", charset));
+ }
+ return 0;
+}
+
+
+int cbuf_puts_case(cbuf* s, const char* str, size_t len, enum fmt_case fmt)
+{
+ size_t pos = cbuf_getpos(s);
+ int ret = cbuf_puts(s, str, len);
+ char* ptr = cbuf_gets(s,pos);
+
+ if (ret <= 0) {
+ return ret;
+ }
+
+ switch (fmt) {
+ case FMT_CASE_PRESERVE:
+ break;
+ case FMT_CASE_UPPER:
+ while(*ptr != '\0') {
+ *ptr = toupper(*ptr);
+ ptr++;
+ }
+ break;
+ case FMT_CASE_TITLE:
+ *ptr = toupper(*ptr);
+ ptr++;
+ FALL_THROUGH;
+ case FMT_CASE_LOWER:
+ while(*ptr != '\0') {
+ *ptr = tolower(*ptr);
+ ptr++;
+ }
+ }
+ return ret;
+}