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 18#define APR_WANT_STRFUNC 19#define APR_WANT_MEMFUNC 20#include "apr_want.h" 21 22#include "apr_errno.h" 23#include "apr_pools.h" 24#include "apr_strings.h" 25#include "apr_tables.h" 26 27#include "apr_private.h" 28 29apr_status_t apr_filepath_list_split_impl(apr_array_header_t **pathelts, 30 const char *liststr, 31 char separator, 32 apr_pool_t *p) 33{ 34 char *path, *part, *ptr; 35 char separator_string[2] = { '\0', '\0' }; 36 apr_array_header_t *elts; 37 int nelts; 38 39 separator_string[0] = separator; 40 /* Count the number of path elements. We know there'll be at least 41 one even if path is an empty string. */ 42 path = apr_pstrdup(p, liststr); 43 for (nelts = 0, ptr = path; ptr != NULL; ++nelts) 44 { 45 ptr = strchr(ptr, separator); 46 if (ptr) 47 ++ptr; 48 } 49 50 /* Split the path into the array. */ 51 elts = apr_array_make(p, nelts, sizeof(char*)); 52 while ((part = apr_strtok(path, separator_string, &ptr)) != NULL) 53 { 54 if (*part == '\0') /* Ignore empty path components. */ 55 continue; 56 57 *(char**)apr_array_push(elts) = part; 58 path = NULL; /* For the next call to apr_strtok */ 59 } 60 61 *pathelts = elts; 62 return APR_SUCCESS; 63} 64 65 66apr_status_t apr_filepath_list_merge_impl(char **liststr, 67 apr_array_header_t *pathelts, 68 char separator, 69 apr_pool_t *p) 70{ 71 apr_size_t path_size = 0; 72 char *path; 73 int i; 74 75 /* This test isn't 100% certain, but it'll catch at least some 76 invalid uses... */ 77 if (pathelts->elt_size != sizeof(char*)) 78 return APR_EINVAL; 79 80 /* Calculate the size of the merged path */ 81 for (i = 0; i < pathelts->nelts; ++i) 82 path_size += strlen(((char**)pathelts->elts)[i]); 83 84 if (path_size == 0) 85 { 86 *liststr = NULL; 87 return APR_SUCCESS; 88 } 89 90 if (i > 0) /* Add space for the separators */ 91 path_size += (i - 1); 92 93 /* Merge the path components */ 94 path = *liststr = apr_palloc(p, path_size + 1); 95 for (i = 0; i < pathelts->nelts; ++i) 96 { 97 /* ### Hmmmm. Calling strlen twice on the same string. Yuck. 98 But is is better than reallocation in apr_pstrcat? */ 99 const char *part = ((char**)pathelts->elts)[i]; 100 apr_size_t part_size = strlen(part); 101 if (part_size == 0) /* Ignore empty path components. */ 102 continue; 103 104 if (i > 0) 105 *path++ = separator; 106 memcpy(path, part, part_size); 107 path += part_size; 108 } 109 *path = '\0'; 110 return APR_SUCCESS; 111} 112