PHP - zend_call_function throws segmentation fault - php

I am getting segmentation fault in zend_call_function() and I am not sure what is wrong with my code. If I comment zend_call_function() core dump doesn't happen.
This function is basically responsible for mapping user functions defined in user code or if not defined check in EG scope .
My code looks like:
#if PHP_VERSION_ID >= 70000
static zend_always_inline zval *tracing_call_user_method_va(zval *object, const char *name, size_t name_len, zval **retval_ptr_ptr TSRMLS_DC, uint32_t params_count, va_list passed_params)
{
int result;
uint32_t i;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zend_class_entry *obj_ce;
HashTable *function_table;
zend_string *lc_name;
zval retval, *params = NULL, **orig_params;
zval *retval_ptr = *retval_ptr_ptr;
ALLOCA_FLAG(use_heap0);
ALLOCA_FLAG(use_heap1);
if (params_count) {
params = (zval*)do_alloca(sizeof(zval)*params_count, use_heap0);
orig_params = (zval **)do_alloca(sizeof(zval*)*params_count, use_heap1);
for (i = 0; i < params_count; i++) {
zval *val = va_arg(passed_params, zval*);
orig_params[i] = val;
ZVAL_COPY(&params[i], val);
}
}
fci.params = params;
fci.object = (object && Z_TYPE_P(object) == IS_OBJECT) ? Z_OBJ_P(object) : NULL;
fci.retval = retval_ptr ? retval_ptr : &retval;
fci.size = sizeof(fci);
#if PHP_VERSION_ID < 70100
fci.symbol_table = NULL;
fci.function_table = NULL;
#endif
fci.param_count = params_count;
#if PHP_VERSION_ID < 80000
fci.no_separation = 1;
#endif
#if PHP_VERSION_ID >= 80000
fci.named_params = NULL;
#endif
obj_ce = object ? Z_OBJCE_P(object) : NULL;
if (obj_ce) {
function_table = &obj_ce->function_table;
} else {
function_table = EG(function_table);
}
lc_name = zend_string_alloc(name_len, 0);
zend_str_tolower_copy(ZSTR_VAL(lc_name), name, name_len);
if (UNEXPECTED((fcc.function_handler = zend_hash_find_ptr(function_table, lc_name)) == NULL)) {
ZVAL_STRINGL(&fci.function_name, name, name_len);
result = zend_call_function(&fci, NULL);
zval_ptr_dtor(&fci.function_name);
} else {
#if PHP_VERSION_ID < 70300
fcc.initialized = 1;
#endif
fcc.calling_scope = obj_ce;
if (object) {
fcc.called_scope = Z_OBJCE_P(object);
} else {
zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
if (obj_ce &&
(!called_scope ||
!instanceof_function(called_scope, obj_ce))) {
fcc.called_scope = obj_ce;
} else {
fcc.called_scope = called_scope;
}
}
fcc.object = object ? Z_OBJ_P(object) : NULL;
result = zend_call_function(&fci, &fcc TSRMLS_CC);
}
zend_string_release(lc_name);
if (result == FAILURE) {
if (!EG(exception)) {
php_error_docref(NULL, E_WARNING, "Couldn't trace method %s%s%s", obj_ce ? ZSTR_VAL(obj_ce->name) : "", obj_ce ? "::" : "", name);
}
}
for (i = 0; i < params_count; i++) {
if (Z_ISREF(params[i]) && !Z_ISREF_P(orig_params[i])) {
ZVAL_COPY_VALUE(orig_params[i], &params[i]);
}
zval_ptr_dtor(&params[i]);
}
if (params_count) {
free_alloca(orig_params, use_heap0);
free_alloca(params, use_heap1);
}
if (!retval_ptr) {
zval_ptr_dtor(&retval);
return NULL;
}
return retval_ptr;
}
The segmentation fault backtrace is :
024+ # 1: /lib64/libc.so.6(+0x36400) [0x7f0bdc2f2400]
025+ # 2: /usr/local/bin/php() [0xe35a17]
026+ # 3: /usr/local/bin/php() [0xe35ee3]
027+ # 4: /usr/local/bin/php(zval_ptr_dtor+0x36) [0xe36394]
028+ # 5: /usr/local/bin/php() [0xc1054d]
029+ # 6: /usr/local/bin/php(zend_call_function+0xee5) [0xe16044]

Related

Send data to webserver from Arduino using Ethercad lib

i'm trying to send multiple data to a webserver using Ethercard library but for any reason is is only sending one data at a time.
Here is the the code I'm using:
#include <enc28j60.h>
#include <EtherCard.h>
#include <net.h>
#define HTTP_HEADER_OFFSET 163
#define MAX_STRINGS 100
#define MAX_STRING_LENGTH 8
/* Setup for Ethernet Library */
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
const char website[] PROGMEM = "www.arksecurity.net16.net";
const char device[] = "0004";
char test[MAX_STRINGS][MAX_STRING_LENGTH+1];
unsigned long timer;
unsigned long tempo = 5000;
String register[20];
unsigned int sentOK = 0;
char* localID[MAX_STRINGS];
int countRegister = 2;
//int countRegister = 1;
int countID;
byte Ethernet::buffer[700];
void setup()
{
Serial.begin(57600);
register[0] = "empty";
if (!ether.begin(sizeof Ethernet::buffer, mymac, 53))
{
Serial.println("Failed to access Ethernet controller");
while(1);
}
else
Serial.println("Ethernet controller initialized");
Serial.println();
if (!ether.dhcpSetup())
{
Serial.println("Failed to get configuration from DHCP");
while(1);
}
else
Serial.println("DHCP configuration done");
if (!ether.dnsLookup(website))
{
Serial.println("DNS failed");
while(1);
}
else
Serial.println("DNS resolution done");
ether.printIp("SRV IP:\t", ether.hisip);
Serial.println();
timer = millis() - tempo;
}
void loop()
{
char tempRegister[80];
ether.packetLoop(ether.packetReceive());
if (millis() - timer > tempo)
{
timer += tempo;
ether.browseUrl(PSTR("/DevicesQuery.php?device="), device , website, response_callback);
if(test[0][0] != 0)
{
int missing = 0;
Serial.println("Data Received");
for(int i = 0; i < countID ; i++)
{
for(int x = 0; x < 8 ; x++)
{
if (test[i][x] == '\0')
{
missing = 1;
}
}
}
if(missing)
{
Serial.println("Data Missing");
tempo = 5000;
}
else
{
for(int g; g < countID ; g++)
{
register[g] = String(test[g]);
}
tempo = 40000;
}
}
else{
Serial.println("Waiting for server response...");
tempo = 5000;
}
//register[0] = "?ID=1234";
//register[1] = "?ID=5678";
if(register[0] != "empty")
{
for(int i = 0; i < countRegister ; i++)
{
register[i].toCharArray(tempRegister, 80);
//delay(5000);
//Serial.println(tempRegister);
ether.browseUrl(PSTR("/log.php"), tempRegister , website, browser_callback);
//while(sentOK == 0);
//sentOK = 0;
}
countRegister = 0;
register[0] = "empty";
}
}
}
static void response_callback (byte status, word off, word len) {
for(int i=0;i<MAX_STRINGS;i++)
for(int j=0;j<=MAX_STRING_LENGTH;j++)
test[i][j] = 0;
int i_string = 0;
int i_char = 0;
int i_ethBuff = off + HTTP_HEADER_OFFSET;
char carat;
countID = 0;
for (i_ethBuff = off + HTTP_HEADER_OFFSET; (carat = (char)Ethernet::buffer[i_ethBuff]) != 0; i_ethBuff++)
{
if (carat == '\n')
{ // New line char = new string
if (i_string < MAX_STRINGS - 1){
i_string++;
i_char = 0;
}
else
break; // Limite de memória do Arduino
}
else
{
if (i_char < MAX_STRING_LENGTH)
{
test[i_string][i_char] = carat;
i_char++;
} // otherwise discard the char (max length of string reached)
}
}
}
static void browser_callback (byte status, word off, word len)
{
Serial.println("Data sent");
//sentOK = 1;
}
countRegister is a variable and when it equals 1, it works great but, if he equals 2,for example, he only sends the second data to the server and ignore the first one. Anyone knows why is happening?
PS.:As for right now, I'm forcing register[0],register[1] values as you can see in the code above,but the idea is that later this values come from an outsource.
The short of it is that browseurl works asynchronously. Have a look at
http://forum.jeelabs.net/node/1477.html

auto-increment alphanumeric php , javascript

I want to make an auto-increment alphanumeric and this is just for output
if i press a button , there is an output AA001 and then i press a button again there is an output AA002
This doesn't use any 'clever' tricks but is shorter and easier to understand and tweak. It also uses numbers so it doesn't grow the length of the string as quickly. It increments from 0-9 then a-z, but it is intended that you should feed in 'a' to start with. Output always starts with an alphabet character, as long as your input also starts with an alphabet character, so it can be used as PHP variable names
var nextVarName = function(str) {
// Position of char to change.
var change = str.length - 1;
// The value of that char.
var change_char = str[change];
// Number of zeros to append when flipping.
var zeros = 0;
// Iterate backwards while there's a z (flipping).
while (change_char == 'z') {
// Increase the length of appended zeros
zeros++;
// Move the char to change back.
change_char = str[--change];
}
if (change_char == undefined) {
// Full flip - string increases in length.
str = 'a' + Array(str.length + 1).join("0");
} else {
// Normal increment with partial flip and 9->a handling.
str = str.substr(0, change)
+ (change_char == '9' ? 'a' : String.fromCharCode(str.charCodeAt(change) + 1))
+ Array(zeros + 1).join('0');
}
return str;
};
var vname = 'a';
for (var i = 0; i < 5; i++) {
vname = nextVarName(vname);
console.log(vname);
}
The results will be as follows:
z ---> a0
9z ---> a0 (unexpected input)
ab1zde ---> ab1zdf
abcdzz ---> abce00
zzzzz ---> a00000
abcyzz ---> abcz00
9000 ---> 9001 (unexpected input)
https://jsfiddle.net/e20kfvky/
The schedule of how many variables (that start with an alphabet char) are created of each length is as follows:
1: 26, 2: 936, 3: 33696, 4: 1213056 ... n: 36 ^ n - 10 * 36 ^ (n - 1)
The following code will generate a token that you can advance by one. It uses some small classes to make it modular. The function you attach to the button will call the function next on the token as shown in the very bottom.
//Element in a big token
function Increment(startval, endval) {
this.start = startval.charCodeAt(0);
this.cur = this.start;
this.end = endval.charCodeAt(0);
//Returns the current value
this.get = function() {
if (this.cur <= this.end) {
return String.fromCharCode(this.cur);
} else {
return null;
}
}
//Advances the value we will show
this.next = function() {
this.cur += 1;
return this.get();
}
//Reset it to the beginning
this.reset = function() {
this.cur = this.start;
}
}
function Token() {
this.token = [
new Increment("A", "Z"),
new Increment("A", "Z"),
new Increment("0", "9"),
new Increment("0", "9"),
new Increment("0", "9")
];
this.get = function() {
return this.token.map(function(cur) {
return cur.get();
}).join("");
}
this.next = function() {
//From the back to the front
for (var i = this.token.length - 1; i >= 0; i--) {
if (this.token[i].next() == null) {
//If we exhausted all possible values, continue
this.token[i].reset();
} else {
//Until we advance one that has still values left
break;
}
}
return this.get();
}
}
//Now we are just showing off...
var a = new Token();
for (var i = 0; i < 15; i++) {
console.log(a.next());
}
const getNextAlphaString = function (str) {
"use strict";
str=str.toUpperCase();
let chars;
chars = str.split("");
const strLen = str.length;
let continueIncermenting = true;
for (let i = strLen - 1; i >= 0; i = i - 1) {
let asciiVal;
asciiVal = chars[i].charCodeAt(0);
if (isNaN(asciiVal)) {
return str;
}
if (continueIncermenting === true) {
if (asciiVal >= 48 && asciiVal < 57) {
chars[i] = String.fromCharCode(asciiVal + 1);
continueIncermenting = false;
break;
} else if (asciiVal == 57) {
chars[i] = '0';
continueIncermenting = true;
}
if (asciiVal >= 65 && asciiVal < 90) {
chars[i] = String.fromCharCode(asciiVal + 1);
continueIncermenting = false;
break;
} else if (asciiVal == 90) {
chars[i] = String.fromCharCode(65);
continueIncermenting = true;
}
} else {
if (asciiVal == 90) {
continueIncermenting = true;
chars[i] = String.fromCharCode(65);
}
if (asciiVal == 57) {
continueIncermenting = true;
chars[i] = '0';
}
}
}
if (continueIncermenting === true) {
let firstAcii = chars[0].charCodeAt(0);
if (isNaN(firstAcii)) {
return str;
}
if ((firstAcii >= 65 && firstAcii <= 90) || (firstAcii >= 97 && firstAcii <= 122)) {
return 'A' + chars.join('').toUpperCase();
}
if (firstAcii >= 48 && firstAcii <= 57) {
return '0' + chars.join('').toUpperCase();
}
}
return chars.join('').toUpperCase();
};
The results will be as follows:
ab1zde ---> AB1ZDF
abcdzz ---> ABCEAA
zzzzz ---> AAAAAA
abcyzz ---> ABCZAA
9000 ---> 9001

how to call a php extension method from another php extension method

I write a php extension which contains a simple method, and it works well.
I want to call "mysql_connect" method in this method. I have tried to find some documents or some guides ,but failed.
My extension method code is here:
PHP_FUNCTION(wdd_mysql_connect)
{
char *name;
int name_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE)
{
return;
}
php_printf("Hello %s!", name);
// how to call mysql_connect????????
RETURN_TRUE;
}
Basically, you call zend_call_function(). Example of two helper functions to do that:
/* {{{ zval*** get_params_ex(const char *fmt,size_t len, va_list argp) */
static zval*** get_params_ex(const char *fmt, size_t len TSRMLS_DC, va_list argp) {
zval*** params;
size_t i, j;
char *s=NULL;
long l=-1,r=-1;
double d=-1;
zval *z=NULL;
zend_bool b=0;
params = safe_emalloc(len, sizeof(zval**), 0);
if(NULL == params) {
return NULL;
}
for(i=0; i < len; i++) {
params[i] = emalloc(sizeof(zval*));
}
for(i=0; i < len; i++) {
switch(fmt[i]) {
case 's':
s = va_arg(argp, char*);
MAKE_STD_ZVAL(*params[i]);
ZVAL_STRING(*params[i], s, 1);
break;
case 'l':
l = va_arg(argp, long);
MAKE_STD_ZVAL(*params[i]);
ZVAL_LONG(*params[i], l);
break;
case 'd':
d = va_arg(argp, double);
MAKE_STD_ZVAL(*params[i]);
ZVAL_DOUBLE(*params[i], d);
break;
case 'b':
b = va_arg(argp, int);
MAKE_STD_ZVAL(*params[i]);
ZVAL_BOOL(*params[i], b);
break;
case 'r':
r = va_arg(argp, long);
MAKE_STD_ZVAL(*params[i]);
ZVAL_RESOURCE(*params[i], r);
break;
case 'z':
z = va_arg(argp, zval*);
if(NULL != z) {
*params[i] = z;
}
else {
ALLOC_INIT_ZVAL(*params[i]);
}
break;
default:
php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Unexpected character '%c' in format specifier \"%s\"", fmt[i], fmt);
for(j = 0; j < i; j++) {
zval_ptr_dtor(params[j]);
}
efree(params);
return NULL;
}
}
return params;
}
/* }}} */
/* {{{ META_API zval* obj_call_method_internal_ex(zval *obj, zend_class_entry *ce, zend_function *func, zend_class_entry* calling_scope, zend_bool native_null TSRMLS_DC, char* fmt, ...)
* call method func of the object obj of type ce from the specified scope and return the value returned by the calee.
* if native_null is true, and the method returns a IS_NULL zval, then free that zval and return a NULL pointer
* valid format specifiers are [sldbrz] for string, long, double, boolean, resource, zval */
META_API zval* obj_call_method_internal_ex(zval *obj, zend_class_entry *ce, zend_function *func, zend_class_entry* calling_scope,
zend_bool native_null TSRMLS_DC, char* fmt, ...) {
zval ***params;
int argc;
zval *retval_ptr;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
if(NULL != fmt) {
va_list argv;
argc = strlen(fmt);
va_start(argv, fmt);
params = get_params_ex(fmt, argc TSRMLS_CC, argv);
va_end(argv);
}
else {
argc = 0;
params = NULL;
}
retval_ptr = NULL;
fci.size = sizeof(fci);
fci.function_table = EG(function_table);
fci.function_name = NULL;
fci.symbol_table = NULL;
fci.object_ptr = obj;
fci.retval_ptr_ptr = &retval_ptr;
fci.param_count = argc;
fci.params = params;
fci.no_separation = 1;
fcc.initialized = 1;
fcc.function_handler = func;
fcc.object_ptr = obj;
fcc.calling_scope = calling_scope;
fcc.called_scope = ce;
/*if we want the object, and the object is not an object yet, we init it*/
if(func == ce->constructor) {
if(IS_NULL == Z_TYPE_P(obj)) {
object_init_ex(obj, ce);
}
else {
php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Cannot create an object");
native_null = 1;
goto clean_params;
}
}
if(FAILURE == zend_call_function(&fci, &fcc TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Cannot call %s::%s", ce->name, func->common.function_name);
if(NULL != retval_ptr) {
zval_ptr_dtor(&retval_ptr);
}
}
clean_params:
if(NULL != params) {
int i;
for(i=0; i < argc; i++) {
zval_ptr_dtor(params[i]);
efree(params[i]);
}
efree(params);
}
if(func == ce->constructor) {
zval_ptr_dtor(&retval_ptr);
retval_ptr = fci.object_ptr;
}
else {
if(native_null) {
if(NULL != retval_ptr && IS_NULL == Z_TYPE_P(retval_ptr)) {
zval_ptr_dtor(&retval_ptr);
retval_ptr = NULL;
}
else {
php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "The call %s::%s() does not return NULL as expected", ce->name, func->common.function_name);
}
}
}
return retval_ptr;
}
/* }}} */

Where in the PHP source is the code for incrementing strings?

PHP has a feature where you can use increment operators on strings. It behaves similarly to an odometer, where once you reach the end of a range, it "rolls over".
<?php
$str = 'zy';
$str++;
echo "$str\n"; // zz
$str++;
echo "$str\n"; // aaa
Just curious where in the PHP source code this is. I often look in the source code at functions/extensions, but something like this I have no idea where to look.
A link to the file using their web based SVN would be awesome.
The implementation for this operator is conveniently located in zend_operators.c, in a function that's even more conveniently called increment_string():
static void increment_string(zval *str) /* {{{ */
{
int carry=0;
int pos=Z_STRLEN_P(str)-1;
char *s=Z_STRVAL_P(str);
char *t;
int last=0; /* Shut up the compiler warning */
int ch;
if (Z_STRLEN_P(str) == 0) {
STR_FREE(Z_STRVAL_P(str));
Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1);
Z_STRLEN_P(str) = 1;
return;
}
if (IS_INTERNED(s)) {
s = (char*) emalloc(Z_STRLEN_P(str) + 1);
memcpy(s, Z_STRVAL_P(str), Z_STRLEN_P(str) + 1);
Z_STRVAL_P(str) = s;
}
while (pos >= 0) {
ch = s[pos];
if (ch >= 'a' && ch <= 'z') {
if (ch == 'z') {
s[pos] = 'a';
carry=1;
} else {
s[pos]++;
carry=0;
}
last=LOWER_CASE;
} else if (ch >= 'A' && ch <= 'Z') {
if (ch == 'Z') {
s[pos] = 'A';
carry=1;
} else {
s[pos]++;
carry=0;
}
last=UPPER_CASE;
} else if (ch >= '0' && ch <= '9') {
if (ch == '9') {
s[pos] = '0';
carry=1;
} else {
s[pos]++;
carry=0;
}
last = NUMERIC;
} else {
carry=0;
break;
}
if (carry == 0) {
break;
}
pos--;
}
if (carry) {
t = (char *) emalloc(Z_STRLEN_P(str)+1+1);
memcpy(t+1, Z_STRVAL_P(str), Z_STRLEN_P(str));
Z_STRLEN_P(str)++;
t[Z_STRLEN_P(str)] = '\0';
switch (last) {
case NUMERIC:
t[0] = '1';
break;
case UPPER_CASE:
t[0] = 'A';
break;
case LOWER_CASE:
t[0] = 'a';
break;
}
STR_FREE(Z_STRVAL_P(str));
Z_STRVAL_P(str) = t;
}
}
/* }}} */

Actionscript Serialization Class

I have an actionscript class that serializes and unserializes data compatible with php's serialization functions. I expanded it to support binary data but now the unserialization does not seem to work.
For example, this data is not unserialized correctly:
a:2:{i:0;s:1:"õ";i:1;a:2:{i:0;s:32:"mÎiyl·T=doÁ°ýNd_¤ÁÝ`:AåÁˆ#";i:1;s:32:"ÿ^ò`d^|“T¶&JÐÞG[±iÏ*Ÿ!–Ü’IÍ";}}
Here is the class:
package pack
{
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.core.*;
use namespace mx_internal;
public class Serializer extends Object
{
public static const version:String = "3.0.0";
mx_internal static var c:uint;
mx_internal static var pattern:RegExp = /[A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4} \d{2}:\d{2}:\d{2} \+|\-\d{4}/g
public static function serialize(data:*):ByteArray
{
var bas:ByteArray = new ByteArray();
var tmp:ByteArray = new ByteArray();
var i:int = 0;
var key:String;
if(data is Boolean){
bas.writeUTFBytes('b:');
bas.writeUnsignedInt(data);
bas.writeUTFBytes(';');
} else if(data is int){
bas.writeUTFBytes('i:');
bas.writeUTFBytes(data);
bas.writeUTFBytes(';');
} else if(data is Number){
bas.writeUTFBytes('d:');
bas.writeUTFBytes(data);
bas.writeUTFBytes(';');
} else if(data is ByteArray){
bas.writeUTFBytes('s:');
bas.writeUTFBytes(data.length.toString());
bas.writeUTFBytes(':"');
bas.writeBytes(data);
bas.writeUTFBytes('";');
} else if(data is String){
bas.writeUTFBytes('s:');
bas.writeUTFBytes(data.length.toString());
bas.writeUTFBytes(':"');
bas.writeUTFBytes(data);
bas.writeUTFBytes('";');
} else if(data is Date){
bas.writeUTFBytes('s:');
bas.writeUTFBytes(data.toString().length.toString());
bas.writeUTFBytes(':"');
bas.writeUTFBytes(data);
bas.writeUTFBytes('";');
} else if(data is ArrayCollection){
for(key in data){
tmp.writeBytes(Serializer.serialize(i));
tmp.writeBytes(Serializer.serialize(data[key]));
i += 1;
}
bas.writeUTFBytes('a:');
bas.writeUTFBytes(i.toString());
bas.writeUTFBytes(':{');
bas.writeBytes(tmp);
bas.writeUTFBytes('}');
} else if(data is Array){
for(key in data){
tmp.writeBytes(Serializer.serialize(i));
tmp.writeBytes(Serializer.serialize(data[key]));
i += 1;
}
bas.writeUTFBytes('a:');
bas.writeUTFBytes(i.toString());
bas.writeUTFBytes(':{');
bas.writeBytes(tmp);
bas.writeUTFBytes('}');
} else if(data is Object){
for(key in data){
tmp.writeBytes(Serializer.serialize(key));
tmp.writeBytes(Serializer.serialize(data[key]));
i += 1;
}
bas.writeUTFBytes('O:8:"stdClass":');
bas.writeUTFBytes(i.toString());
bas.writeUTFBytes(':{');
bas.writeBytes(tmp);
bas.writeUTFBytes('}');
} else if(data == null || data == undefined){
bas.writeUTFBytes('N;');
} else {
bas.writeUTFBytes('i:0;');
}
return bas;
}
public static function unserialize(data:ByteArray):*
{
Serializer.c = 0;
return Serializer.unserialize_internal(data);
}
mx_internal static function unserialize_internal(data:ByteArray):*
{
var result:*;
var tmpvar:*;
var tmp:Array = new Array();
var type:String = Serializer.charAt(data, Serializer.c);
var pos:uint = 0;
var islist:Boolean = true;
var i:uint;
switch(type){
case "N":
Serializer.c += 2;
break;
case "b":
result = Serializer.substr(data, Serializer.c+2, 1).toString() == '1'
//result = data.substr(Serializer.c+2, 1) == "1"
Serializer.c += 4
break;
case "i":
tmp.push(Serializer.indexOf(data, ';', Serializer.c));
//tmp.push(data.indexOf(";", Serializer.c))
pos = Serializer.c+2
Serializer.c = tmp[0]+1
result = int(Serializer.substring(data, pos, tmp[0]));
//result = int(data.substring(pos,tmp[0]))
break;
case "d":
tmp.push(Serializer.indexOf(data, ';', Serializer.c));
//tmp.push(data.indexOf(";", Serializer.c))
pos = Serializer.c + 2
Serializer.c = tmp[0]+1
result = Number(Serializer.substring(data, pos, tmp[0]));
//result = Number(data.substring(pos,tmp[0]))
break;
case "s":
tmp.push(int(Serializer.indexOf(data, ':', Serializer.c+2)));
//tmp.push(int(data.indexOf(":", Serializer.c+2)))
tmp.push(tmp[0]+2)
pos = Serializer.c+2
tmp.push(0)
tmp.push(int(Serializer.substring(data, pos, tmp[0])));
//tmp.push(int(data.substring(pos, tmp[0])));
if(tmp[3] == 0)
{
result = "";
Serializer.c = pos+5
} else {
var lenc:uint = Serializer.stringBCLenght(data, Serializer.c, tmp[3]);
if(lenc != tmp[3])
{
result = Serializer.substr(data, tmp[0]+2, lenc);
//result = data.substr(tmp[0]+2, lenc);
Serializer.c = tmp[0]+4+lenc;
} else {
result = Serializer.substr(data, tmp[0]+2, tmp[3]);
//result = data.substr(tmp[0]+2, tmp[3]);
Serializer.c = tmp[0]+4+tmp[3];
}
}
if(Serializer.pattern.test(result))
{
result = new Date(result)
}
break;
case "a":
//result:ByteArray;
pos = Serializer.c+2
tmp.push(int(Serializer.indexOf(data, ":", pos)))
tmp.push(int(Serializer.substring(data, pos, tmp[0])))
//tmp.push(int(data.indexOf(":", pos)))
//tmp.push(int(data.substring(pos, tmp[0])))
Serializer.c = tmp[0]+2
result = []
for(i = 0; i < tmp[1]; i++){
tmpvar = Serializer.unserialize_internal(data)
result[tmpvar] = Serializer.unserialize_internal(data)
if(!(tmpvar is int) || tmpvar < 0){
islist = false
}
}
if(islist){
tmp.push([])
for(var key:uint = 0; key < result.length; key++){
pos = tmp[2].length
while(key > pos){
tmp[2].push(null)
pos +=1
}
tmp[2].push(result[key])
}
result = tmp[2]
}
Serializer.c += 1
break;
case "O":
pos = Serializer.indexOf(data, "\"", Serializer.c)+1;
Serializer.c = Serializer.indexOf(data, "\"", pos);
tmp.push(Serializer.substring(data, pos, Serializer.c))
//pos = data.indexOf("\"", Serializer.c)+1;
//Serializer.c = data.indexOf("\"", pos);
//tmp.push(data.substring(pos, Serializer.c))
Serializer.c += 2
i = Serializer.c
Serializer.c = Serializer.indexOf(data, ":", i)
i = int(Serializer.substring(data, i, Serializer.c))
//Serializer.c = data.indexOf(":", i)
//i = int(data.substring(i, Serializer.c))
Serializer.c +=2;
result = {};
var tmps:*;
while(i > 0){
tmps = Serializer.unserialize_internal(data)
result[tmps] = Serializer.unserialize_internal(data)
i -= 1
}
break;
}
return result;
}
mx_internal static function stringCLenght(data:String, from:uint = 0, len:uint = 0):int
{
var i:uint;
var j:uint = len;
var startIndex:uint = from + 4 + len.toString().length;
for (i = 0; i < j; i++){
if (data.charCodeAt(i+startIndex) > 128)
{
j = j - 1
}
}
return j;
}
mx_internal static function stringBCLenght(data:ByteArray, from:uint = 0, len:uint = 0):int
{
var i:uint;
var j:uint = len;
var startIndex:uint = from + 4 + len.toString().length;
for (i = 0; i < j; i++){
if (Serializer.charCodeAt(data, i+startIndex) > 128)
{
j = j - 1
}
}
return j;
}
mx_internal static function stringLength(data:String):uint
{
var code:int = 0
var result:int = 0
var slen:int = data.length;
while(slen){
slen = slen - 1
try
{
code = data.charCodeAt(slen)
} catch(e:Error){
code = 65536
}
if(code < 128){
result = result + 1
} else if(code < 2048){
result = result + 2
} else if(code < 65536){
result = result + 3
} else {
result = result + 4
}
}
return result
}
public static function charAt(bytes:ByteArray, index:int):String {
if (bytes.length <= index) return null;
return String.fromCharCode(bytes[index]);
}
public static function charCodeAt(bytes:ByteArray, index:int):int {
if (bytes.length <= index) return -1;
return bytes[index];
}
public static function substr(bytes:ByteArray, start:int, length:int=0):ByteArray {
var res:ByteArray = new ByteArray();
bytes.position = start;
bytes.readBytes(res, 0, length);
return res;
}
public static function substring(bytes:ByteArray, start:int, end:int=0):ByteArray {
return substr(bytes, start, end-start);
}
public static function indexOf(bytes:ByteArray, str:String, startIndex:int):int {
var num:int = 0;
for (var i:int=0; i<bytes.length; i++) {
var strPos:int = 0;
while (bytes[i+strPos] == str.charCodeAt(strPos)) {
strPos++;
if (strPos == str.length) {
num++;
if(num == startIndex) {
return i;
}
}
}
}
return -1;
}
}
}
I resolved the issue, no need for answers.

Categories