src/server/util/pblock.cpp

changeset 386
b91f8efadb63
parent 385
a1f4cb076d2f
parent 365
2ea1ed291e9f
child 387
f5caf41b4db6
equal deleted inserted replaced
385:a1f4cb076d2f 386:b91f8efadb63
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 const pb_key *const pb_key_depth = _create_key("depth");
328 const pb_key *const pb_key_if = _create_key("if");
329 const pb_key *const pb_key_vfs = _create_key("vfs");
330 const pb_key *const pb_key_dav = _create_key("dav");
331 const pb_key *const pb_key_vfsclass = _create_key("vfsclass");
332 const pb_key *const pb_key_davclass = _create_key("davclass");
333
334 /* ------------------------------ _find_key ------------------------------- */
335
336 static inline const pb_key *_find_key(const char *name, unsigned int hashval)
337 {
338 /* Check to see if name corresponds to a pb_key */
339 CListConstIterator<pb_key> iter(&_hashKeys.Find(hashval));
340 const pb_key *key;
341 while((key = ++iter)) {
342 if (key->hashval == hashval && !strcmp(key->name, name))
343 return key;
344 }
345 return NULL;
346 }
347
348
349 /* --------------------------- _get_hash_index ---------------------------- */
350
351 static inline int _get_hash_index(const PListStruct_t *pl, const pb_key *key)
352 {
353 /* Get the hash index from the key. Requires a symbol table. */
354 int i;
355 if (key->sizendx == pl->pl_symtab->pt_sizendx)
356 i = key->hashndx;
357 else
358 i = key->hashval % PLSIZENDX(pl->pl_symtab->pt_sizendx);
359 return i;
360 }
361
362
363 /* ---------------------------- _param_create ----------------------------- */
364
365 static inline pb_param *_param_create(pool_handle_t *pool_handle, const char *name, int namelen, const char *value, int valuelen)
366 {
367 PLValueStruct_t *ret;
368
369 ret = (PLValueStruct_t *)pool_malloc(pool_handle, sizeof(PLValueStruct_t));
370
371 ret->pv_pbentry.param = &ret->pv_pbparam;
372 ret->pv_pbentry.next = 0;
373 ret->pv_next = 0;
374 ret->pv_type = 0;
375 ret->pv_mempool = pool_handle;
376
377 if (name || namelen) {
378 ret->pv_name = (char*)pool_malloc(pool_handle, namelen + 1);
379 if (name) {
380 memcpy(ret->pv_name, name, namelen);
381 ret->pv_name[namelen] = '\0';
382 } else {
383 ret->pv_name[0] = '\0';
384 }
385 } else {
386 ret->pv_name = 0;
387 }
388
389 if (value || valuelen) {
390 ret->pv_value = (char*)pool_malloc(pool_handle, valuelen + 1);
391 if (value) {
392 memcpy(ret->pv_value, value, valuelen);
393 ret->pv_value[valuelen] = '\0';
394 } else {
395 ret->pv_value[0] = '\0';
396 }
397 } else {
398 ret->pv_value = 0;
399 }
400
401 return &ret->pv_pbparam;
402 }
403
404
405 /* ----------------------- pblock_key_param_create ----------------------- */
406
407 NSAPI_PUBLIC pb_param *pblock_key_param_create(pblock *pb, const pb_key *key, const char *value, int valuelen)
408 {
409 /*
410 * Allocate a PLValueStruct_t from the property list's memory pool.
411 */
412 PListStruct_t *pl = PBTOPL(pb);
413 return _param_create(pl->pl_mempool, key->name, key->namelen, value, valuelen);
414 }
415
416
417 /* ------------------------- pblock_param_create -------------------------- */
418
419 NSAPI_PUBLIC pb_param *pblock_param_create(pblock *pb, const char *name, const char *value)
420 {
421 /*
422 * Allocate a PLValueStruct_t from the property list's memory pool.
423 */
424 PListStruct_t *pl = PBTOPL(pb);
425 return _param_create(pl->pl_mempool, name, name ? strlen(name) : 0, value, value ? strlen(value) : 0);
426 }
427
428
429 /* ----------------------------- param_create ----------------------------- */
430
431 NSAPI_PUBLIC pb_param *param_create(const char *name, const char *value)
432 {
433 /*
434 * Allocate a PLValueStruct_t containing the pb_param that will
435 * be returned. Normally PLValueStruct_ts are allocated from the
436 * memory pool associated with a property list, but we don't have
437 * that here, so we just use the thread's pool and indicate we were
438 * allocated from a specific pool.
439 */
440 return _param_create(system_pool(), name, name ? strlen(name) : 0, value, value ? strlen(value) : 0);
441 }
442
443
444 /* ------------------------------ param_free ------------------------------ */
445
446 NSAPI_PUBLIC int param_free(pb_param *pp)
447 {
448 if (pp) {
449 PLValueStruct_t *pv = PATOPV(pp);
450
451 /* Don't bother if the pblock was allocated from a pool */
452 if (!pv->pv_mempool) {
453 pool_free(pv->pv_mempool, pv->pv_name);
454 pool_free(pv->pv_mempool, pv->pv_value);
455 pool_free(pv->pv_mempool, pv);
456 }
457
458 return 1;
459 }
460
461 return 0;
462 }
463
464
465 /* -------------------------- pblock_create_pool -------------------------- */
466
467 NSAPI_PUBLIC pblock *pblock_create_pool(pool_handle_t *pool_handle, int n)
468 {
469 /* Create a property list with n property indices */
470 PListStruct_t *plist = (PListStruct_t *)PListCreate(pool_handle, n, 0, 0);
471 if (!plist)
472 return NULL;
473
474 plist->pl_resvpi = 0;
475
476 return &plist->pl_pb;
477 }
478
479
480 /* ----------------------------- pblock_pool ------------------------------ */
481
482 NSAPI_PUBLIC pool_handle_t *pblock_pool(pblock *pb)
483 {
484 PListStruct_t *pl = PBTOPL(pb);
485 return pl->pl_mempool;
486 }
487
488
489 /* ---------------------------- pblock_create ----------------------------- */
490
491 NSAPI_PUBLIC pblock *pblock_create(int n)
492 {
493 return pblock_create_pool(MALLOC_POOL_HANDLE, n);
494 }
495
496
497 /* ----------------------------- pblock_free ------------------------------ */
498
499 NSAPI_PUBLIC void pblock_free(pblock *pb)
500 {
501 PListStruct_t *pl = PBTOPL(pb);
502 PLValueStruct_t **ppval;
503 PLValueStruct_t *pv;
504 int i;
505
506 if (!pb) {
507 return;
508 }
509
510 /* If the pools are enabled, this routine has no effect anyway, so
511 * just return.
512 */
513 if (pl->pl_mempool || pool_enabled()) {
514 return;
515 }
516
517 /* Free the property name symbol table if any */
518 if (pl->pl_symtab) {
519 pool_free(pl->pl_mempool, (void *)(pl->pl_symtab));
520 }
521
522 ppval = (PLValueStruct_t **)(pl->pl_ppval);
523
524 /* Loop over the initialized property indices */
525 for (i = 0; i < pl->pl_initpi; ++i) {
526
527 /* Got a property here? */
528 pv = ppval[i];
529 if (pv) {
530
531 param_free(&pv->pv_pbparam);
532 }
533 }
534
535 /* Free the array of pointers to property values */
536 pool_free(pl->pl_mempool, (void *)ppval);
537
538 /* Free the property list head */
539 pool_free(pl->pl_mempool, (void *)pl);
540 }
541
542
543 /* ------------------------------ pblock_key ------------------------------ */
544
545 NSAPI_PUBLIC const pb_key *pblock_key(const char *name)
546 {
547 if (!name)
548 return NULL;
549
550 return _find_key(name, PListHash(name));
551 }
552
553
554 /* --------------------------- pblock_kpinsert ---------------------------- */
555
556 NSAPI_PUBLIC void pblock_kpinsert(const pb_key *key, pb_param *pp, pblock *pb)
557 {
558 PListStruct_t *pl = PBTOPL(pb);
559 PLValueStruct_t *pv = PATOPV(pp);
560
561 //PR_ASSERT(pv->pv_mempool == pl->pl_mempool); // TODO
562
563 /* Check to see if the name corresponds to a pb_key */
564 unsigned int hashval;
565 if (!key) {
566 hashval = PListHash(pv->pv_name);
567 key = _find_key(pv->pv_name, hashval);
568 }
569
570 /* Find property index */
571 int pindex = PListGetFreeIndex(pl);
572 if (pindex < 1) {
573 /* Error - invalid property index */
574 printf("Error - invalid property index\n");
575 return;
576 }
577
578 /* Allocate/grow the symbol table as needed */
579 PLSymbolTable_t *pt = PListSymbolTable(pl);
580 if (!pt) {
581 printf("!pt\n");
582 return;
583 }
584
585 /* Add PLValueStruct_t to the property list */
586 PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval);
587 pv->pv_pbkey = key;
588 pv->pv_pi = pindex;
589 ppval[pv->pv_pi - 1] = pv;
590
591 /* Add name to symbol table */
592 int i = key ? _get_hash_index(pl, key) : (hashval % PLSIZENDX(pt->pt_sizendx));
593 pv->pv_next = pt->pt_hash[i];
594 pt->pt_hash[i] = pv;
595 pt->pt_nsyms++;
596
597 //PR_ASSERT(param_key(pp) == key); // TODO
598 }
599
600
601 /* ---------------------------- pblock_pinsert ---------------------------- */
602
603 NSAPI_PUBLIC void pblock_pinsert(pb_param *pp, pblock *pb)
604 {
605 pblock_kpinsert(NULL, pp, pb);
606 }
607
608
609 /* --------------------------- pblock_nvinsert ---------------------------- */
610
611 NSAPI_PUBLIC pb_param *pblock_nvinsert(const char *name, const char *value, pblock *pb)
612 {
613 pb_param *pp = pblock_param_create(pb, name, value);
614 if (pp)
615 pblock_kpinsert(NULL, pp, pb);
616 return pp;
617 }
618
619
620 /* --------------------------- pblock_kvinsert ---------------------------- */
621
622 NSAPI_PUBLIC pb_param *pblock_kvinsert(const pb_key *key, const char *value, int valuelen, pblock *pb)
623 {
624 pb_param *pp = pblock_key_param_create(pb, key, value, valuelen);
625 if (pp)
626 pblock_kpinsert(key, pp, pb);
627 return pp;
628 }
629
630
631 /* --------------------------- pblock_nninsert ---------------------------- */
632
633 NSAPI_PUBLIC pb_param *pblock_nninsert(const char *name, int value, pblock *pb)
634 {
635 char num[UTIL_ITOA_SIZE];
636
637 util_itoa(value, num);
638 return pblock_nvinsert(name, num, pb);
639 }
640
641
642 /* --------------------------- pblock_kninsert ---------------------------- */
643
644 NSAPI_PUBLIC pb_param *pblock_kninsert(const pb_key *key, int value, pblock *pb)
645 {
646 pb_param *pp = pblock_key_param_create(pb, key, NULL, UTIL_ITOA_SIZE);
647 if (pp) {
648 util_itoa(value, pp->value);
649 pblock_kpinsert(key, pp, pb);
650 }
651 return pp;
652 }
653
654
655 /* --------------------------- pblock_kllinsert --------------------------- */
656
657 NSAPI_PUBLIC pb_param *pblock_kllinsert(const pb_key *key, int64_t value, pblock *pb)
658 {
659 pb_param *pp = pblock_key_param_create(pb, key, NULL, UTIL_I64TOA_SIZE);
660 if (pp) {
661 util_i64toa(value, pp->value);
662 pblock_kpinsert(key, pp, pb);
663 }
664 return pp;
665 }
666
667
668 /* ---------------------------pblock_nvlinsert ---------------------------- */
669
670 NSAPI_PUBLIC pb_param *pblock_nvlinsert(const char *name, int namelen, const char *value, int valuelen, pblock *pb)
671 {
672 PListStruct_t *pl = PBTOPL(pb);
673
674 pb_param *pp = _param_create(pl->pl_mempool, name, namelen, value, valuelen);
675
676 if(pp) {
677 pblock_kpinsert(NULL, pp, pb);
678 }
679
680 return pp;
681 }
682
683
684 /* ---------------------------- pblock_findkey ---------------------------- */
685
686 NSAPI_PUBLIC pb_param *pblock_findkey(const pb_key *key, const pblock *pb)
687 {
688 PListStruct_t *pl = PBTOPL(pb);
689
690 /* Lookup key by examining symbol table */
691 if (pl->pl_symtab) {
692 int i = _get_hash_index(pl, key);
693 PLValueStruct_t *pv;
694
695 /* Search hash collision list for matching name */
696 for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
697 if (pv->pv_pbkey == key)
698 return &pv->pv_pbparam;
699 }
700 }
701
702 return NULL;
703 }
704
705
706 /* -------------------------- pblock_findkeyval --------------------------- */
707
708 NSAPI_PUBLIC char *pblock_findkeyval(const pb_key *key, const pblock *pb)
709 {
710 pb_param *pp = pblock_findkey(key, pb);
711 return pp ? pp->value : NULL;
712 }
713
714
715 /* ---------------------------- pblock_findval ---------------------------- */
716
717 NSAPI_PUBLIC char *pblock_findval(const char *name, const pblock *pb)
718 {
719 void *pvalue = 0;
720
721 (void)PListFindValue((PList_t)(PBTOPL(pb)), name, &pvalue, 0);
722
723 return (char *)pvalue;
724 }
725
726
727 /* ------------------------------ pblock_fr ------------------------------ */
728
729 NSAPI_PUBLIC pb_param *pblock_fr(const char *name, pblock *pb, int remove)
730 {
731 PListStruct_t *pl = PBTOPL(pb);
732 PLValueStruct_t **ppval;
733 PLValueStruct_t **pvp;
734 PLValueStruct_t *pv = NULL;
735 int pindex;
736 int i;
737
738 if (pl->pl_symtab) {
739
740 /* Compute hash index of specified property name */
741 i = PListHashName(pl->pl_symtab, name);
742
743 /* Search hash collision list for matching name */
744 for (pvp = &pl->pl_symtab->pt_hash[i];
745 (pv = *pvp); pvp = &(*pvp)->pv_next) {
746
747 if (!strcmp(name, pv->pv_name)) {
748
749 if (remove) {
750 /* Remove PLValueStruct_t from symbol table */
751 *pvp = pv->pv_next;
752 pl->pl_symtab->pt_nsyms--;
753
754 /* Remove it from pl_ppval too */
755 ppval = (PLValueStruct_t **)(pl->pl_ppval);
756 pindex = pv->pv_pi;
757 ppval[pindex - 1] = 0;
758 }
759 break;
760 }
761 }
762 }
763
764 return (pv) ? &pv->pv_pbparam : NULL;
765 }
766
767
768 /* --------------------------- pblock_removekey --------------------------- */
769
770 NSAPI_PUBLIC pb_param *pblock_removekey(const pb_key *key, pblock *pb)
771 {
772 PListStruct_t *pl = PBTOPL(pb);
773 PLValueStruct_t **ppval;
774 PLValueStruct_t **pvp;
775 PLValueStruct_t *pv = NULL;
776 int pindex;
777 int i;
778
779 if (pl->pl_symtab) {
780 /* Lookup hash index for specified property key */
781 i = _get_hash_index(pl, key);
782
783 /* Search hash collision list for matching key */
784 for (pvp = &pl->pl_symtab->pt_hash[i]; (pv = *pvp); pvp = &pv->pv_next) {
785 /* If this value has the requested key... */
786 if (pv->pv_pbkey == key) {
787 /* Remove PLValueStruct_t from symbol table */
788 *pvp = pv->pv_next;
789 pl->pl_symtab->pt_nsyms--;
790
791 /* Remove it from pl_ppval too */
792 ppval = (PLValueStruct_t **)(pl->pl_ppval);
793 pindex = pv->pv_pi;
794 ppval[pindex - 1] = 0;
795
796 break;
797 }
798 }
799 }
800
801 return (pv) ? &pv->pv_pbparam : NULL;
802 }
803
804
805 /* -------------------------- pblock_removeone --------------------------- */
806
807 NSAPI_PUBLIC pb_param *pblock_removeone(pblock *pb)
808 {
809 PListStruct_t *pl = PBTOPL(pb);
810
811 if (pl && pl->pl_symtab) {
812 /* Search hash buckets */
813 for (int i = 0; i < PLSIZENDX(pl->pl_symtab->pt_sizendx); i++) {
814 /* Search hash collision list */
815 PLValueStruct_t *pv = pl->pl_symtab->pt_hash[i];
816 if (pv) {
817 /* Remove PLValueStruct_t from symbol table */
818 pl->pl_symtab->pt_hash[i] = pv->pv_next;
819 pl->pl_symtab->pt_nsyms--;
820
821 /* Remove it from pl_ppval too */
822 PLValueStruct_t **ppval = (PLValueStruct_t**)pl->pl_ppval;
823 ppval[pv->pv_pi - 1] = 0;
824
825 return &pv->pv_pbparam;
826 }
827 }
828 }
829
830 return NULL;
831 }
832
833
834 /* -------------------------- pblock_str2pblock --------------------------- */
835
836
837 int _verify_pbstr(const char *str)
838 {
839 const char *cp;
840 const char *scp;
841 int np;
842 int state;
843 int quote;
844
845 for(cp = str, np = 0, state = 0; *cp; ) {
846 switch (state) {
847 case 0: /* skipping leading spaces */
848
849 while (*cp && isspace(*cp)) ++cp;
850 if (*cp == '=') {
851 return -1;
852 }
853 if (*cp) state = 1;
854 break;
855
856 case 1: /* scanning parameter name */
857
858 scp = cp;
859 while (*cp && (*cp != '=') && !isspace(*cp)) ++cp;
860 if (*cp == '=') ++cp;
861 else cp = scp;
862 state = 2;
863 break;
864
865 case 2: /* scanning parameter value */
866 quote = 0;
867 if (*cp == '\"') {
868 quote = 1;
869 ++cp;
870 }
871 for (;;) {
872 if (*cp == '\\') {
873 ++cp;
874 if (*cp == 0) {
875 return -1;
876 }
877 }
878 else if (*cp == '\"') {
879 if (!quote) {
880 return -1;
881 }
882 ++np;
883 ++cp;
884 quote = 0;
885 state = 0;
886 break;
887 }
888 else if (!quote && (!*cp || isspace(*cp))) {
889 ++np;
890 if (*cp) ++cp;
891 state = 0;
892 break;
893 }
894 else if (*cp == 0) {
895 return -1;
896 }
897 ++cp;
898 }
899 if (quote) {
900 return -1;
901 }
902 break;
903 }
904 }
905
906 return (state == 0) ? np : -1;
907 }
908
909 NSAPI_PUBLIC int
910 INTpblock_str2pblock_lowercasename(const char *str, pblock *pb)
911 {
912 return _pblock_str2pblock(str, pb, PR_TRUE);
913 }
914
915 NSAPI_PUBLIC int pblock_str2pblock(const char *str, pblock *pb)
916 {
917 return _pblock_str2pblock(str, pb, PR_FALSE);
918 }
919
920 int
921 _pblock_str2pblock(const char* str, pblock* pb, PRBool lowerCase)
922 {
923 char *cpy;
924 char *cp;
925 char *dp;
926 char *pname;
927 char *pvalue;
928 int np;
929 int quote;
930 int state;
931 char numbuf[UTIL_ITOA_SIZE];
932
933 if((np = _verify_pbstr(str)) < 1)
934 return -1;
935
936 while (*str && isspace(*str)) ++str;
937
938 cpy = STRDUP(str);
939
940 for (np = 0, cp = cpy, state = 0; *cp; ) {
941 switch (state) {
942
943 case 0: /* skipping leading spaces */
944
945 while (*cp && isspace(*cp)) ++cp;
946 if (*cp) state = 1;
947 break;
948
949 case 1: /* scanning parameter name */
950
951 pname = cp;
952 while (*cp && (*cp != '=') && !isspace(*cp)) ++cp;
953 if (*cp == '=') {
954 *cp++ = 0;
955 }
956 else {
957 cp = pname;
958 pname = numbuf;
959 util_itoa(np+1, numbuf);
960 }
961 state = 2;
962 break;
963
964 case 2: /* scanning parameter value */
965 quote = 0;
966 if (*cp == '\"') {
967 quote = 1;
968 ++cp;
969 }
970 for (pvalue = cp, dp = cp; ; ++cp, ++dp) {
971 if (*cp == '\\') {
972 ++cp;
973 }
974 else if (*cp == '\"') {
975 ++np;
976 ++cp;
977 *dp = 0;
978 quote = 0;
979 state = 0;
980 break;
981 }
982 else if (!quote && ((*cp == 0) || isspace(*cp))) {
983 ++np;
984 if (*cp != 0) {
985 ++cp;
986 }
987 *dp = 0;
988 state = 0;
989 break;
990 }
991 if (cp != dp) *dp = *cp;
992 }
993 if (lowerCase == PR_TRUE) {
994 for (char* p = pname; *p; p++) {
995 *p = tolower(*p);
996 }
997 }
998 pblock_nvinsert(pname, pvalue, pb);
999 break;
1000 }
1001 }
1002
1003 FREE(cpy);
1004
1005 return np;
1006 }
1007
1008
1009 /* -------------------------- pblock_pblock2str --------------------------- */
1010
1011
1012 NSAPI_PUBLIC char *pblock_pblock2str(const pblock *pb, char *str)
1013 {
1014 register char *s = str, *t, *u;
1015 PListStruct_t *pl = PBTOPL(pb);
1016 PLValueStruct_t **ppval;
1017 PLValueStruct_t *pv;
1018 int i;
1019 int sl;
1020 int xlen;
1021
1022 ppval = (PLValueStruct_t **)(pl->pl_ppval);
1023
1024 /* Loop over the initialized property indices */
1025 for (i = 0, xlen = 0; i < pl->pl_initpi; ++i) {
1026
1027 /* Got a property here? */
1028 pv = ppval[i];
1029 if (pv && pv->pv_name) {
1030
1031 int ln = strlen(pv->pv_name);
1032 int lv = strlen((char *)(pv->pv_value));
1033
1034 /* Check for " or \ because we'll have to escape them */
1035 for (t = (char *)(pv->pv_value); *t; ++t) {
1036 if ((*t == '\"') || (*t == '\\')) ++lv;
1037 }
1038
1039 /* 4: two quotes, =, and a null */
1040 xlen += (ln + lv + 4);
1041 }
1042 }
1043
1044 /* Allocate string to hold parameter settings, or increase size */
1045 if (!s) {
1046 s = (char *)MALLOC(xlen);
1047 s[0] = '\0';
1048 t = &s[0];
1049 sl = xlen;
1050 }
1051 else {
1052 sl = strlen(s);
1053 t = &s[sl];
1054 sl += xlen;
1055 s = (char *)REALLOC(s, sl);
1056 }
1057
1058 /* Loop over the initialized property indices */
1059 for (i = 0; i < pl->pl_initpi; ++i) {
1060
1061 /* Got a property here? */
1062 pv = ppval[i];
1063 if (pv && pv->pv_name) {
1064
1065 if (t != s) *t++ = ' ';
1066
1067 for (u = pv->pv_name; *u; ) *t++ = *u++;
1068
1069 *t++ = '=';
1070 *t++ = '\"';
1071
1072 for (u = (char *)(pv->pv_value); *u; ) {
1073 if ((*u == '\\') || (*u == '\"')) *t++ = '\\';
1074 *t++ = *u++;
1075 }
1076
1077 *t++ = '\"';
1078 *t = '\0';
1079 }
1080 }
1081
1082 return s;
1083 }
1084
1085
1086 /* ----------------------------- pblock_copy ------------------------------ */
1087
1088
1089 NSAPI_PUBLIC int pblock_copy(const pblock *src, pblock *dst)
1090 {
1091 PListStruct_t *pl = PBTOPL(src);
1092 PLValueStruct_t **ppval;
1093 PLValueStruct_t *pv;
1094 int rv = 0;
1095 int i;
1096
1097 ppval = (PLValueStruct_t **)(pl->pl_ppval);
1098
1099 for (i = 0; i < pl->pl_initpi; ++i) {
1100 pv = ppval[i];
1101 if (pv) {
1102 if (pv->pv_pbkey) {
1103 if (pv->pv_pbkey != pb_key_magnus_internal) {
1104 if (!pblock_kvinsert(pv->pv_pbkey, (char *)(pv->pv_value), strlen(pv->pv_value), dst))
1105 rv = -1;
1106 }
1107 } else {
1108 if (!pblock_nvinsert(pv->pv_name, (char *)(pv->pv_value), dst))
1109 rv = -1;
1110 }
1111 }
1112 }
1113
1114 return rv;
1115 }
1116
1117 /* ---------------------------- pblock_dup -------------------------------- */
1118
1119 NSAPI_PUBLIC pblock *pblock_dup(const pblock *src)
1120 {
1121 pblock *dst;
1122
1123 if (!src)
1124 return NULL;
1125
1126 if ( (dst = pblock_create(src->hsize)) )
1127 pblock_copy(src, dst);
1128
1129 return dst;
1130 }
1131
1132
1133 /* ---------------------------- pblock_pb2env ----------------------------- */
1134
1135
1136 NSAPI_PUBLIC char **pblock_pb2env(const pblock *pb, char **env)
1137 {
1138 PListStruct_t *pl = PBTOPL(pb);
1139 PLValueStruct_t **ppval;
1140 PLValueStruct_t *pv;
1141 int i;
1142 int nval;
1143 int pos;
1144
1145 /* Find out how many there are. */
1146
1147 ppval = (PLValueStruct_t **)(pl->pl_ppval);
1148
1149 for (i = 0, nval = 0; i < pl->pl_initpi; ++i) {
1150 if (ppval[i]) ++nval;
1151 }
1152
1153 env = util_env_create(env, nval, &pos);
1154
1155 for (i = 0; i < pl->pl_initpi; ++i) {
1156 pv = ppval[i];
1157 if (pv) {
1158 env[pos++] = util_env_str(pv->pv_name, (char *)(pv->pv_value));
1159 }
1160 }
1161 env[pos] = NULL;
1162
1163 return env;
1164 }
1165
1166
1167 /* ---------------------------- pblock_replace ---------------------------- */
1168
1169 NSAPI_PUBLIC char * pblock_replace(const char *name,
1170 char * new_value, pblock *pb)
1171 {
1172 PListStruct_t *pl = PBTOPL(pb);
1173
1174 /* Replace an existing value */
1175 pb_param *pp = pblock_find(name, pb);
1176 if (!pp)
1177 return NULL;
1178 pool_free(pl->pl_mempool, pp->value);
1179 pp->value = new_value;
1180
1181 return new_value;
1182 }
1183
1184
1185 /* --------------------------- pblock_nvreplace --------------------------- */
1186
1187 NSAPI_PUBLIC void pblock_nvreplace (const char *name, const char *value, pblock *pb)
1188 {
1189 PListStruct_t *pl = PBTOPL(pb);
1190
1191 /* Replace an existing value or insert a new value */
1192 pb_param *pp = pblock_find(name, pb);
1193 if (pp) {
1194 pool_free(pl->pl_mempool, pp->value);
1195 pp->value = pool_strdup(pl->pl_mempool, value);
1196 } else {
1197 pblock_nvinsert(name, value, pb);
1198 }
1199 }
1200
1201
1202 /* --------------------------- pblock_kvreplace --------------------------- */
1203
1204 NSAPI_PUBLIC void pblock_kvreplace(const pb_key *key, const char *value, int valuelen, pblock *pb)
1205 {
1206 PListStruct_t *pl = PBTOPL(pb);
1207
1208 /* Replace an existing value or insert a new value */
1209 pb_param *pp = pblock_findkey(key, pb);
1210 if (pp) {
1211 pool_free(pl->pl_mempool, pp->value);
1212 pp->value = (char*)pool_malloc(pl->pl_mempool, valuelen + 1);
1213 memcpy(pp->value, value, valuelen + 1);
1214 } else {
1215 pblock_kvinsert(key, value, valuelen, pb);
1216 }
1217 }

mercurial