| | 2286 | /* variable namespace */ |
| | 2287 | #ifdef IS_UNICODE |
| | 2288 | void xc_var_namespace_init_from_unicodel(const UChar *string, int len TSRMLS_DC) /* {{{ */ |
| | 2289 | { |
| | 2290 | if (!len) { |
| | 2291 | #ifdef IS_UNICODE |
| | 2292 | ZVAL_EMPTY_UNICODE(&XG(uvar_namespace_hard)); |
| | 2293 | #endif |
| | 2294 | ZVAL_EMPTY_STRING(&XG(var_namespace_hard)); |
| | 2295 | } |
| | 2296 | else { |
| | 2297 | ZVAL_UNICODE_L(&XG(uvar_namespace_hard), string, len, 1); |
| | 2298 | /* TODO: copy to var */ |
| | 2299 | } |
| | 2300 | } |
| | 2301 | /* }}} */ |
| | 2302 | #endif |
| | 2303 | void xc_var_namespace_init_from_stringl(const char *string, int len TSRMLS_DC) /* {{{ */ |
| | 2304 | { |
| | 2305 | if (!len) { |
| | 2306 | #ifdef IS_UNICODE |
| | 2307 | ZVAL_EMPTY_UNICODE(&XG(uvar_namespace_hard)); |
| | 2308 | #endif |
| | 2309 | ZVAL_EMPTY_STRING(&XG(var_namespace_hard)); |
| | 2310 | } |
| | 2311 | else { |
| | 2312 | ZVAL_STRINGL(&XG(var_namespace_hard), string, len, 1); |
| | 2313 | #ifdef IS_UNICODE |
| | 2314 | /* TODO: copy to uvar */ |
| | 2315 | #endif |
| | 2316 | } |
| | 2317 | } |
| | 2318 | /* }}} */ |
| | 2319 | void xc_var_namespace_init_from_long(long value TSRMLS_DC) /* {{{ */ |
| | 2320 | { |
| | 2321 | ZVAL_LONG(&XG(var_namespace_hard), value); |
| | 2322 | #ifdef IS_UNICODE |
| | 2323 | /* TODO: copy to uvar_namespace */ |
| | 2324 | #endif |
| | 2325 | } |
| | 2326 | /* }}} */ |
| | 2327 | #ifdef IS_UNICODE |
| | 2328 | void xc_var_namespace_set_unicodel(const UChar *unicode, int len TSRMLS_DC) /* {{{ */ |
| | 2329 | { |
| | 2330 | zval_dtor(&XG(uvar_namespace_soft)); |
| | 2331 | zval_dtor(&XG(var_namespace_soft)); |
| | 2332 | if (len) { |
| | 2333 | if (!Z_USTRLEN_P(&XG(uvar_namespace_soft))) { |
| | 2334 | ZVAL_UNICODEL(&XG(uvar_namespace_soft), unicode, len, 1); |
| | 2335 | } |
| | 2336 | else { |
| | 2337 | int buffer_len = Z_USTRLEN_P(&XG(var_namespace_hard)) + 1 + len; |
| | 2338 | char *buffer = emalloc((buffer_len + 1) * sizeof(unicode[0])); |
| | 2339 | char *p = buffer; |
| | 2340 | memcpy(p, Z_USTRVAL_P(&XG(var_namespace_hard)), (Z_USTRLEN_P(&XG(var_namespace_hard)) + 1)); |
| | 2341 | p += (Z_USTRLEN_P(&XG(var_namespace_hard)) + 1) * sizeof(unicode[0]); |
| | 2342 | memcpy(p, unicode, (len + 1) * sizeof(unicode[0])); |
| | 2343 | ZVAL_UNICODEL(&XG(uvar_namespace_soft), buffer, buffer_len, 0); |
| | 2344 | } |
| | 2345 | /* TODO: copy to var */ |
| | 2346 | } |
| | 2347 | else { |
| | 2348 | #ifdef IS_UNICODE |
| | 2349 | XG(uvar_namespace_soft) = XG(uvar_namespace_hard); |
| | 2350 | zval_copy_ctor(&XG(uvar_namespace_soft)); |
| | 2351 | #endif |
| | 2352 | XG(var_namespace_soft) = XG(var_namespace_hard); |
| | 2353 | zval_copy_ctor(&XG(var_namespace_soft)); |
| | 2354 | } |
| | 2355 | } |
| | 2356 | /* }}} */ |
| | 2357 | #endif |
| | 2358 | void xc_var_namespace_set_stringl(const char *string, int len TSRMLS_DC) /* {{{ */ |
| | 2359 | { |
| | 2360 | #ifdef IS_UNICODE |
| | 2361 | zval_dtor(&XG(uvar_namespace_soft)); |
| | 2362 | #endif |
| | 2363 | zval_dtor(&XG(var_namespace_soft)); |
| | 2364 | if (len) { |
| | 2365 | if (!Z_STRLEN_P(&XG(var_namespace_soft))) { |
| | 2366 | ZVAL_STRINGL(&XG(var_namespace_soft), string, len, 1); |
| | 2367 | } |
| | 2368 | else { |
| | 2369 | int buffer_len = Z_STRLEN_P(&XG(var_namespace_hard)) + 1 + len; |
| | 2370 | char *buffer = emalloc(buffer_len + 1); |
| | 2371 | char *p = buffer; |
| | 2372 | memcpy(p, Z_STRVAL_P(&XG(var_namespace_hard)), Z_STRLEN_P(&XG(var_namespace_hard)) + 1); |
| | 2373 | p += Z_STRLEN_P(&XG(var_namespace_hard)) + 1; |
| | 2374 | memcpy(p, string, len + 1); |
| | 2375 | ZVAL_STRINGL(&XG(var_namespace_soft), buffer, buffer_len, 0); |
| | 2376 | } |
| | 2377 | #ifdef IS_UNICODE |
| | 2378 | /* TODO: copy to uvar */ |
| | 2379 | #endif |
| | 2380 | } |
| | 2381 | else { |
| | 2382 | #ifdef IS_UNICODE |
| | 2383 | XG(uvar_namespace_soft) = XG(uvar_namespace_hard); |
| | 2384 | zval_copy_ctor(&XG(uvar_namespace_soft)); |
| | 2385 | #endif |
| | 2386 | XG(var_namespace_soft) = XG(var_namespace_hard); |
| | 2387 | zval_copy_ctor(&XG(var_namespace_soft)); |
| | 2388 | } |
| | 2389 | } |
| | 2390 | /* }}} */ |
| | 2391 | static void xc_var_namespace_break(TSRMLS_D) /* {{{ */ |
| | 2392 | { |
| | 2393 | #ifdef IS_UNICODE |
| | 2394 | zval_dtor(&XG(uvar_namespace_soft)); |
| | 2395 | #endif |
| | 2396 | zval_dtor(&XG(var_namespace_soft)); |
| | 2397 | #ifdef IS_UNICODE |
| | 2398 | ZVAL_EMPTY_UNICODE(&XG(uvar_namespace_soft)); |
| | 2399 | #endif |
| | 2400 | ZVAL_EMPTY_STRING(&XG(var_namespace_soft)); |
| | 2401 | } |
| | 2402 | /* }}} */ |
| | 2403 | static void xc_var_namespace_init(TSRMLS_D) /* {{{ */ |
| | 2404 | { |
| | 2405 | uid_t id = (uid_t) -1; |
| | 2406 | |
| | 2407 | switch (xc_var_namespace_mode) { |
| | 2408 | case 1: |
| | 2409 | { |
| | 2410 | zval **server; |
| | 2411 | HashTable *ht; |
| | 2412 | zval **val; |
| | 2413 | |
| | 2414 | #ifdef ZEND_ENGINE_2_1 |
| | 2415 | zend_is_auto_global("_SERVER", sizeof("_SERVER") - 1 TSRMLS_CC); |
| | 2416 | #endif |
| | 2417 | |
| | 2418 | if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void**)&server) == FAILURE |
| | 2419 | || Z_TYPE_PP(server) != IS_ARRAY |
| | 2420 | || !(ht = Z_ARRVAL_P(*server)) |
| | 2421 | || zend_hash_find(ht, xc_var_namespace, strlen(xc_var_namespace) + 1, (void**)&val) == FAILURE) { |
| | 2422 | xc_var_namespace_init_from_stringl(NULL, 0 TSRMLS_CC); |
| | 2423 | } |
| | 2424 | else { |
| | 2425 | #ifdef IS_UNICODE |
| | 2426 | if (Z_TYPE_PP(val) == IS_UNICODE) { |
| | 2427 | xc_var_namespace_init_from_unicodel(Z_USTRVAL_PP(val), Z_USTRLEN_PP(val) TSRMLS_CC); |
| | 2428 | } |
| | 2429 | else |
| | 2430 | #endif |
| | 2431 | { |
| | 2432 | xc_var_namespace_init_from_stringl(Z_STRVAL_PP(val), Z_STRLEN_PP(val) TSRMLS_CC); |
| | 2433 | } |
| | 2434 | } |
| | 2435 | } |
| | 2436 | break; |
| | 2437 | |
| | 2438 | case 2: |
| | 2439 | if (strncmp(xc_var_namespace, "uid", 3) == 0) { |
| | 2440 | id = getuid(); |
| | 2441 | } |
| | 2442 | else if (strncmp(xc_var_namespace, "gid", 3) == 0) { |
| | 2443 | id = getgid(); |
| | 2444 | } |
| | 2445 | |
| | 2446 | if (id == (uid_t) -1){ |
| | 2447 | xc_var_namespace_init_from_stringl(NULL, 0 TSRMLS_CC); |
| | 2448 | } |
| | 2449 | else { |
| | 2450 | xc_var_namespace_init_from_long((long) id TSRMLS_CC); |
| | 2451 | } |
| | 2452 | break; |
| | 2453 | |
| | 2454 | case 0: |
| | 2455 | default: |
| | 2456 | xc_var_namespace_init_from_stringl(xc_var_namespace, strlen(xc_var_namespace) TSRMLS_CC); |
| | 2457 | break; |
| | 2458 | } |
| | 2459 | |
| | 2460 | #ifdef IS_UNICODE |
| | 2461 | INIT_ZVAL(XG(uvar_namespace_soft)); |
| | 2462 | #endif |
| | 2463 | INIT_ZVAL(XG(var_namespace_soft)); |
| | 2464 | xc_var_namespace_set_stringl("", 0 TSRMLS_CC); |
| | 2465 | } |
| | 2466 | /* }}} */ |
| | 2467 | static void xc_var_namespace_destroy(TSRMLS_D) /* {{{ */ |
| | 2468 | { |
| | 2469 | #ifdef IS_UNICODE |
| | 2470 | zval_dtor(&XG(uvar_namespace_hard)); |
| | 2471 | zval_dtor(&XG(uvar_namespace_soft)); |
| | 2472 | #endif |
| | 2473 | zval_dtor(&XG(var_namespace_hard)); |
| | 2474 | zval_dtor(&XG(var_namespace_soft)); |
| | 2475 | } |
| | 2476 | /* }}} */ |
| | 2477 | static int xc_var_buffer_prepare(zval *name TSRMLS_DC) /* {{{ prepare name, calculate buffer size */ |
| | 2478 | { |
| | 2479 | int namespace_len; |
| | 2480 | switch (name->type) { |
| | 2481 | #ifdef IS_UNICODE |
| | 2482 | case IS_UNICODE: |
| | 2483 | do_unicode: |
| | 2484 | namespace_len = Z_USTRLEN_P(&XG(uvar_namespace_soft)); |
| | 2485 | return (namespace_len ? namespace_len + 1 : 0) + Z_USTRLEN_P(name); |
| | 2486 | #endif |
| | 2487 | |
| | 2488 | case IS_STRING: |
| | 2489 | do_string: |
| | 2490 | namespace_len = Z_STRLEN_P(&XG(var_namespace_soft)); |
| | 2491 | return (namespace_len ? namespace_len + 1 : 0) + Z_STRLEN_P(name); |
| | 2492 | |
| | 2493 | default: |
| | 2494 | #ifdef IS_UNICODE |
| | 2495 | convert_to_unicode(name); |
| | 2496 | goto do_unicode; |
| | 2497 | #else |
| | 2498 | convert_to_string(name); |
| | 2499 | goto do_string; |
| | 2500 | #endif |
| | 2501 | } |
| | 2502 | } |
| | 2503 | /* }}} */ |
| | 2504 | static int xc_var_buffer_alloca_size(zval *name TSRMLS_DC) /* {{{ prepare name, calculate buffer size */ |
| | 2505 | { |
| | 2506 | int namespace_len; |
| | 2507 | switch (name->type) { |
| | 2508 | #ifdef IS_UNICODE |
| | 2509 | case IS_UNICODE: |
| | 2510 | namespace_len = Z_USTRLEN_P(&XG(uvar_namespace_soft)); |
| | 2511 | return !namespace_len ? 0 : (namespace_len + 1 + Z_USTRLEN_P(name) + 1) * sizeof(Z_USTRVAL_P(&XG(uvar_namespace_soft))[0]); |
| | 2512 | #endif |
| | 2513 | |
| | 2514 | case IS_STRING: |
| | 2515 | namespace_len = Z_STRLEN_P(&XG(var_namespace_soft)); |
| | 2516 | return !namespace_len ? 0 : (namespace_len + 1 + Z_STRLEN_P(name) + 1); |
| | 2517 | } |
| | 2518 | assert(0); |
| | 2519 | return 0; |
| | 2520 | } |
| | 2521 | /* }}} */ |
| | 2522 | static void xc_var_buffer_init(char *buffer, zval *name TSRMLS_DC) /* {{{ prepare name, calculate buffer size */ |
| | 2523 | { |
| | 2524 | #ifdef IS_UNICODE |
| | 2525 | if (Z_TYPE(name) == IS_UNICODE) { |
| | 2526 | memcpy(buffer, Z_USTRVAL_P(&XG(uvar_namespace_soft)), (Z_USTRLEN_P(&XG(uvar_namespace_soft)) + 1) * sizeof(Z_USTRVAL_P(name)[0])); |
| | 2527 | buffer += (Z_USTRLEN_P(&XG(uvar_namespace_soft)) + 1) * sizeof(Z_USTRVAL_P(name)[0]); |
| | 2528 | memcpy(buffer, Z_USTRVAL_P(name), (Z_USTRLEN_P(name) + 1) * sizeof(Z_USTRVAL_P(name)[0])); |
| | 2529 | } |
| | 2530 | #endif |
| | 2531 | memcpy(buffer, Z_STRVAL_P(&XG(var_namespace_soft)), (Z_STRLEN_P(&XG(var_namespace_soft)) + 1)); |
| | 2532 | buffer += (Z_STRLEN_P(&XG(var_namespace_soft)) + 1); |
| | 2533 | memcpy(buffer, Z_STRVAL_P(name), (Z_STRLEN_P(name) + 1)); |
| | 2534 | } |
| | 2535 | /* }}} */ |
| | 2536 | typedef struct xc_namebuffer_t_ { /* {{{ */ |
| | 2537 | ALLOCA_FLAG(useheap); |
| | 2538 | void *buffer; |
| | 2539 | int alloca_size; |
| | 2540 | int len; |
| | 2541 | } xc_namebuffer_t; |
| | 2542 | /* }}} */ |
| | 2543 | |
| | 2544 | #define VAR_BUFFER_FLAGS(name) \ |
| | 2545 | xc_namebuffer_t name##_buffer; |
| | 2546 | |
| | 2547 | #define VAR_BUFFER_INIT(name) \ |
| | 2548 | name##_buffer.len = xc_var_buffer_prepare(name TSRMLS_CC); \ |
| | 2549 | name##_buffer.alloca_size = xc_var_buffer_alloca_size(name TSRMLS_CC); \ |
| | 2550 | name##_buffer.buffer = name##_buffer.alloca_size \ |
| | 2551 | ? do_alloca(name##_buffer.alloca_size, name##_buffer.useheap) \ |
| | 2552 | : UNISW(Z_STRVAL_P(name), Z_TYPE(name) == IS_UNICODE ? Z_USTRVAL_P(name) : Z_STRVAL_P(name)); \ |
| | 2553 | if (name##_buffer.alloca_size) xc_var_buffer_init(name##_buffer.buffer, name TSRMLS_CC); |
| | 2554 | |
| | 2555 | #define VAR_BUFFER_FREE(name) \ |
| | 2556 | if (name##_buffer.alloca_size) { \ |
| | 2557 | free_alloca(name##_buffer.buffer, name##_buffer.useheap); \ |
| | 2558 | } |
| | 2559 | |
| | 2560 | static inline int xc_var_has_prefix(xc_entry_t *entry, zval *prefix TSRMLS_DC) /* {{{ */ |
| | 2561 | { |
| | 2562 | zend_bool result = 0; |
| | 2563 | VAR_BUFFER_FLAGS(prefix); |
| | 2564 | |
| | 2565 | if (UNISW(IS_STRING, entry->name_type) != prefix->type) { |
| | 2566 | return 0; |
| | 2567 | } |
| | 2568 | VAR_BUFFER_INIT(prefix); |
| | 2569 | |
| | 2570 | #ifdef IS_UNICODE |
| | 2571 | if (Z_TYPE(prefix) == IS_UNICODE) { |
| | 2572 | result = entry->name.ustr.len >= prefix_buffer.len |
| | 2573 | && memcmp(entry->name.ustr.val, prefix_buffer.buffer, prefix_buffer.len * sizeof(Z_USTRVAL_P(prefix)[0])) == 0; |
| | 2574 | goto finish; |
| | 2575 | } |
| | 2576 | #endif |
| | 2577 | |
| | 2578 | result = entry->name.str.len >= prefix_buffer.len |
| | 2579 | && memcmp(entry->name.str.val, prefix_buffer.buffer, prefix_buffer.len) == 0; |
| | 2580 | goto finish; |
| | 2581 | |
| | 2582 | finish: |
| | 2583 | VAR_BUFFER_FREE(prefix); |
| | 2584 | return result; |
| | 2585 | } |
| | 2586 | /* }}} */ |
| | 2587 | |