!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: nginx/1.23.4. PHP/5.6.40-65+ubuntu20.04.1+deb.sury.org+1 

uname -a: Linux foro-restaurado-2 5.15.0-1040-oracle #46-Ubuntu SMP Fri Jul 14 21:47:21 UTC 2023
aarch64
 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/home/sources/eaccelerator-eaccelerator-42067ac/   drwxrwxr-x
Free 83.29 GB of 96.73 GB (86.11%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     eaccelerator.c (81.88 KB)      -rw-rw-r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
   +----------------------------------------------------------------------+
   | eAccelerator project                                                 |
   +----------------------------------------------------------------------+
   | Copyright (c) 2004 - 2012 eAccelerator                               |
   | http://eaccelerator.net                                              |
   +----------------------------------------------------------------------+
   | This program is free software; you can redistribute it and/or        |
   | modify it under the terms of the GNU General Public License          |
   | as published by the Free Software Foundation; either version 2       |
   | of the License, or (at your option) any later version.               |
   |                                                                      |
   | This program is distributed in the hope that it will be useful,      |
   | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
   | GNU General Public License for more details.                         |
   |                                                                      |
   | You should have received a copy of the GNU General Public License    |
   | along with this program; if not, write to the Free Software          |
   | Foundation, Inc., 59 Temple Place - Suite 330, Boston,               |
   | MA  02111-1307, USA.                                                 |
   |                                                                      |
   | A copy is availble at http://www.gnu.org/copyleft/gpl.txt            |
   +----------------------------------------------------------------------+
   $Id: eaccelerator.c 426 2010-07-28 09:41:24Z bart $
*/

#include "eaccelerator.h"
#include "eaccelerator_version.h"

#ifdef HAVE_EACCELERATOR

#include "opcodes.h"

#include "zend.h"
#include "zend_API.h"
#include "zend_extensions.h"

#include "debug.h"
#include "ea_store.h"
#include "ea_restore.h"
#include "ea_info.h"
#include "ea_dasm.h"

#include <sys/types.h>
#include <sys/stat.h>
#ifdef ZEND_WIN32
#  include "fnmatch.h"
#  include "win32/time.h"
#  include <time.h>
#  include <sys/utime.h>
#else
#  include <fnmatch.h>
#  include <sys/file.h>
#  include <sys/time.h>
#  include <utime.h>
#endif
#include <fcntl.h>

#ifndef O_BINARY
#  define O_BINARY 0
#endif

#include "php.h"
#include "php_ini.h"
#include "php_logos.h"
#include "main/fopen_wrappers.h"
#include "ext/standard/info.h"
#include "ext/standard/php_incomplete_class.h"
#include "ext/standard/md5.h"

#include "SAPI.h"

#define MAX_DUP_STR_LEN 256

/* Globals (different for each process/thread) */
ZEND_DECLARE_MODULE_GLOBALS(eaccelerator)

/* Globals (common for each process/thread) */
static long ea_shm_size = 0;
static long ea_shm_ttl = 0;
static long ea_shm_prune_period = 0;
extern long ea_debug;
zend_bool ea_scripts_shm_only = 0;

eaccelerator_mm *ea_mm_instance = NULL;
static int ea_is_zend_extension = 0;
static int ea_is_extension      = 0;
zend_extension* ZendOptimizer = NULL;

static HashTable ea_global_function_table;
static HashTable ea_global_class_table;

int binary_eaccelerator_version[2];
int binary_php_version[2];
int binary_zend_version[2];

/* pointer to the properties_info hashtable destructor */
extern dtor_func_t properties_info_dtor;

/* saved original functions */
static zend_op_array *(*ea_saved_zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);

#ifdef DEBUG
static void (*ea_saved_zend_execute)(zend_op_array *op_array TSRMLS_DC);
#endif

/* external declarations */
PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC);

ZEND_DLEXPORT zend_op_array* eaccelerator_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC);

/******************************************************************************/
/* hash mm functions                                                          */
/******************************************************************************/

/* Find a script entry with the given hash key */
static ea_cache_entry* hash_find_mm(const char  *key,
                                    struct stat *buf,
                                    int         *nreloads,
                                    time_t      ttl TSRMLS_DC)
{
    unsigned int hv, slot;
    ea_cache_entry *p, *q;

    hv = zend_get_hash_value((char *)key, strlen(key));
    slot = hv & EA_HASH_MAX;

    EACCELERATOR_LOCK_RW();
    q = NULL;
    p = ea_mm_instance->hash[slot];
    while (p != NULL) {
        if ((p->hv == hv) && (strcmp(p->realfilename, key) == 0)) {
            if (EAG(check_mtime_enabled) && ea_mm_instance->check_mtime_enabled &&
                    (buf->st_mtime != p->mtime || buf->st_size != p->filesize)) {
                /* key is invalid. Remove it. */
                *nreloads = p->nreloads+1;
                if (q == NULL) {
                    ea_mm_instance->hash[slot] = p->next;
                } else {
                    q->next = p->next;
                }
                ea_mm_instance->hash_cnt--;
                if (p->use_cnt > 0) {
                    /* key is used by other process/thread. Schedule it for removal */
                    p->removed = 1;
                    p->next = ea_mm_instance->removed;
                    ea_mm_instance->removed = p;
                    ea_mm_instance->rem_cnt++;
                    EACCELERATOR_UNLOCK_RW();
                    return NULL;
                } else {
                    /* key is unused. Remove it. */
                    eaccelerator_free_nolock(p);
                    EACCELERATOR_UNLOCK_RW();
                    return NULL;
                }
            } else {
                /* key is valid */
                p->nhits++;
                p->use_cnt++;
                p->ttl = ttl;
                EACCELERATOR_UNLOCK_RW();
                return p;
            }
        }
        q = p;
        p = p->next;
    }
    EACCELERATOR_UNLOCK_RW();
    return NULL;
}

/* Add a new entry to the hashtable */
static void hash_add_mm(ea_cache_entry *x)
{
    ea_cache_entry *p,*q;
    unsigned int slot;
    x->hv = zend_get_hash_value(x->realfilename, strlen(x->realfilename));
    slot = x->hv & EA_HASH_MAX;

    EACCELERATOR_LOCK_RW();
    x->next = ea_mm_instance->hash[slot];
    ea_mm_instance->hash[slot] = x;
    ea_mm_instance->hash_cnt++;
    q = x;
    p = x->next;
    while (p != NULL) {
        if ((p->hv == x->hv) &&
                (strcmp(p->realfilename, x->realfilename) == 0)) {
            q->next = p->next;
            ea_mm_instance->hash_cnt--;
            ea_mm_instance->hash[slot]->nreloads += p->nreloads;
            if (p->use_cnt > 0) {
                /* key is used by other process/thread. Shedule it to remove */
                p->removed = 1;
                p->next = ea_mm_instance->removed;
                ea_mm_instance->removed = p;
                ea_mm_instance->rem_cnt++;
                EACCELERATOR_UNLOCK_RW();
                return;
            } else {
                /* key is unused. Remove it. */
                eaccelerator_free_nolock(p);
                EACCELERATOR_UNLOCK_RW();
                return;
            }
        }
        q = p;
        p = p->next;
    }
    EACCELERATOR_UNLOCK_RW();
}

/* Initialise the shared memory */
static int init_mm(TSRMLS_D)
{
    pid_t  owner = getpid();
    MM     *mm;
    size_t total;
    char   mm_path[MAXPATHLEN];

#ifdef ZEND_WIN32
    snprintf(mm_path, MAXPATHLEN, "%s.%s", EACCELERATOR_MM_FILE, sapi_module.name);
#else
    snprintf(mm_path, MAXPATHLEN, "%s.%s%d", EACCELERATOR_MM_FILE, sapi_module.name, owner);
#endif
    /*  snprintf(mm_path, MAXPATHLEN, "%s.%s%d", EACCELERATOR_MM_FILE, sapi_module.name, geteuid());*/
    if ((ea_mm_instance = (eaccelerator_mm*)mm_attach(ea_shm_size*1024*1024, mm_path)) != NULL) {
#ifdef ZTS
        ea_mutex = tsrm_mutex_alloc();
#endif
        return SUCCESS;
    }
    mm = mm_create(ea_shm_size*1024*1024, mm_path);
    if (!mm) {
        return FAILURE;
    }
#ifdef ZEND_WIN32
    DBG(ea_debug_printf, (EA_DEBUG, "init_mm [%d]\n", owner));
#else
    DBG(ea_debug_printf, (EA_DEBUG, "init_mm [%d,%d]\n", owner, getppid()));
#endif
#ifdef ZTS
    ea_mutex = tsrm_mutex_alloc();
#endif
    total = mm_available(mm);
    ea_mm_instance = mm_malloc_lock(mm, sizeof(eaccelerator_mm));
    if (!ea_mm_instance) {
        return FAILURE;
    }
    mm_set_attach(mm, ea_mm_instance);
    memset(ea_mm_instance, 0, sizeof(eaccelerator_mm));
    ea_mm_instance->owner = owner;
    ea_mm_instance->mm    = mm;
    ea_mm_instance->total = total;
    ea_mm_instance->hash_cnt = 0;
    ea_mm_instance->rem_cnt  = 0;
    ea_mm_instance->enabled = 1;
    ea_mm_instance->optimizer_enabled = 1;
    ea_mm_instance->check_mtime_enabled = 1;
    ea_mm_instance->removed = NULL;
    ea_mm_instance->cache_dir_uid = 0;
    ea_mm_instance->last_prune = time(NULL);    /* this time() call is harmless since this is init phase */
    return SUCCESS;
}

/* Clean up the shared memory */
static void shutdown_mm(TSRMLS_D)
{
    if (ea_mm_instance) {
#ifdef ZEND_WIN32
        if (ea_mm_instance->owner == getpid()) {
#else
        if (getpgrp() == getpid()) {
#endif
            MM *mm = ea_mm_instance->mm;
#ifdef ZEND_WIN32
            DBG(ea_debug_printf, (EA_DEBUG, "shutdown_mm [%d]\n", getpid()));
#else
            DBG(ea_debug_printf, (EA_DEBUG, "shutdown_mm [%d,%d]\n", getpid(), getppid()));
#endif
#ifdef ZTS
            tsrm_mutex_free(ea_mutex);
#endif
            if (mm) {
                mm_destroy(mm);
            }
            ea_mm_instance = NULL;
        }
    }
}

void encode_version(const char *str, int *version, int *extra)
{
    unsigned int a = 0;
    unsigned int b = 0;
    unsigned int c = 0;
    unsigned int d = 0;
    size_t len;
    char s[255];
    char buf[255];

    len = strlen(str);
    memcpy(buf, str, (len > 255) ? 255 : len);
    buf[254] = '\0';

    memset(s, 0, 255);
    sscanf(str, "%u.%u.%u%s", &a, &b, &c, s);

    if (s[0] == '.') {
        sscanf(s, ".%u-%s", &d, buf);
    } else if (s[0] == '-') {
        memcpy(buf, &s[1], 254);
    } else {
        memcpy(buf, s, 255);
    }

    *version = ((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff);

    if (buf[0] == 0) {
        a = 0;
        b = 0;
    } else if (strncasecmp(buf, "rev", 3) == 0) {
        a = 1;
        sscanf(buf, "rev%u", &b);
    } else if (strncasecmp(buf, "rc", 2) == 0) {
        a = 2;
        sscanf(buf, "rc%u", &b);
    } else if (strncasecmp(buf, "beta", 4) == 0) {
        a = 3;
        sscanf(buf, "beta%u", &b);
    } else {
        a = 0xf;
        // just encode the first 4 bytes
        b = ((buf[0] & 0x7f) << 21) | ((buf[1] & 0x7f) << 14) | ((buf[2] & 0x7f) << 7) | (buf[3] & 0x7f);
    }

    *extra = ((a & 0xf) << 28) | (0x0fffffff & b);
}

#ifdef DEBUG
static void decode_version(int version, int extra, char *str, size_t len)
{
    int number;

    if ((version & 0xff) == 0) {
        number = snprintf(str, len, "%u.%u.%u", (version >> 24), ((version >> 16) & 0xff), ((version >> 8) & 0xff));
    } else {
        number = snprintf(str, len, "%u.%u.%u.%u", (version >> 24), ((version >> 16) & 0xff), ((version >> 8) & 0xff), (version & 0xff));
    }

    if (extra != 0) {
        unsigned int type = ((extra >> 28) & 0xf);
        extra = (extra & 0x0fffffff);
        switch (type) {
        case 1:
            snprintf(&str[number], len, "-rev%u", extra);
            break;
        case 2:
            snprintf(&str[number], len, "-rc%u", extra);
            break;
        case 3:
            snprintf(&str[number], len, "-beta%u", extra);
            break;
        case 15:
            if ((int)len >= number + 5) {
                str[number] = '-';
                str[number + 1] = (extra >> 21) & 0x7f;
                str[number + 2] = (extra >> 14) & 0x7f;
                str[number + 3] = (extra >> 7) & 0x7f;
                str[number + 4] = extra & 0x7f;
                str[number + 5] = '\0';
            }
            break;
        default:
            break;
        }
    }
}
#endif

static char num2hex[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};

/* Function to create a hash key when filenames are used */
int eaccelerator_md5(char* s, const char* prefix, const char* key TSRMLS_DC)
{
    char md5str[33];
    PHP_MD5_CTX context;
    unsigned char digest[16];
    int i;
    int n;

    md5str[0] = '\0';
    PHP_MD5Init(&context);
    PHP_MD5Update(&context, (unsigned char*)key, strlen(key));
    PHP_MD5Final(digest, &context);
    make_digest(md5str, digest);
    snprintf(s, MAXPATHLEN-1, "%s/%d/", EAG(cache_dir), ea_mm_instance->cache_dir_uid);
    n = strlen(s);
    for (i = 0; i < EACCELERATOR_HASH_LEVEL && n < MAXPATHLEN - 1; i++) {
        s[n++] = md5str[i];
        s[n++] = '/';
    }
    s[n] = 0;
    snprintf(&s[n], MAXPATHLEN-1-n, "%s%s", prefix, md5str);
    return 1;
}

/* Remove expired keys, content and scripts from the memory cache */
void eaccelerator_prune(time_t t)
{
    unsigned int i;

    EACCELERATOR_LOCK_RW();
    ea_mm_instance->last_prune = t;
    for (i = 0; i < EA_HASH_SIZE; i++) {
        ea_cache_entry **p = &ea_mm_instance->hash[i];
        while (*p != NULL) {
            struct stat buf;
            if (((*p)->ttl != 0 && (*p)->ttl < t && (*p)->use_cnt <= 0) ||
                    stat((*p)->realfilename,&buf) != 0 ||
                    (*p)->mtime != buf.st_mtime ||
                    (*p)->filesize != buf.st_size) {
                ea_cache_entry *r = *p;
                *p = (*p)->next;
                ea_mm_instance->hash_cnt--;
                eaccelerator_free_nolock(r);
            } else {
                p = &(*p)->next;
            }
        }
    }
    EACCELERATOR_UNLOCK_RW();
}

/* Allocate a new cache chunk */
void* eaccelerator_malloc2(size_t size TSRMLS_DC)
{
    void *p = NULL;

    if (ea_shm_prune_period > 0) {
        if (EAG(req_start) - ea_mm_instance->last_prune > ea_shm_prune_period) {
            eaccelerator_prune(EAG(req_start));
            p = eaccelerator_malloc(size);
        }
    }
    return p;
}

#define EACCELERATOR_CRC32(crc, ch)   (crc = (crc >> 8) ^ crc32tab[(crc ^ (ch)) & 0xff])

static const unsigned int crc32tab[256] = {
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
    0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
    0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
    0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
    0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
    0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
    0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
    0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
    0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
    0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
    0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
    0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
    0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
    0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
    0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
    0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};

unsigned int eaccelerator_crc32(const char *p, size_t n)
{
    unsigned int crc = ~0;
    for (; n--; ++p) {
        EACCELERATOR_CRC32(crc, *p);
    }
    return ~crc;
}

/******************************************************************************/
/* Cache file functions.                                                        */
/******************************************************************************/

/* A function to check if the header of a cache file valid is.
 */
inline int check_header(ea_file_header *hdr)
{
#ifdef DEBUG
    char current[255];
    char cache[255];
#endif

    if (strncmp(hdr->magic, EA_MAGIC, 8) != 0) {
#ifdef DEBUG
        ea_debug_printf(EA_DEBUG, "Magic header mismatch.");
#endif
        return 0;
    }
    if (hdr->eaccelerator_version[0] != binary_eaccelerator_version[0]
            || hdr->eaccelerator_version[1] != binary_eaccelerator_version[1]) {
#ifdef DEBUG
        decode_version(hdr->eaccelerator_version[0], hdr->eaccelerator_version[1], cache, 255);
        decode_version(binary_eaccelerator_version[0], binary_eaccelerator_version[1], current, 255);
        ea_debug_printf(EA_DEBUG, "eAccelerator version mismatch, cache file %s and current version %s\n", cache, current);
#endif
        return 0;
    }
    if (hdr->zend_version[0] != binary_zend_version[0]
            || hdr->zend_version[1] != binary_zend_version[1]) {
#ifdef DEBUG
        decode_version(hdr->zend_version[0], hdr->zend_version[1], cache, 255);
        decode_version(binary_zend_version[0], binary_zend_version[1], current, 255);
        ea_debug_printf(EA_DEBUG, "Zend version mismatch, cache file %s and current version %s\n", cache, current);
#endif
        return 0;
    }
    if (hdr->php_version[0] != binary_php_version[0]
            || hdr->php_version[1] != binary_php_version[1]) {
#ifdef DEBUG
        decode_version(hdr->php_version[0], hdr->php_version[1], cache, 255);
        decode_version(binary_php_version[0], binary_php_version[1], current, 255);
        ea_debug_printf(EA_DEBUG, "PHP version mismatch, cache file %s and current version %s\n", cache, current);
#endif
        return 0;
    }
    return 1;
}

/* A function to create the header for a cache file.
 */
inline void init_header(ea_file_header *hdr)
{
    strncpy(hdr->magic, EA_MAGIC, 8);
    hdr->eaccelerator_version[0] = binary_eaccelerator_version[0];
    hdr->eaccelerator_version[1] = binary_eaccelerator_version[1];
    hdr->zend_version[0] = binary_zend_version[0];
    hdr->zend_version[1] = binary_zend_version[1];
    hdr->php_version[0] = binary_php_version[0];
    hdr->php_version[1] = binary_php_version[1];
}
/* Retrieve a cache entry from the cache directory */
static ea_cache_entry* hash_find_file(const char  *key, struct stat *buf TSRMLS_DC)
{
    int f;
    char s[MAXPATHLEN];
    ea_file_header hdr;
    ea_cache_entry *p = NULL;
    int use_shm = 1;

    if (!eaccelerator_md5(s, "/eaccelerator-", key TSRMLS_CC)) {
        return NULL;
    }

    if ((f = open(s, O_RDONLY | O_BINARY)) > 0) {
        EACCELERATOR_FLOCK(f, LOCK_SH);
        if (read(f, &hdr, sizeof(hdr)) != sizeof(hdr)) {
            EACCELERATOR_FLOCK(f, LOCK_UN);
            close(f);
            return NULL;
        }
        if (!check_header(&hdr)) {
            EACCELERATOR_FLOCK(f, LOCK_UN);
            close(f);
            unlink(s);
            return NULL;
        }
        p = eaccelerator_malloc(hdr.size);
        if (p == NULL) {
            p = eaccelerator_malloc2(hdr.size TSRMLS_CC);
        }
        if (p == NULL) {
            p = emalloc(hdr.size);
            use_shm = 0;
        }
        if (p == NULL) {
            EACCELERATOR_FLOCK(f, LOCK_UN);
            close(f);
            return NULL;
        }
        if (read(f, p, hdr.size) != hdr.size ||
                p->size != hdr.size ||
                hdr.crc32 != eaccelerator_crc32((const char*)p,p->size)) {
            EACCELERATOR_FLOCK(f, LOCK_UN);
            close(f);
            unlink(s);
            if (use_shm) {
                eaccelerator_free(p);
            } else {
                efree(p);
            }
            DBG(ea_debug_printf, (EA_DEBUG, "cache file is corrupted\n"));
            return NULL;
        }
        EACCELERATOR_FLOCK(f, LOCK_UN);
        close(f);
        if (strcmp(key,p->realfilename) != 0) {
            if (use_shm) {
                eaccelerator_free(p);
            } else {
                efree(p);
            }
            return NULL;
        }
        if ((EAG(check_mtime_enabled) && ea_mm_instance->check_mtime_enabled &&
                (buf->st_mtime != p->mtime || buf->st_size != p->filesize))
           ) {
            /* key is invalid. Remove it. */
            if (use_shm) {
                eaccelerator_free(p);
            } else {
                efree(p);
            }
            unlink(s);
            return NULL;
        }
        eaccelerator_fixup(p TSRMLS_CC);
        if (use_shm) {
            p->nhits    = 1;
            p->nreloads = 1;
            p->use_cnt  = 1;
            p->removed  = 0;
            if (ea_shm_ttl > 0) {
                p->ttl = EAG(req_start) + ea_shm_ttl;
            } else {
                p->ttl = 0;
            }
            p->ts       = hdr.ts;    /* get cached item creation timestamp from cache file */
            hash_add_mm(p);
        } else {
            p->use_cnt  = 0;
            p->removed  = 1;
        }
        mm_check_mem(p);
        return p;
    }
    return NULL;
}

/* Add a cache entry to the cache directory */
static int hash_add_file(ea_cache_entry *p TSRMLS_DC)
{
    int f;
    int ret = 0;
    char s[MAXPATHLEN];
    ea_file_header hdr;

    if (!eaccelerator_md5(s, "/eaccelerator-", p->realfilename TSRMLS_CC)) {
        return 0;
    }

    unlink(s);
    f = open(s, O_CREAT | O_WRONLY | O_EXCL | O_BINARY, S_IRUSR | S_IWUSR);
    if (f > 0) {
        EACCELERATOR_FLOCK(f, LOCK_EX);
        init_header(&hdr);
        hdr.size  = p->size;
        hdr.mtime = p->mtime;
        hdr.ts    = p->ts;
        p->next = p;
        hdr.crc32 = eaccelerator_crc32((const char*)p,p->size);
        ret = (write(f, &hdr, sizeof(hdr)) == sizeof(hdr));
        if (ret) {
            ret = (write(f, p, p->size) == p->size);
        }
        EACCELERATOR_FLOCK(f, LOCK_UN);
        close(f);
    } else {
        ea_debug_log("EACCELERATOR: Open for write failed for \"%s\": %s\n", s, strerror(errno));
    }
    return ret;
}

/* called after succesful compilation, from eaccelerator_compile file */
/* Adds the data from the compilation of the script to the cache */
static int eaccelerator_store(char* key, struct stat *buf, int nreloads,
                              zend_op_array* op_array,
                              Bucket* f, Bucket *c TSRMLS_DC)
{
    ea_cache_entry *p;
    int len = strlen(key);
    int use_shm = 1;
    int ret = 0;
    int size = 0;
    void *data = NULL;

    zend_try {
        size = calc_size(key, op_array, f, c TSRMLS_CC);
    } zend_catch {
        size =  0;
    } zend_end_try();
    if (size == 0) {
        return 0;
    }

    EAG(mem) = eaccelerator_malloc(size);
    if (EAG(mem) == NULL) {
        EAG(mem) = eaccelerator_malloc2(size TSRMLS_CC);
    }
    if (!EAG(mem) && !ea_scripts_shm_only) {
        EAG(mem) = emalloc(size);
        use_shm = 0;
    }
    if (EAG(mem)) {
        data = EAG(mem);
        memset(EAG(mem), 0, size);
        p = (ea_cache_entry *)EAG(mem);
        eaccelerator_store_int(p, key, len, op_array, f, c TSRMLS_CC);
        p->mtime    = buf->st_mtime;
        p->ts       = EAG(req_start);
        p->filesize = buf->st_size;
        p->size     = size;
        p->nreloads = nreloads;
        if (use_shm) {
            if (ea_shm_ttl > 0) {
                p->ttl = EAG(req_start) + ea_shm_ttl;
            } else {
                p->ttl = 0;
            }
            if (!ea_scripts_shm_only) {
                hash_add_file(p TSRMLS_CC);
            }
            hash_add_mm(p);
            ret = 1;
            mm_check_mem(data);
        } else {
            ret =  hash_add_file(p TSRMLS_CC);
            efree(p);
        }
    }
    return ret;
}

/* Try to restore a file from the cache. If the file isn't found in memory, the
   the disk cache is checked */
static zend_op_array* eaccelerator_restore(char *realname, struct stat *buf,
        int *nreloads, time_t compile_time TSRMLS_DC)
{
    ea_cache_entry *p;
    zend_op_array *op_array = NULL;

    *nreloads = 1;
    p = hash_find_mm(realname, buf, nreloads, ((ea_shm_ttl > 0)?(compile_time + ea_shm_ttl):0) TSRMLS_CC);
    if (p == NULL && !ea_scripts_shm_only) {
        p = hash_find_file(realname, buf TSRMLS_CC);
    }
    if (p != NULL && p->op_array != NULL) {
        /* only restore file when open_basedir allows it */
        if (PG(open_basedir) && php_check_open_basedir(p->realfilename TSRMLS_CC)) {
            return NULL;
        }
        EAG(class_entry) = NULL;
        op_array = restore_op_array(NULL, p->op_array TSRMLS_CC);
        if (op_array != NULL) {
            ea_fc_entry *e;
            ea_used_entry *used = emalloc(sizeof(ea_used_entry));
            used->entry  = p;
            used->next   = (ea_used_entry*)EAG(used_entries);
            EAG(used_entries) = (void*)used;
            EAG(mem) = (char*)op_array->filename;
            /* only restore the classes and functions when we restore this script
             * for the first time.
             */
            if (!zend_hash_exists(&EAG(restored), p->realfilename, strlen(p->realfilename))) {
                for (e = p->c_head; e!=NULL; e = e->next) {
                    restore_class(e TSRMLS_CC);
                }
                for (e = p->f_head; e!=NULL; e = e->next) {
                    restore_function(e TSRMLS_CC);
                }
                zend_hash_add(&EAG(restored), p->realfilename, strlen(p->realfilename), NULL, 0, NULL);
            }
            EAG(mem) = p->realfilename;
        }
#ifdef ZEND_COMPILE_DELAYED_BINDING
        zend_do_delayed_early_binding(op_array TSRMLS_CC);
#endif
    }
    return op_array;
}

/*
 * Returns the realpath for given filename according to include path
 */
static char *ea_resolve_path(const char *filename, int filename_length, const char *path TSRMLS_DC)
{
    char resolved_path[MAXPATHLEN];
    char trypath[MAXPATHLEN];
    const char *ptr, *end, *p;
    char *actual_path;
    php_stream_wrapper *wrapper;

    if (!filename) {
        return NULL;
    }

    /* Don't resolve paths which contain protocol (except of file://) */
    for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) {
        ;
    }
    if ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/')) {
        wrapper = php_stream_locate_url_wrapper(filename, &actual_path, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
        if (wrapper == &php_plain_files_wrapper) {
            if (tsrm_realpath(actual_path, resolved_path TSRMLS_CC)) {
                return estrdup(resolved_path);
            }
        }
        return NULL;
    }

    if ((*filename == '.' &&
            (IS_SLASH(filename[1]) ||
             ((filename[1] == '.') && IS_SLASH(filename[2])))) ||
            IS_ABSOLUTE_PATH(filename, filename_length) ||
            !path ||
            !*path) {
        if (tsrm_realpath(filename, resolved_path TSRMLS_CC)) {
            return estrdup(resolved_path);
        } else {
            return NULL;
        }
    }

    ptr = path;
    while (ptr && *ptr) {
        /* Check for stream wrapper */
        int is_stream_wrapper = 0;

        for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) {
            ;
        }
        if ((*p == ':') && (p - ptr > 1) && (p[1] == '/') && (p[2] == '/')) {
            /* .:// or ..:// is not a stream wrapper */
            if (p[-1] != '.' || p[-2] != '.' || p - 2 != ptr) {
                p += 3;
                is_stream_wrapper = 1;
            }
        }
        end = strchr(p, DEFAULT_DIR_SEPARATOR);
        if (end) {
            if ((end-ptr) + 1 + filename_length + 1 >= MAXPATHLEN) {
                ptr = end + 1;
                continue;
            }
            memcpy(trypath, ptr, end-ptr);
            trypath[end-ptr] = '/';
            memcpy(trypath+(end-ptr)+1, filename, filename_length+1);
            ptr = end+1;
        } else {
            int len = strlen(ptr);

            if (len + 1 + filename_length + 1 >= MAXPATHLEN) {
                break;
            }
            memcpy(trypath, ptr, len);
            trypath[len] = '/';
            memcpy(trypath+len+1, filename, filename_length+1);
            ptr = NULL;
        }
        actual_path = trypath;
        if (is_stream_wrapper) {
            wrapper = php_stream_locate_url_wrapper(trypath, &actual_path, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
            if (!wrapper) {
                continue;
            } else if (wrapper != &php_plain_files_wrapper) {
                if (wrapper->wops->url_stat) {
                    php_stream_statbuf ssb;

                    if (SUCCESS == wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL TSRMLS_CC)) {
                        return estrdup(trypath);
                    }
                }
                continue;
            }
        }
        if (tsrm_realpath(actual_path, resolved_path TSRMLS_CC)) {
            return estrdup(resolved_path);
        }
    } /* end provided path */

    /* check in calling scripts' current working directory as a fall back case
     */
    if (zend_is_executing(TSRMLS_C)) {
#ifdef ZEND_ENGINE_2_4
        const char *exec_fname = zend_get_executed_filename(TSRMLS_C);
#else
        char *exec_fname = zend_get_executed_filename(TSRMLS_C);
#endif
        int exec_fname_length = strlen(exec_fname);

        while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length])) {
            ;
        }
        if (exec_fname && exec_fname[0] != '[' &&
                exec_fname_length > 0 &&
                exec_fname_length + 1 + filename_length + 1 < MAXPATHLEN) {
            memcpy(trypath, exec_fname, exec_fname_length + 1);
            memcpy(trypath+exec_fname_length + 1, filename, filename_length+1);
            actual_path = trypath;

            /* Check for stream wrapper */
            for (p = trypath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) {
                ;
            }
            if ((*p == ':') && (p - trypath > 1) && (p[1] == '/') && (p[2] == '/')) {
                wrapper = php_stream_locate_url_wrapper(trypath, &actual_path, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
                if (!wrapper) {
                    return NULL;
                } else if (wrapper != &php_plain_files_wrapper) {
                    if (wrapper->wops->url_stat) {
                        php_stream_statbuf ssb;

                        if (SUCCESS == wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL TSRMLS_CC)) {
                            return estrdup(trypath);
                        }
                    }
                    return NULL;
                }
            }

            if (tsrm_realpath(actual_path, resolved_path TSRMLS_CC)) {
                return estrdup(resolved_path);
            }
        }
    }

    return NULL;
}

/**
 * Get the real filename of the file represented by the given file_handle.
 * If unable to determine the realfilename this function returns 0, otherwise
 * it returns 1.
 *
 * realfilename should be MAXPATHLEN long.
 */
static int ea_get_realname(zend_file_handle *file_handle, char* realname TSRMLS_DC)
{
    // at least one of these should have value
    if (file_handle->opened_path == NULL && file_handle->filename == NULL) {
        return 0;
    }

    if (file_handle->opened_path != NULL) {
        strcpy(realname, file_handle->opened_path);
        return 1;
    }

    if (PG(include_path) == NULL ||
            file_handle->filename[0] == '.' ||
            IS_SLASH(file_handle->filename[0]) ||
            IS_ABSOLUTE_PATH(file_handle->filename, strlen(file_handle->filename))) {

        return VCWD_REALPATH(file_handle->filename, realname) != NULL;
    } else {
        int filename_len = strlen(file_handle->filename);
        char* temp_name = ea_resolve_path(file_handle->filename, filename_len, PG(include_path) TSRMLS_CC);

        if (temp_name == NULL) {
            return 0;
        }

        strcpy(realname, temp_name);
        efree(temp_name);
        return 1;
    }

    return 0;
}

static int ea_get_phar_name(const char* filename, size_t filename_len, char* phar_name)
{
    size_t i = 0;

    for (i = sizeof("phar://"); i < filename_len - sizeof(".phar"); ++i) {
        if (filename[i] == '.' && filename[i + 1] == 'p' && filename[i + 2] == 'h' &&
                filename[i + 3] == 'a' && filename[i + 4] == 'r') {
            int copy_len = (i - sizeof("phar://") + sizeof(".phar"));
            if (copy_len >= MAXPATHLEN - 1) {
                return 0;
            }
            memcpy(phar_name, &filename[sizeof("phar://") - 1], copy_len);
            phar_name[copy_len] = '\0';
            return 1;
        }
    }
    return 0;
}

/*
 * Stat the file that belongs to file_handle. It puts result of the stat call
 * in buf and the real filename in realname.
 *
 * Returns 0 when the stat failed or if unable to perform a stat call. If successful
 * it returns 1
 */
static int eaccelerator_stat(zend_file_handle *file_handle,
                             char* realname, struct stat* buf TSRMLS_DC)
{
    if (!ea_get_realname(file_handle, realname TSRMLS_CC)) {
#ifdef ZEND_ENGINE_2_3
        if (strncmp(file_handle->filename, "phar://", sizeof("phar://"))) {
            // Determine the name of the phar archive and use this filename to do the
            // stat call. Return filename as realname.
            char phar_name[MAXPATHLEN];
            size_t filename_len = strlen(file_handle->filename);

            if (!ea_get_phar_name(file_handle->filename, filename_len, phar_name)) {
                return 0;
            }
            // TODO: resolve this problem
            if (filename_len >= MAXPATHLEN) {
                return 0;
            }
            strcpy(realname, file_handle->filename);
            return (stat(phar_name, buf) == 0 && S_ISREG(buf->st_mode));
        }
#endif
        return 0;
    }


    if (EAG(check_mtime_enabled) && ea_mm_instance->check_mtime_enabled) {
        return (stat(realname, buf) == 0 && S_ISREG(buf->st_mode));
    }
    return 1;
}

static int ea_match(struct ea_pattern_t *list, const char *path)
{
    struct ea_pattern_t *p;
    char result, positive;

    // apply all patterns
    //  - when not patterns are given, *accept*
    //  - when a pattern with a ! matches, *reject*
    //  - when no negative pattern matches and a positive pattern match, *accept*
    //  - when no negative pattern matches and there are no possitive patterns, *accept*
    //  - *reject*

    if (list == NULL) {
        // there are no patterns, accept
        return 1;
    }

    result = 0; // there are patterns, so if no positive pattern matches, reject
    positive = 0;
    p = list;
    while (p != NULL) {
        if (p->pattern[0] == '!') {
            if ((fnmatch((const char *)(p->pattern + 1), path, 0) == 0)) {
                // a negative pattern matches, accept
                return 0;
            }
        } else {
            result |= (fnmatch((const char *)p->pattern, path, 0) == 0);
            positive = 1;
        }
        p = p->next;
    }

    return result | !positive;
}

/* copy of zend_class_add_ref, the linker isn't able to link to it any more
 * in php 5.3
 * TODO: see if we can steal the pointer
 */
void ea_class_add_ref(zend_class_entry **ce)
{
    (*ce)->refcount++;
}

/*
 * Intercept compilation of PHP file.  If we already have the file in
 * our cache, restore it.  Otherwise call the original Zend compilation
 * function and store the compiled zend_op_array in out cache.
 * This function is called again for each PHP file included in the
 * main PHP file.
 */
ZEND_DLEXPORT zend_op_array* eaccelerator_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
{
    zend_op_array *t;
    struct stat buf;
    char  realname[MAXPATHLEN];
    int   nreloads;
    int stat_result = 0;
#ifdef DEBUG
    struct timeval tv_start;
#endif
    int ok_to_cache = 0;
#ifdef ZEND_ENGINE_2_3
    zend_uint orig_compiler_options;
#endif

    DBG(ea_debug_start_time, (&tv_start));
    DBG(ea_debug_printf, (EA_DEBUG, "[%d] Enter COMPILE\n",getpid()));
    DBG(ea_debug_printf, (EA_DEBUG, "[%d] compile_file: \"%s\"\n",getpid(), file_handle->filename));
#ifdef DEBUG
    EAG(xpad)+=2;
#endif

    stat_result = eaccelerator_stat(file_handle, realname, &buf TSRMLS_CC);

    ok_to_cache = ea_match(EAG(pattern_list), file_handle->filename);

    // eAccelerator isn't working, so just compile the file
    if (!EAG(enabled) || (ea_mm_instance == NULL) ||
            !ea_mm_instance->enabled || file_handle == NULL ||
            file_handle->filename == NULL || stat_result == 0 || !ok_to_cache) {
        DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: compiling\n", getpid()));
        t = ea_saved_zend_compile_file(file_handle, type TSRMLS_CC);
        DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: end (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));
        DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: end\n", getpid()));
#ifdef DEBUG
        EAG(xpad)-=2;
#endif
        DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave COMPILE\n", getpid()));
        return t;
    }

    if (buf.st_mtime >= EAG(req_start) && ea_debug > 0) {
        ea_debug_log("EACCELERATOR: Warning: \"%s\" is cached but it's mtime is in the future.\n", file_handle->filename);
    }

    t = eaccelerator_restore(realname, &buf, &nreloads, EAG(req_start) TSRMLS_CC);

    /* segv74: really cheap work around to auto_global problem.
               it makes just in time to every time.
       hrak: TODO this is a really lame hack which totally breaks auto_globals_jit
    */

    zend_is_auto_global("_GET", sizeof("_GET")-1 TSRMLS_CC);
    zend_is_auto_global("_POST", sizeof("_POST")-1 TSRMLS_CC);
    zend_is_auto_global("_COOKIE", sizeof("_COOKIE")-1 TSRMLS_CC);
    zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
    zend_is_auto_global("_ENV", sizeof("_ENV")-1 TSRMLS_CC);
    zend_is_auto_global("_REQUEST", sizeof("_REQUEST")-1 TSRMLS_CC);
    zend_is_auto_global("_FILES", sizeof("_FILES")-1 TSRMLS_CC);
#ifdef ZEND_ENGINE_2_4
    zend_is_auto_global("GLOBALS", sizeof("GLOBALS")-1 TSRMLS_CC);
#endif

    if (t != NULL) { // restore from cache
#ifdef DEBUG
        ea_debug_log("[%d] EACCELERATOR hit: \"%s\"\n", getpid(), t->filename);
#else
        ea_debug_log("EACCELERATOR hit: \"%s\"\n", t->filename);
#endif

        zend_llist_add_element(&CG(open_files), file_handle);
        if (file_handle->opened_path == NULL && file_handle->type != ZEND_HANDLE_STREAM) {
            file_handle->handle.stream.handle = (void*)1;
            file_handle->opened_path = EAG(mem);    /* EAG(mem) = p->realfilename from eaccelerator_restore here */
        }

        DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: restored (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));
        DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: restored\n", getpid()));
#ifdef DEBUG
        EAG(xpad)-=2;
#endif
        DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave COMPILE\n", getpid()));

        return t;

    } else { // not in cache or must be recompiled
        Bucket *function_table_tail;
        Bucket *class_table_tail;
        HashTable* orig_function_table;
        HashTable* orig_class_table;
        HashTable* orig_eg_class_table = NULL;
        HashTable tmp_function_table;
        HashTable tmp_class_table;
        zend_function tmp_func;
        zend_class_entry tmp_class;
        int ea_bailout;

        zend_hash_init_ex(&tmp_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
        zend_hash_copy(&tmp_function_table, &ea_global_function_table, NULL, &tmp_func, sizeof(zend_function));
        orig_function_table = CG(function_table);
        CG(function_table) = &tmp_function_table;

        zend_hash_init_ex(&tmp_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
        zend_hash_copy(&tmp_class_table, &ea_global_class_table, (copy_ctor_func_t)ea_class_add_ref, &tmp_class, sizeof(zend_class_entry *));

        orig_class_table = CG(class_table);;
        CG(class_table) = &tmp_class_table;
        orig_eg_class_table = EG(class_table);;
        EG(class_table) = &tmp_class_table;

        /* Storing global pre-compiled functions and classes */
        function_table_tail = CG(function_table)->pListTail;
        class_table_tail = CG(class_table)->pListTail;

        DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: compiling (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));

        if (EAG(optimizer_enabled) && ea_mm_instance->optimizer_enabled) {
            EAG(compiler) = 1;
        }

        /* try to compile the script */
        ea_bailout = 0;
        zend_try {
#ifdef ZEND_ENGINE_2_3
            orig_compiler_options = CG(compiler_options);
            CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES | ZEND_COMPILE_DELAYED_BINDING;
#endif
            t = ea_saved_zend_compile_file(file_handle, type TSRMLS_CC);
#ifdef ZEND_ENGINE_2_3
            CG(compiler_options) = orig_compiler_options;
#endif
        } zend_catch {
            CG(function_table) = orig_function_table;
            CG(class_table) = orig_class_table;
            EG(class_table) = orig_eg_class_table;
            ea_bailout = 1;
        } zend_end_try();
        if (ea_bailout) {
            zend_bailout();
        }
        DBG(ea_debug_log_hashkeys, ("class_table\n", CG(class_table)));

        EAG(compiler) = 0;
        if (t != NULL && file_handle->opened_path != NULL && ((EAG(check_mtime_enabled) && ea_mm_instance->check_mtime_enabled) ||
                ((stat(file_handle->opened_path, &buf) == 0) && S_ISREG(buf.st_mode)))) {

            DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: storing in cache (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));
            DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: storing in cache\n", getpid()));
            function_table_tail = function_table_tail ? function_table_tail->pListNext : CG(function_table)->pListHead;
            class_table_tail = class_table_tail ? class_table_tail->pListNext : CG(class_table)->pListHead;

            if (eaccelerator_store(file_handle->opened_path, &buf, nreloads, t, function_table_tail, class_table_tail TSRMLS_CC)) {
#ifdef DEBUG
                ea_debug_log("[%d] EACCELERATOR %s: \"%s\"\n", getpid(), (nreloads == 1) ? "cached" : "re-cached", file_handle->opened_path);
#else
                ea_debug_log("EACCELERATOR %s: \"%s\"\n", (nreloads == 1) ? "cached" : "re-cached", file_handle->opened_path);
#endif
            } else {
#ifdef DEBUG
                ea_debug_log("[%d] EACCELERATOR can't cache: \"%s\"\n", getpid(), file_handle->opened_path);
#else
                ea_debug_log("EACCELERATOR can't cache: \"%s\"\n", file_handle->opened_path);
#endif
            }
        } else {
            function_table_tail = function_table_tail ? function_table_tail->pListNext : CG(function_table)->pListHead;
            class_table_tail = class_table_tail ? class_table_tail->pListNext : CG(class_table)->pListHead;
        }
        CG(function_table) = orig_function_table;
        CG(class_table) = orig_class_table;
        EG(class_table) = orig_eg_class_table;

        while (function_table_tail != NULL) {
            zend_op_array *op_array = (zend_op_array*)function_table_tail->pData;
            if (op_array->type == ZEND_USER_FUNCTION) {
                if (zend_hash_add(CG(function_table), function_table_tail->arKey, function_table_tail->nKeyLength, op_array,
                                  sizeof(zend_op_array), NULL) == FAILURE && function_table_tail->arKey[0] != '\000') {
                    CG(in_compilation) = 1;
                    CG(compiled_filename) = file_handle->opened_path;
                    CG(zend_lineno) = op_array->line_start;
                    zend_error(E_ERROR, "Cannot redeclare %s()", function_table_tail->arKey);
                }
            }
            function_table_tail = function_table_tail->pListNext;
        }

        while (class_table_tail != NULL) {
            zend_class_entry **ce = (zend_class_entry**)class_table_tail->pData;
            if ((*ce)->type == ZEND_USER_CLASS) {
                if (zend_hash_add(CG(class_table), class_table_tail->arKey, class_table_tail->nKeyLength,
                                  ce, sizeof(zend_class_entry*), NULL) == FAILURE && class_table_tail->arKey[0] != '\000') {
                    CG(in_compilation) = 1;
                    CG(compiled_filename) = file_handle->opened_path;
#ifdef ZEND_ENGINE_2_4
                    CG(zend_lineno) = (*ce)->info.user.line_start;
#else
                    CG(zend_lineno) = (*ce)->line_start;
#endif
                    zend_error(E_ERROR, "Cannot redeclare class %s", class_table_tail->arKey);
                }
            }
            class_table_tail = class_table_tail->pListNext;
        }
        tmp_function_table.pDestructor = NULL;
        tmp_class_table.pDestructor = NULL;
        zend_hash_destroy(&tmp_function_table);
        zend_hash_destroy(&tmp_class_table);
    }
    DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: end (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));
    DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: end\n", getpid()));
#ifdef DEBUG
    EAG(xpad)-=2;
#endif
    DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave COMPILE\n", getpid()));
#ifdef ZEND_COMPILE_DELAYED_BINDING
    zend_do_delayed_early_binding(t TSRMLS_CC);
#endif
    return t;
}

#ifdef DEBUG
static void profile_execute(zend_op_array *op_array TSRMLS_DC)
{
    int i;
    struct timeval tv_start;
    long usec;

    for (i=0; i<EAG(profile_level); i++) {
        DBG(ea_debug_put, (EA_PROFILE_OPCODES, "  "));
    }
    ea_debug_printf(EA_PROFILE_OPCODES, "enter profile_execute: %s:%s\n", op_array->filename, op_array->function_name);
    ea_debug_start_time(&tv_start);
    EAG(self_time)[EAG(profile_level)] = 0;
    EAG(profile_level)++;
    ea_debug_printf(EA_PROFILE_OPCODES, "About to enter zend_execute...\n");
    ea_saved_zend_execute(op_array TSRMLS_CC);
    ea_debug_printf(EA_PROFILE_OPCODES, "Finished zend_execute...\n");
    usec = ea_debug_elapsed_time(&tv_start);
    EAG(profile_level)--;
    if (EAG(profile_level) > 0) {
        EAG(self_time)[EAG(profile_level)-1] += usec;
    }
    for (i=0; i<EAG(profile_level); i++) {
        DBG(ea_debug_put, (EA_PROFILE_OPCODES, "  "));
    }
    ea_debug_printf(EA_PROFILE_OPCODES, "leave profile_execute: %s:%s (%ld,%ld)\n", op_array->filename, op_array->function_name, usec, usec-EAG(self_time)[EAG(profile_level)]);
}

ZEND_DLEXPORT zend_op_array* profile_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
{
    zend_op_array *t;
    int i;
    struct timeval tv_start;
    long usec;

    ea_debug_start_time(&tv_start);
    EAG(self_time)[EAG(profile_level)] = 0;
    t = eaccelerator_compile_file(file_handle, type TSRMLS_CC);
    usec = ea_debug_elapsed_time(&tv_start);
    if (EAG(profile_level) > 0) {
        EAG(self_time)[EAG(profile_level)-1] += usec;
    }
    for (i=0; i<EAG(profile_level); i++) {
        DBG(ea_debug_put, (EA_PROFILE_OPCODES, "  "));
    }
    return t;
}

#endif  /* DEBUG */

/* Format Bytes */
void format_size(char* s, unsigned int size, int legend)
{
    unsigned int i = 0;
    unsigned int n = 0;
    char ch;
    do {
        if ((n != 0) && (n % 3 == 0)) {
            s[i++] = ',';
        }
        s[i++] = (char)((int)'0' + (size % 10));
        n++;
        size = size / 10;
    } while (size != 0);
    s[i] = '\0';
    n = 0;
    i--;
    while (n < i) {
        ch = s[n];
        s[n] = s[i];
        s[i] = ch;
        n++, i--;
    }
    if (legend) {
        strcat(s, " Bytes");
    }
}

/* eAccelerator entry for phpinfo() */
PHP_MINFO_FUNCTION(eaccelerator)
{
    char s[32];

    php_info_print_table_start();
    php_info_print_table_header(2, "eAccelerator support", "enabled");
    php_info_print_table_row(2, "Version", EACCELERATOR_VERSION);
    php_info_print_table_row(2, "Caching Enabled", (EAG(enabled) && (ea_mm_instance != NULL) &&
                             ea_mm_instance->enabled)?"true":"false");
    php_info_print_table_row(2, "Optimizer Enabled", (EAG(optimizer_enabled) &&
                             (ea_mm_instance != NULL) && ea_mm_instance->optimizer_enabled)?"true":"false");
    php_info_print_table_row(2, "Check mtime Enabled", (EAG(check_mtime_enabled) &&
                             (ea_mm_instance != NULL) && ea_mm_instance->check_mtime_enabled)?"true":"false");
    if (ea_mm_instance != NULL) {
        size_t available;
        available = mm_available(ea_mm_instance->mm);
        EACCELERATOR_LOCK_RD();
        format_size(s, ea_mm_instance->total, 1);
        php_info_print_table_row(2, "Memory Size", s);
        format_size(s, available, 1);
        php_info_print_table_row(2, "Memory Available", s);
        format_size(s, ea_mm_instance->total - available, 1);
        php_info_print_table_row(2, "Memory Allocated", s);
        snprintf(s, 32, "%u", ea_mm_instance->hash_cnt);
        php_info_print_table_row(2, "Cached Scripts", s);
        snprintf(s, 32, "%u", ea_mm_instance->rem_cnt);
        php_info_print_table_row(2, "Removed Scripts", s);
        EACCELERATOR_UNLOCK_RD();
    }
    php_info_print_table_end();

    DISPLAY_INI_ENTRIES();
}

/*
 * Parse a list of filters which is seperated by a " "
 */
static struct ea_pattern_t *ea_parse_filter(char *filter) {
    char *saveptr = NULL, *token = NULL;
    struct ea_pattern_t *list_head = NULL, *p = NULL;
    size_t len;

    // tokenize the filter string on a space
    while ((token = php_strtok_r(filter, " ", &saveptr)) != NULL) {
        filter = NULL;
        list_head = malloc(sizeof(struct ea_pattern_t));
        memset(list_head, 0, sizeof(struct ea_pattern_t));

        len = strlen(token);
        list_head->pattern = malloc(len + 1);
        strncpy(list_head->pattern, token, len + 1);
        list_head->next = p;
        p = list_head;
    }

    return list_head;
}

/******************************************************************************/
/*
 * Begin of dynamic loadable module interfaces.
 * There are two interfaces:
 *  - standard php module,
 *  - zend extension.
 */
PHP_INI_MH(eaccelerator_filter)
{
    EAG(pattern_list) = ea_parse_filter(new_value);
    return SUCCESS;
}

static PHP_INI_MH(eaccelerator_OnUpdateLong)
{
    long *p = (long*)mh_arg1;
    *p = zend_atoi(new_value, new_value_length);
    return SUCCESS;
}

static PHP_INI_MH(eaccelerator_OnUpdateBool)
{
    zend_bool *p = (zend_bool*)mh_arg1;
    if (strncasecmp("on", new_value, sizeof("on"))) {
        *p = (zend_bool) atoi(new_value);
    } else {
        *p = (zend_bool) 1;
    }
    return SUCCESS;
}

PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("eaccelerator.enable",         "1", PHP_INI_ALL, OnUpdateBool, enabled, zend_eaccelerator_globals, eaccelerator_globals)
STD_PHP_INI_ENTRY("eaccelerator.optimizer",      "1", PHP_INI_ALL, OnUpdateBool, optimizer_enabled, zend_eaccelerator_globals, eaccelerator_globals)
ZEND_INI_ENTRY1("eaccelerator.shm_size",        "0", PHP_INI_SYSTEM, eaccelerator_OnUpdateLong, &ea_shm_size)
ZEND_INI_ENTRY1("eaccelerator.shm_ttl",         "0", PHP_INI_SYSTEM, eaccelerator_OnUpdateLong, &ea_shm_ttl)
ZEND_INI_ENTRY1("eaccelerator.shm_prune_period", "0", PHP_INI_SYSTEM, eaccelerator_OnUpdateLong, &ea_shm_prune_period)
ZEND_INI_ENTRY1("eaccelerator.debug",           "1", PHP_INI_SYSTEM, eaccelerator_OnUpdateLong, &ea_debug)
STD_PHP_INI_ENTRY("eaccelerator.log_file",      "", PHP_INI_SYSTEM, OnUpdateString, ea_log_file, zend_eaccelerator_globals, eaccelerator_globals)
STD_PHP_INI_ENTRY("eaccelerator.check_mtime",     "1", PHP_INI_SYSTEM, OnUpdateBool, check_mtime_enabled, zend_eaccelerator_globals, eaccelerator_globals)
ZEND_INI_ENTRY1("eaccelerator.shm_only",        "0", PHP_INI_SYSTEM, eaccelerator_OnUpdateBool, &ea_scripts_shm_only)
#ifdef WITH_EACCELERATOR_INFO
STD_PHP_INI_ENTRY("eaccelerator.allowed_admin_path",       "", PHP_INI_SYSTEM, OnUpdateString, allowed_admin_path, zend_eaccelerator_globals, eaccelerator_globals)
#endif
STD_PHP_INI_ENTRY("eaccelerator.cache_dir",      "/tmp/eaccelerator", PHP_INI_SYSTEM, OnUpdateString, cache_dir, zend_eaccelerator_globals, eaccelerator_globals)
PHP_INI_ENTRY("eaccelerator.filter",             "",  PHP_INI_ALL, eaccelerator_filter)
PHP_INI_END()

static void eaccelerator_clean_request(TSRMLS_D)
{
    ea_used_entry  *p = (ea_used_entry*)EAG(used_entries);
    if (ea_mm_instance != NULL) {
        if (p != NULL) {
            EACCELERATOR_LOCK_RW();
            while (p != NULL) {
                p->entry->use_cnt--;
                if (p->entry->removed && p->entry->use_cnt <= 0) {
                    if (ea_mm_instance->removed == p->entry) {
                        ea_mm_instance->removed = p->entry->next;
                        ea_mm_instance->rem_cnt--;
                        eaccelerator_free_nolock(p->entry);
                        p->entry = NULL;
                    } else {
                        ea_cache_entry *q = ea_mm_instance->removed;
                        while (q != NULL && q->next != p->entry) {
                            q = q->next;
                        }
                        if (q != NULL) {
                            q->next = p->entry->next;
                            ea_mm_instance->rem_cnt--;
                            eaccelerator_free_nolock(p->entry);
                            p->entry = NULL;
                        }
                    }
                }
                p = p->next;
            }
            EACCELERATOR_UNLOCK_RW();
        }
        p = (ea_used_entry*)EAG(used_entries);
        while (p != NULL) {
            ea_used_entry* r = p;
            p = p->next;
            if (r->entry != NULL && r->entry->use_cnt < 0) {
                eaccelerator_free(r->entry);
            }
            efree(r);
        }
    }
    EAG(used_entries) = NULL;
    EAG(in_request) = 0;
}

/* signal handlers */
#ifdef WITH_EACCELERATOR_CRASH_DETECTION
static void eaccelerator_crash_handler(int dummy)
{
    struct tm *loctime;

    TSRMLS_FETCH();
    fflush(stdout);
    fflush(stderr);
#ifdef SIGSEGV
    if (EAG(original_sigsegv_handler) != eaccelerator_crash_handler) {
        signal(SIGSEGV, EAG(original_sigsegv_handler));
    } else {
        signal(SIGSEGV, SIG_DFL);
    }
#endif
#ifdef SIGFPE
    if (EAG(original_sigfpe_handler) != eaccelerator_crash_handler) {
        signal(SIGFPE, EAG(original_sigfpe_handler));
    } else {
        signal(SIGFPE, SIG_DFL);
    }
#endif
#ifdef SIGBUS
    if (EAG(original_sigbus_handler) != eaccelerator_crash_handler) {
        signal(SIGBUS, EAG(original_sigbus_handler));
    } else {
        signal(SIGBUS, SIG_DFL);
    }
#endif
#ifdef SIGILL
    if (EAG(original_sigill_handler) != eaccelerator_crash_handler) {
        signal(SIGILL, EAG(original_sigill_handler));
    } else {
        signal(SIGILL, SIG_DFL);
    }
#endif
#ifdef SIGABRT
    if (EAG(original_sigabrt_handler) != eaccelerator_crash_handler) {
        signal(SIGABRT, EAG(original_sigabrt_handler));
    } else {
        signal(SIGABRT, SIG_DFL);
    }
#endif
    eaccelerator_clean_request(TSRMLS_C);

    loctime = localtime(&EAG(req_start));

    if (EG(active_op_array)) {
        fprintf(stderr, "[%s] [notice] EACCELERATOR(%d): PHP crashed on opline %ld of %s() at %s:%u\n\n",
                asctime(loctime),
                getpid(),
                (long)(active_opline-EG(active_op_array)->opcodes),
                get_active_function_name(TSRMLS_C),
                zend_get_executed_filename(TSRMLS_C),
                zend_get_executed_lineno(TSRMLS_C));
    } else {
        fprintf(stderr, "[%s] [notice] EACCELERATOR(%d): PHP crashed\n\n", asctime(loctime), getpid());
    }
#if !defined(WIN32) && !defined(NETWARE)
    kill(getpid(), dummy);
#else
    raise(dummy);
#endif
}
#endif

static void eaccelerator_init_globals(zend_eaccelerator_globals *eag)
{
    eag->used_entries = NULL;
    eag->enabled = 1;
    eag->cache_dir = NULL;
    eag->optimizer_enabled = 1;
    eag->check_mtime_enabled = 1;
    eag->compiler = 0;
    eag->ea_log_file = '\000';
    eag->in_request = 0;
    eag->allowed_admin_path= NULL;
    eag->pattern_list = NULL;
}

static void eaccelerator_globals_dtor(zend_eaccelerator_globals *eag)
{
    struct ea_pattern_t *p, *q;

    /* free the list of patterns */
    p = eag->pattern_list;
    while (p != NULL) {
        q = p->next;
        free(p->pattern);
        free(p);
        p = q;
    }
    eag->pattern_list = NULL;
}

static void register_eaccelerator_as_zend_extension();

static int eaccelerator_check_php_version(TSRMLS_D)
{
    zval v;
    int ret = 0;
    if (zend_get_constant("PHP_VERSION", sizeof("PHP_VERSION")-1, &v TSRMLS_CC)) {
        if (Z_TYPE(v) == IS_STRING &&
                Z_STRLEN(v) == sizeof(PHP_VERSION)-1 &&
                strcmp(Z_STRVAL(v),PHP_VERSION) == 0) {
            ret = 1;
        } else {
            ea_debug_error("[%s] This build of \"%s\" was compiled for PHP version %s. Rebuild it for your PHP version (%s) or download precompiled binaries.\n",
                           EACCELERATOR_EXTENSION_NAME, EACCELERATOR_EXTENSION_NAME,PHP_VERSION,Z_STRVAL(v));
        }
        zval_dtor(&v);
    } else {
        ea_debug_error("[%s] This build of \"%s\" was compiled for PHP version %s. Rebuild it for your PHP version.\n",
                       EACCELERATOR_EXTENSION_NAME, EACCELERATOR_EXTENSION_NAME, PHP_VERSION);
    }
    return ret;
}

/*
 * Create a hash directory
 */
static void make_hash_dirs(char *fullpath, int lvl)
{
    int j;
    int n = strlen(fullpath);

    //ea_debug_error("Creating hash in %s at level %d\n", fullpath, lvl);

    if (lvl < 1) {
        return;
    }

    if (fullpath[n-1] != '/') {
        fullpath[n++] = '/';
    }

    for (j = 0; j < 16; j++) {
        fullpath[n] = num2hex[j];
        fullpath[n+1] = 0;
        mkdir(fullpath, 0700);
        make_hash_dirs(fullpath, lvl-1);
    }
    fullpath[n+2] = 0;
}

/*
 * Initialise the cache directory for use
 */
static void init_cache_dir(const char *cache_path)
{
    char fullpath[MAXPATHLEN];
    uid_t uid = getuid();
    mode_t old_umask = umask(077);
    struct stat buffer;

    snprintf(fullpath, MAXPATHLEN-1, "%s/%d/", cache_path, uid);
    if (lstat(fullpath, &buffer) != 0) {
        // error, create the directory
        if (mkdir(fullpath, 0700) != 0) {
            ea_debug_error("Unable to create cachedir %s\n", fullpath);
            return;
        }
    } else if (!S_ISDIR(buffer.st_mode)) {
        // not a directory
        ea_debug_error("Cachedir %s exists but is not a directory\n",
                       fullpath);
        return;
    }

    // create the hashed dirs
    make_hash_dirs(fullpath, EACCELERATOR_HASH_LEVEL);

    umask(old_umask);

    ea_mm_instance->cache_dir_uid = uid;
}

/*
 * Check if the cache dir exists and is world-writable so the forked process
 * can create the cache directories
 */
static void check_cache_dir(const char *cache_path)
{
    struct stat buffer;
    mode_t old_umask = umask(0);

    int status = stat(cache_path, &buffer);

    if (status == 0) {
        // check permissions
        if (buffer.st_mode != 777) {
            status = chmod(cache_path, 0777);
            if (status < 0) {
                ea_debug_error(
                    "eAccelerator: Unable to change cache directory %s permissions\n",
                    cache_path);
            }
        }
    } else {
        // create the cache directory if possible
        status = mkdir(cache_path, 0777);
        if (status < 0) {
            ea_debug_error("eAccelerator: Unable to create cache directory %s\n", cache_path);
        }
    }

    umask(old_umask);
}

PHP_MINIT_FUNCTION(eaccelerator)
{
    if (type == MODULE_PERSISTENT) {
#ifndef ZEND_WIN32
        if (strcmp(sapi_module.name,"apache") == 0) {
            if (getpid() != getpgrp()) {
                return SUCCESS;
            }
        }
#endif
    }
    if (!eaccelerator_check_php_version(TSRMLS_C)) {
        /*
             * do not return FAILURE, because it causes PHP to completely fail.
             * Just disable eAccelerator instead of making eA fail starting php
             */
        return SUCCESS;
    }
    ZEND_INIT_MODULE_GLOBALS(eaccelerator, eaccelerator_init_globals, NULL);
    REGISTER_INI_ENTRIES();
    REGISTER_STRING_CONSTANT("EACCELERATOR_VERSION", EACCELERATOR_VERSION, CONST_CS | CONST_PERSISTENT);
    REGISTER_LONG_CONSTANT("EACCELERATOR_SHM_AND_DISK", ea_shm_and_disk, CONST_CS | CONST_PERSISTENT);
    REGISTER_LONG_CONSTANT("EACCELERATOR_SHM", ea_shm, CONST_CS | CONST_PERSISTENT);
    REGISTER_LONG_CONSTANT("EACCELERATOR_SHM_ONLY", ea_shm_only, CONST_CS | CONST_PERSISTENT);
    REGISTER_LONG_CONSTANT("EACCELERATOR_DISK_ONLY", ea_disk_only, CONST_CS | CONST_PERSISTENT);
    REGISTER_LONG_CONSTANT("EACCELERATOR_NONE", ea_none, CONST_CS | CONST_PERSISTENT);
    encode_version(EACCELERATOR_VERSION, &binary_eaccelerator_version[0], &binary_eaccelerator_version[1]);
    encode_version(PHP_VERSION, &binary_php_version[0], &binary_php_version[1]);
    encode_version(ZEND_VERSION, &binary_zend_version[0], &binary_zend_version[1]);
    ea_is_extension = 1;

    ea_debug_init(TSRMLS_C);

#ifndef ZEND_WIN32
    if (!ea_scripts_shm_only) {
        check_cache_dir(EAG(cache_dir));
    }
#endif

    if (type == MODULE_PERSISTENT &&
            strcmp(sapi_module.name, "cgi") != 0 &&
            strcmp(sapi_module.name, "cli") != 0) {
        DBG(ea_debug_put, (EA_DEBUG, "\n=======================================\n"));
        DBG(ea_debug_printf, (EA_DEBUG, "[%d] EACCELERATOR STARTED\n", getpid()));
        DBG(ea_debug_put, (EA_DEBUG, "=======================================\n"));

        if (init_mm(TSRMLS_C) == FAILURE) {
            zend_error(E_CORE_WARNING,"[%s] Can not create shared memory area", EACCELERATOR_EXTENSION_NAME);
            return FAILURE;
        }
        ea_saved_zend_compile_file = zend_compile_file;

#ifdef DEBUG
        zend_compile_file = profile_compile_file;
        ea_saved_zend_execute = zend_execute;
        zend_execute = profile_execute;
#else
        zend_compile_file = eaccelerator_compile_file;
#endif
    }

    if (!ea_is_zend_extension) {
        register_eaccelerator_as_zend_extension();
    }

    /* cache the properties_info destructor */
    properties_info_dtor = get_zend_destroy_property_info(TSRMLS_C);
    return SUCCESS;
}

PHP_MSHUTDOWN_FUNCTION(eaccelerator)
{
    if (ea_mm_instance == NULL || !ea_is_extension) {
        return SUCCESS;
    }
    zend_compile_file = ea_saved_zend_compile_file;
    shutdown_mm(TSRMLS_C);
    DBG(ea_debug_put, (EA_DEBUG, "========================================\n"));
    DBG(ea_debug_printf, (EA_DEBUG, "[%d] EACCELERATOR STOPPED\n", getpid()));
    DBG(ea_debug_put, (EA_DEBUG, "========================================\n\n"));
    ea_debug_shutdown();
    UNREGISTER_INI_ENTRIES();
#ifdef ZTS
    ts_free_id(eaccelerator_globals_id);
#else
    eaccelerator_globals_dtor(&eaccelerator_globals TSRMLS_CC);
#endif
    ea_is_zend_extension = 0;
    ea_is_extension = 0;
    return SUCCESS;
}

PHP_RINIT_FUNCTION(eaccelerator)
{
    if (ea_mm_instance == NULL) {
        return SUCCESS;
    }

    DBG(ea_debug_printf, (EA_DEBUG, "[%d] Enter RINIT\n",getpid()));
    DBG(ea_debug_put, (EA_PROFILE_OPCODES, "\n========================================\n"));

    EAG(in_request) = 1;
    EAG(used_entries) = NULL;
    EAG(compiler) = 0;
    EAG(refcount_helper) = 1;
    EAG(req_start) = sapi_get_request_time(TSRMLS_C);    /* record request start time for later use */

    zend_hash_init(&EAG(restored), 0, NULL, NULL, 0);

#ifdef DEBUG
    EAG(xpad) = 0;
    EAG(profile_level) = 0;
#endif

#ifdef WITH_EACCELERATOR_CRASH_DETECTION
#ifdef SIGSEGV
    EAG(original_sigsegv_handler) = signal(SIGSEGV, eaccelerator_crash_handler);
#endif
#ifdef SIGFPE
    EAG(original_sigfpe_handler) = signal(SIGFPE, eaccelerator_crash_handler);
#endif
#ifdef SIGBUS
    EAG(original_sigbus_handler) = signal(SIGBUS, eaccelerator_crash_handler);
#endif
#ifdef SIGILL
    EAG(original_sigill_handler) = signal(SIGILL, eaccelerator_crash_handler);
#endif
#ifdef SIGABRT
    EAG(original_sigabrt_handler) = signal(SIGABRT, eaccelerator_crash_handler);
#endif
#endif

    DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave RINIT\n",getpid()));

#ifndef ZEND_WIN32
    if (!ea_scripts_shm_only && ea_mm_instance->cache_dir_uid != getuid()) {
        // lock this operation with a global eA lock and do the check again
        // to avoid multiple calls during startup
        EACCELERATOR_LOCK_RW();
        if (ea_mm_instance->cache_dir_uid != getuid()) {
            init_cache_dir(EAG(cache_dir));
        }
        EACCELERATOR_UNLOCK();
    }
#else
    if(!ea_scripts_shm_only) {
        char fullpath[MAXPATHLEN];

        snprintf(fullpath, MAXPATHLEN-1, "%s/", EAG(cache_dir));
        make_hash_dirs(fullpath, EACCELERATOR_HASH_LEVEL);
    }
#endif

    return SUCCESS;
}

PHP_RSHUTDOWN_FUNCTION(eaccelerator)
{
    if (ea_mm_instance == NULL) {
        return SUCCESS;
    }
    zend_hash_destroy(&EAG(restored));
#ifdef WITH_EACCELERATOR_CRASH_DETECTION
#ifdef SIGSEGV
    if (EAG(original_sigsegv_handler) != eaccelerator_crash_handler) {
        signal(SIGSEGV, EAG(original_sigsegv_handler));
    } else {
        signal(SIGSEGV, SIG_DFL);
    }
#endif
#ifdef SIGFPE
    if (EAG(original_sigfpe_handler) != eaccelerator_crash_handler) {
        signal(SIGFPE, EAG(original_sigfpe_handler));
    } else {
        signal(SIGFPE, SIG_DFL);
    }
#endif
#ifdef SIGBUS
    if (EAG(original_sigbus_handler) != eaccelerator_crash_handler) {
        signal(SIGBUS, EAG(original_sigbus_handler));
    } else {
        signal(SIGBUS, SIG_DFL);
    }
#endif
#ifdef SIGILL
    if (EAG(original_sigill_handler) != eaccelerator_crash_handler) {
        signal(SIGILL, EAG(original_sigill_handler));
    } else {
        signal(SIGILL, SIG_DFL);
    }
#endif
#ifdef SIGABRT
    if (EAG(original_sigabrt_handler) != eaccelerator_crash_handler) {
        signal(SIGABRT, EAG(original_sigabrt_handler));
    } else {
        signal(SIGABRT, SIG_DFL);
    }
#endif
#endif
    DBG(ea_debug_printf, (EA_DEBUG, "[%d] Enter RSHUTDOWN\n",getpid()));
    eaccelerator_clean_request(TSRMLS_C);
    DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave RSHUTDOWN\n",getpid()));
    return SUCCESS;
}

ZEND_BEGIN_ARG_INFO(eaccelerator_second_arg_force_ref, 0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();

zend_function_entry eaccelerator_functions[] = {
#ifdef WITH_EACCELERATOR_INFO
    PHP_FE(eaccelerator_caching, NULL)
    PHP_FE(eaccelerator_clear, NULL)
    PHP_FE(eaccelerator_clean, NULL)
    PHP_FE(eaccelerator_info, NULL)
    PHP_FE(eaccelerator_purge, NULL)
    PHP_FE(eaccelerator_cached_scripts, NULL)
    PHP_FE(eaccelerator_removed_scripts, NULL)
    PHP_FE(eaccelerator_check_mtime, NULL)
#ifdef WITH_EACCELERATOR_OPTIMIZER
    PHP_FE(eaccelerator_optimizer, NULL)
#endif
#endif
#ifdef WITH_EACCELERATOR_DISASSEMBLER
    PHP_FE(eaccelerator_dasm_file, NULL)
#endif
    {
        NULL, NULL, NULL, 0U, 0U
    }
};

zend_module_entry eaccelerator_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    EACCELERATOR_EXTENSION_NAME,
    eaccelerator_functions,
    PHP_MINIT(eaccelerator),
    PHP_MSHUTDOWN(eaccelerator),
    PHP_RINIT(eaccelerator),
    PHP_RSHUTDOWN(eaccelerator),
    PHP_MINFO(eaccelerator),
#if ZEND_MODULE_API_NO >= 20010901
    EACCELERATOR_VERSION,          /* extension version number (string) */
#endif
    STANDARD_MODULE_PROPERTIES
};

#if defined(COMPILE_DL_EACCELERATOR)
ZEND_GET_MODULE(eaccelerator)
#endif

static startup_func_t last_startup;
static zend_llist_element *eaccelerator_el;

static const unsigned char eaccelerator_logo[] = {
    71,  73,  70,  56,  57,  97,  88,   0,  31,   0,
    213,   0,   0, 150, 153, 196, 237, 168,  86, 187,
    206, 230,   4,   4,   4, 108, 110, 144,  99, 144,
    199, 136, 138, 184,  87,  88, 109, 165, 165, 167,
    163, 166, 202, 240, 151,  44, 149,  91,  21, 225,
    225, 229,   4,  76, 164, 252, 215, 171, 255, 255,
    255, 212, 212, 224, 241, 200, 149, 141, 144, 192,
    216, 216, 226, 251, 230, 205, 192, 193, 218, 207,
    221, 238, 181, 188, 216, 130, 132, 168, 150, 152,
    185, 152, 152, 154, 180, 181, 198, 215, 184, 147,
    40, 102, 177, 224, 232, 242, 244, 244, 244, 235,
    236, 239, 118, 121, 157, 193, 193, 194, 146, 148,
    174, 181, 143,  96, 154, 183, 219, 156, 159, 200,
    126, 128, 170, 174, 175, 193,  65,  39,   7, 232,
    214, 192, 254, 241, 226, 246, 246, 248, 108,  65,
    13, 142, 144, 185, 252, 224, 189, 138, 171, 213,
    69, 122, 188, 239, 244, 249,  48,  49,  60, 176,
    178, 209, 200, 201, 222, 252, 252, 253, 251, 251,
    251, 162, 163, 187, 208, 208, 213, 169, 171, 205,
    241, 234, 225, 255, 252, 249, 254, 248, 241, 140,
    142, 169, 249, 186, 111,  33, 249,   4,   0,   0,
    0,   0,   0,  44,   0,   0,   0,   0,  88,   0,
    31,   0,   0,   6, 255,  64, 137, 112,  72,  44,
    26, 143, 200, 164, 114, 201,  92,  62, 158, 208,
    168, 116,  74, 173,  90, 175, 216, 108,  85, 168,
    237, 122, 191,  15,  25, 163, 118, 209, 153,   0,
    68, 128,  73, 119, 169,  49, 100,  86,  46, 120,
    78, 127, 216,  60,  21,  93,  83,   8, 208,  85,
    60,  54,  83, 114, 117, 132,  89,  32,  23,  38,
    73,  38, 103,  72,  38,  23,  32,  82, 123, 146,
    147,  69, 106,   9,  52,  21,  19,  53, 137, 138,
    51,  51, 156, 141,  21, 100,  52,   9, 148, 166,
    123,   0, 106, 126,  16,  21, 104,  67, 169, 106,
    140,   9,   3, 159, 140,  18, 176, 182,   0,  23,
    21, 101,  67,  21,  80,  32,  52, 192,  52,  44,
    6,  16,  15,   6,  23,  44,  81,  24,  81,  25,
    81, 194,  80,  25,   6,  18,  12,  80,  23,  15,
    169,  15, 172, 155, 105,  33,   7,   4, 158,  46,
    0,  33,   3,   7,   7,  51,   7, 139, 231, 225,
    7,  25, 124,  23,  23,  52, 190,  19,   4, 205,
    44,  27,   4,   4,  19,  57,  15,  33,  15,  32,
    54,  64, 168, 241,   0,   5,  10,  28, 255,  54,
    160, 120, 128, 163, 160,  65,   2,  15, 244, 229,
    200, 113, 162,  26,   4,  20, 252,  22, 130, 128,
    48,  98, 131,  30,  34,  38, 102, 208,  58,  64,
    203,   4,  73, 115,   3,   6, 184, 152,  69,  75,
    228,   1,  87,  38,  80, 204,  19, 242, 235,   9,
    54,  31,   4,  78, 212, 152, 192, 128,   1,   8,
    255,  31,  79,  78, 108,  99, 245, 239,  24,   3,
    136,  16,  32, 212, 139,  24,  34,  83,   8,   3,
    62,  33, 128,  56,  90,   3,  68, 136,  17, 173,
    138, 176,  76,  16, 114,  64,   2, 145,   4,   0,
    136, 196, 128, 129,  22, 215, 146,  66,  50, 224,
    248,  40,  33, 147,  62,   2,  11,  39, 120, 120,
    48, 162,  33,  10,   2,  44,  62,  64, 156, 144,
    244,  31, 129,  17,  12,  31, 240, 157, 240,  76,
    238, 131,  12,   4, 160, 110,   4,   1, 130, 192,
    6,   6,  33, 112, 212,  48, 226, 195, 220,  25,
    145,  95, 189, 118,  77,  64,  50, 236, 172,  79,
    66,  92, 140,  96,  11,   0,  71,  78,  12,  39,
    12, 108, 200,  71,  32,  68, 190,  16,  38,  70,
    56,  54, 120,  87,  71, 136,  16,  25,  70,  36,
    160, 141,  65,  33,  10,  12,  57,  13,  36, 240,
    173,  15,  64,   2,  31,  58, 186, 189,  34,  96,
    238,  86,  73,  90, 198,  75, 146,  12,   1, 128,
    249, 203, 208,  62,  74,   9,  49,  96,   0,   3,
    53,   9,   6,  78, 220,  78, 141, 218, 251, 137,
    19, 168, 199, 163, 230,  46, 254, 246, 120, 247,
    169, 193, 183, 127, 234,  34,  67,   6,  63,  51,
    249, 156,  12,  55, 160, 181,  57, 114, 255, 137,
    52,   3, 127,  62,  12, 129,  65, 118,  74, 112,
    247,  29, 120, 219,  81, 163, 224, 130, 224,  61,
    40, 225, 130,  15, 222, 162,  74,  60, 160, 116,
    181,  95,   6,  36, 189, 212, 255, 225, 103,  39,
    97, 224,  74, 119, 186, 157,  98, 162,  18, 169,
    172,  65,   3,  13,  40, 184, 178, 149,  14,   9,
    160,  97,   2,  87,  18, 204, 104,  66,  89,  51,
    24,  23, 163,  16,  62, 132, 224, 195,  90,  39,
    6, 121, 132,  37,  58, 176, 136, 195,  59,  46,
    152, 133,  98, 135, 174,   8, 129, 129, 143,  56,
    36, 160,  93,  33,  84,  82,  97,   3,  11,  12,
    136, 128,   3,  66, 227,  44,  49,   2, 110,  67,
    248, 224, 131,   6,  34,  48, 176, 204,   3, 131,
    84, 169, 230,  19,  44, 128, 144, 195,   6,  71,
    190, 179,   4,  26,  46, 136, 169,   1,  10,  57,
    236, 192,   2,  15,  79, 164, 185, 166, 154,  55,
    124, 192, 192, 155,   8, 228,  54, 130,  11, 136,
    134,  86, 167, 152,  99,  34, 176,  65,  14,  12,
    124,  16,   8,  20, 126,  62, 176,   2,   5,  20,
    188, 160, 233, 166, 155,  58, 224, 105,   4,  61,
    252,  73,  69, 160,  59,  12,  42,   2,  10,   8,
    32, 160, 193, 170, 171, 166, 138, 130,   8, 144,
    238, 240,   1, 159, 145,  72,   0,   5,  15,  20,
    56,  16,  65,   4,  63,   4, 224, 171,   2,   1,
    0, 171, 192, 176, 195,   6,  32, 234,  21, 129,
    126,  48,  85,  79, 204,  50,  43, 235,   7,  55,
    196,  97, 171, 165, 159, 254, 240, 195, 176,  63,
    188, 240,   0, 173,  80, 244, 192, 194, 153,   2,
    192, 113, 236, 184, 114, 172,  96, 174, 185, 152,
    82, 160, 255, 133,   7,  13,  20, 240, 132,  12,
    5, 196,  80, 192,  92,  15, 192,  32, 175,   0,
    15,  88,  16, 195, 190,  22, 148, 224, 238,  19,
    250, 242,  27, 176, 188, 226, 198, 128, 205, 190,
    252, 202,  96, 111,   1, 248,  62, 128, 112,   1,
    22,  80, 106, 235,  11,  14,  80, 188, 107, 175,
    190, 250, 106,  45, 198,   1, 144, 192, 193,  19,
    5,  52, 208,  64,  24,  29, 116,  96, 111,   3,
    240,  54,   0,  67, 200,   2,   8, 160,  50,  12,
    30, 216,  11, 133, 203,  48, 192,  76,  51,  12,
    237,  62, 112,  65, 187,  54, 216, 107, 178,   7,
    49, 168,  28,  52, 190, 237, 194,  80, 178, 196,
    43, 108,  28, 172,   2,  11, 120, 204, 193, 211,
    17, 112, 176, 235, 211,  28, 236, 240,  68,   7,
    33, 151, 128, 179, 184,  45,  55,  32,  64, 180,
    22, 120, 224, 114, 203,  10, 199,  48, 179, 215,
    225, 186,  12, 178, 217,  33, 163,  92, 175, 217,
    22, 120, 125, 131,  13, 242,  62, 224, 117, 189,
    35, 247,  41, 129,   3, 196,  50, 189,  64,  11,
    36, 216,  48, 183,  29,  79,   4,  98, 195, 164,
    46, 119,  80, 180, 217, 103,  75, 225, 178, 200,
    2, 200, 252, 196, 227, 104, 139,  44, 242,   5,
    50,  52, 160,  56,  12, 111,  63, 160, 246,  19,
    246, 218,  96, 121, 206, 122, 191, 224, 247, 223,
    45, 164, 238, 244, 174, 172,  63, 173, 238,   3,
    5, 152,  28,  50, 206,  17,  43,  76, 154,  51,
    232,  93,  67,  33, 185, 231, 121, 243,  46,  64,
    12,  29,  60,  80, 130, 208, 193, 203, 204,  46,
    231,  50,  96, 109, 119, 205,  13, 208, 139, 166,
    173,  42, 144, 176,  64,  10, 212,  87, 159, 250,
    2, 216, 103, 191, 192,  14, 129, 168, 252, 132,
    202,  33,   7,  93, 188, 230, 138, 139, 221,   0,
    191,  56, 239, 203, 240, 249,  49,  88, 160, 118,
    220,  43, 155, 189, 115, 204, 140, 227, 172, 120,
    243, 118, 135, 139, 245, 164, 149,  78,  74, 248,
    220, 130, 187, 193, 224,  30,  16,  51, 113, 149,
    160,   4,  54, 208,  90,   9, 102,  86,  51,  56,
    196, 172, 102,  98, 171,  25,  12,  74, 240,  64,
    152, 197, 204,  38,  53, 139,  88, 189,  90, 182,
    192, 201, 213, 236,  76,  48, 179, 129,   5,  96,
    166, 183, 113, 153,  80,  77,  66,  74, 161,  10,
    41,  17,   4,   0,  59,   0
};

static int eaccelerator_last_startup(zend_extension *extension)
{
    int ret;
    extension->startup = last_startup;
    ret = extension->startup(extension);
    zend_extensions.count++;
    eaccelerator_el->next = zend_extensions.head;
    eaccelerator_el->prev = NULL;
    zend_extensions.head->prev = eaccelerator_el;
    zend_extensions.head = eaccelerator_el;
    if (ZendOptimizer) {
        if ((ZendOptimizer = zend_get_extension("Zend Optimizer")) != NULL) {
            ZendOptimizer->op_array_handler = NULL;
        }
    }
    return ret;
}

/*
static int eaccelerator_ioncube_startup(zend_extension *extension) {
  int ret;
  zend_extension* last_ext = (zend_extension*)zend_extensions.tail->data;
  extension->startup = last_startup;
  ret = extension->startup(extension);
  last_startup = last_ext->startup;
  last_ext->startup = eaccelerator_last_startup;
  return ret;
}
*/


ZEND_DLEXPORT int eaccelerator_zend_startup(zend_extension *extension)
{
    ea_is_zend_extension = 1;
    eaccelerator_el   = NULL;
    last_startup = NULL;

    if (!ea_is_extension) {
        if (zend_startup_module(&eaccelerator_module_entry) != SUCCESS) {
            return FAILURE;
        }
    }

    if (zend_llist_count(&zend_extensions) > 1) {
        zend_llist_element *p = zend_extensions.head;
        while (p != NULL) {
            zend_extension* ext = (zend_extension*)(p->data);
            if (strcmp(ext->name, EACCELERATOR_EXTENSION_NAME) == 0) {
                /* temporary removing eAccelerator extension */
                zend_extension* last_ext = (zend_extension*)zend_extensions.tail->data;
                if (eaccelerator_el != NULL) {
                    zend_error(E_CORE_ERROR,"[%s] %s %s can not be loaded twice",
                               EACCELERATOR_EXTENSION_NAME,
                               EACCELERATOR_EXTENSION_NAME,
                               EACCELERATOR_VERSION);
                    exit(1);
                }
                if (last_ext != ext) {
                    eaccelerator_el = p;
                    last_startup = last_ext->startup;
                    last_ext->startup = eaccelerator_last_startup;
                    zend_extensions.count--;
                    if (p->prev != NULL) {
                        p->prev->next = p->next;
                    } else {
                        zend_extensions.head = p->next;
                    }
                    if (p->next != NULL) {
                        p->next->prev = p->prev;
                    } else {
                        zend_extensions.tail = p->prev;
                    }
                }
            } else if (strcmp(ext->name, "Zend Extension Manager") == 0 ||
                       strcmp(ext->name, "Zend Optimizer") == 0) {
                /* Disable ZendOptimizer Optimizations */
                ZendOptimizer = ext;
                ext->op_array_handler = NULL;
            }
            p = p->next;
        }
    }

    php_register_info_logo(EACCELERATOR_VERSION_GUID, "text/plain", (unsigned char*)EACCELERATOR_VERSION_STRING, sizeof(EACCELERATOR_VERSION_STRING));
    php_register_info_logo(EACCELERATOR_LOGO_GUID,    "image/gif",  (unsigned char*)eaccelerator_logo, sizeof(eaccelerator_logo));

    return SUCCESS;
}

#ifndef ZEND_EXT_API
#  define ZEND_EXT_API    ZEND_DLEXPORT
#endif

ZEND_EXTENSION();

ZEND_DLEXPORT zend_extension zend_extension_entry = {
    EACCELERATOR_EXTENSION_NAME,
    EACCELERATOR_VERSION,
    "eAccelerator",
    "http://eaccelerator.net",
    "Copyright (c) 2004-2012 eAccelerator",
    eaccelerator_zend_startup,
    NULL,
    NULL,   /* void (*activate)() */
    NULL,   /* void (*deactivate)() */
    NULL,   /* void (*message_handle)(int message, void *arg) */
#ifdef WITH_EACCELERATOR_OPTIMIZER
    eaccelerator_optimize,   /* void (*op_array_handler)(zend_op_array *o_a); */
#else
    NULL,   /* void (*op_array_handler)(zend_op_array *o_a); */
#endif
    NULL,   /* void (*statement_handler)(zend_op_array *o_a); */
    NULL,   /* void (*fcall_begin_handler)(zend_op_array *o_a); */
    NULL,   /* void (*fcall_end_handler)(zend_op_array *o_a); */
    NULL,   /* void (*op_array_ctor)(zend_op_array *o_a); */
    NULL,   /* void (*op_array_dtor)(zend_op_array *o_a); */
#ifdef COMPAT_ZEND_EXTENSION_PROPERTIES
    NULL,   /* api_no_check */
    COMPAT_ZEND_EXTENSION_PROPERTIES
#else
    STANDARD_ZEND_EXTENSION_PROPERTIES
#endif
};

static zend_extension eaccelerator_extension_entry = {
    EACCELERATOR_EXTENSION_NAME,
    EACCELERATOR_VERSION,
    "eAccelerator",
    "http://eaccelerator.net",
    "Copyright (c) 2004-2012 eAccelerator",
    eaccelerator_zend_startup,
    NULL,
    NULL,   /* void (*activate)() */
    NULL,   /* void (*deactivate)() */
    NULL,   /* void (*message_handle)(int message, void *arg) */
#ifdef WITH_EACCELERATOR_OPTIMIZER
    eaccelerator_optimize,   /* void (*op_array_handler)(zend_op_array *o_a); */
#else
    NULL,   /* void (*op_array_handler)(zend_op_array *o_a); */
#endif
    NULL,   /* void (*statement_handler)(zend_op_array *o_a); */
    NULL,   /* void (*fcall_begin_handler)(zend_op_array *o_a); */
    NULL,   /* void (*fcall_end_handler)(zend_op_array *o_a); */
    NULL,   /* void (*op_array_ctor)(zend_op_array *o_a); */
    NULL,   /* void (*op_array_dtor)(zend_op_array *o_a); */
#ifdef COMPAT_ZEND_EXTENSION_PROPERTIES
    NULL,   /* api_no_check */
    COMPAT_ZEND_EXTENSION_PROPERTIES
#else
    STANDARD_ZEND_EXTENSION_PROPERTIES
#endif
};

static void register_eaccelerator_as_zend_extension()
{
    zend_extension extension = eaccelerator_extension_entry;
    extension.handle = 0;
    zend_llist_prepend_element(&zend_extensions, &extension);
}

/******************************************************************************/

#endif  /* #ifdef HAVE_EACCELERATOR */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 * vim<600: expandtab sw=4 ts=4 sts=4
 */

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by HackingTool | HackingTool | Generation time: 0.0083 ]--