feat:replace boost library with C++11 std library
This commit is contained in:
+80
@@ -0,0 +1,80 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Usage Notes:
|
||||
*
|
||||
* this module, and the misc/win32/utf8.c modules must be
|
||||
* compiled APR_EXPORT_STATIC and linked to an application with
|
||||
* the /entry:wmainCRTStartup flag (which this module kindly
|
||||
* provides to the developer who links to libaprapp-1.lib).
|
||||
* This module becomes the true wmain entry point, and passes
|
||||
* utf-8 reformatted argv and env arrays to the application's
|
||||
* main() function as if nothing happened.
|
||||
*
|
||||
* This module is only compatible with Unicode operating systems.
|
||||
* Mixed (Win9x backwards compatible) binaries should refer instead
|
||||
* to the apr_startup.c module.
|
||||
*
|
||||
* _dbg_malloc/realloc is used in place of the usual API, in order
|
||||
* to convince the MSVCRT that it created these entities. If we
|
||||
* do not create them as _CRT_BLOCK entities, the crt will fault
|
||||
* on an assert. We are not worrying about the crt's locks here,
|
||||
* since we are single threaded [so far].
|
||||
*/
|
||||
|
||||
#include "apr_general.h"
|
||||
#include "ShellAPI.h"
|
||||
#include "wchar.h"
|
||||
#include "apr_arch_file_io.h"
|
||||
#include "assert.h"
|
||||
#include "apr_private.h"
|
||||
#include "apr_arch_misc.h"
|
||||
|
||||
#pragma comment(linker,"/ENTRY:wmainCRTStartup")
|
||||
|
||||
extern int main(int argc, const char **argv, const char **env);
|
||||
|
||||
int wmain(int argc, const wchar_t **wargv, const wchar_t **wenv)
|
||||
{
|
||||
char **argv;
|
||||
char **env;
|
||||
int dupenv;
|
||||
|
||||
(void)apr_wastrtoastr(&argv, wargv, argc);
|
||||
|
||||
dupenv = apr_wastrtoastr(&env, wenv, -1);
|
||||
|
||||
_environ = apr_malloc_dbg((dupenv + 1) * sizeof (char *),
|
||||
__FILE__, __LINE__ );
|
||||
memcpy(_environ, env, (dupenv + 1) * sizeof (char *));
|
||||
|
||||
/* MSVCRT will attempt to maintain the wide environment calls
|
||||
* on _putenv(), which is bogus if we've passed a non-ascii
|
||||
* string to _putenv(), since they use MultiByteToWideChar
|
||||
* and breaking the implicit utf-8 assumption we've built.
|
||||
*
|
||||
* Reset _wenviron for good measure.
|
||||
*/
|
||||
if (_wenviron) {
|
||||
wenv = _wenviron;
|
||||
_wenviron = NULL;
|
||||
free((wchar_t **)wenv);
|
||||
}
|
||||
|
||||
apr_app_init_complete = 1;
|
||||
|
||||
return main(argc, argv, env);
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_portable.h"
|
||||
|
||||
|
||||
APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool)
|
||||
{
|
||||
return apr_psprintf(pool, "CP%u", (unsigned) GetACP());
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(const char*) apr_os_locale_encoding (apr_pool_t *pool)
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
int i;
|
||||
#endif
|
||||
#if defined(_WIN32_WCE)
|
||||
LCID locale = GetUserDefaultLCID();
|
||||
#else
|
||||
LCID locale = GetThreadLocale();
|
||||
#endif
|
||||
int len = GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, NULL, 0);
|
||||
char *cp = apr_palloc(pool, (len * sizeof(TCHAR)) + 2);
|
||||
if (0 < GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, (TCHAR*) (cp + 2), len))
|
||||
{
|
||||
/* Fix up the returned number to make a valid codepage name of
|
||||
the form "CPnnnn". */
|
||||
cp[0] = 'C';
|
||||
cp[1] = 'P';
|
||||
#ifdef _UNICODE
|
||||
for(i = 0; i < len; i++) {
|
||||
cp[i + 2] = (char) ((TCHAR*) (cp + 2))[i];
|
||||
}
|
||||
#endif
|
||||
return cp;
|
||||
}
|
||||
|
||||
return apr_os_default_encoding(pool);
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define APR_WANT_STRFUNC
|
||||
#include "apr_want.h"
|
||||
#include "apr.h"
|
||||
#include "apr_arch_misc.h"
|
||||
#include "apr_arch_utf8.h"
|
||||
#include "apr_env.h"
|
||||
#include "apr_errno.h"
|
||||
#include "apr_pools.h"
|
||||
#include "apr_strings.h"
|
||||
|
||||
#if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE)
|
||||
static apr_status_t widen_envvar_name (apr_wchar_t *buffer,
|
||||
apr_size_t bufflen,
|
||||
const char *envvar)
|
||||
{
|
||||
apr_size_t inchars;
|
||||
apr_status_t status;
|
||||
|
||||
inchars = strlen(envvar) + 1;
|
||||
status = apr_conv_utf8_to_ucs2(envvar, &inchars, buffer, &bufflen);
|
||||
if (status == APR_INCOMPLETE)
|
||||
status = APR_ENAMETOOLONG;
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_env_get(char **value,
|
||||
const char *envvar,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
return APR_ENOTIMPL;
|
||||
#else
|
||||
char *val = NULL;
|
||||
DWORD size;
|
||||
|
||||
#if APR_HAS_UNICODE_FS
|
||||
IF_WIN_OS_IS_UNICODE
|
||||
{
|
||||
apr_wchar_t wenvvar[APR_PATH_MAX];
|
||||
apr_size_t inchars, outchars;
|
||||
apr_wchar_t *wvalue, dummy;
|
||||
apr_status_t status;
|
||||
|
||||
status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
SetLastError(0);
|
||||
size = GetEnvironmentVariableW(wenvvar, &dummy, 0);
|
||||
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
|
||||
/* The environment variable doesn't exist. */
|
||||
return APR_ENOENT;
|
||||
|
||||
if (size == 0) {
|
||||
/* The environment value exists, but is zero-length. */
|
||||
*value = apr_pstrdup(pool, "");
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
wvalue = apr_palloc(pool, size * sizeof(*wvalue));
|
||||
size = GetEnvironmentVariableW(wenvvar, wvalue, size);
|
||||
|
||||
inchars = wcslen(wvalue) + 1;
|
||||
outchars = 3 * inchars; /* Enough for any UTF-8 representation */
|
||||
val = apr_palloc(pool, outchars);
|
||||
status = apr_conv_ucs2_to_utf8(wvalue, &inchars, val, &outchars);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
#if APR_HAS_ANSI_FS
|
||||
ELSE_WIN_OS_IS_ANSI
|
||||
{
|
||||
char dummy;
|
||||
|
||||
SetLastError(0);
|
||||
size = GetEnvironmentVariableA(envvar, &dummy, 0);
|
||||
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
|
||||
/* The environment variable doesn't exist. */
|
||||
return APR_ENOENT;
|
||||
|
||||
if (size == 0) {
|
||||
/* The environment value exists, but is zero-length. */
|
||||
*value = apr_pstrdup(pool, "");
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
val = apr_palloc(pool, size);
|
||||
size = GetEnvironmentVariableA(envvar, val, size);
|
||||
if (size == 0)
|
||||
/* Mid-air collision?. Somebody must've changed the env. var. */
|
||||
return APR_INCOMPLETE;
|
||||
}
|
||||
#endif
|
||||
|
||||
*value = val;
|
||||
return APR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_env_set(const char *envvar,
|
||||
const char *value,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
return APR_ENOTIMPL;
|
||||
#else
|
||||
#if APR_HAS_UNICODE_FS
|
||||
IF_WIN_OS_IS_UNICODE
|
||||
{
|
||||
apr_wchar_t wenvvar[APR_PATH_MAX];
|
||||
apr_wchar_t *wvalue;
|
||||
apr_size_t inchars, outchars;
|
||||
apr_status_t status;
|
||||
|
||||
status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
outchars = inchars = strlen(value) + 1;
|
||||
wvalue = apr_palloc(pool, outchars * sizeof(*wvalue));
|
||||
status = apr_conv_utf8_to_ucs2(value, &inchars, wvalue, &outchars);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (!SetEnvironmentVariableW(wenvvar, wvalue))
|
||||
return apr_get_os_error();
|
||||
}
|
||||
#endif
|
||||
#if APR_HAS_ANSI_FS
|
||||
ELSE_WIN_OS_IS_ANSI
|
||||
{
|
||||
if (!SetEnvironmentVariableA(envvar, value))
|
||||
return apr_get_os_error();
|
||||
}
|
||||
#endif
|
||||
|
||||
return APR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_env_delete(const char *envvar, apr_pool_t *pool)
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
return APR_ENOTIMPL;
|
||||
#else
|
||||
#if APR_HAS_UNICODE_FS
|
||||
IF_WIN_OS_IS_UNICODE
|
||||
{
|
||||
apr_wchar_t wenvvar[APR_PATH_MAX];
|
||||
apr_status_t status;
|
||||
|
||||
status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (!SetEnvironmentVariableW(wenvvar, NULL))
|
||||
return apr_get_os_error();
|
||||
}
|
||||
#endif
|
||||
#if APR_HAS_ANSI_FS
|
||||
ELSE_WIN_OS_IS_ANSI
|
||||
{
|
||||
if (!SetEnvironmentVariableA(envvar, NULL))
|
||||
return apr_get_os_error();
|
||||
}
|
||||
#endif
|
||||
|
||||
return APR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_private.h"
|
||||
|
||||
#include "apr_arch_misc.h"
|
||||
#include "apr_arch_file_io.h"
|
||||
#include <assert.h>
|
||||
|
||||
/* This module is the source of -static- helper functions that are
|
||||
* entirely internal to apr. If the fn is exported - it does not
|
||||
* belong here.
|
||||
*
|
||||
* Namespace decoration is still required to protect us from symbol
|
||||
* clashes in static linkages.
|
||||
*/
|
||||
|
||||
|
||||
/* Shared by apr_app.c and start.c
|
||||
*
|
||||
* An internal apr function to convert an array of strings (either
|
||||
* a counted or NULL terminated list, such as an argv[argc] or env[]
|
||||
* list respectively) from wide Unicode strings to narrow utf-8 strings.
|
||||
* These are allocated from the MSVCRT's _CRT_BLOCK to trick the system
|
||||
* into trusting our store.
|
||||
*/
|
||||
int apr_wastrtoastr(char const * const * *retarr,
|
||||
wchar_t const * const *arr, int args)
|
||||
{
|
||||
apr_size_t elesize = 0;
|
||||
char **newarr;
|
||||
char *elements;
|
||||
char *ele;
|
||||
int arg;
|
||||
|
||||
if (args < 0) {
|
||||
for (args = 0; arr[args]; ++args)
|
||||
;
|
||||
}
|
||||
|
||||
newarr = apr_malloc_dbg((args + 1) * sizeof(char *),
|
||||
__FILE__, __LINE__);
|
||||
|
||||
for (arg = 0; arg < args; ++arg) {
|
||||
newarr[arg] = (void*)(wcslen(arr[arg]) + 1);
|
||||
elesize += (apr_size_t)newarr[arg];
|
||||
}
|
||||
|
||||
/* This is a safe max allocation, we will realloc after
|
||||
* processing and return the excess to the free store.
|
||||
* 3 ucs bytes hold any single wchar_t value (16 bits)
|
||||
* 4 ucs bytes will hold a wchar_t pair value (20 bits)
|
||||
*/
|
||||
elesize = elesize * 3 + 1;
|
||||
ele = elements = apr_malloc_dbg(elesize * sizeof(char),
|
||||
__FILE__, __LINE__);
|
||||
|
||||
for (arg = 0; arg < args; ++arg) {
|
||||
apr_size_t len = (apr_size_t)newarr[arg];
|
||||
apr_size_t newlen = elesize;
|
||||
|
||||
newarr[arg] = ele;
|
||||
(void)apr_conv_ucs2_to_utf8(arr[arg], &len,
|
||||
newarr[arg], &elesize);
|
||||
|
||||
newlen -= elesize;
|
||||
ele += newlen;
|
||||
assert(elesize && (len == 0));
|
||||
}
|
||||
|
||||
newarr[arg] = NULL;
|
||||
*(ele++) = '\0';
|
||||
|
||||
/* Return to the free store if the heap realloc is the least bit optimized
|
||||
*/
|
||||
ele = apr_realloc_dbg(elements, ele - elements,
|
||||
__FILE__, __LINE__);
|
||||
|
||||
if (ele != elements) {
|
||||
apr_size_t diff = ele - elements;
|
||||
for (arg = 0; arg < args; ++arg) {
|
||||
newarr[arg] += diff;
|
||||
}
|
||||
}
|
||||
|
||||
*retarr = (char const * const *)newarr;
|
||||
return args;
|
||||
}
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_private.h"
|
||||
#include "apr_arch_misc.h"
|
||||
#include "apr_arch_file_io.h"
|
||||
#include "assert.h"
|
||||
#include "apr_lib.h"
|
||||
#include "tchar.h"
|
||||
|
||||
APR_DECLARE_DATA apr_oslevel_e apr_os_level = APR_WIN_UNK;
|
||||
|
||||
apr_status_t apr_get_oslevel(apr_oslevel_e *level)
|
||||
{
|
||||
if (apr_os_level == APR_WIN_UNK)
|
||||
{
|
||||
static OSVERSIONINFO oslev;
|
||||
oslev.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&oslev);
|
||||
|
||||
if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
||||
{
|
||||
static unsigned int servpack = 0;
|
||||
TCHAR *pservpack;
|
||||
if ((pservpack = oslev.szCSDVersion)) {
|
||||
while (*pservpack && !apr_isdigit(*pservpack)) {
|
||||
pservpack++;
|
||||
}
|
||||
if (*pservpack)
|
||||
#ifdef _UNICODE
|
||||
servpack = _wtoi(pservpack);
|
||||
#else
|
||||
servpack = atoi(pservpack);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (oslev.dwMajorVersion < 3) {
|
||||
apr_os_level = APR_WIN_UNSUP;
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 3) {
|
||||
if (oslev.dwMajorVersion < 50) {
|
||||
apr_os_level = APR_WIN_UNSUP;
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 50) {
|
||||
apr_os_level = APR_WIN_NT_3_5;
|
||||
}
|
||||
else {
|
||||
apr_os_level = APR_WIN_NT_3_51;
|
||||
}
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 4) {
|
||||
if (servpack < 2)
|
||||
apr_os_level = APR_WIN_NT_4;
|
||||
else if (servpack <= 2)
|
||||
apr_os_level = APR_WIN_NT_4_SP2;
|
||||
else if (servpack <= 3)
|
||||
apr_os_level = APR_WIN_NT_4_SP3;
|
||||
else if (servpack <= 4)
|
||||
apr_os_level = APR_WIN_NT_4_SP4;
|
||||
else if (servpack <= 5)
|
||||
apr_os_level = APR_WIN_NT_4_SP5;
|
||||
else
|
||||
apr_os_level = APR_WIN_NT_4_SP6;
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 5) {
|
||||
if (oslev.dwMinorVersion == 0) {
|
||||
if (servpack == 0)
|
||||
apr_os_level = APR_WIN_2000;
|
||||
else if (servpack == 1)
|
||||
apr_os_level = APR_WIN_2000_SP1;
|
||||
else
|
||||
apr_os_level = APR_WIN_2000_SP2;
|
||||
}
|
||||
else if (oslev.dwMinorVersion == 2) {
|
||||
apr_os_level = APR_WIN_2003;
|
||||
}
|
||||
else {
|
||||
if (servpack < 1)
|
||||
apr_os_level = APR_WIN_XP;
|
||||
else if (servpack == 1)
|
||||
apr_os_level = APR_WIN_XP_SP1;
|
||||
else
|
||||
apr_os_level = APR_WIN_XP_SP2;
|
||||
}
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 6) {
|
||||
if (oslev.dwMinorVersion == 0)
|
||||
apr_os_level = APR_WIN_VISTA;
|
||||
else
|
||||
apr_os_level = APR_WIN_7;
|
||||
}
|
||||
else {
|
||||
apr_os_level = APR_WIN_XP;
|
||||
}
|
||||
}
|
||||
#ifndef WINNT
|
||||
else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
|
||||
TCHAR *prevision;
|
||||
if (prevision = oslev.szCSDVersion) {
|
||||
while (*prevision && !apr_isupper(*prevision)) {
|
||||
prevision++;
|
||||
}
|
||||
}
|
||||
else prevision = _T("");
|
||||
|
||||
if (oslev.dwMinorVersion < 10) {
|
||||
if (*prevision < _T('C'))
|
||||
apr_os_level = APR_WIN_95;
|
||||
else
|
||||
apr_os_level = APR_WIN_95_OSR2;
|
||||
}
|
||||
else if (oslev.dwMinorVersion < 90) {
|
||||
if (*prevision < _T('A'))
|
||||
apr_os_level = APR_WIN_98;
|
||||
else
|
||||
apr_os_level = APR_WIN_98_SE;
|
||||
}
|
||||
else {
|
||||
apr_os_level = APR_WIN_ME;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef _WIN32_WCE
|
||||
else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_CE)
|
||||
{
|
||||
if (oslev.dwMajorVersion < 3) {
|
||||
apr_os_level = APR_WIN_UNSUP;
|
||||
}
|
||||
else {
|
||||
apr_os_level = APR_WIN_CE_3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
apr_os_level = APR_WIN_UNSUP;
|
||||
}
|
||||
}
|
||||
|
||||
*level = apr_os_level;
|
||||
|
||||
if (apr_os_level < APR_WIN_UNSUP) {
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* This is the helper code to resolve late bound entry points
|
||||
* missing from one or more releases of the Win32 API
|
||||
*/
|
||||
|
||||
static const char* const lateDllName[DLL_defined] = {
|
||||
"kernel32", "advapi32", "mswsock", "ws2_32", "shell32", "ntdll.dll" };
|
||||
static HMODULE lateDllHandle[DLL_defined] = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
|
||||
FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal)
|
||||
{
|
||||
if (!lateDllHandle[fnLib]) {
|
||||
lateDllHandle[fnLib] = LoadLibraryA(lateDllName[fnLib]);
|
||||
if (!lateDllHandle[fnLib])
|
||||
return NULL;
|
||||
}
|
||||
#if defined(_WIN32_WCE)
|
||||
if (ordinal)
|
||||
return GetProcAddressA(lateDllHandle[fnLib], (const char *)
|
||||
(apr_ssize_t)ordinal);
|
||||
else
|
||||
return GetProcAddressA(lateDllHandle[fnLib], fnName);
|
||||
#else
|
||||
if (ordinal)
|
||||
return GetProcAddress(lateDllHandle[fnLib], (const char *)
|
||||
(apr_ssize_t)ordinal);
|
||||
else
|
||||
return GetProcAddress(lateDllHandle[fnLib], fnName);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Declared in include/arch/win32/apr_dbg_win32_handles.h
|
||||
*/
|
||||
APR_DECLARE_NONSTD(HANDLE) apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln,
|
||||
int nh, /* HANDLE hv, char *dsc */...)
|
||||
{
|
||||
static DWORD tlsid = 0xFFFFFFFF;
|
||||
static HANDLE fh = NULL;
|
||||
static long ctr = 0;
|
||||
static CRITICAL_SECTION cs;
|
||||
long seq;
|
||||
DWORD wrote;
|
||||
char *sbuf;
|
||||
|
||||
seq = (InterlockedIncrement)(&ctr);
|
||||
|
||||
if (tlsid == 0xFFFFFFFF) {
|
||||
tlsid = (TlsAlloc)();
|
||||
}
|
||||
|
||||
sbuf = (TlsGetValue)(tlsid);
|
||||
if (!fh || !sbuf) {
|
||||
sbuf = (malloc)(1024);
|
||||
(TlsSetValue)(tlsid, sbuf);
|
||||
sbuf[1023] = '\0';
|
||||
if (!fh) {
|
||||
(GetModuleFileNameA)(NULL, sbuf, 250);
|
||||
sprintf(strchr(sbuf, '\0'), ".%u",
|
||||
(unsigned int)(GetCurrentProcessId)());
|
||||
fh = (CreateFileA)(sbuf, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, 0, NULL);
|
||||
(InitializeCriticalSection)(&cs);
|
||||
}
|
||||
}
|
||||
|
||||
if (!nh) {
|
||||
(sprintf)(sbuf, "%p %08x %08x %s() %s:%d\n",
|
||||
ha, (unsigned int)seq, (unsigned int)GetCurrentThreadId(),
|
||||
fn, fl, ln);
|
||||
(EnterCriticalSection)(&cs);
|
||||
(WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL);
|
||||
(LeaveCriticalSection)(&cs);
|
||||
}
|
||||
else {
|
||||
va_list a;
|
||||
va_start(a,nh);
|
||||
(EnterCriticalSection)(&cs);
|
||||
do {
|
||||
HANDLE *hv = va_arg(a, HANDLE*);
|
||||
char *dsc = va_arg(a, char*);
|
||||
if (strcmp(dsc, "Signaled") == 0) {
|
||||
if ((apr_ssize_t)ha >= STATUS_WAIT_0
|
||||
&& (apr_ssize_t)ha < STATUS_ABANDONED_WAIT_0) {
|
||||
hv += (apr_ssize_t)ha;
|
||||
}
|
||||
else if ((apr_ssize_t)ha >= STATUS_ABANDONED_WAIT_0
|
||||
&& (apr_ssize_t)ha < STATUS_USER_APC) {
|
||||
hv += (apr_ssize_t)ha - STATUS_ABANDONED_WAIT_0;
|
||||
dsc = "Abandoned";
|
||||
}
|
||||
else if ((apr_ssize_t)ha == WAIT_TIMEOUT) {
|
||||
dsc = "Timed Out";
|
||||
}
|
||||
}
|
||||
(sprintf)(sbuf, "%p %08x %08x %s(%s) %s:%d\n",
|
||||
*hv, (unsigned int)seq,
|
||||
(unsigned int)GetCurrentThreadId(),
|
||||
fn, dsc, fl, ln);
|
||||
(WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL);
|
||||
} while (--nh);
|
||||
(LeaveCriticalSection)(&cs);
|
||||
va_end(a);
|
||||
}
|
||||
return ha;
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include <rpc.h>
|
||||
#include <wincrypt.h>
|
||||
#include "apr_private.h"
|
||||
#include "apr_general.h"
|
||||
#include "apr_portable.h"
|
||||
#include "apr_arch_misc.h"
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf,
|
||||
apr_size_t length)
|
||||
{
|
||||
HCRYPTPROV hProv;
|
||||
apr_status_t res = APR_SUCCESS;
|
||||
|
||||
/* 0x40 bit = CRYPT_SILENT, only introduced in more recent PSDKs
|
||||
* and will only work for Win2K and later.
|
||||
*/
|
||||
DWORD flags = CRYPT_VERIFYCONTEXT
|
||||
| ((apr_os_level >= APR_WIN_2000) ? 0x40 : 0);
|
||||
|
||||
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, flags)) {
|
||||
return apr_get_os_error();
|
||||
}
|
||||
/* XXX: An ugly hack for Win64, randomness is such that noone should
|
||||
* ever expect > 2^31 bytes of data at once without the prng
|
||||
* coming to a complete halt.
|
||||
*/
|
||||
if (!CryptGenRandom(hProv, (DWORD)length, buf)) {
|
||||
res = apr_get_os_error();
|
||||
}
|
||||
CryptReleaseContext(hProv, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
|
||||
{
|
||||
/* Note: this call doesn't actually require CoInitialize() first
|
||||
*
|
||||
* XXX: we should scramble the bytes or some such to eliminate the
|
||||
* possible misuse/abuse since uuid is based on the NIC address, and
|
||||
* is therefore not only a uniqifier, but an identity (which might not
|
||||
* be appropriate in all cases.
|
||||
*
|
||||
* Note that Win2000, XP and later no longer suffer from this problem,
|
||||
* a scrambling fix is only needed for (apr_os_level < APR_WIN_2000)
|
||||
*/
|
||||
if (FAILED(UuidCreate((UUID *)uuid_data))) {
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_private.h"
|
||||
#include "apr_general.h"
|
||||
#include "apr_pools.h"
|
||||
#include "apr_signal.h"
|
||||
#include "shellapi.h"
|
||||
|
||||
#include "apr_arch_misc.h" /* for WSAHighByte / WSALowByte */
|
||||
#include "wchar.h"
|
||||
#include "apr_arch_file_io.h" /* bring in unicode-ness */
|
||||
#include "apr_arch_threadproc.h" /* bring in apr_threadproc_init */
|
||||
#include "assert.h"
|
||||
|
||||
/* This symbol is _private_, although it must be exported.
|
||||
*/
|
||||
int APR_DECLARE_DATA apr_app_init_complete = 0;
|
||||
|
||||
#if !defined(_WIN32_WCE)
|
||||
/* Used by apr_app_initialize to reprocess the environment
|
||||
*
|
||||
* An internal apr function to convert a double-null terminated set
|
||||
* of single-null terminated strings from wide Unicode to narrow utf-8
|
||||
* as a list of strings. These are allocated from the MSVCRT's
|
||||
* _CRT_BLOCK to trick the system into trusting our store.
|
||||
*/
|
||||
static int warrsztoastr(const char * const * *retarr,
|
||||
const wchar_t * arrsz)
|
||||
{
|
||||
const apr_wchar_t *wch;
|
||||
apr_size_t totlen;
|
||||
apr_size_t newlen;
|
||||
apr_size_t wsize;
|
||||
char **env;
|
||||
char *pstrs;
|
||||
char *strs;
|
||||
int arg, args;
|
||||
|
||||
for (args = 1, wch = arrsz; wch[0] || wch[1]; ++wch)
|
||||
if (!*wch)
|
||||
++args;
|
||||
wsize = 1 + wch - arrsz;
|
||||
|
||||
/* This is a safe max allocation, we will alloc each
|
||||
* string exactly after processing and return this
|
||||
* temporary buffer to the free store.
|
||||
* 3 ucs bytes hold any single wchar_t value (16 bits)
|
||||
* 4 ucs bytes will hold a wchar_t pair value (20 bits)
|
||||
*/
|
||||
newlen = totlen = wsize * 3 + 1;
|
||||
pstrs = strs = apr_malloc_dbg(newlen * sizeof(char),
|
||||
__FILE__, __LINE__);
|
||||
|
||||
(void)apr_conv_ucs2_to_utf8(arrsz, &wsize, strs, &newlen);
|
||||
|
||||
assert(newlen && !wsize);
|
||||
|
||||
*retarr = env = apr_malloc_dbg((args + 1) * sizeof(char*),
|
||||
__FILE__, __LINE__);
|
||||
for (arg = 0; arg < args; ++arg) {
|
||||
char* p = pstrs;
|
||||
int len = 0;
|
||||
while (*p++)
|
||||
++len;
|
||||
len += 1;
|
||||
|
||||
*env = apr_malloc_dbg(len * sizeof(char),
|
||||
__FILE__, __LINE__);
|
||||
memcpy(*env, pstrs, len * sizeof(char));
|
||||
|
||||
pstrs += len;
|
||||
++env;
|
||||
}
|
||||
|
||||
*env = NULL;
|
||||
free(strs);
|
||||
|
||||
return args;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reprocess the arguments to main() for a completely apr-ized application
|
||||
*/
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_app_initialize(int *argc,
|
||||
const char * const * *argv,
|
||||
const char * const * *env)
|
||||
{
|
||||
apr_status_t rv = apr_initialize();
|
||||
|
||||
if (rv != APR_SUCCESS) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
apr_app_init_complete = 1;
|
||||
#elif APR_HAS_UNICODE_FS
|
||||
IF_WIN_OS_IS_UNICODE
|
||||
{
|
||||
apr_wchar_t **wstrs;
|
||||
apr_wchar_t *sysstr;
|
||||
int wstrc;
|
||||
int dupenv;
|
||||
|
||||
if (apr_app_init_complete) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
apr_app_init_complete = 1;
|
||||
|
||||
sysstr = GetCommandLineW();
|
||||
if (sysstr) {
|
||||
wstrs = CommandLineToArgvW(sysstr, &wstrc);
|
||||
if (wstrs) {
|
||||
*argc = apr_wastrtoastr(argv, wstrs, wstrc);
|
||||
GlobalFree(wstrs);
|
||||
}
|
||||
}
|
||||
|
||||
sysstr = GetEnvironmentStringsW();
|
||||
dupenv = warrsztoastr(&_environ, sysstr);
|
||||
|
||||
if (env) {
|
||||
*env = apr_malloc_dbg((dupenv + 1) * sizeof (char *),
|
||||
__FILE__, __LINE__ );
|
||||
memcpy((void*)*env, _environ, (dupenv + 1) * sizeof (char *));
|
||||
}
|
||||
else {
|
||||
}
|
||||
|
||||
FreeEnvironmentStringsW(sysstr);
|
||||
|
||||
/* MSVCRT will attempt to maintain the wide environment calls
|
||||
* on _putenv(), which is bogus if we've passed a non-ascii
|
||||
* string to _putenv(), since they use MultiByteToWideChar
|
||||
* and breaking the implicit utf-8 assumption we've built.
|
||||
*
|
||||
* Reset _wenviron for good measure.
|
||||
*/
|
||||
if (_wenviron) {
|
||||
apr_wchar_t **wenv = _wenviron;
|
||||
_wenviron = NULL;
|
||||
free(wenv);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
/* Provide to win32/thread.c */
|
||||
extern DWORD tls_apr_thread;
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_initialize(void)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
apr_status_t status;
|
||||
int iVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
apr_oslevel_e osver;
|
||||
|
||||
if (initialized++) {
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Initialize apr_os_level global */
|
||||
if (apr_get_oslevel(&osver) != APR_SUCCESS) {
|
||||
return APR_EEXIST;
|
||||
}
|
||||
|
||||
tls_apr_thread = TlsAlloc();
|
||||
if ((status = apr_pool_initialize()) != APR_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
|
||||
return APR_ENOPOOL;
|
||||
}
|
||||
|
||||
apr_pool_tag(pool, "apr_initialize");
|
||||
|
||||
iVersionRequested = MAKEWORD(WSAHighByte, WSALowByte);
|
||||
err = WSAStartup((WORD) iVersionRequested, &wsaData);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (LOBYTE(wsaData.wVersion) != WSAHighByte ||
|
||||
HIBYTE(wsaData.wVersion) != WSALowByte) {
|
||||
WSACleanup();
|
||||
return APR_EEXIST;
|
||||
}
|
||||
|
||||
apr_signal_init(pool);
|
||||
|
||||
apr_threadproc_init(pool);
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE_NONSTD(void) apr_terminate(void)
|
||||
{
|
||||
initialized--;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
apr_pool_terminate();
|
||||
|
||||
WSACleanup();
|
||||
|
||||
TlsFree(tls_apr_thread);
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_terminate2(void)
|
||||
{
|
||||
apr_terminate();
|
||||
}
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_private.h"
|
||||
#include "apr_errno.h"
|
||||
#include "apr_arch_utf8.h"
|
||||
|
||||
/* Implementation of RFC 3629, "UTF-8, a transformation format of ISO 10646"
|
||||
* with particular attention to canonical translation forms (see section 10
|
||||
* "Security Considerations" of the RFC for more info).
|
||||
*
|
||||
* Since several architectures including Windows support unicode, with UCS2
|
||||
* used as the actual storage conventions by that archicture, these functions
|
||||
* exist to transform or validate UCS2 strings into APR's 'char' type
|
||||
* convention. It is left up to the operating system to determine the
|
||||
* validitity of the string, e.g. normative forms, in the context of
|
||||
* its native language support. Other file systems which support filename
|
||||
* characters of 0x80-0xff but have no explicit requirement for Unicode
|
||||
* will find this function useful only for validating the character sequences
|
||||
* and rejecting poorly encoded UTF8 sequences.
|
||||
*
|
||||
* Len UCS-4 range (hex) UTF-8 octet sequence (binary)
|
||||
* 1:2 00000000-0000007F 0xxxxxxx
|
||||
* 2:2 00000080-000007FF 110XXXXx 10xxxxxx
|
||||
* 3:2 00000800-0000FFFF 1110XXXX 10Xxxxxx 10xxxxxx
|
||||
* 4:4 00010000-001FFFFF 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx
|
||||
* 00200000-03FFFFFF 111110XX 10XXXxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 04000000-7FFFFFFF 1111110X 10XXXXxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*
|
||||
* One of the X bits must be 1 to avoid overlong representation of ucs2 values.
|
||||
*
|
||||
* For conversion into ucs2, the 4th form is limited in range to 0010 FFFF,
|
||||
* and the final two forms are used only by full ucs4, per RFC 3629;
|
||||
*
|
||||
* "Pairs of UCS-2 values between D800 and DFFF (surrogate pairs in
|
||||
* Unicode parlance), being actually UCS-4 characters transformed
|
||||
* through UTF-16, need special treatment: the UTF-16 transformation
|
||||
* must be undone, yielding a UCS-4 character that is then transformed
|
||||
* as above."
|
||||
*
|
||||
* From RFC2781 UTF-16: the compressed ISO 10646 encoding bitmask
|
||||
*
|
||||
* U' = U - 0x10000
|
||||
* U' = 00000000 0000yyyy yyyyyyxx xxxxxxxx
|
||||
* W1 = 110110yy yyyyyyyy
|
||||
* W2 = 110111xx xxxxxxxx
|
||||
* Max U' = 0000 00001111 11111111 11111111
|
||||
* Max U = 0000 00010000 11111111 11111111
|
||||
*
|
||||
* Len is the table above is a mapping of bytes used for utf8:ucs2 values,
|
||||
* which results in these conclusions of maximum allocations;
|
||||
*
|
||||
* apr_conv_utf8_to_ucs2 out bytes:sizeof(in) * 1 <= Req <= sizeof(in) * 2
|
||||
* apr_conv_ucs2_to_utf8 out words:sizeof(in) / 2 <= Req <= sizeof(in) * 3 / 2
|
||||
*/
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_conv_utf8_to_ucs2(const char *in,
|
||||
apr_size_t *inbytes,
|
||||
apr_wchar_t *out,
|
||||
apr_size_t *outwords)
|
||||
{
|
||||
apr_int64_t newch, mask;
|
||||
apr_size_t expect, eating;
|
||||
int ch;
|
||||
|
||||
while (*inbytes && *outwords)
|
||||
{
|
||||
ch = (unsigned char)(*in++);
|
||||
if (!(ch & 0200)) {
|
||||
/* US-ASCII-7 plain text
|
||||
*/
|
||||
--*inbytes;
|
||||
--*outwords;
|
||||
*(out++) = ch;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ch & 0300) != 0300) {
|
||||
/* Multibyte Continuation is out of place
|
||||
*/
|
||||
return APR_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Multibyte Sequence Lead Character
|
||||
*
|
||||
* Compute the expected bytes while adjusting
|
||||
* or lead byte and leading zeros mask.
|
||||
*/
|
||||
mask = 0340;
|
||||
expect = 1;
|
||||
while ((ch & mask) == mask) {
|
||||
mask |= mask >> 1;
|
||||
if (++expect > 3) /* (truly 5 for ucs-4) */
|
||||
return APR_EINVAL;
|
||||
}
|
||||
newch = ch & ~mask;
|
||||
eating = expect + 1;
|
||||
if (*inbytes <= expect)
|
||||
return APR_INCOMPLETE;
|
||||
/* Reject values of excessive leading 0 bits
|
||||
* utf-8 _demands_ the shortest possible byte length
|
||||
*/
|
||||
if (expect == 1) {
|
||||
if (!(newch & 0036))
|
||||
return APR_EINVAL;
|
||||
}
|
||||
else {
|
||||
/* Reject values of excessive leading 0 bits
|
||||
*/
|
||||
if (!newch && !((unsigned char)*in & 0077 & (mask << 1)))
|
||||
return APR_EINVAL;
|
||||
if (expect == 2) {
|
||||
/* Reject values D800-DFFF when not utf16 encoded
|
||||
* (may not be an appropriate restriction for ucs-4)
|
||||
*/
|
||||
if (newch == 0015 && ((unsigned char)*in & 0040))
|
||||
return APR_EINVAL;
|
||||
}
|
||||
else if (expect == 3) {
|
||||
/* Short circuit values > 110000
|
||||
*/
|
||||
if (newch > 4)
|
||||
return APR_EINVAL;
|
||||
if (newch == 4 && ((unsigned char)*in & 0060))
|
||||
return APR_EINVAL;
|
||||
}
|
||||
}
|
||||
/* Where the boolean (expect > 2) is true, we will need
|
||||
* an extra word for the output.
|
||||
*/
|
||||
if (*outwords < (apr_size_t)(expect > 2) + 1)
|
||||
break; /* buffer full */
|
||||
while (expect--)
|
||||
{
|
||||
/* Multibyte Continuation must be legal */
|
||||
if (((ch = (unsigned char)*(in++)) & 0300) != 0200)
|
||||
return APR_EINVAL;
|
||||
newch <<= 6;
|
||||
newch |= (ch & 0077);
|
||||
}
|
||||
*inbytes -= eating;
|
||||
/* newch is now a true ucs-4 character
|
||||
*
|
||||
* now we need to fold to ucs-2
|
||||
*/
|
||||
if (newch < 0x10000)
|
||||
{
|
||||
--*outwords;
|
||||
*(out++) = (apr_wchar_t) newch;
|
||||
}
|
||||
else
|
||||
{
|
||||
*outwords -= 2;
|
||||
newch -= 0x10000;
|
||||
*(out++) = (apr_wchar_t) (0xD800 | (newch >> 10));
|
||||
*(out++) = (apr_wchar_t) (0xDC00 | (newch & 0x03FF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Buffer full 'errors' aren't errors, the client must inspect both
|
||||
* the inbytes and outwords values
|
||||
*/
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_conv_ucs2_to_utf8(const apr_wchar_t *in,
|
||||
apr_size_t *inwords,
|
||||
char *out,
|
||||
apr_size_t *outbytes)
|
||||
{
|
||||
apr_int64_t newch, require;
|
||||
apr_size_t need;
|
||||
char *invout;
|
||||
int ch;
|
||||
|
||||
while (*inwords && *outbytes)
|
||||
{
|
||||
ch = (unsigned short)(*in++);
|
||||
if (ch < 0x80)
|
||||
{
|
||||
--*inwords;
|
||||
--*outbytes;
|
||||
*(out++) = (unsigned char) ch;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ch & 0xFC00) == 0xDC00) {
|
||||
/* Invalid Leading ucs-2 Multiword Continuation Character
|
||||
*/
|
||||
return APR_EINVAL;
|
||||
}
|
||||
if ((ch & 0xFC00) == 0xD800) {
|
||||
/* Leading ucs-2 Multiword Character
|
||||
*/
|
||||
if (*inwords < 2) {
|
||||
/* Missing ucs-2 Multiword Continuation Character
|
||||
*/
|
||||
return APR_INCOMPLETE;
|
||||
}
|
||||
if (((unsigned short)(*in) & 0xFC00) != 0xDC00) {
|
||||
/* Invalid ucs-2 Multiword Continuation Character
|
||||
*/
|
||||
return APR_EINVAL;
|
||||
}
|
||||
newch = (ch & 0x03FF) << 10 | ((unsigned short)(*in++) & 0x03FF);
|
||||
newch += 0x10000;
|
||||
}
|
||||
else {
|
||||
/* ucs-2 Single Word Character
|
||||
*/
|
||||
newch = ch;
|
||||
}
|
||||
/* Determine the absolute minimum utf-8 bytes required
|
||||
*/
|
||||
require = newch >> 11;
|
||||
need = 1;
|
||||
while (require)
|
||||
require >>= 5, ++need;
|
||||
if (need >= *outbytes)
|
||||
break; /* Insufficient buffer */
|
||||
*inwords -= (need > 2) + 1;
|
||||
*outbytes -= need + 1;
|
||||
/* Compute the utf-8 characters in last to first order,
|
||||
* calculating the lead character length bits along the way.
|
||||
*/
|
||||
ch = 0200;
|
||||
out += need + 1;
|
||||
invout = out;
|
||||
while (need--) {
|
||||
ch |= ch >> 1;
|
||||
*(--invout) = (unsigned char)(0200 | (newch & 0077));
|
||||
newch >>= 6;
|
||||
}
|
||||
/* Compute the lead utf-8 character and move the dest offset
|
||||
*/
|
||||
*(--invout) = (unsigned char)(ch | newch);
|
||||
}
|
||||
}
|
||||
/* Buffer full 'errors' aren't errors, the client must inspect both
|
||||
* the inwords and outbytes values
|
||||
*/
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user