1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter 18251875Speter#define APR_WANT_STRFUNC 19251875Speter#define APR_WANT_MEMFUNC 20251875Speter#include "apr_want.h" 21251875Speter 22251875Speter#include "apr_errno.h" 23251875Speter#include "apr_pools.h" 24251875Speter#include "apr_strings.h" 25251875Speter#include "apr_tables.h" 26251875Speter 27251875Speter#include "apr_private.h" 28251875Speter 29251875Speterapr_status_t apr_filepath_list_split_impl(apr_array_header_t **pathelts, 30251875Speter const char *liststr, 31251875Speter char separator, 32251875Speter apr_pool_t *p) 33251875Speter{ 34251875Speter char *path, *part, *ptr; 35251875Speter char separator_string[2] = { '\0', '\0' }; 36251875Speter apr_array_header_t *elts; 37251875Speter int nelts; 38251875Speter 39251875Speter separator_string[0] = separator; 40251875Speter /* Count the number of path elements. We know there'll be at least 41251875Speter one even if path is an empty string. */ 42251875Speter path = apr_pstrdup(p, liststr); 43251875Speter for (nelts = 0, ptr = path; ptr != NULL; ++nelts) 44251875Speter { 45251875Speter ptr = strchr(ptr, separator); 46251875Speter if (ptr) 47251875Speter ++ptr; 48251875Speter } 49251875Speter 50251875Speter /* Split the path into the array. */ 51251875Speter elts = apr_array_make(p, nelts, sizeof(char*)); 52251875Speter while ((part = apr_strtok(path, separator_string, &ptr)) != NULL) 53251875Speter { 54251875Speter if (*part == '\0') /* Ignore empty path components. */ 55251875Speter continue; 56251875Speter 57251875Speter *(char**)apr_array_push(elts) = part; 58251875Speter path = NULL; /* For the next call to apr_strtok */ 59251875Speter } 60251875Speter 61251875Speter *pathelts = elts; 62251875Speter return APR_SUCCESS; 63251875Speter} 64251875Speter 65251875Speter 66251875Speterapr_status_t apr_filepath_list_merge_impl(char **liststr, 67251875Speter apr_array_header_t *pathelts, 68251875Speter char separator, 69251875Speter apr_pool_t *p) 70251875Speter{ 71251875Speter apr_size_t path_size = 0; 72251875Speter char *path; 73251875Speter int i; 74251875Speter 75251875Speter /* This test isn't 100% certain, but it'll catch at least some 76251875Speter invalid uses... */ 77251875Speter if (pathelts->elt_size != sizeof(char*)) 78251875Speter return APR_EINVAL; 79251875Speter 80251875Speter /* Calculate the size of the merged path */ 81251875Speter for (i = 0; i < pathelts->nelts; ++i) 82251875Speter path_size += strlen(((char**)pathelts->elts)[i]); 83251875Speter 84251875Speter if (path_size == 0) 85251875Speter { 86251875Speter *liststr = NULL; 87251875Speter return APR_SUCCESS; 88251875Speter } 89251875Speter 90251875Speter if (i > 0) /* Add space for the separators */ 91251875Speter path_size += (i - 1); 92251875Speter 93251875Speter /* Merge the path components */ 94251875Speter path = *liststr = apr_palloc(p, path_size + 1); 95251875Speter for (i = 0; i < pathelts->nelts; ++i) 96251875Speter { 97251875Speter /* ### Hmmmm. Calling strlen twice on the same string. Yuck. 98251875Speter But is is better than reallocation in apr_pstrcat? */ 99251875Speter const char *part = ((char**)pathelts->elts)[i]; 100251875Speter apr_size_t part_size = strlen(part); 101251875Speter if (part_size == 0) /* Ignore empty path components. */ 102251875Speter continue; 103251875Speter 104251875Speter if (i > 0) 105251875Speter *path++ = separator; 106251875Speter memcpy(path, part, part_size); 107251875Speter path += part_size; 108251875Speter } 109251875Speter *path = '\0'; 110251875Speter return APR_SUCCESS; 111251875Speter} 112