1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_private.h"
18
19#include "apr_arch_misc.h"
20#include "apr_arch_file_io.h"
21#include <assert.h>
22
23/* This module is the source of -static- helper functions that are
24 * entirely internal to apr.  If the fn is exported - it does not
25 * belong here.
26 *
27 * Namespace decoration is still required to protect us from symbol
28 * clashes in static linkages.
29 */
30
31
32/* Shared by apr_app.c and start.c
33 *
34 * An internal apr function to convert an array of strings (either
35 * a counted or NULL terminated list, such as an argv[argc] or env[]
36 * list respectively) from wide Unicode strings to narrow utf-8 strings.
37 * These are allocated from the MSVCRT's _CRT_BLOCK to trick the system
38 * into trusting our store.
39 */
40int apr_wastrtoastr(char const * const * *retarr,
41                    wchar_t const * const *arr, int args)
42{
43    apr_size_t elesize = 0;
44    char **newarr;
45    char *elements;
46    char *ele;
47    int arg;
48
49    if (args < 0) {
50        for (args = 0; arr[args]; ++args)
51            ;
52    }
53
54    newarr = apr_malloc_dbg((args + 1) * sizeof(char *),
55                            __FILE__, __LINE__);
56
57    for (arg = 0; arg < args; ++arg) {
58        newarr[arg] = (void*)(wcslen(arr[arg]) + 1);
59        elesize += (apr_size_t)newarr[arg];
60    }
61
62    /* This is a safe max allocation, we will realloc after
63     * processing and return the excess to the free store.
64     * 3 ucs bytes hold any single wchar_t value (16 bits)
65     * 4 ucs bytes will hold a wchar_t pair value (20 bits)
66     */
67    elesize = elesize * 3 + 1;
68    ele = elements = apr_malloc_dbg(elesize * sizeof(char),
69                                    __FILE__, __LINE__);
70
71    for (arg = 0; arg < args; ++arg) {
72        apr_size_t len = (apr_size_t)newarr[arg];
73        apr_size_t newlen = elesize;
74
75        newarr[arg] = ele;
76        (void)apr_conv_ucs2_to_utf8(arr[arg], &len,
77                                    newarr[arg], &elesize);
78
79        newlen -= elesize;
80        ele += newlen;
81        assert(elesize && (len == 0));
82    }
83
84    newarr[arg] = NULL;
85    *(ele++) = '\0';
86
87    /* Return to the free store if the heap realloc is the least bit optimized
88     */
89    ele = apr_realloc_dbg(elements, ele - elements,
90                          __FILE__, __LINE__);
91
92    if (ele != elements) {
93        apr_size_t diff = ele - elements;
94        for (arg = 0; arg < args; ++arg) {
95            newarr[arg] += diff;
96        }
97    }
98
99    *retarr = (char const * const *)newarr;
100    return args;
101}
102