PHP_METHOD(MongoDB, execute) { zval *code = NULL, *args = NULL, *options = NULL, *zdata; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|aa", &code, &args, &options) == FAILURE) { return; } /* turn the first argument into MongoCode */ if (Z_TYPE_P(code) != IS_OBJECT || Z_OBJCE_P(code) != mongo_ce_Code) { if (Z_TYPE_P(code) == IS_STRING) { zval *obj; MAKE_STD_ZVAL(obj); object_init_ex(obj, mongo_ce_Code); MONGO_METHOD1(MongoCode, __construct, return_value, obj, code); code = obj; } else { /* This is broken code */ php_error_docref(NULL TSRMLS_CC, E_ERROR, "The argument is neither an object of MongoCode or a string"); return; } } else { zval_add_ref(&code); } if (!args) { MAKE_STD_ZVAL(args); array_init(args); } else { zval_add_ref(&args); } /* create { $eval : code, args : [] } */ MAKE_STD_ZVAL(zdata); array_init(zdata); add_assoc_zval(zdata, "$eval", code); add_assoc_zval(zdata, "args", args); /* Check whether we have nolock as an option */ if (options) { zval **nolock; if (zend_hash_find(HASH_P(options), "nolock", strlen("nolock") + 1, (void**) &nolock) == SUCCESS) { convert_to_boolean_ex(nolock); zval_add_ref(nolock); add_assoc_zval(zdata, "nolock", *nolock); } } MONGO_METHOD1(MongoDB, command, return_value, getThis(), zdata); zval_ptr_dtor(&zdata); }
bool samphp::callBool(char *fn, char *argspec, ...) { bool rrv = false; zval *rv; va_list ap; va_start(ap, argspec); rv = call(fn, argspec, ap TSRMLS_CC); va_end(ap); if(rv) { if(Z_TYPE_P(rv) != IS_BOOL) { // copy rv into new memory for the in place conversion zval *cp; MAKE_STD_ZVAL(cp); *cp = *rv; zval_copy_ctor(cp); INIT_PZVAL(cp); // destroy the original now that we have a copy zval_ptr_dtor(&rv); // rename rv to our copy rv = cp; convert_to_boolean_ex(&rv); } rrv = (bool)Z_LVAL_P(rv); zval_ptr_dtor(&rv); } return rrv; }
/* Returns the bytes read on success * Returns -31 on unknown failure * Returns -80 on timeout * Returns -32 when remote server closes the connection */ int php_mongo_io_stream_read(mongo_connection *con, mongo_server_options *options, int timeout, void *data, int size, char **error_message) { int num = 1, received = 0; TSRMLS_FETCH(); int socketTimeoutMS = options->socketTimeoutMS ? options->socketTimeoutMS : FG(default_socket_timeout) * 1000; /* Convert negative values to -1 second, which implies no timeout */ socketTimeoutMS = socketTimeoutMS < 0 ? -1000 : socketTimeoutMS; timeout = timeout < 0 ? -1000 : timeout; /* Socket timeout behavior varies based on the following: * - Negative => no timeout (i.e. block indefinitely) * - Zero => not specified (no changes to existing configuration) * - Positive => used specified timeout (revert to previous value later) */ if (timeout && timeout != socketTimeoutMS) { struct timeval rtimeout = {0, 0}; rtimeout.tv_sec = timeout / 1000; rtimeout.tv_usec = (timeout % 1000) * 1000; php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout); mongo_manager_log(MonGlo(manager), MLOG_CON, MLOG_FINE, "Setting the stream timeout to %d.%06d", rtimeout.tv_sec, rtimeout.tv_usec); } else { mongo_manager_log(MonGlo(manager), MLOG_CON, MLOG_FINE, "No timeout changes for %s", con->hash); } php_mongo_stream_notify_io(options, MONGO_STREAM_NOTIFY_IO_READ, 0, size TSRMLS_CC); /* this can return FAILED if there is just no more data from db */ while (received < size && num > 0) { int len = 4096 < (size - received) ? 4096 : size - received; ERROR_HANDLER_DECLARATION(error_handler) ERROR_HANDLER_REPLACE(error_handler, mongo_ce_ConnectionException); num = php_stream_read(con->socket, (char *) data, len); ERROR_HANDLER_RESTORE(error_handler); if (num < 0) { /* Doesn't look like this can happen, php_sockop_read overwrites * the failure from recv() to return 0 */ *error_message = strdup("Read from socket failed"); return -31; } /* It *may* have failed. It also may simply have no data */ if (num == 0) { zval *metadata; MAKE_STD_ZVAL(metadata); array_init(metadata); if (php_stream_populate_meta_data(con->socket, metadata)) { zval **tmp; if (zend_hash_find(Z_ARRVAL_P(metadata), "timed_out", sizeof("timed_out"), (void**)&tmp) == SUCCESS) { convert_to_boolean_ex(tmp); if (Z_BVAL_PP(tmp)) { struct timeval rtimeout = {0, 0}; if (timeout > 0 && options->socketTimeoutMS != timeout) { rtimeout.tv_sec = timeout / 1000; rtimeout.tv_usec = (timeout % 1000) * 1000; } else { /* Convert timeout=-1 to -1second, which PHP interprets as no timeout */ int socketTimeoutMS = options->socketTimeoutMS == -1 ? -1000 : options->socketTimeoutMS; rtimeout.tv_sec = socketTimeoutMS / 1000; rtimeout.tv_usec = (socketTimeoutMS % 1000) * 1000; } *error_message = malloc(256); snprintf(*error_message, 256, "Read timed out after reading %d bytes, waited for %d.%06d seconds", num, rtimeout.tv_sec, rtimeout.tv_usec); zval_ptr_dtor(&metadata); return -80; } } if (zend_hash_find(Z_ARRVAL_P(metadata), "eof", sizeof("eof"), (void**)&tmp) == SUCCESS) { convert_to_boolean_ex(tmp); if (Z_BVAL_PP(tmp)) { *error_message = strdup("Remote server has closed the connection"); zval_ptr_dtor(&metadata); return -32; } } } zval_ptr_dtor(&metadata); } data = (char*)data + num; received += num; } /* PHP may have sent notify-progress of *more then* 'received' in some * cases. * PHP will read 8192 byte chunks at a time, but if we request less data * then that PHP will just buffer the rest, which is fine. It could * confuse users a little, why their progress update was higher then the * max-bytes-expected though... */ php_mongo_stream_notify_io(options, MONGO_STREAM_NOTIFY_IO_COMPLETED, received, size TSRMLS_CC); /* If the timeout was changed, revert to the previous value now */ if (timeout && timeout != socketTimeoutMS) { struct timeval rtimeout = {0, 0}; /* If socketTimeoutMS was never specified, revert to default_socket_timeout */ if (options->socketTimeoutMS == 0) { mongo_manager_log(MonGlo(manager), MLOG_CON, MLOG_FINE, "Stream timeout will be reverted to default_socket_timeout (%d)", FG(default_socket_timeout)); } rtimeout.tv_sec = socketTimeoutMS / 1000; rtimeout.tv_usec = (socketTimeoutMS % 1000) * 1000; php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout); mongo_manager_log(MonGlo(manager), MLOG_CON, MLOG_FINE, "Now setting stream timeout back to %d.%06d", rtimeout.tv_sec, rtimeout.tv_usec); } return received; }
/* Returns the bytes read on success * Returns -31 on unknown failure * Returns -80 on timeout * Returns -32 when remote server closes the connection */ int php_mongo_io_stream_read(mongo_connection *con, mongo_server_options *options, int timeout, void *data, int size, char **error_message) { int num = 1, received = 0; TSRMLS_FETCH(); if (timeout > 0 && options->socketTimeoutMS != timeout) { struct timeval rtimeout = {0, 0}; rtimeout.tv_sec = timeout / 1000; rtimeout.tv_usec = (timeout % 1000) * 1000; php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout); } php_mongo_stream_notify_io(options, MONGO_STREAM_NOTIFY_IO_READ, 0, size TSRMLS_CC); /* this can return FAILED if there is just no more data from db */ while (received < size && num > 0) { int len = 4096 < (size - received) ? 4096 : size - received; ERROR_HANDLER_DECLARATION(error_handler) ERROR_HANDLER_REPLACE(error_handler, mongo_ce_ConnectionException); num = php_stream_read(con->socket, (char *) data, len); ERROR_HANDLER_RESTORE(error_handler); if (num < 0) { /* Doesn't look like this can happen, php_sockop_read overwrites * the failure from recv() to return 0 */ *error_message = strdup("Read from socket failed"); return -31; } /* It *may* have failed. It also may simply have no data */ if (num == 0) { zval *metadata; MAKE_STD_ZVAL(metadata); array_init(metadata); if (php_stream_populate_meta_data(con->socket, metadata)) { zval **tmp; if (zend_hash_find(Z_ARRVAL_P(metadata), "timed_out", sizeof("timed_out"), (void**)&tmp) == SUCCESS) { convert_to_boolean_ex(tmp); if (Z_BVAL_PP(tmp)) { struct timeval rtimeout = {0, 0}; if (timeout > 0 && options->socketTimeoutMS != timeout) { rtimeout.tv_sec = timeout / 1000; rtimeout.tv_usec = (timeout % 1000) * 1000; } else { rtimeout.tv_sec = options->socketTimeoutMS / 1000; rtimeout.tv_usec = (options->socketTimeoutMS % 1000) * 1000; } *error_message = malloc(256); snprintf(*error_message, 256, "Read timed out after reading %d bytes, waited for %d.%06d seconds", num, rtimeout.tv_sec, rtimeout.tv_usec); zval_ptr_dtor(&metadata); return -80; } } if (zend_hash_find(Z_ARRVAL_P(metadata), "eof", sizeof("eof"), (void**)&tmp) == SUCCESS) { convert_to_boolean_ex(tmp); if (Z_BVAL_PP(tmp)) { *error_message = strdup("Remote server has closed the connection"); zval_ptr_dtor(&metadata); return -32; } } } zval_ptr_dtor(&metadata); } data = (char*)data + num; received += num; } /* PHP may have sent notify-progress of *more then* 'received' in some * cases. * PHP will read 8192 byte chunks at a time, but if we request less data * then that PHP will just buffer the rest, which is fine. It could * confuse users a little, why their progress update was higher then the * max-bytes-expected though... */ php_mongo_stream_notify_io(options, MONGO_STREAM_NOTIFY_IO_COMPLETED, received, size TSRMLS_CC); if (timeout > 0 && options->socketTimeoutMS != timeout) { struct timeval rtimeout = {0, 0}; rtimeout.tv_sec = options->socketTimeoutMS / 1000; rtimeout.tv_usec = (options->socketTimeoutMS % 1000) * 1000; php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout); } return received; }
void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval** value, HashTable* fieldspec) { // At this point the typeID (and field num, if applicable) should've already been written to the output so all we need to do is write the payload. switch (thrift_typeID) { case T_STOP: case T_VOID: return; case T_STRUCT: { TSRMLS_FETCH(); zval* spec = zend_read_static_property(zend_get_class_entry(*value TSRMLS_CC), "_TSPEC", 6, false TSRMLS_CC); binary_serialize_spec(*value, transport, Z_ARRVAL_P(spec)); } return; case T_BOOL: convert_to_boolean_ex(value); transport.writeI8(Z_BVAL_PP(value) ? 1 : 0); return; case T_BYTE: convert_to_long_ex(value); transport.writeI8(Z_LVAL_PP(value)); return; case T_I16: convert_to_long_ex(value); transport.writeI16(Z_LVAL_PP(value)); return; case T_I32: convert_to_long_ex(value); transport.writeI32(Z_LVAL_PP(value)); return; case T_I64: case T_U64: convert_to_long_ex(value); transport.writeI64(Z_LVAL_PP(value)); return; case T_DOUBLE: { union { int64_t c; double d; } a; convert_to_double_ex(value); a.d = Z_DVAL_PP(value); transport.writeI64(a.c); } return; //case T_UTF7: case T_UTF8: case T_UTF16: case T_STRING: convert_to_string(*value); transport.writeString(Z_STRVAL_PP(value), Z_STRLEN_PP(value)); return; case T_MAP: { HashTable* ht = Z_ARRVAL_PP(value); zval** val_ptr; zend_hash_find(fieldspec, "ktype", 6, (void**)&val_ptr); convert_to_long_ex(val_ptr); uint8_t keytype = Z_LVAL_PP(val_ptr); transport.writeI8(keytype); zend_hash_find(fieldspec, "vtype", 6, (void**)&val_ptr); convert_to_long_ex(val_ptr); uint8_t valtype = Z_LVAL_PP(val_ptr); transport.writeI8(valtype); zend_hash_find(fieldspec, "val", 4, (void**)&val_ptr); HashTable* valspec = Z_ARRVAL_PP(val_ptr); transport.writeI32(zend_hash_num_elements(ht)); HashPosition key_ptr; for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) { binary_serialize_hashtable_key(keytype, transport, ht, key_ptr); binary_serialize(valtype, transport, val_ptr, valspec); } } return; case T_LIST: { HashTable* ht = Z_ARRVAL_PP(value); zval** val_ptr; zend_hash_find(fieldspec, "etype", 6, (void**)&val_ptr); convert_to_long_ex(val_ptr); uint8_t valtype = Z_LVAL_PP(val_ptr); transport.writeI8(valtype); zend_hash_find(fieldspec, "elem", 5, (void**)&val_ptr); HashTable* valspec = Z_ARRVAL_PP(val_ptr); transport.writeI32(zend_hash_num_elements(ht)); HashPosition key_ptr; for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) { binary_serialize(valtype, transport, val_ptr, valspec); } } return; case T_SET: { HashTable* ht = Z_ARRVAL_PP(value); zval** val_ptr; zend_hash_find(fieldspec, "etype", 6, (void**)&val_ptr); convert_to_long_ex(val_ptr); uint8_t keytype = Z_LVAL_PP(val_ptr); transport.writeI8(keytype); transport.writeI32(zend_hash_num_elements(ht)); HashPosition key_ptr; for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); zend_hash_get_current_data_ex(ht, (void**)&val_ptr, &key_ptr) == SUCCESS; zend_hash_move_forward_ex(ht, &key_ptr)) { binary_serialize_hashtable_key(keytype, transport, ht, key_ptr); } } return; }; char errbuf[128]; sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID); throw_tprotocolexception(errbuf, INVALID_DATA); }
/* Returns the bytes read on success * Returns -31 on unknown failure * Returns -80 on timeout * Returns -32 when remote server closes the connection */ int php_mongo_io_stream_read(mongo_connection *con, mongo_server_options *options, int timeout, void *data, int size, char **error_message) { int num = 1, received = 0; TSRMLS_FETCH(); if (timeout > 0 && options->socketTimeoutMS != timeout) { struct timeval rtimeout = {0}; rtimeout.tv_sec = timeout / 1000; rtimeout.tv_usec = (timeout % 1000) * 1000; php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout); } /* this can return FAILED if there is just no more data from db */ while (received < size && num > 0) { int len = 4096 < (size - received) ? 4096 : size - received; num = php_stream_read(con->socket, (char *) data, len); if (num < 0) { /* Doesn't look like this can happen, php_sockop_read overwrites * the failure from recv() to return 0 */ *error_message = strdup("Read from socket failed"); return -31; } /* It *may* have failed. It also may simply have no data */ if (num == 0) { zval *metadata; MAKE_STD_ZVAL(metadata); array_init(metadata); if (php_stream_populate_meta_data(con->socket, metadata)) { zval **tmp; if (zend_hash_find(Z_ARRVAL_P(metadata), "timed_out", sizeof("timed_out"), (void**)&tmp) == SUCCESS) { convert_to_boolean_ex(tmp); if (Z_BVAL_PP(tmp)) { struct timeval rtimeout = {0}; if (timeout > 0 && options->socketTimeoutMS != timeout) { rtimeout.tv_sec = timeout / 1000; rtimeout.tv_usec = (timeout % 1000) * 1000; } else { rtimeout.tv_sec = options->socketTimeoutMS / 1000; rtimeout.tv_usec = (options->socketTimeoutMS % 1000) * 1000; } *error_message = malloc(256); snprintf(*error_message, 256, "Read timed out after reading %d bytes, waited for %d.%06d seconds", num, rtimeout.tv_sec, rtimeout.tv_usec); zval_ptr_dtor(&metadata); return -80; } } if (zend_hash_find(Z_ARRVAL_P(metadata), "eof", sizeof("eof"), (void**)&tmp) == SUCCESS) { convert_to_boolean_ex(tmp); if (Z_BVAL_PP(tmp)) { *error_message = strdup("Remote server has closed the connection"); zval_ptr_dtor(&metadata); return -32; } } } zval_ptr_dtor(&metadata); } data = (char*)data + num; received += num; } if (options && options->ctx) { php_stream_notify_progress_increment((php_stream_context *)options->ctx, received, size); } if (timeout > 0 && options->socketTimeoutMS != timeout) { struct timeval rtimeout = {0}; rtimeout.tv_sec = options->socketTimeoutMS / 1000; rtimeout.tv_usec = (options->socketTimeoutMS % 1000) * 1000; php_stream_set_option(con->socket, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &rtimeout); } return received; }
int php_do_setsockopt_ipv6_mcast(php_socket *php_sock, int level, int optname, zval *arg4) { unsigned int if_index; void *opt_ptr; socklen_t optlen; int ov; int retval; switch (optname) { case PHP_MCAST_JOIN_GROUP: case PHP_MCAST_LEAVE_GROUP: #ifdef HAS_MCAST_EXT case PHP_MCAST_BLOCK_SOURCE: case PHP_MCAST_UNBLOCK_SOURCE: case PHP_MCAST_JOIN_SOURCE_GROUP: case PHP_MCAST_LEAVE_SOURCE_GROUP: #endif if (php_do_mcast_opt(php_sock, level, optname, arg4) == FAILURE) { return FAILURE; } else { return SUCCESS; } case IPV6_MULTICAST_IF: if (php_get_if_index_from_zval(arg4, &if_index) == FAILURE) { return FAILURE; } opt_ptr = &if_index; optlen = sizeof(if_index); goto dosockopt; case IPV6_MULTICAST_LOOP: convert_to_boolean_ex(arg4); ov = (int) Z_TYPE_P(arg4) == IS_TRUE; goto ipv6_loop_hops; case IPV6_MULTICAST_HOPS: convert_to_long_ex(arg4); if (Z_LVAL_P(arg4) < -1L || Z_LVAL_P(arg4) > 255L) { php_error_docref(NULL, E_WARNING, "Expected a value between -1 and 255"); return FAILURE; } ov = (int) Z_LVAL_P(arg4); ipv6_loop_hops: opt_ptr = &ov; optlen = sizeof(ov); goto dosockopt; } return 1; /* not handled */ dosockopt: retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen); if (retval != 0) { PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno); return FAILURE; } return SUCCESS; }
int php_do_setsockopt_ip_mcast(php_socket *php_sock, int level, int optname, zval *arg4) { unsigned int if_index; struct in_addr if_addr; void *opt_ptr; socklen_t optlen; unsigned char ipv4_mcast_ttl_lback; int retval; switch (optname) { case PHP_MCAST_JOIN_GROUP: case PHP_MCAST_LEAVE_GROUP: #ifdef HAS_MCAST_EXT case PHP_MCAST_BLOCK_SOURCE: case PHP_MCAST_UNBLOCK_SOURCE: case PHP_MCAST_JOIN_SOURCE_GROUP: case PHP_MCAST_LEAVE_SOURCE_GROUP: #endif if (php_do_mcast_opt(php_sock, level, optname, arg4) == FAILURE) { return FAILURE; } else { return SUCCESS; } case IP_MULTICAST_IF: if (php_get_if_index_from_zval(arg4, &if_index) == FAILURE) { return FAILURE; } if (php_if_index_to_addr4(if_index, php_sock, &if_addr) == FAILURE) { return FAILURE; } opt_ptr = &if_addr; optlen = sizeof(if_addr); goto dosockopt; case IP_MULTICAST_LOOP: convert_to_boolean_ex(arg4); ipv4_mcast_ttl_lback = (unsigned char) (Z_TYPE_P(arg4) == IS_TRUE); goto ipv4_loop_ttl; case IP_MULTICAST_TTL: convert_to_long_ex(arg4); if (Z_LVAL_P(arg4) < 0L || Z_LVAL_P(arg4) > 255L) { php_error_docref(NULL, E_WARNING, "Expected a value between 0 and 255"); return FAILURE; } ipv4_mcast_ttl_lback = (unsigned char) Z_LVAL_P(arg4); ipv4_loop_ttl: opt_ptr = &ipv4_mcast_ttl_lback; optlen = sizeof(ipv4_mcast_ttl_lback); goto dosockopt; } return 1; dosockopt: retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen); if (retval != 0) { PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno); return FAILURE; } return SUCCESS; }
// PHP函数参数转换为go类型的参数 static void* phpgo_function_conv_arg(int cbid, int idx, char ch, int zty, zval **zarg) { int prmty = zty; void *rv = NULL; if (ch == 's') { if (prmty != IS_STRING) { zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s", ch, type2name(prmty)); } convert_to_string_ex(zarg); char *arg = Z_STRVAL_PP(zarg); printf("arg%d(%c), %s(%d)\n", idx, ch, arg, Z_STRLEN_PP(zarg)); goapi_new_value(GT_String, (uint64_t)arg, &rv); } else if (ch == 'l') { if (prmty != IS_LONG) { zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s", ch, type2name(prmty)); } convert_to_long_ex(zarg); long arg = (long)Z_LVAL_PP(zarg); printf("arg%d(%c), %d\n", idx, ch, arg); goapi_new_value(GT_Int64, (uint64_t)arg, &rv); } else if (ch == 'b') { convert_to_boolean_ex(zarg); zend_bool arg = (zend_bool)Z_BVAL_PP(zarg); goapi_new_value(GT_Bool, (uint64_t)arg, &rv); } else if (ch == 'd') { convert_to_double_ex(zarg); double arg = (double)Z_DVAL_PP(zarg); double* parg = calloc(1, sizeof(double)); *parg = (double)Z_DVAL_PP(zarg); // argv[idx] = (void*)(ulong)arg; // error // memcpy(&argv[idx], &arg, sizeof(argv[idx])); // ok // float32(uintptr(ax)) goapi_new_value(GT_Float64, (uint64_t)parg, &rv); } else if (ch == 'a') { if (Z_TYPE_PP(zarg) == IS_STRING) { char *arg = Z_STRVAL_PP(zarg); goapi_new_value(GT_String, (uint64_t)arg, &rv); #ifdef ZEND_ENGINE_3 } else if (Z_TYPE_PP(zarg) == _IS_BOOL) { #else } else if (Z_TYPE_PP(zarg) == IS_BOOL) { #endif zend_bool arg = (zend_bool)Z_BVAL_PP(zarg); goapi_new_value(GT_Bool, (uint64_t)arg, &rv); } else if (Z_TYPE_PP(zarg) == IS_DOUBLE) { double* parg = calloc(1, sizeof(double)); *parg = (double)Z_DVAL_PP(zarg); goapi_new_value(GT_Float64, (uint64_t)parg, &rv); } else if (Z_TYPE_PP(zarg) == IS_LONG) { long arg = (long)Z_LVAL_PP(zarg); goapi_new_value(GT_Int64, (uint64_t)arg, &rv); } else if (Z_TYPE_PP(zarg) == IS_OBJECT) { void *parg = (void*)zarg; goapi_new_value(GT_UnsafePointer, (uint64_t)parg, &rv); } else if (Z_TYPE_PP(zarg) == IS_RESOURCE) { void *parg = (void*)zarg; goapi_new_value(GT_UnsafePointer, (uint64_t)parg, &rv); } else { printf("arg%d(%c), %s(%d) unsported to Any\n", idx, ch, type2name(Z_TYPE_PP(zarg)), Z_TYPE_PP(zarg)); } // TODO array/vector convert } else if (ch == 'v') { HashTable *arr_hash = Z_ARRVAL_PP(zarg); HashPosition pos; zval **edata; for (zend_hash_internal_pointer_reset_ex(arr_hash, &pos); #ifdef ZEND_ENGINE_3 (edata = zend_hash_get_current_data_ex(arr_hash, &pos)) != NULL; #else zend_hash_get_current_data_ex(arr_hash, (void**)&edata, &pos) == SUCCESS; #endif zend_hash_move_forward_ex(arr_hash, &pos)) { if (rv == NULL) { switch (Z_TYPE_PP(edata)) { case IS_LONG: goapi_array_new(GT_Int64, &rv); break; default: goapi_array_new(GT_String, &rv); break; } } switch (Z_TYPE_PP(edata)) { case IS_LONG: goapi_array_push(rv, (void*)Z_LVAL_PP(edata), &rv); break; default: convert_to_string_ex(edata); printf("array idx(%d)=T(%d=%s, val=%s)\n", pos, Z_TYPE_PP(edata), type2name(Z_TYPE_PP(edata)), Z_STRVAL_PP(edata)); goapi_array_push(rv, Z_STRVAL_PP(edata), &rv); break; } } // TODO array/map convert } else if (ch == 'm') {
PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage) { OLECHAR *unicode_str; var_arg->vt = (short) pval_type->value.lval; switch(var_arg->vt) { case VT_UI1: convert_to_long_ex(&pval_arg); var_arg->bVal = (unsigned char)pval_arg->value.lval; break; case VT_I2: convert_to_long_ex(&pval_arg); var_arg->iVal = (short)pval_arg->value.lval; break; case VT_I4: convert_to_long_ex(&pval_arg); var_arg->lVal = pval_arg->value.lval; break; case VT_R4: convert_to_double_ex(&pval_arg); var_arg->fltVal = (float)pval_arg->value.dval; break; case VT_R8: convert_to_double_ex(&pval_arg); var_arg->dblVal = pval_arg->value.dval; break; case VT_BOOL: convert_to_boolean_ex(&pval_arg); var_arg->boolVal = (short)pval_arg->value.lval; break; case VT_ERROR: convert_to_long_ex(&pval_arg); var_arg->scode = pval_arg->value.lval; break; case VT_CY: convert_to_double_ex(&pval_arg); VarCyFromR8(pval_arg->value.dval, &(var_arg->cyVal)); break; case VT_DATE: { SYSTEMTIME wintime; struct tm *phptime; phptime = gmtime(&(pval_arg->value.lval)); wintime.wYear = phptime->tm_year + 1900; wintime.wMonth = phptime->tm_mon + 1; wintime.wDay = phptime->tm_mday; wintime.wHour = phptime->tm_hour; wintime.wMinute = phptime->tm_min; wintime.wSecond = phptime->tm_sec; SystemTimeToVariantTime(&wintime, &(var_arg->date)); } case VT_BSTR: convert_to_string_ex(&pval_arg); unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage); var_arg->bstrVal = SysAllocString(unicode_str); efree(unicode_str); break; case VT_DECIMAL: convert_to_string_ex(&pval_arg); unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage); VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &(var_arg->decVal)); break; case VT_DECIMAL|VT_BYREF: convert_to_string_ex(&pval_arg); unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage); VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, var_arg->pdecVal); break; case VT_UNKNOWN: php_pval_to_variant(pval_arg, var_arg, codepage); if(var_arg->vt != VT_DISPATCH) var_arg->vt = VT_EMPTY; else { HRESULT hr; hr = var_arg->pdispVal->lpVtbl->QueryInterface(var_arg->pdispVal, &IID_IUnknown, &(var_arg->punkVal)); if (FAILED(hr)) { php_error(E_WARNING,"can't query IUnknown"); var_arg->vt = VT_EMPTY; } else var_arg->vt = VT_UNKNOWN; } break; case VT_DISPATCH: php_pval_to_variant(pval_arg, var_arg, codepage); if(var_arg->vt != VT_DISPATCH) var_arg->vt = VT_EMPTY; break; case VT_UI1|VT_BYREF: convert_to_long(pval_arg); var_arg->pbVal = (unsigned char FAR*) &(pval_arg->value.lval); break; case VT_I2|VT_BYREF: convert_to_long(pval_arg); var_arg->piVal = (short FAR*) &(pval_arg->value.lval); break; case VT_I4|VT_BYREF: convert_to_long(pval_arg); var_arg->plVal = (long FAR*) &(pval_arg->value.lval); break; case VT_R4|VT_BYREF: convert_to_double(pval_arg); var_arg->pfltVal = (float FAR*) &(pval_arg->value.lval); break; case VT_R8|VT_BYREF: convert_to_double(pval_arg); var_arg->pdblVal = (double FAR*) &(pval_arg->value.lval); break; case VT_BOOL|VT_BYREF: convert_to_boolean(pval_arg); var_arg->pboolVal = (short FAR*) &(pval_arg->value.lval); break; case VT_ERROR|VT_BYREF: convert_to_long(pval_arg); var_arg->pscode = (long FAR*) &(pval_arg->value.lval); break; case VT_CY|VT_BYREF: convert_to_double_ex(&pval_arg); VarCyFromR8(pval_arg->value.dval, var_arg->pcyVal); break; case VT_DATE|VT_BYREF: { SYSTEMTIME wintime; struct tm *phptime; phptime = gmtime(&(pval_arg->value.lval)); wintime.wYear = phptime->tm_year + 1900; wintime.wMonth = phptime->tm_mon + 1; wintime.wDay = phptime->tm_mday; wintime.wHour = phptime->tm_hour; wintime.wMinute = phptime->tm_min; wintime.wSecond = phptime->tm_sec; SystemTimeToVariantTime(&wintime, var_arg->pdate); } case VT_BSTR|VT_BYREF: convert_to_string(pval_arg); var_arg->pbstrVal = (BSTR FAR*) emalloc(sizeof(BSTR FAR*)); unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage); *(var_arg->pbstrVal) = SysAllocString(unicode_str); efree(unicode_str); break; case VT_UNKNOWN|VT_BYREF: php_pval_to_variant(pval_arg, var_arg, codepage); if(var_arg->vt != VT_DISPATCH) var_arg->vt = VT_EMPTY; else { HRESULT hr; hr = var_arg->pdispVal->lpVtbl->QueryInterface(var_arg->pdispVal, &IID_IUnknown, &(var_arg->punkVal)); if (FAILED(hr)) { php_error(E_WARNING,"can't query IUnknown"); var_arg->vt = VT_EMPTY; } else var_arg->vt = VT_UNKNOWN|VT_BYREF; } break; case VT_DISPATCH|VT_BYREF: php_pval_to_variant(pval_arg, var_arg, codepage); if(var_arg->vt != VT_DISPATCH) var_arg->vt = VT_EMPTY; else var_arg->vt |= VT_BYREF; break; case VT_VARIANT|VT_BYREF: php_pval_to_variant(pval_arg, var_arg, codepage); if(var_arg->vt != (VT_VARIANT | VT_BYREF)) var_arg->vt = VT_EMPTY; break; case VT_I1: convert_to_long_ex(&pval_arg); var_arg->cVal = (char)pval_arg->value.lval; break; case VT_UI2: convert_to_long_ex(&pval_arg); var_arg->uiVal = (unsigned short)pval_arg->value.lval; break; case VT_UI4: convert_to_long_ex(&pval_arg); var_arg->ulVal = (unsigned long)pval_arg->value.lval; break; case VT_INT: convert_to_long_ex(&pval_arg); var_arg->intVal = (int)pval_arg->value.lval; break; case VT_UINT: convert_to_long_ex(&pval_arg); var_arg->uintVal = (unsigned int)pval_arg->value.lval; break; case VT_I1|VT_BYREF: convert_to_long(pval_arg); var_arg->pcVal = (char FAR*) &pval_arg->value.lval; break; case VT_UI2|VT_BYREF: convert_to_long(pval_arg); var_arg->puiVal = (unsigned short FAR*) &pval_arg->value.lval; break; case VT_UI4|VT_BYREF: convert_to_long(pval_arg); var_arg->pulVal = (unsigned long FAR*) &pval_arg->value.lval; break; case VT_INT|VT_BYREF: convert_to_long(pval_arg); var_arg->pintVal = (int FAR*) &pval_arg->value.lval; break; case VT_UINT|VT_BYREF: convert_to_long(pval_arg); var_arg->puintVal = (unsigned int FAR*) &pval_arg->value.lval; break; default: php_error(E_WARNING, "Type not supportet or not yet implemented."); } }
/* {{{ proto object ffmpeg_movie(string filename) Constructor for ffmpeg_movie objects */ FFMPEG_PHP_CONSTRUCTOR(ffmpeg_movie, __construct) { int persistent = 0, hashkey_length = 0; char *filename = NULL, *fullpath = NULL, *hashkey = NULL; zval ***argv; ff_movie_context *ffmovie_ctx = NULL; /* retrieve arguments */ argv = (zval ***) safe_emalloc(sizeof(zval **), ZEND_NUM_ARGS(), 0); if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), argv) != SUCCESS) { efree(argv); php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error parsing arguments"); } switch (ZEND_NUM_ARGS()) { case 2: convert_to_boolean_ex(argv[1]); if (! INI_BOOL("ffmpeg.allow_persistent") && Z_LVAL_PP(argv[1])) { zend_error(E_WARNING, "Persistent movies have been disabled in php.ini"); break; } persistent = Z_LVAL_PP(argv[1]); /* fallthru */ case 1: convert_to_string_ex(argv[0]); filename = Z_STRVAL_PP(argv[0]); break; default: WRONG_PARAM_COUNT; } if (persistent) { list_entry *le; /* resolve the fully-qualified path name to use as the hash key */ fullpath = expand_filepath(filename, NULL TSRMLS_CC); hashkey_length = sizeof("ffmpeg-php_")-1 + strlen(SAFE_STRING(filename)); hashkey = (char *) emalloc(hashkey_length+1); snprintf(hashkey, hashkey_length, "ffmpeg-php_%s", SAFE_STRING(filename)); /* do we have an existing persistent movie? */ if (SUCCESS == zend_hash_find(&EG(persistent_list), hashkey, hashkey_length+1, (void**)&le)) { int type; if (Z_TYPE_P(le) != le_ffmpeg_pmovie) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to retrieve persistent resource"); } ffmovie_ctx = (ff_movie_context*)le->ptr; /* sanity check to ensure that the resource is still a valid * regular resource number */ if (zend_list_find(ffmovie_ctx->rsrc_id, &type) == ffmovie_ctx) { /* add a reference to the persistent movie */ zend_list_addref(ffmovie_ctx->rsrc_id); } else { //php_error_docref(NULL TSRMLS_CC, E_ERROR, //"Not a valid persistent movie resource"); ffmovie_ctx->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ffmovie_ctx, le_ffmpeg_pmovie); } } else { /* no existing persistant movie, create one */ list_entry new_le; ffmovie_ctx = _php_alloc_ffmovie_ctx(1); if (_php_open_movie_file(ffmovie_ctx, filename)) { zend_error(E_WARNING, "Can't open movie file %s", filename); efree(argv); ZVAL_BOOL(getThis(), 0); RETURN_FALSE; } Z_TYPE(new_le) = le_ffmpeg_pmovie; new_le.ptr = ffmovie_ctx; if (FAILURE == zend_hash_update(&EG(persistent_list), hashkey, hashkey_length+1, (void *)&new_le, sizeof(list_entry), NULL)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent resource"); } ffmovie_ctx->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ffmovie_ctx, le_ffmpeg_pmovie); } } else { ffmovie_ctx = _php_alloc_ffmovie_ctx(0); if (_php_open_movie_file(ffmovie_ctx, Z_STRVAL_PP(argv[0]))) { zend_error(E_WARNING, "Can't open movie file %s", Z_STRVAL_PP(argv[0])); efree(argv); ZVAL_BOOL(getThis(), 0); RETURN_FALSE; } /* pass NULL for resource result since we're not returning the resource directly, but adding it to the returned object. */ ffmovie_ctx->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ffmovie_ctx, le_ffmpeg_movie); } object_init_ex(getThis(), ffmpeg_movie_class_entry_ptr); add_property_resource(getThis(), "ffmpeg_movie", ffmovie_ctx->rsrc_id); efree(argv); if (fullpath) { efree(fullpath); } if (hashkey) { efree(hashkey); } }