mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
551532d007
Rename to smbreg_get_charset() function to avoid naming conflict with MariaDB. Signed-off-by: xzhao9 <i@xuzhao.net> Reviewed-by: Jeremy Allison <jra@samba.org> Reviewed-by: David Mulder <dmulder@suse.com> Autobuild-User(master): Jeremy Allison <jra@samba.org> Autobuild-Date(master): Wed Feb 10 21:00:28 UTC 2021 on sn-devel-184
393 lines
8.2 KiB
C
393 lines
8.2 KiB
C
/*
|
|
* 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;
|
|
}
|