mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
r15295: Fix some dependencies
Move unistr-specific code to lib/charset/. Remove _m from some places where it's not needed.
This commit is contained in:
parent
e8d69ff8d0
commit
03224e1124
@ -26,6 +26,7 @@ PRIVATE_PROTO_HEADER = netif/proto.h
|
||||
OBJ_FILES = \
|
||||
netif/interface.o \
|
||||
netif/netif.o
|
||||
PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL
|
||||
# End SUBSYSTEM LIBNETIF
|
||||
##############################
|
||||
|
||||
@ -44,19 +45,17 @@ OBJ_FILES = \
|
||||
################################################
|
||||
# Start SUBSYSTEM LIBCOMPRESSION
|
||||
[SUBSYSTEM::LIBCOMPRESSION]
|
||||
OBJ_FILES = \
|
||||
compression/mszip.o
|
||||
OBJ_FILES = compression/mszip.o
|
||||
# End SUBSYSTEM LIBCOMPRESION
|
||||
################################################
|
||||
|
||||
[SUBSYSTEM::GENCACHE]
|
||||
PRIVATE_PROTO_HEADER = gencache/gencache.h
|
||||
OBJ_FILES = \
|
||||
gencache/gencache.o \
|
||||
OBJ_FILES = gencache/gencache.o \
|
||||
|
||||
[SUBSYSTEM::DB_WRAP]
|
||||
PUBLIC_PROTO_HEADER = db_wrap_proto.h
|
||||
PUBLIC_HEADERS = db_wrap.h
|
||||
OBJ_FILES = db_wrap.o \
|
||||
gendb.o
|
||||
PUBLIC_DEPENDENCIES = ldb LIBTDB LDBSAMBA
|
||||
OBJ_FILES = db_wrap.o gendb.o
|
||||
PUBLIC_DEPENDENCIES = LIBTDB ldb
|
||||
PRIVATE_DEPENDENCIES = LDBSAMBA
|
||||
|
@ -43,17 +43,16 @@
|
||||
**/
|
||||
static const char *charset_name(charset_t ch)
|
||||
{
|
||||
const char *ret = NULL;
|
||||
|
||||
if (ch == CH_UTF16) ret = "UTF-16LE";
|
||||
else if (ch == CH_UNIX) ret = lp_unix_charset();
|
||||
else if (ch == CH_DOS) ret = lp_dos_charset();
|
||||
else if (ch == CH_DISPLAY) ret = lp_display_charset();
|
||||
else if (ch == CH_UTF8) ret = "UTF8";
|
||||
else if (ch == CH_UTF16BE) ret = "UTF-16BE";
|
||||
|
||||
if (!ret || !*ret) ret = "ASCII";
|
||||
return ret;
|
||||
switch (ch) {
|
||||
case CH_UTF16: return "UTF-16LE";
|
||||
case CH_UNIX: return lp_unix_charset();
|
||||
case CH_DOS: return lp_dos_charset();
|
||||
case CH_DISPLAY: return lp_display_charset();
|
||||
case CH_UTF8: return "UTF8";
|
||||
case CH_UTF16BE: return "UTF-16BE";
|
||||
default:
|
||||
return "ASCII";
|
||||
}
|
||||
}
|
||||
|
||||
static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
|
||||
|
@ -73,4 +73,9 @@ typedef struct {
|
||||
|
||||
#include "lib/charset/charset_proto.h"
|
||||
|
||||
/* replace some string functions with multi-byte
|
||||
versions */
|
||||
#define strlower(s) strlower_m(s)
|
||||
#define strupper(s) strupper_m(s)
|
||||
|
||||
#endif /* __CHARSET_H__ */
|
||||
|
@ -3,7 +3,8 @@
|
||||
[SUBSYSTEM::CHARSET]
|
||||
OBJ_FILES = \
|
||||
iconv.o \
|
||||
charcnv.o
|
||||
charcnv.o \
|
||||
util_unistr.o
|
||||
PUBLIC_HEADERS = charset.h
|
||||
PUBLIC_PROTO_HEADER = charset_proto.h
|
||||
PUBLIC_DEPENDENCIES = ICONV
|
||||
|
615
source/lib/charset/util_unistr.c
Normal file
615
source/lib/charset/util_unistr.c
Normal file
@ -0,0 +1,615 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Samba utility functions
|
||||
Copyright (C) Andrew Tridgell 1992-2001
|
||||
Copyright (C) Simo Sorce 2001
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "system/iconv.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Unicode string manipulation
|
||||
*/
|
||||
|
||||
/* these 2 tables define the unicode case handling. They are loaded
|
||||
at startup either via mmap() or read() from the lib directory */
|
||||
static void *upcase_table;
|
||||
static void *lowcase_table;
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
load the case handling tables
|
||||
********************************************************************/
|
||||
static void load_case_tables(void)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
mem_ctx = talloc_init("load_case_tables");
|
||||
if (!mem_ctx) {
|
||||
smb_panic("No memory for case_tables");
|
||||
}
|
||||
upcase_table = map_file(data_path(mem_ctx, "upcase.dat"), 0x20000);
|
||||
lowcase_table = map_file(data_path(mem_ctx, "lowcase.dat"), 0x20000);
|
||||
talloc_free(mem_ctx);
|
||||
if (upcase_table == NULL) {
|
||||
/* try also under codepages for testing purposes */
|
||||
upcase_table = map_file("codepages/upcase.dat", 0x20000);
|
||||
if (upcase_table == NULL) {
|
||||
upcase_table = (void *)-1;
|
||||
}
|
||||
}
|
||||
if (lowcase_table == NULL) {
|
||||
/* try also under codepages for testing purposes */
|
||||
lowcase_table = map_file("codepages/lowcase.dat", 0x20000);
|
||||
if (lowcase_table == NULL) {
|
||||
lowcase_table = (void *)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a codepoint_t to upper case.
|
||||
**/
|
||||
codepoint_t toupper_w(codepoint_t val)
|
||||
{
|
||||
if (val < 128) {
|
||||
return toupper(val);
|
||||
}
|
||||
if (upcase_table == NULL) {
|
||||
load_case_tables();
|
||||
}
|
||||
if (upcase_table == (void *)-1) {
|
||||
return val;
|
||||
}
|
||||
if (val & 0xFFFF0000) {
|
||||
return val;
|
||||
}
|
||||
return SVAL(upcase_table, val*2);
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a codepoint_t to lower case.
|
||||
**/
|
||||
codepoint_t tolower_w(codepoint_t val)
|
||||
{
|
||||
if (val < 128) {
|
||||
return tolower(val);
|
||||
}
|
||||
if (lowcase_table == NULL) {
|
||||
load_case_tables();
|
||||
}
|
||||
if (lowcase_table == (void *)-1) {
|
||||
return val;
|
||||
}
|
||||
if (val & 0xFFFF0000) {
|
||||
return val;
|
||||
}
|
||||
return SVAL(lowcase_table, val*2);
|
||||
}
|
||||
|
||||
/**
|
||||
compare two codepoints case insensitively
|
||||
*/
|
||||
int codepoint_cmpi(codepoint_t c1, codepoint_t c2)
|
||||
{
|
||||
if (c1 == c2 ||
|
||||
toupper_w(c1) == toupper_w(c2)) {
|
||||
return 0;
|
||||
}
|
||||
return c1 - c2;
|
||||
}
|
||||
|
||||
/**
|
||||
Case insensitive string compararison
|
||||
**/
|
||||
_PUBLIC_ int strcasecmp_m(const char *s1, const char *s2)
|
||||
{
|
||||
codepoint_t c1=0, c2=0;
|
||||
size_t size1, size2;
|
||||
|
||||
while (*s1 && *s2) {
|
||||
c1 = next_codepoint(s1, &size1);
|
||||
c2 = next_codepoint(s2, &size2);
|
||||
|
||||
s1 += size1;
|
||||
s2 += size2;
|
||||
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c1 == INVALID_CODEPOINT ||
|
||||
c2 == INVALID_CODEPOINT) {
|
||||
/* what else can we do?? */
|
||||
return strcasecmp(s1, s2);
|
||||
}
|
||||
|
||||
if (toupper_w(c1) != toupper_w(c2)) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
|
||||
return *s1 - *s2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next token from a string, return False if none found.
|
||||
* Handles double-quotes.
|
||||
*
|
||||
* Based on a routine by GJC@VILLAGE.COM.
|
||||
* Extensively modified by Andrew.Tridgell@anu.edu.au
|
||||
**/
|
||||
_PUBLIC_ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
|
||||
{
|
||||
const char *s;
|
||||
BOOL quoted;
|
||||
size_t len=1;
|
||||
|
||||
if (!ptr)
|
||||
return(False);
|
||||
|
||||
s = *ptr;
|
||||
|
||||
/* default to simple separators */
|
||||
if (!sep)
|
||||
sep = " \t\n\r";
|
||||
|
||||
/* find the first non sep char */
|
||||
while (*s && strchr_m(sep,*s))
|
||||
s++;
|
||||
|
||||
/* nothing left? */
|
||||
if (! *s)
|
||||
return(False);
|
||||
|
||||
/* copy over the token */
|
||||
for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
|
||||
if (*s == '\"') {
|
||||
quoted = !quoted;
|
||||
} else {
|
||||
len++;
|
||||
*buff++ = *s;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = (*s) ? s+1 : s;
|
||||
*buff = 0;
|
||||
|
||||
return(True);
|
||||
}
|
||||
|
||||
/**
|
||||
Case insensitive string compararison, length limited
|
||||
**/
|
||||
_PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
codepoint_t c1=0, c2=0;
|
||||
size_t size1, size2;
|
||||
|
||||
while (*s1 && *s2 && n) {
|
||||
n--;
|
||||
|
||||
c1 = next_codepoint(s1, &size1);
|
||||
c2 = next_codepoint(s2, &size2);
|
||||
|
||||
s1 += size1;
|
||||
s2 += size2;
|
||||
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c1 == INVALID_CODEPOINT ||
|
||||
c2 == INVALID_CODEPOINT) {
|
||||
/* what else can we do?? */
|
||||
return strcasecmp(s1, s2);
|
||||
}
|
||||
|
||||
if (toupper_w(c1) != toupper_w(c2)) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *s1 - *s2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare 2 strings.
|
||||
*
|
||||
* @note The comparison is case-insensitive.
|
||||
**/
|
||||
_PUBLIC_ BOOL strequal_w(const char *s1, const char *s2)
|
||||
{
|
||||
if (s1 == s2)
|
||||
return(True);
|
||||
if (!s1 || !s2)
|
||||
return(False);
|
||||
|
||||
return strcasecmp_m(s1,s2) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Compare 2 strings (case sensitive).
|
||||
**/
|
||||
_PUBLIC_ BOOL strcsequal_w(const char *s1,const char *s2)
|
||||
{
|
||||
if (s1 == s2)
|
||||
return(True);
|
||||
if (!s1 || !s2)
|
||||
return(False);
|
||||
|
||||
return strcmp(s1,s2) == 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
String replace.
|
||||
NOTE: oldc and newc must be 7 bit characters
|
||||
**/
|
||||
_PUBLIC_ void string_replace_w(char *s, char oldc, char newc)
|
||||
{
|
||||
while (*s) {
|
||||
size_t size;
|
||||
codepoint_t c = next_codepoint(s, &size);
|
||||
if (c == oldc) {
|
||||
*s = newc;
|
||||
}
|
||||
s += size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Paranoid strcpy into a buffer of given length (includes terminating
|
||||
zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
|
||||
and replaces with '_'. Deliberately does *NOT* check for multibyte
|
||||
characters. Don't change it !
|
||||
**/
|
||||
|
||||
_PUBLIC_ char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
|
||||
{
|
||||
size_t len, i;
|
||||
|
||||
if (maxlength == 0) {
|
||||
/* can't fit any bytes at all! */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dest) {
|
||||
DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!src) {
|
||||
*dest = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
len = strlen(src);
|
||||
if (len >= maxlength)
|
||||
len = maxlength - 1;
|
||||
|
||||
if (!other_safe_chars)
|
||||
other_safe_chars = "";
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
int val = (src[i] & 0xff);
|
||||
if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
|
||||
dest[i] = src[i];
|
||||
else
|
||||
dest[i] = '_';
|
||||
}
|
||||
|
||||
dest[i] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
Count the number of UCS2 characters in a string. Normally this will
|
||||
be the same as the number of bytes in a string for single byte strings,
|
||||
but will be different for multibyte.
|
||||
**/
|
||||
_PUBLIC_ size_t strlen_m(const char *s)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (*s && !(((uint8_t)*s) & 0x80)) {
|
||||
s++;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!*s) {
|
||||
return count;
|
||||
}
|
||||
|
||||
while (*s) {
|
||||
size_t c_size;
|
||||
codepoint_t c = next_codepoint(s, &c_size);
|
||||
if (c < 0x10000) {
|
||||
count += 1;
|
||||
} else {
|
||||
count += 2;
|
||||
}
|
||||
s += c_size;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
Work out the number of multibyte chars in a string, including the NULL
|
||||
terminator.
|
||||
**/
|
||||
_PUBLIC_ size_t strlen_m_term(const char *s)
|
||||
{
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return strlen_m(s) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Strchr and strrchr_m are a bit complex on general multi-byte strings.
|
||||
**/
|
||||
_PUBLIC_ char *strchr_m(const char *s, char c)
|
||||
{
|
||||
/* characters below 0x3F are guaranteed to not appear in
|
||||
non-initial position in multi-byte charsets */
|
||||
if ((c & 0xC0) == 0) {
|
||||
return strchr(s, c);
|
||||
}
|
||||
|
||||
while (*s) {
|
||||
size_t size;
|
||||
codepoint_t c2 = next_codepoint(s, &size);
|
||||
if (c2 == c) {
|
||||
return discard_const(s);
|
||||
}
|
||||
s += size;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multibyte-character version of strrchr
|
||||
*/
|
||||
_PUBLIC_ char *strrchr_m(const char *s, char c)
|
||||
{
|
||||
char *ret = NULL;
|
||||
|
||||
/* characters below 0x3F are guaranteed to not appear in
|
||||
non-initial position in multi-byte charsets */
|
||||
if ((c & 0xC0) == 0) {
|
||||
return strrchr(s, c);
|
||||
}
|
||||
|
||||
while (*s) {
|
||||
size_t size;
|
||||
codepoint_t c2 = next_codepoint(s, &size);
|
||||
if (c2 == c) {
|
||||
ret = discard_const(s);
|
||||
}
|
||||
s += size;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
return True if any (multi-byte) character is lower case
|
||||
*/
|
||||
_PUBLIC_ BOOL strhaslower(const char *string)
|
||||
{
|
||||
while (*string) {
|
||||
size_t c_size;
|
||||
codepoint_t s;
|
||||
codepoint_t t;
|
||||
|
||||
s = next_codepoint(string, &c_size);
|
||||
string += c_size;
|
||||
|
||||
t = toupper_w(s);
|
||||
|
||||
if (s != t) {
|
||||
return True; /* that means it has lower case chars */
|
||||
}
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/**
|
||||
return True if any (multi-byte) character is upper case
|
||||
*/
|
||||
_PUBLIC_ BOOL strhasupper(const char *string)
|
||||
{
|
||||
while (*string) {
|
||||
size_t c_size;
|
||||
codepoint_t s;
|
||||
codepoint_t t;
|
||||
|
||||
s = next_codepoint(string, &c_size);
|
||||
string += c_size;
|
||||
|
||||
t = tolower_w(s);
|
||||
|
||||
if (s != t) {
|
||||
return True; /* that means it has upper case chars */
|
||||
}
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a string to lower case, allocated with talloc
|
||||
**/
|
||||
_PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
|
||||
{
|
||||
size_t size=0;
|
||||
char *dest;
|
||||
|
||||
/* this takes advantage of the fact that upper/lower can't
|
||||
change the length of a character by more than 1 byte */
|
||||
dest = talloc_size(ctx, 2*(strlen(src))+1);
|
||||
if (dest == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*src) {
|
||||
size_t c_size;
|
||||
codepoint_t c = next_codepoint(src, &c_size);
|
||||
src += c_size;
|
||||
|
||||
c = tolower_w(c);
|
||||
|
||||
c_size = push_codepoint(dest+size, c);
|
||||
if (c_size == -1) {
|
||||
talloc_free(dest);
|
||||
return NULL;
|
||||
}
|
||||
size += c_size;
|
||||
}
|
||||
|
||||
dest[size] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a string to UPPER case, allocated with talloc
|
||||
**/
|
||||
_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
|
||||
{
|
||||
size_t size=0;
|
||||
char *dest;
|
||||
|
||||
if (!src) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* this takes advantage of the fact that upper/lower can't
|
||||
change the length of a character by more than 1 byte */
|
||||
dest = talloc_size(ctx, 2*(strlen(src))+1);
|
||||
if (dest == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*src) {
|
||||
size_t c_size;
|
||||
codepoint_t c = next_codepoint(src, &c_size);
|
||||
src += c_size;
|
||||
|
||||
c = toupper_w(c);
|
||||
|
||||
c_size = push_codepoint(dest+size, c);
|
||||
if (c_size == -1) {
|
||||
talloc_free(dest);
|
||||
return NULL;
|
||||
}
|
||||
size += c_size;
|
||||
}
|
||||
|
||||
dest[size] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a string to lower case.
|
||||
**/
|
||||
_PUBLIC_ void strlower_m(char *s)
|
||||
{
|
||||
char *d;
|
||||
|
||||
/* this is quite a common operation, so we want it to be
|
||||
fast. We optimise for the ascii case, knowing that all our
|
||||
supported multi-byte character sets are ascii-compatible
|
||||
(ie. they match for the first 128 chars) */
|
||||
while (*s && !(((uint8_t)*s) & 0x80)) {
|
||||
*s = tolower((uint8_t)*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
return;
|
||||
|
||||
d = s;
|
||||
|
||||
while (*s) {
|
||||
size_t c_size, c_size2;
|
||||
codepoint_t c = next_codepoint(s, &c_size);
|
||||
c_size2 = push_codepoint(d, tolower_w(c));
|
||||
if (c_size2 > c_size) {
|
||||
DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
|
||||
c, tolower_w(c), (int)c_size, (int)c_size2));
|
||||
smb_panic("codepoint expansion in strlower_m\n");
|
||||
}
|
||||
s += c_size;
|
||||
d += c_size2;
|
||||
}
|
||||
*d = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a string to UPPER case.
|
||||
**/
|
||||
_PUBLIC_ void strupper_m(char *s)
|
||||
{
|
||||
char *d;
|
||||
|
||||
/* this is quite a common operation, so we want it to be
|
||||
fast. We optimise for the ascii case, knowing that all our
|
||||
supported multi-byte character sets are ascii-compatible
|
||||
(ie. they match for the first 128 chars) */
|
||||
while (*s && !(((uint8_t)*s) & 0x80)) {
|
||||
*s = toupper((uint8_t)*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
return;
|
||||
|
||||
d = s;
|
||||
|
||||
while (*s) {
|
||||
size_t c_size, c_size2;
|
||||
codepoint_t c = next_codepoint(s, &c_size);
|
||||
c_size2 = push_codepoint(d, toupper_w(c));
|
||||
if (c_size2 > c_size) {
|
||||
DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
|
||||
c, toupper_w(c), (int)c_size, (int)c_size2));
|
||||
smb_panic("codepoint expansion in strupper_m\n");
|
||||
}
|
||||
s += c_size;
|
||||
d += c_size2;
|
||||
}
|
||||
*d = 0;
|
||||
}
|
||||
|
@ -59,11 +59,6 @@ static void ldb_wrap_debug(void *context, enum ldb_debug_level level,
|
||||
free(s);
|
||||
}
|
||||
|
||||
int wrap_caseless_cmp(void *context, const char *s1, const char *s2)
|
||||
{
|
||||
return strcasecmp_m(s1, s2);
|
||||
}
|
||||
|
||||
char *wrap_casefold(void *context, void *mem_ctx, const char *s)
|
||||
{
|
||||
return strupper_talloc(mem_ctx, s);
|
||||
|
@ -71,6 +71,7 @@ OBJ_FILES = \
|
||||
################################################
|
||||
# Start MODULE ldb_ildap
|
||||
[MODULE::ldb_ildap]
|
||||
ENABLE = NO
|
||||
SUBSYSTEM = ldb
|
||||
INIT_FUNCTION = ldb_ildap_init
|
||||
ALIASES = ldapi ldaps ldap
|
||||
@ -164,7 +165,7 @@ PUBLIC_HEADERS = include/ldb.h include/ldb_errors.h
|
||||
# Start SUBSYSTEM LDBSAMBA
|
||||
[SUBSYSTEM::LDBSAMBA]
|
||||
PRIVATE_PROTO_HEADER = samba/ldif_handlers.h
|
||||
PUBLIC_DEPENDENCIES = LIB_SECURITY SAMDB
|
||||
PUBLIC_DEPENDENCIES = LIBSECURITY SAMDB
|
||||
OBJ_FILES = \
|
||||
samba/ldif_handlers.o
|
||||
# End SUBSYSTEM LDBSAMBA
|
||||
@ -176,6 +177,7 @@ OBJ_FILES = \
|
||||
OBJ_FILES= \
|
||||
tools/cmdline.o
|
||||
PUBLIC_DEPENDENCIES = ldb LIBSAMBA-UTIL LIBPOPT POPT_SAMBA POPT_CREDENTIALS
|
||||
PRIVATE_DEPENDENCIES = gensec
|
||||
# End SUBSYSTEM LIBLDB_CMDLINE
|
||||
################################################
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
OBJ_FILES = \
|
||||
messaging.o
|
||||
PUBLIC_DEPENDENCIES = \
|
||||
DB_WRAP \
|
||||
NDR_IRPC \
|
||||
UNIX_PRIVS
|
||||
# End SUBSYSTEM MESSAGING
|
||||
|
@ -98,7 +98,7 @@ OBJ_FILES = \
|
||||
reg_samba.o \
|
||||
patchfile.o
|
||||
PUBLIC_DEPENDENCIES = \
|
||||
LIBSAMBA-UTIL
|
||||
LIBSAMBA-UTIL CHARSET
|
||||
PRIVATE_PROTO_HEADER = registry_proto.h
|
||||
PUBLIC_HEADERS = registry.h
|
||||
# End MODULE registry_ldb
|
||||
@ -132,7 +132,8 @@ MANPAGE = man/regpatch.1
|
||||
INSTALLDIR = BINDIR
|
||||
OBJ_FILES = tools/regshell.o
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
LIBSAMBA-CONFIG LIBPOPT registry POPT_SAMBA POPT_CREDENTIALS LIBREADLINE
|
||||
LIBSAMBA-CONFIG LIBPOPT registry POPT_SAMBA POPT_CREDENTIALS \
|
||||
SMBREADLINE
|
||||
MANPAGE = man/regshell.1
|
||||
# End BINARY regshell
|
||||
################################################
|
||||
|
@ -16,7 +16,3 @@ OBJ_FILES = replace.o \
|
||||
PUBLIC_DEPENDENCIES = REPLACE_READDIR
|
||||
# End SUBSYSTEM LIBREPLACE
|
||||
##############################
|
||||
|
||||
[SUBSYSTEM::SMBREADLINE]
|
||||
OBJ_FILES = readline.o
|
||||
PRIVATE_PROTO_HEADER = readline.h
|
||||
|
@ -72,10 +72,10 @@ AC_MSG_CHECKING(whether to use extern readline)
|
||||
if test x"$EXTERNAL_READLINE" = x"yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_LIBREADLINE,1,[Whether the system has readline])
|
||||
SMB_SUBSYSTEM(LIBREADLINE, [], [SMBREADLINE EXT_READLINE])
|
||||
SMB_EXT_LIB(EXT_READLINE, [${TERMLIBS}])
|
||||
SMB_ENABLE(EXT_READLINE,YES)
|
||||
SMB_SUBSYSTEM(SMBREADLINE, [lib/replace/readline.o], [READLINE])
|
||||
SMB_EXT_LIB(READLINE, [${TERMLIBS}])
|
||||
SMB_ENABLE(READLINE,YES)
|
||||
else
|
||||
SMB_SUBSYSTEM(LIBREADLINE, [], [SMBREADLINE])
|
||||
SMB_SUBSYSTEM(SMBREADLINE, [lib/replace/readline.o], [])
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
@ -7,6 +7,7 @@ OUTPUT_TYPE = MERGEDOBJ
|
||||
OBJ_FILES = \
|
||||
socket_ipv4.o
|
||||
PUBLIC_DEPENDENCIES = EXT_SOCKET
|
||||
PRIVATE_DEPENDENCIES = LIBSAMBA-ERRORS
|
||||
# End MODULE socket_ipv4
|
||||
################################################
|
||||
|
||||
@ -41,6 +42,6 @@ OBJ_FILES = \
|
||||
connect_multi.o \
|
||||
connect.o
|
||||
PUBLIC_DEPENDENCIES = LIBTALLOC
|
||||
PRIVATE_DEPENDENCIES = LIBCLI_RESOLVE SOCKET_WRAPPER
|
||||
PRIVATE_DEPENDENCIES = SOCKET_WRAPPER LIBCLI_COMPOSITE
|
||||
# End SUBSYSTEM SOCKET
|
||||
################################################
|
||||
|
@ -2,7 +2,7 @@
|
||||
################################################
|
||||
# Start SUBSYSTEM LIBPACKET
|
||||
[SUBSYSTEM::LIBPACKET]
|
||||
OBJ_FILES = \
|
||||
packet.o
|
||||
OBJ_FILES = packet.o
|
||||
PRIVATE_DEPENDENCIES = LIBTLS
|
||||
# End SUBSYSTEM LIBPACKET
|
||||
################################################
|
||||
|
@ -19,7 +19,6 @@ OBJ_FILES = xfile.o \
|
||||
dprintf.o \
|
||||
util_str.o \
|
||||
util_strlist.o \
|
||||
util_unistr.o \
|
||||
util_file.o \
|
||||
data_blob.o \
|
||||
util.o \
|
||||
@ -32,10 +31,8 @@ OBJ_FILES = xfile.o \
|
||||
idtree.o \
|
||||
module.o
|
||||
PUBLIC_DEPENDENCIES = \
|
||||
CHARSET LIBREPLACE LIBCRYPTO DL LIBTALLOC \
|
||||
SOCKET_WRAPPER \
|
||||
# for the base64 functions
|
||||
ldb
|
||||
LIBREPLACE LIBCRYPTO DL LIBTALLOC \
|
||||
SOCKET_WRAPPER
|
||||
|
||||
[SUBSYSTEM::PIDFILE]
|
||||
PRIVATE_PROTO_HEADER = pidfile.h
|
||||
|
@ -42,9 +42,4 @@
|
||||
|
||||
#endif /* !_SPLINT_ */
|
||||
|
||||
/* replace some string functions with multi-byte
|
||||
versions */
|
||||
#define strlower(s) strlower_m(s)
|
||||
#define strupper(s) strupper_m(s)
|
||||
|
||||
#endif
|
||||
|
@ -52,7 +52,7 @@ _PUBLIC_ struct hostent *sys_gethostbyname(const char *name)
|
||||
|
||||
/* Does this name have any dots in it? If so, make no change */
|
||||
|
||||
if (strchr_m(name, '.'))
|
||||
if (strchr(name, '.'))
|
||||
return(gethostbyname(name));
|
||||
|
||||
/* Get my hostname, which should have domain name
|
||||
@ -62,7 +62,7 @@ _PUBLIC_ struct hostent *sys_gethostbyname(const char *name)
|
||||
|
||||
gethostname(hostname, sizeof(hostname) - 1);
|
||||
hostname[sizeof(hostname) - 1] = 0;
|
||||
if ((domain = strchr_m(hostname, '.')) == NULL)
|
||||
if ((domain = strchr(hostname, '.')) == NULL)
|
||||
return(gethostbyname(name));
|
||||
|
||||
/* Attach domain name to query and do modified query.
|
||||
|
@ -289,7 +289,7 @@ _PUBLIC_ char* get_myname(void)
|
||||
hostname[host_name_max] = '\0';
|
||||
|
||||
/* split off any parts after an initial . */
|
||||
p = strchr_m(hostname,'.');
|
||||
p = strchr(hostname,'.');
|
||||
|
||||
if (p)
|
||||
*p = 0;
|
||||
@ -311,7 +311,7 @@ _PUBLIC_ BOOL is_ipaddress(const char *str)
|
||||
pure_address = False;
|
||||
|
||||
/* Check that a pure number is not misinterpreted as an IP */
|
||||
pure_address = pure_address && (strchr_m(str, '.') != NULL);
|
||||
pure_address = pure_address && (strchr(str, '.') != NULL);
|
||||
|
||||
return pure_address;
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ _PUBLIC_ void set_socket_options(int fd, const char *options)
|
||||
char *p;
|
||||
BOOL got_value = False;
|
||||
|
||||
if ((p = strchr_m(tok,'='))) {
|
||||
if ((p = strchr(tok,'='))) {
|
||||
*p = 0;
|
||||
value = atoi(p+1);
|
||||
got_value = True;
|
||||
|
@ -23,208 +23,16 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "system/iconv.h"
|
||||
#include "smb.h"
|
||||
#include "pstring.h"
|
||||
#include "lib/ldb/include/ldb.h"
|
||||
#include "system/iconv.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief String utilities.
|
||||
**/
|
||||
|
||||
/**
|
||||
* Get the next token from a string, return False if none found.
|
||||
* Handles double-quotes.
|
||||
*
|
||||
* Based on a routine by GJC@VILLAGE.COM.
|
||||
* Extensively modified by Andrew.Tridgell@anu.edu.au
|
||||
**/
|
||||
_PUBLIC_ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
|
||||
{
|
||||
const char *s;
|
||||
BOOL quoted;
|
||||
size_t len=1;
|
||||
|
||||
if (!ptr)
|
||||
return(False);
|
||||
|
||||
s = *ptr;
|
||||
|
||||
/* default to simple separators */
|
||||
if (!sep)
|
||||
sep = " \t\n\r";
|
||||
|
||||
/* find the first non sep char */
|
||||
while (*s && strchr_m(sep,*s))
|
||||
s++;
|
||||
|
||||
/* nothing left? */
|
||||
if (! *s)
|
||||
return(False);
|
||||
|
||||
/* copy over the token */
|
||||
for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
|
||||
if (*s == '\"') {
|
||||
quoted = !quoted;
|
||||
} else {
|
||||
len++;
|
||||
*buff++ = *s;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = (*s) ? s+1 : s;
|
||||
*buff = 0;
|
||||
|
||||
return(True);
|
||||
}
|
||||
|
||||
/**
|
||||
Case insensitive string compararison
|
||||
**/
|
||||
_PUBLIC_ int strcasecmp_m(const char *s1, const char *s2)
|
||||
{
|
||||
codepoint_t c1=0, c2=0;
|
||||
size_t size1, size2;
|
||||
|
||||
while (*s1 && *s2) {
|
||||
c1 = next_codepoint(s1, &size1);
|
||||
c2 = next_codepoint(s2, &size2);
|
||||
|
||||
s1 += size1;
|
||||
s2 += size2;
|
||||
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c1 == INVALID_CODEPOINT ||
|
||||
c2 == INVALID_CODEPOINT) {
|
||||
/* what else can we do?? */
|
||||
return strcasecmp(s1, s2);
|
||||
}
|
||||
|
||||
if (toupper_w(c1) != toupper_w(c2)) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
|
||||
return *s1 - *s2;
|
||||
}
|
||||
|
||||
/**
|
||||
Case insensitive string compararison, length limited
|
||||
**/
|
||||
_PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
codepoint_t c1=0, c2=0;
|
||||
size_t size1, size2;
|
||||
|
||||
while (*s1 && *s2 && n) {
|
||||
n--;
|
||||
|
||||
c1 = next_codepoint(s1, &size1);
|
||||
c2 = next_codepoint(s2, &size2);
|
||||
|
||||
s1 += size1;
|
||||
s2 += size2;
|
||||
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c1 == INVALID_CODEPOINT ||
|
||||
c2 == INVALID_CODEPOINT) {
|
||||
/* what else can we do?? */
|
||||
return strcasecmp(s1, s2);
|
||||
}
|
||||
|
||||
if (toupper_w(c1) != toupper_w(c2)) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *s1 - *s2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare 2 strings.
|
||||
*
|
||||
* @note The comparison is case-insensitive.
|
||||
**/
|
||||
_PUBLIC_ BOOL strequal(const char *s1, const char *s2)
|
||||
{
|
||||
if (s1 == s2)
|
||||
return(True);
|
||||
if (!s1 || !s2)
|
||||
return(False);
|
||||
|
||||
return strcasecmp_m(s1,s2) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Compare 2 strings (case sensitive).
|
||||
**/
|
||||
_PUBLIC_ BOOL strcsequal(const char *s1,const char *s2)
|
||||
{
|
||||
if (s1 == s2)
|
||||
return(True);
|
||||
if (!s1 || !s2)
|
||||
return(False);
|
||||
|
||||
return strcmp(s1,s2) == 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Do a case-insensitive, whitespace-ignoring string compare.
|
||||
**/
|
||||
_PUBLIC_ int strwicmp(const char *psz1, const char *psz2)
|
||||
{
|
||||
/* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
|
||||
/* appropriate value. */
|
||||
if (psz1 == psz2)
|
||||
return (0);
|
||||
else if (psz1 == NULL)
|
||||
return (-1);
|
||||
else if (psz2 == NULL)
|
||||
return (1);
|
||||
|
||||
/* sync the strings on first non-whitespace */
|
||||
while (1) {
|
||||
while (isspace((int)*psz1))
|
||||
psz1++;
|
||||
while (isspace((int)*psz2))
|
||||
psz2++;
|
||||
if (toupper((unsigned char)*psz1) != toupper((unsigned char)*psz2)
|
||||
|| *psz1 == '\0'
|
||||
|| *psz2 == '\0')
|
||||
break;
|
||||
psz1++;
|
||||
psz2++;
|
||||
}
|
||||
return (*psz1 - *psz2);
|
||||
}
|
||||
|
||||
/**
|
||||
String replace.
|
||||
NOTE: oldc and newc must be 7 bit characters
|
||||
**/
|
||||
_PUBLIC_ void string_replace(char *s, char oldc, char newc)
|
||||
{
|
||||
while (*s) {
|
||||
size_t size;
|
||||
codepoint_t c = next_codepoint(s, &size);
|
||||
if (c == oldc) {
|
||||
*s = newc;
|
||||
}
|
||||
s += size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Trim the specified elements off the front and back of a string.
|
||||
@ -363,52 +171,6 @@ _PUBLIC_ char *safe_strcat(char *dest, const char *src, size_t maxlength)
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
Paranoid strcpy into a buffer of given length (includes terminating
|
||||
zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
|
||||
and replaces with '_'. Deliberately does *NOT* check for multibyte
|
||||
characters. Don't change it !
|
||||
**/
|
||||
|
||||
_PUBLIC_ char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
|
||||
{
|
||||
size_t len, i;
|
||||
|
||||
if (maxlength == 0) {
|
||||
/* can't fit any bytes at all! */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dest) {
|
||||
DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!src) {
|
||||
*dest = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
len = strlen(src);
|
||||
if (len >= maxlength)
|
||||
len = maxlength - 1;
|
||||
|
||||
if (!other_safe_chars)
|
||||
other_safe_chars = "";
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
int val = (src[i] & 0xff);
|
||||
if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
|
||||
dest[i] = src[i];
|
||||
else
|
||||
dest[i] = '_';
|
||||
}
|
||||
|
||||
dest[i] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
Like strncpy but always null terminates. Make sure there is room!
|
||||
The variable n should always be one less than the available size.
|
||||
@ -454,12 +216,12 @@ _PUBLIC_ size_t strhex_to_str(char *p, size_t len, const char *strhex)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(p1 = strchr_m(hexchars, toupper((unsigned char)strhex[i]))))
|
||||
if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i]))))
|
||||
break;
|
||||
|
||||
i++; /* next hex digit */
|
||||
|
||||
if (!(p2 = strchr_m(hexchars, toupper((unsigned char)strhex[i]))))
|
||||
if (!(p2 = strchr(hexchars, toupper((unsigned char)strhex[i]))))
|
||||
break;
|
||||
|
||||
/* get the two nybbles */
|
||||
@ -662,294 +424,6 @@ _PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, siz
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Strchr and strrchr_m are a bit complex on general multi-byte strings.
|
||||
**/
|
||||
_PUBLIC_ char *strchr_m(const char *s, char c)
|
||||
{
|
||||
/* characters below 0x3F are guaranteed to not appear in
|
||||
non-initial position in multi-byte charsets */
|
||||
if ((c & 0xC0) == 0) {
|
||||
return strchr(s, c);
|
||||
}
|
||||
|
||||
while (*s) {
|
||||
size_t size;
|
||||
codepoint_t c2 = next_codepoint(s, &size);
|
||||
if (c2 == c) {
|
||||
return discard_const(s);
|
||||
}
|
||||
s += size;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multibyte-character version of strrchr
|
||||
*/
|
||||
_PUBLIC_ char *strrchr_m(const char *s, char c)
|
||||
{
|
||||
char *ret = NULL;
|
||||
|
||||
/* characters below 0x3F are guaranteed to not appear in
|
||||
non-initial position in multi-byte charsets */
|
||||
if ((c & 0xC0) == 0) {
|
||||
return strrchr(s, c);
|
||||
}
|
||||
|
||||
while (*s) {
|
||||
size_t size;
|
||||
codepoint_t c2 = next_codepoint(s, &size);
|
||||
if (c2 == c) {
|
||||
ret = discard_const(s);
|
||||
}
|
||||
s += size;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
return True if any (multi-byte) character is lower case
|
||||
*/
|
||||
_PUBLIC_ BOOL strhaslower(const char *string)
|
||||
{
|
||||
while (*string) {
|
||||
size_t c_size;
|
||||
codepoint_t s;
|
||||
codepoint_t t;
|
||||
|
||||
s = next_codepoint(string, &c_size);
|
||||
string += c_size;
|
||||
|
||||
t = toupper_w(s);
|
||||
|
||||
if (s != t) {
|
||||
return True; /* that means it has lower case chars */
|
||||
}
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/**
|
||||
return True if any (multi-byte) character is upper case
|
||||
*/
|
||||
_PUBLIC_ BOOL strhasupper(const char *string)
|
||||
{
|
||||
while (*string) {
|
||||
size_t c_size;
|
||||
codepoint_t s;
|
||||
codepoint_t t;
|
||||
|
||||
s = next_codepoint(string, &c_size);
|
||||
string += c_size;
|
||||
|
||||
t = tolower_w(s);
|
||||
|
||||
if (s != t) {
|
||||
return True; /* that means it has upper case chars */
|
||||
}
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a string to lower case, allocated with talloc
|
||||
**/
|
||||
_PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
|
||||
{
|
||||
size_t size=0;
|
||||
char *dest;
|
||||
|
||||
/* this takes advantage of the fact that upper/lower can't
|
||||
change the length of a character by more than 1 byte */
|
||||
dest = talloc_size(ctx, 2*(strlen(src))+1);
|
||||
if (dest == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*src) {
|
||||
size_t c_size;
|
||||
codepoint_t c = next_codepoint(src, &c_size);
|
||||
src += c_size;
|
||||
|
||||
c = tolower_w(c);
|
||||
|
||||
c_size = push_codepoint(dest+size, c);
|
||||
if (c_size == -1) {
|
||||
talloc_free(dest);
|
||||
return NULL;
|
||||
}
|
||||
size += c_size;
|
||||
}
|
||||
|
||||
dest[size] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a string to UPPER case, allocated with talloc
|
||||
**/
|
||||
_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
|
||||
{
|
||||
size_t size=0;
|
||||
char *dest;
|
||||
|
||||
if (!src) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* this takes advantage of the fact that upper/lower can't
|
||||
change the length of a character by more than 1 byte */
|
||||
dest = talloc_size(ctx, 2*(strlen(src))+1);
|
||||
if (dest == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*src) {
|
||||
size_t c_size;
|
||||
codepoint_t c = next_codepoint(src, &c_size);
|
||||
src += c_size;
|
||||
|
||||
c = toupper_w(c);
|
||||
|
||||
c_size = push_codepoint(dest+size, c);
|
||||
if (c_size == -1) {
|
||||
talloc_free(dest);
|
||||
return NULL;
|
||||
}
|
||||
size += c_size;
|
||||
}
|
||||
|
||||
dest[size] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a string to lower case.
|
||||
**/
|
||||
_PUBLIC_ void strlower_m(char *s)
|
||||
{
|
||||
char *d;
|
||||
|
||||
/* this is quite a common operation, so we want it to be
|
||||
fast. We optimise for the ascii case, knowing that all our
|
||||
supported multi-byte character sets are ascii-compatible
|
||||
(ie. they match for the first 128 chars) */
|
||||
while (*s && !(((uint8_t)*s) & 0x80)) {
|
||||
*s = tolower((uint8_t)*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
return;
|
||||
|
||||
d = s;
|
||||
|
||||
while (*s) {
|
||||
size_t c_size, c_size2;
|
||||
codepoint_t c = next_codepoint(s, &c_size);
|
||||
c_size2 = push_codepoint(d, tolower_w(c));
|
||||
if (c_size2 > c_size) {
|
||||
DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
|
||||
c, tolower_w(c), (int)c_size, (int)c_size2));
|
||||
smb_panic("codepoint expansion in strlower_m\n");
|
||||
}
|
||||
s += c_size;
|
||||
d += c_size2;
|
||||
}
|
||||
*d = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a string to UPPER case.
|
||||
**/
|
||||
_PUBLIC_ void strupper_m(char *s)
|
||||
{
|
||||
char *d;
|
||||
|
||||
/* this is quite a common operation, so we want it to be
|
||||
fast. We optimise for the ascii case, knowing that all our
|
||||
supported multi-byte character sets are ascii-compatible
|
||||
(ie. they match for the first 128 chars) */
|
||||
while (*s && !(((uint8_t)*s) & 0x80)) {
|
||||
*s = toupper((uint8_t)*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
return;
|
||||
|
||||
d = s;
|
||||
|
||||
while (*s) {
|
||||
size_t c_size, c_size2;
|
||||
codepoint_t c = next_codepoint(s, &c_size);
|
||||
c_size2 = push_codepoint(d, toupper_w(c));
|
||||
if (c_size2 > c_size) {
|
||||
DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
|
||||
c, toupper_w(c), (int)c_size, (int)c_size2));
|
||||
smb_panic("codepoint expansion in strupper_m\n");
|
||||
}
|
||||
s += c_size;
|
||||
d += c_size2;
|
||||
}
|
||||
*d = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Count the number of UCS2 characters in a string. Normally this will
|
||||
be the same as the number of bytes in a string for single byte strings,
|
||||
but will be different for multibyte.
|
||||
**/
|
||||
_PUBLIC_ size_t strlen_m(const char *s)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (*s && !(((uint8_t)*s) & 0x80)) {
|
||||
s++;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!*s) {
|
||||
return count;
|
||||
}
|
||||
|
||||
while (*s) {
|
||||
size_t c_size;
|
||||
codepoint_t c = next_codepoint(s, &c_size);
|
||||
if (c < 0x10000) {
|
||||
count += 1;
|
||||
} else {
|
||||
count += 2;
|
||||
}
|
||||
s += c_size;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
Work out the number of multibyte chars in a string, including the NULL
|
||||
terminator.
|
||||
**/
|
||||
_PUBLIC_ size_t strlen_m_term(const char *s)
|
||||
{
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return strlen_m(s) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Unescape a URL encoded string, in place.
|
||||
@ -991,32 +465,6 @@ _PUBLIC_ void rfc1738_unescape(char *buf)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a base64 string into a DATA_BLOB - simple and slow algorithm
|
||||
**/
|
||||
_PUBLIC_ DATA_BLOB base64_decode_data_blob(TALLOC_CTX *mem_ctx, const char *s)
|
||||
{
|
||||
DATA_BLOB ret = data_blob_talloc(mem_ctx, s, strlen(s)+1);
|
||||
ret.length = ldb_base64_decode((char *)ret.data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a base64 string in-place - wrapper for the above
|
||||
**/
|
||||
_PUBLIC_ void base64_decode_inplace(char *s)
|
||||
{
|
||||
ldb_base64_decode(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a base64 string into a talloc()ed string caller to free.
|
||||
**/
|
||||
_PUBLIC_ char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data)
|
||||
{
|
||||
return ldb_base64_encode(mem_ctx, (const char *)data.data, data.length);
|
||||
}
|
||||
|
||||
#ifdef VALGRIND
|
||||
size_t valgrind_strlen(const char *s)
|
||||
{
|
||||
@ -1274,3 +722,97 @@ _PUBLIC_ BOOL conv_str_u64(const char * str, uint64_t * val)
|
||||
*val = (uint64_t)lval;
|
||||
return True;
|
||||
}
|
||||
|
||||
/**
|
||||
return the number of bytes occupied by a buffer in CH_UTF16 format
|
||||
the result includes the null termination
|
||||
**/
|
||||
_PUBLIC_ size_t utf16_len(const void *buf)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
for (len = 0; SVAL(buf,len); len += 2) ;
|
||||
|
||||
return len + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
return the number of bytes occupied by a buffer in CH_UTF16 format
|
||||
the result includes the null termination
|
||||
limited by 'n' bytes
|
||||
**/
|
||||
_PUBLIC_ size_t utf16_len_n(const void *src, size_t n)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
|
||||
|
||||
if (len+2 <= n) {
|
||||
len += 2;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
_PUBLIC_ size_t ucs2_align(const void *base_ptr, const void *p, int flags)
|
||||
{
|
||||
if (flags & (STR_NOALIGN|STR_ASCII))
|
||||
return 0;
|
||||
return PTR_DIFF(p, base_ptr) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Do a case-insensitive, whitespace-ignoring string compare.
|
||||
**/
|
||||
_PUBLIC_ int strwicmp(const char *psz1, const char *psz2)
|
||||
{
|
||||
/* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
|
||||
/* appropriate value. */
|
||||
if (psz1 == psz2)
|
||||
return (0);
|
||||
else if (psz1 == NULL)
|
||||
return (-1);
|
||||
else if (psz2 == NULL)
|
||||
return (1);
|
||||
|
||||
/* sync the strings on first non-whitespace */
|
||||
while (1) {
|
||||
while (isspace((int)*psz1))
|
||||
psz1++;
|
||||
while (isspace((int)*psz2))
|
||||
psz2++;
|
||||
if (toupper((unsigned char)*psz1) != toupper((unsigned char)*psz2)
|
||||
|| *psz1 == '\0'
|
||||
|| *psz2 == '\0')
|
||||
break;
|
||||
psz1++;
|
||||
psz2++;
|
||||
}
|
||||
return (*psz1 - *psz2);
|
||||
}
|
||||
|
||||
/**
|
||||
String replace.
|
||||
**/
|
||||
_PUBLIC_ void string_replace(char *s, char oldc, char newc)
|
||||
{
|
||||
while (*s) {
|
||||
s++;
|
||||
if (*s == oldc) *s = newc;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare 2 strings.
|
||||
*
|
||||
* @note The comparison is case-insensitive.
|
||||
**/
|
||||
_PUBLIC_ BOOL strequal(const char *s1, const char *s2)
|
||||
{
|
||||
if (s1 == s2)
|
||||
return(True);
|
||||
if (!s1 || !s2)
|
||||
return(False);
|
||||
|
||||
return strcasecmp(s1,s2) == 0;
|
||||
}
|
||||
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Samba utility functions
|
||||
Copyright (C) Andrew Tridgell 1992-2001
|
||||
Copyright (C) Simo Sorce 2001
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "system/iconv.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Unicode string manipulation
|
||||
*/
|
||||
|
||||
/* these 2 tables define the unicode case handling. They are loaded
|
||||
at startup either via mmap() or read() from the lib directory */
|
||||
static void *upcase_table;
|
||||
static void *lowcase_table;
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
load the case handling tables
|
||||
********************************************************************/
|
||||
static void load_case_tables(void)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
mem_ctx = talloc_init("load_case_tables");
|
||||
if (!mem_ctx) {
|
||||
smb_panic("No memory for case_tables");
|
||||
}
|
||||
upcase_table = map_file(data_path(mem_ctx, "upcase.dat"), 0x20000);
|
||||
lowcase_table = map_file(data_path(mem_ctx, "lowcase.dat"), 0x20000);
|
||||
talloc_free(mem_ctx);
|
||||
if (upcase_table == NULL) {
|
||||
/* try also under codepages for testing purposes */
|
||||
upcase_table = map_file("codepages/upcase.dat", 0x20000);
|
||||
if (upcase_table == NULL) {
|
||||
upcase_table = (void *)-1;
|
||||
}
|
||||
}
|
||||
if (lowcase_table == NULL) {
|
||||
/* try also under codepages for testing purposes */
|
||||
lowcase_table = map_file("codepages/lowcase.dat", 0x20000);
|
||||
if (lowcase_table == NULL) {
|
||||
lowcase_table = (void *)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a codepoint_t to upper case.
|
||||
**/
|
||||
codepoint_t toupper_w(codepoint_t val)
|
||||
{
|
||||
if (val < 128) {
|
||||
return toupper(val);
|
||||
}
|
||||
if (upcase_table == NULL) {
|
||||
load_case_tables();
|
||||
}
|
||||
if (upcase_table == (void *)-1) {
|
||||
return val;
|
||||
}
|
||||
if (val & 0xFFFF0000) {
|
||||
return val;
|
||||
}
|
||||
return SVAL(upcase_table, val*2);
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a codepoint_t to lower case.
|
||||
**/
|
||||
codepoint_t tolower_w(codepoint_t val)
|
||||
{
|
||||
if (val < 128) {
|
||||
return tolower(val);
|
||||
}
|
||||
if (lowcase_table == NULL) {
|
||||
load_case_tables();
|
||||
}
|
||||
if (lowcase_table == (void *)-1) {
|
||||
return val;
|
||||
}
|
||||
if (val & 0xFFFF0000) {
|
||||
return val;
|
||||
}
|
||||
return SVAL(lowcase_table, val*2);
|
||||
}
|
||||
|
||||
/**
|
||||
return the number of bytes occupied by a buffer in CH_UTF16 format
|
||||
the result includes the null termination
|
||||
**/
|
||||
size_t utf16_len(const void *buf)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
for (len = 0; SVAL(buf,len); len += 2) ;
|
||||
|
||||
return len + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
return the number of bytes occupied by a buffer in CH_UTF16 format
|
||||
the result includes the null termination
|
||||
limited by 'n' bytes
|
||||
**/
|
||||
size_t utf16_len_n(const void *src, size_t n)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
|
||||
|
||||
if (len+2 <= n) {
|
||||
len += 2;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
size_t ucs2_align(const void *base_ptr, const void *p, int flags)
|
||||
{
|
||||
if (flags & (STR_NOALIGN|STR_ASCII))
|
||||
return 0;
|
||||
return PTR_DIFF(p, base_ptr) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
compare two codepoints case insensitively
|
||||
*/
|
||||
int codepoint_cmpi(codepoint_t c1, codepoint_t c2)
|
||||
{
|
||||
if (c1 == c2 ||
|
||||
toupper_w(c1) == toupper_w(c2)) {
|
||||
return 0;
|
||||
}
|
||||
return c1 - c2;
|
||||
}
|
Loading…
Reference in New Issue
Block a user