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_pools.h" 18#include "apr_hash.h" 19#include "apr_tables.h" 20#include "apr_strings.h" 21 22#include "ap_provider.h" 23 24static apr_hash_t *global_providers = NULL; 25static apr_hash_t *global_providers_names = NULL; 26 27 28static apr_status_t cleanup_global_providers(void *ctx) 29{ 30 global_providers = NULL; 31 global_providers_names = NULL; 32 return APR_SUCCESS; 33} 34 35AP_DECLARE(apr_status_t) ap_register_provider(apr_pool_t *pool, 36 const char *provider_group, 37 const char *provider_name, 38 const char *provider_version, 39 const void *provider) 40{ 41 apr_hash_t *provider_group_hash, *provider_version_hash; 42 43 if (global_providers == NULL) { 44 global_providers = apr_hash_make(pool); 45 global_providers_names = apr_hash_make(pool); 46 apr_pool_cleanup_register(pool, NULL, cleanup_global_providers, 47 apr_pool_cleanup_null); 48 } 49 50 /* First, deal with storing the provider away */ 51 provider_group_hash = apr_hash_get(global_providers, provider_group, 52 APR_HASH_KEY_STRING); 53 54 if (!provider_group_hash) { 55 provider_group_hash = apr_hash_make(pool); 56 apr_hash_set(global_providers, provider_group, APR_HASH_KEY_STRING, 57 provider_group_hash); 58 59 } 60 61 provider_version_hash = apr_hash_get(provider_group_hash, provider_name, 62 APR_HASH_KEY_STRING); 63 64 if (!provider_version_hash) { 65 provider_version_hash = apr_hash_make(pool); 66 apr_hash_set(provider_group_hash, provider_name, APR_HASH_KEY_STRING, 67 provider_version_hash); 68 69 } 70 71 /* just set it. no biggy if it was there before. */ 72 apr_hash_set(provider_version_hash, provider_version, APR_HASH_KEY_STRING, 73 provider); 74 75 /* Now, tuck away the provider names in an easy-to-get format */ 76 provider_group_hash = apr_hash_get(global_providers_names, provider_group, 77 APR_HASH_KEY_STRING); 78 79 if (!provider_group_hash) { 80 provider_group_hash = apr_hash_make(pool); 81 apr_hash_set(global_providers_names, provider_group, APR_HASH_KEY_STRING, 82 provider_group_hash); 83 84 } 85 86 provider_version_hash = apr_hash_get(provider_group_hash, provider_version, 87 APR_HASH_KEY_STRING); 88 89 if (!provider_version_hash) { 90 provider_version_hash = apr_hash_make(pool); 91 apr_hash_set(provider_group_hash, provider_version, APR_HASH_KEY_STRING, 92 provider_version_hash); 93 94 } 95 96 /* just set it. no biggy if it was there before. */ 97 apr_hash_set(provider_version_hash, provider_name, APR_HASH_KEY_STRING, 98 provider_name); 99 100 return APR_SUCCESS; 101} 102 103AP_DECLARE(void *) ap_lookup_provider(const char *provider_group, 104 const char *provider_name, 105 const char *provider_version) 106{ 107 apr_hash_t *provider_group_hash, *provider_name_hash; 108 109 if (global_providers == NULL) { 110 return NULL; 111 } 112 113 provider_group_hash = apr_hash_get(global_providers, provider_group, 114 APR_HASH_KEY_STRING); 115 116 if (provider_group_hash == NULL) { 117 return NULL; 118 } 119 120 provider_name_hash = apr_hash_get(provider_group_hash, provider_name, 121 APR_HASH_KEY_STRING); 122 123 if (provider_name_hash == NULL) { 124 return NULL; 125 } 126 127 return apr_hash_get(provider_name_hash, provider_version, 128 APR_HASH_KEY_STRING); 129} 130 131AP_DECLARE(apr_array_header_t *) ap_list_provider_names(apr_pool_t *pool, 132 const char *provider_group, 133 const char *provider_version) 134{ 135 apr_array_header_t *ret = apr_array_make(pool, 10, sizeof(ap_list_provider_names_t)); 136 ap_list_provider_names_t *entry; 137 apr_hash_t *provider_group_hash, *h; 138 apr_hash_index_t *hi; 139 char *val; 140 141 if (global_providers_names == NULL) { 142 return ret; 143 } 144 145 provider_group_hash = apr_hash_get(global_providers_names, provider_group, 146 APR_HASH_KEY_STRING); 147 148 if (provider_group_hash == NULL) { 149 return ret; 150 } 151 152 h = apr_hash_get(provider_group_hash, provider_version, 153 APR_HASH_KEY_STRING); 154 155 if (h == NULL) { 156 return ret; 157 } 158 159 for (hi = apr_hash_first(pool, h); hi; hi = apr_hash_next(hi)) { 160 apr_hash_this(hi, NULL, NULL, (void *)&val); 161 entry = apr_array_push(ret); 162 entry->provider_name = apr_pstrdup(pool, val); 163 } 164 return ret; 165} 166 167AP_DECLARE(apr_array_header_t *) ap_list_provider_groups(apr_pool_t *pool) 168{ 169 apr_array_header_t *ret = apr_array_make(pool, 10, sizeof(ap_list_provider_groups_t)); 170 ap_list_provider_groups_t *entry; 171 apr_hash_t *provider_group_hash; 172 apr_hash_index_t *groups_hi, *vers_hi; 173 char *group, *version; 174 175 if (global_providers_names == NULL) 176 return ret; 177 178 for (groups_hi = apr_hash_first(pool, global_providers_names); 179 groups_hi; 180 groups_hi = apr_hash_next(groups_hi)) 181 { 182 apr_hash_this(groups_hi, (void *)&group, NULL, (void *)&provider_group_hash); 183 if (provider_group_hash == NULL) 184 continue; 185 for (vers_hi = apr_hash_first(pool, provider_group_hash); 186 vers_hi; 187 vers_hi = apr_hash_next(vers_hi)) 188 { 189 apr_hash_this(vers_hi, (void *)&version, NULL, NULL); 190 191 entry = apr_array_push(ret); 192 entry->provider_group = group; 193 entry->provider_version = version; 194 } 195 } 196 return ret; 197} 198