UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 5 * 6 * THE BSD LICENSE 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * Redistributions of source code must retain the above copyright notice, this 12 * list of conditions and the following disclaimer. 13 * Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * Neither the name of the nor the names of its contributors may be 18 * used to endorse or promote products derived from this software without 19 * specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 25 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * pblock.c: Handles Parameter Blocks 36 * 37 * See pblock.h for public documentation. 38 * 39 * Rob McCool 40 * 41 * This code uses property lists to implement pblocks. 42 */ 43 44 45 #include <limits.h> 46 #include "pblock.h" 47 #include "plist_pvt.h" 48 #include "plist.h" 49 #include "LinkedList.hh" 50 #include "util.h" /* util_itoa */ 51 #include "pool.h" 52 #include "systhr.h" 53 54 #define MALLOC_POOL_HANDLE (thread_malloc_key != -1 ? (pool_handle_t *)systhread_getdata(thread_malloc_key) : getThreadMallocPool()) 55 56 static int thread_malloc_key = -1; 57 static int _pblock_str2pblock(const char* str, pblock* pb, PRBool lowerCase); 58 59 static pool_handle_t *getThreadMallocPool() 60 { 61 pool_handle_t *thread_malloc_pool = 0; 62 63 thread_malloc_key = getThreadMallocKey(); 64 if (thread_malloc_key != -1) { 65 thread_malloc_pool = (pool_handle_t *)systhread_getdata(thread_malloc_key); 66 } 67 68 return thread_malloc_pool; 69 } 70 71 /* ------------------------------- HashList ------------------------------- */ 72 73 template <class Name, class Value> 74 class HashList { 75 public: 76 HashList(int mask) 77 : _mask(mask), 78 _list(new CList<Value>[mask + 1]) 79 { } 80 81 void Insert(Name name, Value *value) 82 { 83 _list[name & _mask].Append(value); 84 } 85 86 const CList<Value>& Find(Name name) 87 { 88 return _list[name & _mask]; 89 } 90 91 private: 92 CList<Value> *_list; 93 unsigned int _mask; 94 }; 95 96 /* ---------------------- pb_key static initializers ---------------------- */ 97 98 /* 99 * pb_key 100 * 101 * Contains a precomputed hash value for a specific pblock variable name. 102 */ 103 typedef struct pb_key pb_key; 104 struct pb_key { 105 const char *name; 106 int namelen; 107 unsigned int hashval; 108 int sizendx; 109 int hashndx; 110 }; 111 112 static HashList<unsigned int, pb_key> _hashKeys(0x7f); 113 CList<pb_key> _listKeys; 114 115 static const pb_key *const _create_key(const char *name, int sizendx = 0) 116 { 117 /* Create a the new pb_key */ 118 pb_key *key = (pb_key*)malloc(sizeof(pb_key)); 119 key->name = STRDUP(name); 120 key->namelen = strlen(name); 121 key->hashval = PListHash(name); 122 key->sizendx = sizendx; 123 key->hashndx = key->hashval % PLSIZENDX(sizendx); 124 125 /* Group pb_keys by hashval for later retrieval */ 126 _hashKeys.Insert(key->hashval, key); 127 128 /* Keep a list of all the registered keys */ 129 _listKeys.Append(key); 130 131 return key; 132 } 133 134 const pb_key *const pb_key_accept = _create_key("accept"); 135 const pb_key *const pb_key_accept_charset = _create_key("accept-charset"); 136 const pb_key *const pb_key_accept_encoding = _create_key("accept-encoding"); 137 const pb_key *const pb_key_accept_language = _create_key("accept-language"); 138 const pb_key *const pb_key_accept_ranges = _create_key("accept-ranges"); 139 const pb_key *const pb_key_actual_route = _create_key("actual-route"); 140 const pb_key *const pb_key_age = _create_key("age"); 141 const pb_key *const pb_key_always_allow_chunked = _create_key("always-allow-chunked"); 142 const pb_key *const pb_key_always_use_keep_alive = _create_key("always-use-keep-alive"); 143 const pb_key *const pb_key_auth_cert = _create_key("auth-cert"); 144 const pb_key *const pb_key_auth_expiring = _create_key("auth-expiring"); 145 const pb_key *const pb_key_auth_group = _create_key("auth-group"); 146 const pb_key *const pb_key_auth_type = _create_key("auth-type"); 147 const pb_key *const pb_key_auth_user = _create_key("auth-user"); 148 const pb_key *const pb_key_authorization = _create_key("authorization"); 149 const pb_key *const pb_key_browser = _create_key("browser"); 150 const pb_key *const pb_key_c2p_cl = _create_key("c2p-cl"); 151 const pb_key *const pb_key_c2p_hl = _create_key("c2p-hl"); 152 const pb_key *const pb_key_cache_info = _create_key("cache-info"); 153 const pb_key *const pb_key_charset = _create_key("charset"); 154 const pb_key *const pb_key_check_http_server = _create_key("check-http-server"); 155 const pb_key *const pb_key_ChunkedRequestBufferSize = _create_key("ChunkedRequestBufferSize"); 156 const pb_key *const pb_key_ChunkedRequestTimeout = _create_key("ChunkedRequestTimeout"); 157 const pb_key *const pb_key_cipher = _create_key("cipher"); 158 const pb_key *const pb_key_clf_request = _create_key("clf-request"); 159 const pb_key *const pb_key_cli_status = _create_key("cli-status"); 160 const pb_key *const pb_key_client_cert_nickname = _create_key("client-cert-nickname"); 161 const pb_key *const pb_key_client_ip = _create_key("client-ip"); 162 const pb_key *const pb_key_close = _create_key("close"); 163 const pb_key *const pb_key_connect_timeout = _create_key("connect-timeout"); 164 const pb_key *const pb_key_connection = _create_key("connection"); 165 const pb_key *const pb_key_cont = _create_key("cont"); 166 const pb_key *const pb_key_content_encoding = _create_key("content-encoding"); 167 const pb_key *const pb_key_content_language = _create_key("content-language"); 168 const pb_key *const pb_key_content_length = _create_key("content-length"); 169 const pb_key *const pb_key_content_location = _create_key("content-location"); 170 const pb_key *const pb_key_content_md5 = _create_key("content-md5"); 171 const pb_key *const pb_key_content_range = _create_key("content-range"); 172 const pb_key *const pb_key_content_type = _create_key("content-type"); 173 const pb_key *const pb_key_cookie = _create_key("cookie"); 174 const pb_key *const pb_key_date = _create_key("date"); 175 const pb_key *const pb_key_DATE_GMT = _create_key("DATE_GMT"); 176 const pb_key *const pb_key_DATE_LOCAL = _create_key("DATE_LOCAL"); 177 const pb_key *const pb_key_dir = _create_key("dir"); 178 const pb_key *const pb_key_Directive = _create_key("Directive"); 179 const pb_key *const pb_key_dns = _create_key("dns"); 180 const pb_key *const pb_key_DOCUMENT_NAME = _create_key("DOCUMENT_NAME"); 181 const pb_key *const pb_key_DOCUMENT_URI = _create_key("DOCUMENT_URI"); 182 const pb_key *const pb_key_domain = _create_key("domain"); 183 const pb_key *const pb_key_enc = _create_key("enc"); 184 const pb_key *const pb_key_engine = _create_key("engine"); 185 const pb_key *const pb_key_error_action = _create_key("error-action"); 186 const pb_key *const pb_key_error_desc = _create_key("error-desc"); 187 const pb_key *const pb_key_error_fn = _create_key("error-fn"); 188 const pb_key *const pb_key_escape = _create_key("escape"); 189 const pb_key *const pb_key_escaped = _create_key("escaped"); 190 const pb_key *const pb_key_etag = _create_key("etag"); 191 const pb_key *const pb_key_expect = _create_key("expect"); 192 const pb_key *const pb_key_expires = _create_key("expires"); 193 const pb_key *const pb_key_expr = _create_key("expr"); 194 const pb_key *const pb_key_filter = _create_key("filter"); 195 const pb_key *const pb_key_find_pathinfo_forward = _create_key("find-pathinfo-forward"); 196 const pb_key *const pb_key_flushTimer = _create_key("flushTimer"); 197 const pb_key *const pb_key_fn = _create_key("fn"); 198 const pb_key *const pb_key_from = _create_key("from"); 199 const pb_key *const pb_key_full_headers = _create_key("full-headers"); 200 const pb_key *const pb_key_hdr = _create_key("hdr"); 201 const pb_key *const pb_key_host = _create_key("host"); 202 const pb_key *const pb_key_hostname = _create_key("hostname"); 203 const pb_key *const pb_key_if_match = _create_key("if-match"); 204 const pb_key *const pb_key_if_modified_since = _create_key("if-modified-since"); 205 const pb_key *const pb_key_if_none_match = _create_key("if-none-match"); 206 const pb_key *const pb_key_if_range = _create_key("if-range"); 207 const pb_key *const pb_key_if_unmodified_since = _create_key("if-unmodified-since"); 208 const pb_key *const pb_key_ip = _create_key("ip"); 209 const pb_key *const pb_key_iponly = _create_key("iponly"); 210 const pb_key *const pb_key_issuer_dn = _create_key("issuer_dn"); 211 const pb_key *const pb_key_jroute = _create_key("jroute"); 212 const pb_key *const pb_key_keep_alive = _create_key("keep-alive"); 213 const pb_key *const pb_key_keep_alive_timeout = _create_key("keep-alive-timeout"); 214 const pb_key *const pb_key_keysize = _create_key("keysize"); 215 const pb_key *const pb_key_lang = _create_key("lang"); 216 const pb_key *const pb_key_LAST_MODIFIED = _create_key("LAST_MODIFIED"); 217 const pb_key *const pb_key_last_modified = _create_key("last-modified"); 218 const pb_key *const pb_key_level = _create_key("level"); 219 const pb_key *const pb_key_location = _create_key("location"); 220 const pb_key *const pb_key_lock_owner = _create_key("lock-owner"); 221 const pb_key *const pb_key_magnus_charset = _create_key("magnus-charset"); 222 const pb_key *const pb_key_magnus_internal = _create_key("magnus-internal"); 223 const pb_key *const pb_key_magnus_internal_dav_src = _create_key("magnus-internal/dav-src"); 224 const pb_key *const pb_key_magnus_internal_default_acls_only = _create_key("magnus-internal/default-acls-only"); 225 const pb_key *const pb_key_magnus_internal_error_j2ee = _create_key("magnus-internal/error-j2ee"); 226 const pb_key *const pb_key_magnus_internal_j2ee_nsapi = _create_key("magnus-internal/j2ee-nsapi"); 227 const pb_key *const pb_key_magnus_internal_preserve_srvhdrs = _create_key("magnus-internal/preserve-srvhdrs-after-req-restart"); 228 const pb_key *const pb_key_magnus_internal_set_request_status = _create_key("magnus-internal/set-request-status"); 229 const pb_key *const pb_key_magnus_internal_set_response_status = _create_key("magnus-internal/set-response-status"); 230 const pb_key *const pb_key_magnus_internal_webapp_errordesc = _create_key("magnus-internal/webapp-errordesc"); 231 const pb_key *const pb_key_matched_browser = _create_key("matched-browser"); 232 const pb_key *const pb_key_max_age = _create_key("max-age"); 233 const pb_key *const pb_key_max_forwards = _create_key("max-forwards"); 234 const pb_key *const pb_key_message = _create_key("message"); 235 const pb_key *const pb_key_method = _create_key("method"); 236 const pb_key *const pb_key_name = _create_key("name"); 237 const pb_key *const pb_key_nocache = _create_key("nocache"); 238 const pb_key *const pb_key_nostat = _create_key("nostat"); 239 const pb_key *const pb_key_ntrans_base = _create_key("ntrans-base"); 240 const pb_key *const pb_key_offline_origin_addr = _create_key("offline-origin-addr"); 241 const pb_key *const pb_key_offline_proxy_addr = _create_key("offline-proxy-addr"); 242 const pb_key *const pb_key_origin_addr = _create_key("origin-addr"); 243 const pb_key *const pb_key_p2c_cl = _create_key("p2c-cl"); 244 const pb_key *const pb_key_p2c_hl = _create_key("p2c-hl"); 245 const pb_key *const pb_key_p2r_cl = _create_key("p2r-cl"); 246 const pb_key *const pb_key_p2r_hl = _create_key("p2r-hl"); 247 const pb_key *const pb_key_parse_timeout = _create_key("parse-timeout"); 248 const pb_key *const pb_key_password = _create_key("password"); 249 const pb_key *const pb_key_path = _create_key("path"); 250 const pb_key *const pb_key_PATH_INFO = _create_key("PATH_INFO"); 251 const pb_key *const pb_key_path_info = _create_key("path-info"); 252 const pb_key *const pb_key_pblock = _create_key("pblock"); 253 const pb_key *const pb_key_poll_interval = _create_key("poll-interval"); 254 const pb_key *const pb_key_pool = _create_key("pool"); // new 255 const pb_key *const pb_key_port = _create_key("port"); 256 const pb_key *const pb_key_ppath = _create_key("ppath"); 257 const pb_key *const pb_key_pragma = _create_key("pragma"); 258 const pb_key *const pb_key_process_request_body = _create_key("process-request-body"); 259 const pb_key *const pb_key_process_response_body = _create_key("process-response-body"); 260 const pb_key *const pb_key_protocol = _create_key("protocol"); 261 const pb_key *const pb_key_proxy_addr = _create_key("proxy-addr"); 262 const pb_key *const pb_key_proxy_agent = _create_key("proxy-agent"); 263 const pb_key *const pb_key_proxy_auth_cert = _create_key("proxy-auth-cert"); 264 const pb_key *const pb_key_proxy_authorization = _create_key("proxy-authorization"); 265 const pb_key *const pb_key_proxy_cipher = _create_key("proxy-cipher"); 266 const pb_key *const pb_key_proxy_issuer_dn = _create_key("proxy-issuer-dn"); 267 const pb_key *const pb_key_proxy_jroute = _create_key("proxy-jroute"); 268 const pb_key *const pb_key_proxy_keysize = _create_key("proxy-keysize"); 269 const pb_key *const pb_key_proxy_ping = _create_key("proxy-ping"); 270 const pb_key *const pb_key_proxy_request = _create_key("proxy-request"); 271 const pb_key *const pb_key_proxy_secret_keysize = _create_key("proxy-secret-keysize"); 272 const pb_key *const pb_key_proxy_ssl_id = _create_key("proxy-ssl-id"); 273 const pb_key *const pb_key_proxy_user_dn = _create_key("proxy-user-dn"); 274 const pb_key *const pb_key_query = _create_key("query"); 275 const pb_key *const pb_key_QUERY_STRING = _create_key("QUERY_STRING"); 276 const pb_key *const pb_key_QUERY_STRING_UNESCAPED = _create_key("QUERY_STRING_UNESCAPED"); 277 const pb_key *const pb_key_r2p_cl = _create_key("r2p-cl"); 278 const pb_key *const pb_key_r2p_hl = _create_key("r2p-hl"); 279 const pb_key *const pb_key_range = _create_key("range"); 280 const pb_key *const pb_key_referer = _create_key("referer"); 281 const pb_key *const pb_key_reformat_request_headers = _create_key("reformat-request-headers"); 282 const pb_key *const pb_key_remote_status = _create_key("remote-status"); 283 const pb_key *const pb_key_request_jroute = _create_key("request-jroute"); 284 const pb_key *const pb_key_required_rights = _create_key("required-rights"); 285 const pb_key *const pb_key_retries = _create_key("retries"); 286 const pb_key *const pb_key_rewrite_content_location = _create_key("rewrite-content-location"); 287 const pb_key *const pb_key_rewrite_host = _create_key("rewrite-host"); 288 const pb_key *const pb_key_rewrite_location = _create_key("rewrite-location"); 289 const pb_key *const pb_key_rewrite_set_cookie = _create_key("rewrite-set-cookie"); 290 const pb_key *const pb_key_root = _create_key("root"); 291 const pb_key *const pb_key_route = _create_key("route"); 292 const pb_key *const pb_key_route_cookie = _create_key("route-cookie"); 293 const pb_key *const pb_key_route_hdr = _create_key("route-hdr"); 294 const pb_key *const pb_key_route_offline = _create_key("route-offline"); 295 const pb_key *const pb_key_script_name = _create_key("script-name"); 296 const pb_key *const pb_key_secret_keysize = _create_key("secret-keysize"); 297 const pb_key *const pb_key_secure = _create_key("secure"); 298 const pb_key *const pb_key_server = _create_key("server"); 299 const pb_key *const pb_key_set_cookie = _create_key("set-cookie"); 300 const pb_key *const pb_key_socks_addr = _create_key("socks_addr"); 301 const pb_key *const pb_key_ssl_id = _create_key("ssl-id"); 302 const pb_key *const pb_key_ssl_unclean_shutdown = _create_key("ssl-unclean-shutdown"); 303 const pb_key *const pb_key_status = _create_key("status"); 304 const pb_key *const pb_key_sticky_cookie = _create_key("sticky-cookie"); 305 const pb_key *const pb_key_sticky_param = _create_key("sticky-param"); 306 const pb_key *const pb_key_suppress_request_headers = _create_key("suppress-request-headers"); 307 const pb_key *const pb_key_svr_status = _create_key("svr-status"); 308 const pb_key *const pb_key_timeout = _create_key("timeout"); 309 const pb_key *const pb_key_to = _create_key("to"); 310 const pb_key *const pb_key_transfer_encoding = _create_key("transfer-encoding"); 311 const pb_key *const pb_key_transmit_timeout = _create_key("transmit-timeout"); 312 const pb_key *const pb_key_tunnel_non_http_response = _create_key("tunnel-non-http-response"); 313 const pb_key *const pb_key_type = _create_key("type"); 314 const pb_key *const pb_key_upstream_jroute = _create_key("upstream-jroute"); 315 const pb_key *const pb_key_uri = _create_key("uri"); 316 const pb_key *const pb_key_url = _create_key("url"); 317 const pb_key *const pb_key_url_prefix = _create_key("url-prefix"); 318 const pb_key *const pb_key_UseOutputStreamSize = _create_key("UseOutputStreamSize"); 319 const pb_key *const pb_key_user = _create_key("user"); 320 const pb_key *const pb_key_user_agent = _create_key("user-agent"); 321 const pb_key *const pb_key_user_dn = _create_key("user_dn"); 322 const pb_key *const pb_key_validate_server_cert = _create_key("validate-server-cert"); 323 const pb_key *const pb_key_value = _create_key("value"); 324 const pb_key *const pb_key_vary = _create_key("vary"); 325 const pb_key *const pb_key_via = _create_key("via"); 326 const pb_key *const pb_key_warning = _create_key("warning"); 327 328 329 /* ------------------------------ _find_key ------------------------------- */ 330 331 static inline const pb_key *_find_key(const char *name, unsigned int hashval) 332 { 333 /* Check to see if name corresponds to a pb_key */ 334 CListConstIterator<pb_key> iter(&_hashKeys.Find(hashval)); 335 const pb_key *key; 336 while((key = ++iter)) { 337 if (key->hashval == hashval && !strcmp(key->name, name)) 338 return key; 339 } 340 return NULL; 341 } 342 343 344 /* --------------------------- _get_hash_index ---------------------------- */ 345 346 static inline int _get_hash_index(const PListStruct_t *pl, const pb_key *key) 347 { 348 /* Get the hash index from the key. Requires a symbol table. */ 349 int i; 350 if (key->sizendx == pl->pl_symtab->pt_sizendx) 351 i = key->hashndx; 352 else 353 i = key->hashval % PLSIZENDX(pl->pl_symtab->pt_sizendx); 354 return i; 355 } 356 357 358 /* ---------------------------- _param_create ----------------------------- */ 359 360 static inline pb_param *_param_create(pool_handle_t *pool_handle, const char *name, int namelen, const char *value, int valuelen) 361 { 362 PLValueStruct_t *ret; 363 364 ret = (PLValueStruct_t *)pool_malloc(pool_handle, sizeof(PLValueStruct_t)); 365 366 ret->pv_pbentry.param = &ret->pv_pbparam; 367 ret->pv_pbentry.next = 0; 368 ret->pv_next = 0; 369 ret->pv_type = 0; 370 ret->pv_mempool = pool_handle; 371 372 if (name || namelen) { 373 ret->pv_name = (char*)pool_malloc(pool_handle, namelen + 1); 374 if (name) { 375 memcpy(ret->pv_name, name, namelen); 376 ret->pv_name[namelen] = '\0'; 377 } else { 378 ret->pv_name[0] = '\0'; 379 } 380 } else { 381 ret->pv_name = 0; 382 } 383 384 if (value || valuelen) { 385 ret->pv_value = (char*)pool_malloc(pool_handle, valuelen + 1); 386 if (value) { 387 memcpy(ret->pv_value, value, valuelen); 388 ret->pv_value[valuelen] = '\0'; 389 } else { 390 ret->pv_value[0] = '\0'; 391 } 392 } else { 393 ret->pv_value = 0; 394 } 395 396 return &ret->pv_pbparam; 397 } 398 399 400 /* ----------------------- pblock_key_param_create ----------------------- */ 401 402 NSAPI_PUBLIC pb_param *pblock_key_param_create(pblock *pb, const pb_key *key, const char *value, int valuelen) 403 { 404 /* 405 * Allocate a PLValueStruct_t from the property list's memory pool. 406 */ 407 PListStruct_t *pl = PBTOPL(pb); 408 return _param_create(pl->pl_mempool, key->name, key->namelen, value, valuelen); 409 } 410 411 412 /* ------------------------- pblock_param_create -------------------------- */ 413 414 NSAPI_PUBLIC pb_param *pblock_param_create(pblock *pb, const char *name, const char *value) 415 { 416 /* 417 * Allocate a PLValueStruct_t from the property list's memory pool. 418 */ 419 PListStruct_t *pl = PBTOPL(pb); 420 return _param_create(pl->pl_mempool, name, name ? strlen(name) : 0, value, value ? strlen(value) : 0); 421 } 422 423 424 /* ----------------------------- param_create ----------------------------- */ 425 426 NSAPI_PUBLIC pb_param *param_create(const char *name, const char *value) 427 { 428 /* 429 * Allocate a PLValueStruct_t containing the pb_param that will 430 * be returned. Normally PLValueStruct_ts are allocated from the 431 * memory pool associated with a property list, but we don't have 432 * that here, so we just use the thread's pool and indicate we were 433 * allocated from a specific pool. 434 */ 435 return _param_create(system_pool(), name, name ? strlen(name) : 0, value, value ? strlen(value) : 0); 436 } 437 438 439 /* ------------------------------ param_free ------------------------------ */ 440 441 NSAPI_PUBLIC int param_free(pb_param *pp) 442 { 443 if (pp) { 444 PLValueStruct_t *pv = PATOPV(pp); 445 446 /* Don't bother if the pblock was allocated from a pool */ 447 if (!pv->pv_mempool) { 448 pool_free(pv->pv_mempool, pv->pv_name); 449 pool_free(pv->pv_mempool, pv->pv_value); 450 pool_free(pv->pv_mempool, pv); 451 } 452 453 return 1; 454 } 455 456 return 0; 457 } 458 459 460 /* -------------------------- pblock_create_pool -------------------------- */ 461 462 NSAPI_PUBLIC pblock *pblock_create_pool(pool_handle_t *pool_handle, int n) 463 { 464 /* Create a property list with n property indices */ 465 PListStruct_t *plist = (PListStruct_t *)PListCreate(pool_handle, n, 0, 0); 466 if (!plist) 467 return NULL; 468 469 plist->pl_resvpi = 0; 470 471 return &plist->pl_pb; 472 } 473 474 475 /* ----------------------------- pblock_pool ------------------------------ */ 476 477 NSAPI_PUBLIC pool_handle_t *pblock_pool(pblock *pb) 478 { 479 PListStruct_t *pl = PBTOPL(pb); 480 return pl->pl_mempool; 481 } 482 483 484 /* ---------------------------- pblock_create ----------------------------- */ 485 486 NSAPI_PUBLIC pblock *pblock_create(int n) 487 { 488 return pblock_create_pool(MALLOC_POOL_HANDLE, n); 489 } 490 491 492 /* ----------------------------- pblock_free ------------------------------ */ 493 494 NSAPI_PUBLIC void pblock_free(pblock *pb) 495 { 496 PListStruct_t *pl = PBTOPL(pb); 497 PLValueStruct_t **ppval; 498 PLValueStruct_t *pv; 499 int i; 500 501 if (!pb) { 502 return; 503 } 504 505 /* If the pools are enabled, this routine has no effect anyway, so 506 * just return. 507 */ 508 if (pl->pl_mempool || pool_enabled()) { 509 return; 510 } 511 512 /* Free the property name symbol table if any */ 513 if (pl->pl_symtab) { 514 pool_free(pl->pl_mempool, (void *)(pl->pl_symtab)); 515 } 516 517 ppval = (PLValueStruct_t **)(pl->pl_ppval); 518 519 /* Loop over the initialized property indices */ 520 for (i = 0; i < pl->pl_initpi; ++i) { 521 522 /* Got a property here? */ 523 pv = ppval[i]; 524 if (pv) { 525 526 param_free(&pv->pv_pbparam); 527 } 528 } 529 530 /* Free the array of pointers to property values */ 531 pool_free(pl->pl_mempool, (void *)ppval); 532 533 /* Free the property list head */ 534 pool_free(pl->pl_mempool, (void *)pl); 535 } 536 537 538 /* ------------------------------ pblock_key ------------------------------ */ 539 540 NSAPI_PUBLIC const pb_key *pblock_key(const char *name) 541 { 542 if (!name) 543 return NULL; 544 545 return _find_key(name, PListHash(name)); 546 } 547 548 549 /* --------------------------- pblock_kpinsert ---------------------------- */ 550 551 NSAPI_PUBLIC void pblock_kpinsert(const pb_key *key, pb_param *pp, pblock *pb) 552 { 553 PListStruct_t *pl = PBTOPL(pb); 554 PLValueStruct_t *pv = PATOPV(pp); 555 556 //PR_ASSERT(pv->pv_mempool == pl->pl_mempool); // TODO 557 558 /* Check to see if the name corresponds to a pb_key */ 559 unsigned int hashval; 560 if (!key) { 561 hashval = PListHash(pv->pv_name); 562 key = _find_key(pv->pv_name, hashval); 563 } 564 565 /* Find property index */ 566 int pindex = PListGetFreeIndex(pl); 567 if (pindex < 1) { 568 /* Error - invalid property index */ 569 printf("Error - invalid property index\n"); 570 return; 571 } 572 573 /* Allocate/grow the symbol table as needed */ 574 PLSymbolTable_t *pt = PListSymbolTable(pl); 575 if (!pt) { 576 printf("!pt\n"); 577 return; 578 } 579 580 /* Add PLValueStruct_t to the property list */ 581 PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval); 582 pv->pv_pbkey = key; 583 pv->pv_pi = pindex; 584 ppval[pv->pv_pi - 1] = pv; 585 586 /* Add name to symbol table */ 587 int i = key ? _get_hash_index(pl, key) : (hashval % PLSIZENDX(pt->pt_sizendx)); 588 pv->pv_next = pt->pt_hash[i]; 589 pt->pt_hash[i] = pv; 590 pt->pt_nsyms++; 591 592 //PR_ASSERT(param_key(pp) == key); // TODO 593 } 594 595 596 /* ---------------------------- pblock_pinsert ---------------------------- */ 597 598 NSAPI_PUBLIC void pblock_pinsert(pb_param *pp, pblock *pb) 599 { 600 pblock_kpinsert(NULL, pp, pb); 601 } 602 603 604 /* --------------------------- pblock_nvinsert ---------------------------- */ 605 606 NSAPI_PUBLIC pb_param *pblock_nvinsert(const char *name, const char *value, pblock *pb) 607 { 608 pb_param *pp = pblock_param_create(pb, name, value); 609 if (pp) 610 pblock_kpinsert(NULL, pp, pb); 611 return pp; 612 } 613 614 615 /* --------------------------- pblock_kvinsert ---------------------------- */ 616 617 NSAPI_PUBLIC pb_param *pblock_kvinsert(const pb_key *key, const char *value, int valuelen, pblock *pb) 618 { 619 pb_param *pp = pblock_key_param_create(pb, key, value, valuelen); 620 if (pp) 621 pblock_kpinsert(key, pp, pb); 622 return pp; 623 } 624 625 626 /* --------------------------- pblock_nninsert ---------------------------- */ 627 628 NSAPI_PUBLIC pb_param *pblock_nninsert(const char *name, int value, pblock *pb) 629 { 630 char num[UTIL_ITOA_SIZE]; 631 632 util_itoa(value, num); 633 return pblock_nvinsert(name, num, pb); 634 } 635 636 637 /* --------------------------- pblock_kninsert ---------------------------- */ 638 639 NSAPI_PUBLIC pb_param *pblock_kninsert(const pb_key *key, int value, pblock *pb) 640 { 641 pb_param *pp = pblock_key_param_create(pb, key, NULL, UTIL_ITOA_SIZE); 642 if (pp) { 643 util_itoa(value, pp->value); 644 pblock_kpinsert(key, pp, pb); 645 } 646 return pp; 647 } 648 649 650 /* --------------------------- pblock_kllinsert --------------------------- */ 651 652 NSAPI_PUBLIC pb_param *pblock_kllinsert(const pb_key *key, int64_t value, pblock *pb) 653 { 654 pb_param *pp = pblock_key_param_create(pb, key, NULL, UTIL_I64TOA_SIZE); 655 if (pp) { 656 util_i64toa(value, pp->value); 657 pblock_kpinsert(key, pp, pb); 658 } 659 return pp; 660 } 661 662 663 /* ---------------------------pblock_nvlinsert ---------------------------- */ 664 665 NSAPI_PUBLIC pb_param *pblock_nvlinsert(const char *name, int namelen, const char *value, int valuelen, pblock *pb) 666 { 667 PListStruct_t *pl = PBTOPL(pb); 668 669 pb_param *pp = _param_create(pl->pl_mempool, name, namelen, value, valuelen); 670 671 if(pp) { 672 pblock_kpinsert(NULL, pp, pb); 673 } 674 675 return pp; 676 } 677 678 679 /* ---------------------------- pblock_findkey ---------------------------- */ 680 681 NSAPI_PUBLIC pb_param *pblock_findkey(const pb_key *key, const pblock *pb) 682 { 683 PListStruct_t *pl = PBTOPL(pb); 684 685 /* Lookup key by examining symbol table */ 686 if (pl->pl_symtab) { 687 int i = _get_hash_index(pl, key); 688 PLValueStruct_t *pv; 689 690 /* Search hash collision list for matching name */ 691 for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) { 692 if (pv->pv_pbkey == key) 693 return &pv->pv_pbparam; 694 } 695 } 696 697 return NULL; 698 } 699 700 701 /* -------------------------- pblock_findkeyval --------------------------- */ 702 703 NSAPI_PUBLIC char *pblock_findkeyval(const pb_key *key, const pblock *pb) 704 { 705 pb_param *pp = pblock_findkey(key, pb); 706 return pp ? pp->value : NULL; 707 } 708 709 710 /* ---------------------------- pblock_findval ---------------------------- */ 711 712 NSAPI_PUBLIC char *pblock_findval(const char *name, const pblock *pb) 713 { 714 void *pvalue = 0; 715 716 (void)PListFindValue((PList_t)(PBTOPL(pb)), name, &pvalue, 0); 717 718 return (char *)pvalue; 719 } 720 721 722 /* ------------------------------ pblock_fr ------------------------------ */ 723 724 NSAPI_PUBLIC pb_param *pblock_fr(const char *name, pblock *pb, int remove) 725 { 726 PListStruct_t *pl = PBTOPL(pb); 727 PLValueStruct_t **ppval; 728 PLValueStruct_t **pvp; 729 PLValueStruct_t *pv = NULL; 730 int pindex; 731 int i; 732 733 if (pl->pl_symtab) { 734 735 /* Compute hash index of specified property name */ 736 i = PListHashName(pl->pl_symtab, name); 737 738 /* Search hash collision list for matching name */ 739 for (pvp = &pl->pl_symtab->pt_hash[i]; 740 (pv = *pvp); pvp = &(*pvp)->pv_next) { 741 742 if (!strcmp(name, pv->pv_name)) { 743 744 if (remove) { 745 /* Remove PLValueStruct_t from symbol table */ 746 *pvp = pv->pv_next; 747 pl->pl_symtab->pt_nsyms--; 748 749 /* Remove it from pl_ppval too */ 750 ppval = (PLValueStruct_t **)(pl->pl_ppval); 751 pindex = pv->pv_pi; 752 ppval[pindex - 1] = 0; 753 } 754 break; 755 } 756 } 757 } 758 759 return (pv) ? &pv->pv_pbparam : NULL; 760 } 761 762 763 /* --------------------------- pblock_removekey --------------------------- */ 764 765 NSAPI_PUBLIC pb_param *pblock_removekey(const pb_key *key, pblock *pb) 766 { 767 PListStruct_t *pl = PBTOPL(pb); 768 PLValueStruct_t **ppval; 769 PLValueStruct_t **pvp; 770 PLValueStruct_t *pv = NULL; 771 int pindex; 772 int i; 773 774 if (pl->pl_symtab) { 775 /* Lookup hash index for specified property key */ 776 i = _get_hash_index(pl, key); 777 778 /* Search hash collision list for matching key */ 779 for (pvp = &pl->pl_symtab->pt_hash[i]; (pv = *pvp); pvp = &pv->pv_next) { 780 /* If this value has the requested key... */ 781 if (pv->pv_pbkey == key) { 782 /* Remove PLValueStruct_t from symbol table */ 783 *pvp = pv->pv_next; 784 pl->pl_symtab->pt_nsyms--; 785 786 /* Remove it from pl_ppval too */ 787 ppval = (PLValueStruct_t **)(pl->pl_ppval); 788 pindex = pv->pv_pi; 789 ppval[pindex - 1] = 0; 790 791 break; 792 } 793 } 794 } 795 796 return (pv) ? &pv->pv_pbparam : NULL; 797 } 798 799 800 /* -------------------------- pblock_removeone --------------------------- */ 801 802 NSAPI_PUBLIC pb_param *pblock_removeone(pblock *pb) 803 { 804 PListStruct_t *pl = PBTOPL(pb); 805 806 if (pl && pl->pl_symtab) { 807 /* Search hash buckets */ 808 for (int i = 0; i < PLSIZENDX(pl->pl_symtab->pt_sizendx); i++) { 809 /* Search hash collision list */ 810 PLValueStruct_t *pv = pl->pl_symtab->pt_hash[i]; 811 if (pv) { 812 /* Remove PLValueStruct_t from symbol table */ 813 pl->pl_symtab->pt_hash[i] = pv->pv_next; 814 pl->pl_symtab->pt_nsyms--; 815 816 /* Remove it from pl_ppval too */ 817 PLValueStruct_t **ppval = (PLValueStruct_t**)pl->pl_ppval; 818 ppval[pv->pv_pi - 1] = 0; 819 820 return &pv->pv_pbparam; 821 } 822 } 823 } 824 825 return NULL; 826 } 827 828 829 /* -------------------------- pblock_str2pblock --------------------------- */ 830 831 832 int _verify_pbstr(const char *str) 833 { 834 const char *cp; 835 const char *scp; 836 int np; 837 int state; 838 int quote; 839 840 for(cp = str, np = 0, state = 0; *cp; ) { 841 switch (state) { 842 case 0: /* skipping leading spaces */ 843 844 while (*cp && isspace(*cp)) ++cp; 845 if (*cp == '=') { 846 return -1; 847 } 848 if (*cp) state = 1; 849 break; 850 851 case 1: /* scanning parameter name */ 852 853 scp = cp; 854 while (*cp && (*cp != '=') && !isspace(*cp)) ++cp; 855 if (*cp == '=') ++cp; 856 else cp = scp; 857 state = 2; 858 break; 859 860 case 2: /* scanning parameter value */ 861 quote = 0; 862 if (*cp == '\"') { 863 quote = 1; 864 ++cp; 865 } 866 for (;;) { 867 if (*cp == '\\') { 868 ++cp; 869 if (*cp == 0) { 870 return -1; 871 } 872 } 873 else if (*cp == '\"') { 874 if (!quote) { 875 return -1; 876 } 877 ++np; 878 ++cp; 879 quote = 0; 880 state = 0; 881 break; 882 } 883 else if (!quote && (!*cp || isspace(*cp))) { 884 ++np; 885 if (*cp) ++cp; 886 state = 0; 887 break; 888 } 889 else if (*cp == 0) { 890 return -1; 891 } 892 ++cp; 893 } 894 if (quote) { 895 return -1; 896 } 897 break; 898 } 899 } 900 901 return (state == 0) ? np : -1; 902 } 903 904 NSAPI_PUBLIC int 905 INTpblock_str2pblock_lowercasename(const char *str, pblock *pb) 906 { 907 return _pblock_str2pblock(str, pb, PR_TRUE); 908 } 909 910 NSAPI_PUBLIC int pblock_str2pblock(const char *str, pblock *pb) 911 { 912 return _pblock_str2pblock(str, pb, PR_FALSE); 913 } 914 915 int 916 _pblock_str2pblock(const char* str, pblock* pb, PRBool lowerCase) 917 { 918 char *cpy; 919 char *cp; 920 char *dp; 921 char *pname; 922 char *pvalue; 923 int np; 924 int quote; 925 int state; 926 char numbuf[UTIL_ITOA_SIZE]; 927 928 if((np = _verify_pbstr(str)) < 1) 929 return -1; 930 931 while (*str && isspace(*str)) ++str; 932 933 cpy = STRDUP(str); 934 935 for (np = 0, cp = cpy, state = 0; *cp; ) { 936 switch (state) { 937 938 case 0: /* skipping leading spaces */ 939 940 while (*cp && isspace(*cp)) ++cp; 941 if (*cp) state = 1; 942 break; 943 944 case 1: /* scanning parameter name */ 945 946 pname = cp; 947 while (*cp && (*cp != '=') && !isspace(*cp)) ++cp; 948 if (*cp == '=') { 949 *cp++ = 0; 950 } 951 else { 952 cp = pname; 953 pname = numbuf; 954 util_itoa(np+1, numbuf); 955 } 956 state = 2; 957 break; 958 959 case 2: /* scanning parameter value */ 960 quote = 0; 961 if (*cp == '\"') { 962 quote = 1; 963 ++cp; 964 } 965 for (pvalue = cp, dp = cp; ; ++cp, ++dp) { 966 if (*cp == '\\') { 967 ++cp; 968 } 969 else if (*cp == '\"') { 970 ++np; 971 ++cp; 972 *dp = 0; 973 quote = 0; 974 state = 0; 975 break; 976 } 977 else if (!quote && ((*cp == 0) || isspace(*cp))) { 978 ++np; 979 if (*cp != 0) { 980 ++cp; 981 } 982 *dp = 0; 983 state = 0; 984 break; 985 } 986 if (cp != dp) *dp = *cp; 987 } 988 if (lowerCase == PR_TRUE) { 989 for (char* p = pname; *p; p++) { 990 *p = tolower(*p); 991 } 992 } 993 pblock_nvinsert(pname, pvalue, pb); 994 break; 995 } 996 } 997 998 FREE(cpy); 999 1000 return np; 1001 } 1002 1003 1004 /* -------------------------- pblock_pblock2str --------------------------- */ 1005 1006 1007 NSAPI_PUBLIC char *pblock_pblock2str(const pblock *pb, char *str) 1008 { 1009 register char *s = str, *t, *u; 1010 PListStruct_t *pl = PBTOPL(pb); 1011 PLValueStruct_t **ppval; 1012 PLValueStruct_t *pv; 1013 int i; 1014 int sl; 1015 int xlen; 1016 1017 ppval = (PLValueStruct_t **)(pl->pl_ppval); 1018 1019 /* Loop over the initialized property indices */ 1020 for (i = 0, xlen = 0; i < pl->pl_initpi; ++i) { 1021 1022 /* Got a property here? */ 1023 pv = ppval[i]; 1024 if (pv && pv->pv_name) { 1025 1026 int ln = strlen(pv->pv_name); 1027 int lv = strlen((char *)(pv->pv_value)); 1028 1029 /* Check for " or \ because we'll have to escape them */ 1030 for (t = (char *)(pv->pv_value); *t; ++t) { 1031 if ((*t == '\"') || (*t == '\\')) ++lv; 1032 } 1033 1034 /* 4: two quotes, =, and a null */ 1035 xlen += (ln + lv + 4); 1036 } 1037 } 1038 1039 /* Allocate string to hold parameter settings, or increase size */ 1040 if (!s) { 1041 s = (char *)MALLOC(xlen); 1042 s[0] = '\0'; 1043 t = &s[0]; 1044 sl = xlen; 1045 } 1046 else { 1047 sl = strlen(s); 1048 t = &s[sl]; 1049 sl += xlen; 1050 s = (char *)REALLOC(s, sl); 1051 } 1052 1053 /* Loop over the initialized property indices */ 1054 for (i = 0; i < pl->pl_initpi; ++i) { 1055 1056 /* Got a property here? */ 1057 pv = ppval[i]; 1058 if (pv && pv->pv_name) { 1059 1060 if (t != s) *t++ = ' '; 1061 1062 for (u = pv->pv_name; *u; ) *t++ = *u++; 1063 1064 *t++ = '='; 1065 *t++ = '\"'; 1066 1067 for (u = (char *)(pv->pv_value); *u; ) { 1068 if ((*u == '\\') || (*u == '\"')) *t++ = '\\'; 1069 *t++ = *u++; 1070 } 1071 1072 *t++ = '\"'; 1073 *t = '\0'; 1074 } 1075 } 1076 1077 return s; 1078 } 1079 1080 1081 /* ----------------------------- pblock_copy ------------------------------ */ 1082 1083 1084 NSAPI_PUBLIC int pblock_copy(const pblock *src, pblock *dst) 1085 { 1086 PListStruct_t *pl = PBTOPL(src); 1087 PLValueStruct_t **ppval; 1088 PLValueStruct_t *pv; 1089 int rv = 0; 1090 int i; 1091 1092 ppval = (PLValueStruct_t **)(pl->pl_ppval); 1093 1094 for (i = 0; i < pl->pl_initpi; ++i) { 1095 pv = ppval[i]; 1096 if (pv) { 1097 if (pv->pv_pbkey) { 1098 if (pv->pv_pbkey != pb_key_magnus_internal) { 1099 if (!pblock_kvinsert(pv->pv_pbkey, (char *)(pv->pv_value), strlen(pv->pv_value), dst)) 1100 rv = -1; 1101 } 1102 } else { 1103 if (!pblock_nvinsert(pv->pv_name, (char *)(pv->pv_value), dst)) 1104 rv = -1; 1105 } 1106 } 1107 } 1108 1109 return rv; 1110 } 1111 1112 /* ---------------------------- pblock_dup -------------------------------- */ 1113 1114 NSAPI_PUBLIC pblock *pblock_dup(const pblock *src) 1115 { 1116 pblock *dst; 1117 1118 if (!src) 1119 return NULL; 1120 1121 if ( (dst = pblock_create(src->hsize)) ) 1122 pblock_copy(src, dst); 1123 1124 return dst; 1125 } 1126 1127 1128 /* ---------------------------- pblock_pb2env ----------------------------- */ 1129 1130 1131 NSAPI_PUBLIC char **pblock_pb2env(const pblock *pb, char **env) 1132 { 1133 PListStruct_t *pl = PBTOPL(pb); 1134 PLValueStruct_t **ppval; 1135 PLValueStruct_t *pv; 1136 int i; 1137 int nval; 1138 int pos; 1139 1140 /* Find out how many there are. */ 1141 1142 ppval = (PLValueStruct_t **)(pl->pl_ppval); 1143 1144 for (i = 0, nval = 0; i < pl->pl_initpi; ++i) { 1145 if (ppval[i]) ++nval; 1146 } 1147 1148 env = util_env_create(env, nval, &pos); 1149 1150 for (i = 0; i < pl->pl_initpi; ++i) { 1151 pv = ppval[i]; 1152 if (pv) { 1153 env[pos++] = util_env_str(pv->pv_name, (char *)(pv->pv_value)); 1154 } 1155 } 1156 env[pos] = NULL; 1157 1158 return env; 1159 } 1160 1161 1162 /* ---------------------------- pblock_replace ---------------------------- */ 1163 1164 NSAPI_PUBLIC char * pblock_replace(const char *name, 1165 char * new_value, pblock *pb) 1166 { 1167 PListStruct_t *pl = PBTOPL(pb); 1168 1169 /* Replace an existing value */ 1170 pb_param *pp = pblock_find(name, pb); 1171 if (!pp) 1172 return NULL; 1173 pool_free(pl->pl_mempool, pp->value); 1174 pp->value = new_value; 1175 1176 return new_value; 1177 } 1178 1179 1180 /* --------------------------- pblock_nvreplace --------------------------- */ 1181 1182 NSAPI_PUBLIC void pblock_nvreplace (const char *name, const char *value, pblock *pb) 1183 { 1184 PListStruct_t *pl = PBTOPL(pb); 1185 1186 /* Replace an existing value or insert a new value */ 1187 pb_param *pp = pblock_find(name, pb); 1188 if (pp) { 1189 pool_free(pl->pl_mempool, pp->value); 1190 pp->value = pool_strdup(pl->pl_mempool, value); 1191 } else { 1192 pblock_nvinsert(name, value, pb); 1193 } 1194 } 1195 1196 1197 /* --------------------------- pblock_kvreplace --------------------------- */ 1198 1199 NSAPI_PUBLIC void pblock_kvreplace(const pb_key *key, const char *value, int valuelen, pblock *pb) 1200 { 1201 PListStruct_t *pl = PBTOPL(pb); 1202 1203 /* Replace an existing value or insert a new value */ 1204 pb_param *pp = pblock_findkey(key, pb); 1205 if (pp) { 1206 pool_free(pl->pl_mempool, pp->value); 1207 pp->value = (char*)pool_malloc(pl->pl_mempool, valuelen + 1); 1208 memcpy(pp->value, value, valuelen + 1); 1209 } else { 1210 pblock_kvinsert(key, value, valuelen, pb); 1211 } 1212 } 1213