[svn:PHP-Sandwich] rev 1077 - PHP-Sandwich/trunk

[email protected] 8 Jun 2005 14:14:04 -0000
Newsgroups perl.php.sandwich.dev
Message-ID <[email protected]>
Author: gschlossnagle
Date: Wed Jun  8 07:14:03 2005
New Revision: 1077

Modified:
   PHP-Sandwich/trunk/PHP.xs
Log:
add ability to pass optional autoglobals data as a hashref to PHP::Interpreter 
constructor.



Modified: PHP-Sandwich/trunk/PHP.xs
==============================================================================
--- PHP-Sandwich/trunk/PHP.xs	(original)
+++ PHP-Sandwich/trunk/PHP.xs	Wed Jun  8 07:14:03 2005
@@ -328,12 +328,91 @@ static int get_class_name(zval *z, char 
   return 0;
 }
 
+static void my_autoglobal_merge(HashTable *dest, HashTable *src TSRMLS_DC)
+{
+  zval **src_entry, **dest_entry;
+  char *string_key;
+  uint string_key_len;
+  ulong num_key;
+  HashPosition pos;
+  int key_type;
+  int globals_check = (PG(register_globals) && (dest == (&EG(symbol_table))));
+
+  zend_hash_internal_pointer_reset_ex(src, &pos);
+  while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) {
+    key_type = zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key,
+ 0, &pos);
+    if (Z_TYPE_PP(src_entry) != IS_ARRAY
+      || (key_type == HASH_KEY_IS_STRING && zend_hash_find(dest, string_key, string_key_len, (void **) &dest_entry) != SUCCESS)
+      || (key_type == HASH_KEY_IS_LONG && zend_hash_index_find(dest, num_key, (void **)&dest_entry) != SUCCESS)
+      || Z_TYPE_PP(dest_entry) != IS_ARRAY
+    ) {
+      (*src_entry)->refcount++;
+      if (key_type == HASH_KEY_IS_STRING) {
+        /* if register_globals is on and working with main symbol table, prevent overwriting of GLOBALS */
+        if (!globals_check || string_key_len != sizeof("GLOBALS") || memcmp(string_key, "GLOBALS", sizeof("GLOBALS") - 1)) {
+          zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL);
+        } else {
+          (*src_entry)->refcount--;
+        }
+      } else {
+        zend_hash_index_update(dest, num_key, src_entry, sizeof(zval *), NULL);
+      }
+    } else {
+      SEPARATE_ZVAL(dest_entry);
+      my_autoglobal_merge(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry) TSRMLS_CC);
+    }
+    zend_hash_move_forward_ex(src, &pos);
+  }
+}
+
+static my_auto_globals_create_request(void *dummy TSRMLS_DC)
+{
+  zval *form_variables;
+  unsigned char _gpc_flags[3] = {0, 0, 0};
+  char *p;
+
+  ALLOC_ZVAL(form_variables);
+  array_init(form_variables);
+  INIT_PZVAL(form_variables);
+
+  for (p = PG(variables_order); p && *p; p++) {
+    switch (*p) {
+      case 'g':
+      case 'G':
+        if (!_gpc_flags[0]) {
+          my_autoglobal_merge(Z_ARRVAL_P(form_variables), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]) TSRMLS_CC);
+          _gpc_flags[0] = 1;
+        }
+        break;
+      case 'p':
+      case 'P':
+        if (!_gpc_flags[1]) {
+          my_autoglobal_merge(Z_ARRVAL_P(form_variables), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST]) TSRMLS_CC);
+          _gpc_flags[1] = 1;
+        }
+        break;
+      case 'c':
+      case 'C':
+        if (!_gpc_flags[2]) {
+          my_autoglobal_merge(Z_ARRVAL_P(form_variables), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) TSRMLS_CC);
+          _gpc_flags[2] = 1;
+        }
+        break;
+    }
+  }
+
+  zend_hash_update(&EG(symbol_table), "_REQUEST", sizeof("_REQUEST"), &form_variables, sizeof(zval *), NULL);
+  return 0;
+}
+
+
 MODULE = PHP PACKAGE = PHP::Interpreter PREFIX=SAND_
 
 REQUIRE:        1.9505
 PROTOTYPES:     DISABLE
 
-SV* SAND_new(classname)
+SV* SAND_new(classname, ...)
   char *classname;
   CODE:
     {
@@ -343,7 +422,59 @@ SV* SAND_new(classname)
         RETVAL = &PL_sv_undef;
         return;
       }
+      fprintf(stderr, "items: %d\n", items);
       interp = sandwich_per_interp_setup();
+      if(items > 1 && SvROK(ST(1)) && (SvTYPE(SvRV(ST(1))) == SVt_PVHV)) {
+        HV *args = (HV *) SvRV(ST(1));
+        SV *trackvars;
+        char *trackvars_key;
+        I32 trackvars_keylen;
+        void *old_ctx = tsrm_set_interpreter_context(interp->ctx);
+        TSRMLS_FETCH();
+        hv_iterinit(args);
+        while((trackvars = hv_iternextsv(args, &trackvars_key, &trackvars_keylen)) != NULL) {
+          HV *hv;
+          SV *autoglobal;
+          char *key;
+          I32 keylen;
+          zval *track_vars_array = NULL;
+
+          if(!strcmp(trackvars_key, "GET")) {
+            track_vars_array = PG(http_globals)[TRACK_VARS_GET];
+          }
+          else if(!strcmp(trackvars_key, "POST")) {
+            track_vars_array = PG(http_globals)[TRACK_VARS_POST];
+          }
+          else if(!strcmp(trackvars_key, "COOKIE")) {
+            track_vars_array = PG(http_globals)[TRACK_VARS_COOKIE];
+          }
+          else if(!strcmp(trackvars_key, "SERVER")) {
+            track_vars_array = PG(http_globals)[TRACK_VARS_SERVER];
+          }
+          else if(!strcmp(trackvars_key, "ENV")) {
+            track_vars_array = PG(http_globals)[TRACK_VARS_ENV];
+          }
+          else if(!strcmp(trackvars_key, "FILES")) {
+            track_vars_array = PG(http_globals)[TRACK_VARS_FILES];
+          } else {
+            /* special case - this isn't an autoglobal - register it and continue */
+            int old_register_globals = PG(register_globals);
+            PG(register_globals) = 1;
+            php_register_variable_ex(trackvars_key, SvZval(trackvars TSRMLS_CC), NULL TSRMLS_CC);
+            PG(register_globals) = old_register_globals;
+            continue;
+          }
+          if(!SvROK(trackvars) || !(SvTYPE(SvRV(trackvars)) == SVt_PVHV)) continue;
+          hv = (HV *) SvRV(trackvars);
+          hv_iterinit(hv);
+          while((autoglobal = hv_iternextsv(hv, &key, &keylen)) != NULL) {
+            zval *zag = SvZval(autoglobal TSRMLS_CC);
+            php_register_variable_ex(key, zag, track_vars_array TSRMLS_CC);
+          }
+        }
+        my_auto_globals_create_request(NULL TSRMLS_CC);
+        tsrm_set_interpreter_context(old_ctx);
+      }
       RETVAL = newSV(0);
       sv_setref_pv(RETVAL, classname, (void *)interp);
     }