"Fossies" - the Fresh Open Source Software Archive

Member "dbg-2.15.5/dbg_cmd.c" (28 Apr 2007, 35310 Bytes) of package /linux/www/old/dbg-2.15.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dbg_cmd.c" see the Fossies "Dox" file reference documentation.

    1 /***************************************************************************
    2                           dbg_cmd.c  -  description
    3                              -------------------
    4     begin                : Sun Sep 24 2000
    5     copyright            : (C) 2001 by Dmitri Dmitrienko
    6                          : (C) 2002, 2007 NuSphere Corp.
    7     www                  : http://dd.cron.ru
    8                          : http://www.nusphere.com/
    9     author               : written by Dmitri Dmitrienko
   10     license              : This source file is subject to version 3.0 of 
   11                            the License,  that is bundled with this package 
   12                            in the file LICENSE, and is available at through 
   13                            the world-wide-web at http://www.nusphere.com/dbg
   14  ***************************************************************************/
   15 
   16 
   17 #ifdef HAVE_CONFIG_H
   18 #include "config.h"
   19 #endif
   20 
   21 #include "php.h"
   22 #include "php_network.h"
   23 
   24 #if HAVE_NETDB_H
   25 #include <netdb.h>
   26 #endif
   27 
   28 #include "php_dbg.h"
   29 #include "dbg_net.h"
   30 #include "dbg_cmd.h"
   31 #include "dbg_prof.h"
   32 #include "dbg_ser.h"
   33 #include "dbg_bp.h"
   34 #include "SAPI.h"
   35 
   36 
   37 
   38 typedef int (*framehandler)(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E));
   39 
   40 typedef struct tag_cmddef {
   41     framename name;
   42     framehandler handler;
   43 } cmddef;
   44 
   45 int cmpll(void *element1, void *element2) {
   46     return (element1 == element2);
   47 }
   48 
   49 int dbg_lookup_hostname(const char *addr, struct in_addr *in) {
   50     struct hostent *host_info;
   51     
   52     DBG_TRACE(("dbg_lookup_hostname\n"));
   53 #ifdef PHP_WIN32
   54     (*in).s_addr = inet_addr(addr);
   55     if ((*in).s_addr == INADDR_NONE) {
   56 #else
   57     if (!inet_aton(addr, in)) {
   58 #endif
   59         host_info = gethostbyname(addr);
   60         if (!host_info) {
   61             return FAILURE;
   62         }
   63         *in = *((struct in_addr *) host_info->h_addr);
   64     }
   65     return SUCCESS;
   66 }
   67 
   68 char* get_redirected_address(TSRMLS_D2(DBG, E)) {
   69     int rv;
   70     zval **httpvars, **remoteaddr, **forwardedfor;
   71     char *p, *ret_val = NULL;
   72 
   73     DBG_TRACE(("get_redirected_address\n"));
   74     rv = zend_hash_find(&EG(symbol_table), "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), (void **) &httpvars);
   75     if (rv != FAILURE && ((*httpvars)->type==IS_ARRAY)) {
   76         rv = zend_hash_find((*httpvars)->value.ht, "HTTP_X_FORWARDED_FOR", sizeof("HTTP_X_FORWARDED_FOR"), (void **) &forwardedfor);
   77         if (rv != FAILURE && ((*forwardedfor)->type==IS_STRING) && (*forwardedfor)->value.str.len > 0) {
   78             p = strchr(Z_STRVAL_P(*forwardedfor), ',');
   79             if (p == NULL) {
   80                 ret_val = estrndup(Z_STRVAL_P(*forwardedfor),Z_STRLEN_P(*forwardedfor));
   81             } else {
   82                 ret_val = estrndup(Z_STRVAL_P(*forwardedfor),p-Z_STRVAL_P(*forwardedfor));
   83             }
   84         } else {
   85             rv = zend_hash_find((*httpvars)->value.ht, "REMOTE_ADDR", sizeof("REMOTE_ADDR"), (void **) &remoteaddr);
   86             if (rv != FAILURE &&  ((*remoteaddr)->type==IS_STRING)) {
   87                 ret_val = estrndup(Z_STRVAL_P(*remoteaddr),Z_STRLEN_P(*remoteaddr));
   88             }
   89         }
   90     }
   91     return ret_val;
   92 }
   93 
   94 /*
   95  * Connects to a specified host and port, and returns a socket for the connection.
   96  */
   97 
   98 int create_debugger_socket(SESSTYPE sesstype TSRMLS_DC2(DBG, E)) {
   99     struct sockaddr_in address;
  100     int err=-1;
  101     int sockfd;
  102     int ret_val;
  103 
  104     DBG_TRACE(("create_debugger_socket(%d)\n", sesstype));
  105     memset(&address, 0, sizeof(address));
  106     address.sin_family = AF_INET;
  107 
  108     if (DBG(client_address)) {
  109         efree(DBG(client_address));
  110         DBG(client_address) = NULL;
  111     }
  112 
  113     DBG(client_address) = (DBGF(DBGF_REQUESTFOUND)) ? (DBG(req_client_ip_address)) : (DBG(cfgprm_JIT_host));
  114     if (!DBG(client_address)) DBG(client_address) = CLIENT_HOST;
  115     DBG(client_address) = estrdup(DBG(client_address));
  116 
  117     if (DBG(client_address) && stricmp(DBG(client_address), CLIENT_HOST) == 0) {
  118         efree(DBG(client_address));
  119         DBG(client_address) = get_redirected_address(TSRMLS_C2(DBG, E));
  120         if (!DBG(client_address)) {
  121             DBG(client_address) = estrdup("localhost");
  122         }
  123     }
  124     
  125     DBG_TRACE(("address(%s)\n", SON(DBG(client_address))));
  126 
  127     if (!DBG(client_address) || dbg_lookup_hostname(DBG(client_address), &address.sin_addr) == FAILURE) {
  128         if (!DBG(cfgprm_fail_silently)) {
  129             SysError("dbg_lookup() failed (address=\"%s\")\n", DBG(client_address));    
  130         }
  131         return ESESS_LOOKUP;
  132     }
  133 
  134     DBG(client_port) = (DBGF(DBGF_REQUESTFOUND)) ? (DBG(req_client_port)) : (DBG(cfgprm_JIT_port));
  135     if (DBG(client_port) == 0) DBG(client_port) = DEFAULT_PORT;
  136     address.sin_port = htons((unsigned short)DBG(client_port));
  137     
  138 
  139     DBG_TRACE(("conn. allowed to %s:%ld\n", SON(DBG(client_address)), DBG(client_port)));
  140 
  141 
  142     sockfd = socket(AF_INET, SOCK_STREAM, 0);
  143     ret_val = sockfd;
  144     if (sockfd == SOCK_ERR) {
  145         if (!DBG(cfgprm_fail_silently)) {
  146             SysError("socket() failed\n");
  147         }
  148         ret_val = ESESS_SOCK;
  149     } else {
  150         while ((err = connect(sockfd, (struct sockaddr *) &address,
  151                               sizeof(address))) == SOCK_ERR && errno == EAGAIN);
  152         if (err < 0) {
  153             if (!DBG(cfgprm_fail_silently)) {
  154                 SysError("connect() failed\n");
  155             }
  156             SCLOSE(sockfd);
  157             ret_val = ESESS_CONN;
  158         } else {
  159             DBG_TRACE(("socket (%d) opened\n", sockfd));
  160         }
  161     }
  162     return ret_val;
  163 }
  164 
  165 
  166 /* ************************************************* */
  167 
  168 inline int dbg_mod_item_by_name(const char *mod_name, int addifnotfound TSRMLS_DC1(DBG)) {
  169     mod_item* p_mod = dbg_findmodule(mod_name, addifnotfound TSRMLS_CC1(DBG));
  170     return (p_mod) ? (p_mod->mod_no) : (0);
  171 }
  172 
  173 inline mod_item* dbg_mod_item_by_no(int mod_no TSRMLS_DC1(DBG)) {
  174     if (mod_no != 0 && DBG(curr_mod) && DBG(curr_mod)->mod_no==mod_no)
  175         return DBG(curr_mod);
  176     LLIST_FOREACH(DBG(mod_list), mod_item,
  177         if (data->mod_no == mod_no) {
  178             return data;
  179         }
  180     );
  181     return NULL;
  182 }
  183 
  184 inline char *dbg_mod_name_by_no(int mod_no TSRMLS_DC1(DBG)) {
  185     mod_item *src_item;
  186     src_item = dbg_mod_item_by_no(mod_no TSRMLS_CC1(DBG));
  187     return (src_item) ? (src_item->mod_name) : NULL;
  188 }
  189 
  190 inline int MATCHFILE(const char *name1, const char *name2 TSRMLS_DC1(DBG)) {
  191     if (DBGO(SOF_MATCHFILESINLOWCASE)) 
  192         return (stricmp(name1,name2)==0);
  193     else
  194         return (strcmp(name1,name2)==0);
  195 }
  196 
  197 inline mod_item* dbg_findmodule(const char *mod_name, int addifnotfound TSRMLS_DC1(DBG)) {
  198     int idx;
  199     mod_item newitem, *p_mod;
  200 
  201     if (mod_name == DBG(curr_mod_name)) {
  202         return DBG(curr_mod);
  203     }
  204     if (!mod_name)
  205         return NULL;
  206     
  207     idx = 1;
  208     LLIST_FOREACH(DBG(mod_list), mod_item, {
  209         if (MATCHFILE(mod_name, data->mod_name TSRMLS_CC1(DBG))) {
  210             return data;
  211         }
  212         idx++;
  213     });
  214 
  215     if (!addifnotfound) return NULL;
  216 
  217     memset(&newitem, 0, sizeof(newitem));
  218     newitem.mod_no = idx;
  219     newitem.mod_name = estrdup(mod_name);
  220     newitem.rsrv1 = 0;
  221     zend_llist_add_element(&DBG(mod_list), &newitem);
  222     p_mod = dbg_mod_item_by_no(newitem.mod_no TSRMLS_CC1(DBG));
  223     return p_mod;
  224 }
  225 
  226 /******** R E P L Y **********/
  227 
  228 int handler_add_source_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  229     char *fn;
  230     FILE *f = NULL;
  231     dbg_source_body body;
  232 #if ZEND_EXTENSION_API_NO < 20020903
  233     int issock = 0, socketd = 0;
  234 #endif
  235     int ret_val, mod_no, rest_size;
  236     int error = 0, from_pos = -1, full_size = -1, bufsize = 128*1024;
  237     void *buf = NULL;
  238     char ok=0, *mod_name;
  239 
  240     dbg_source_request *req = FRAME_DATA_PTR(dbg_source_request,frame);
  241 
  242     mod_no = req->mod_no;
  243     from_pos = req->from_filepos;
  244 
  245     if (from_pos >= 0) {
  246         error = -2;                 /* file open error */
  247         fn = dbg_mod_name_by_no(mod_no TSRMLS_CC1(DBG));
  248         if (fn && *fn!='-') {
  249             f = fopen(fn, "rb");    
  250             if (!f) {
  251 #if ZEND_EXTENSION_API_NO < 20020903
  252                 f = php_fopen_wrapper(fn, "rb", USE_PATH|IGNORE_URL_WIN, &issock, &socketd, NULL TSRMLS_CC0);
  253 #else
  254                 f = php_stream_open_wrapper_as_file(fn, "rb", USE_PATH|IGNORE_URL_WIN, NULL);
  255 #endif
  256             }
  257         }
  258         ok = (f!=NULL);
  259         if (ok) {
  260             ret_val = fseek(f, 0, SEEK_END);
  261             ok = (ret_val == 0);
  262             if (!ok){
  263                 error = ferror(f); /* seek error */
  264             }
  265         }
  266         if (ok) {
  267             full_size = ftell(f);
  268             ret_val = fseek(f, from_pos, SEEK_SET);
  269             ok = (ret_val == 0);
  270             if (!ok){
  271                 error = ferror(f); /* seek error */
  272             }
  273         }
  274         if (ok) {
  275             rest_size = full_size - from_pos; 
  276             bufsize = (rest_size > bufsize) ? bufsize:rest_size;
  277             buf = emalloc(bufsize);
  278             ok = (buf != NULL);
  279             if (!ok){
  280                 error = -3; /*No memory for buffer*/
  281             }
  282         }
  283         if (ok) {
  284             ret_val = fread(buf, 1, bufsize, f);
  285             ok = (ret_val == bufsize) || feof(f);
  286             if (!ok){
  287                 error = ferror(f); /* read error */
  288             }
  289             bufsize = ret_val;
  290         }
  291     }
  292 
  293     if (!ok){
  294         bufsize = 0;
  295     }
  296 
  297 
  298     mod_name = (from_pos <= 0) ? dbg_mod_name_by_no(mod_no TSRMLS_CC1(DBG)) : NULL;
  299     body.imod_name = (mod_name) ? dbg_packet_add_string(pack, mod_name) : 0;
  300     body.itext = (from_pos >= 0 && buf) ? dbg_packet_add_rawdata(pack, buf, bufsize) : 0;
  301     body.error = error;
  302     body.mod_no = mod_no;
  303     body.from_filepos = from_pos;
  304     body.full_size =  full_size;
  305     
  306     dbg_packet_add_frame(pack, FRAME_SOURCE, &body, sizeof(body));
  307     
  308     if (buf) {
  309         efree(buf);
  310     }
  311     if (f) {
  312         fclose(f);
  313     }
  314     return bufsize;
  315 }
  316 
  317 int handler_add_stack_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  318     dbg_stack_body stk;
  319     char *mod_name, *func_name;
  320     int depth;
  321     int line_no, mod_no;
  322     int sz = 0;
  323     char descr[256];
  324                                     
  325     if (DBG(deactivate_inprocess)) return 1;
  326 
  327 /*current location*/
  328     if (zend_is_executing(TSRMLS_C0)) {
  329         mod_name = zend_get_executed_filename(TSRMLS_C1(E));
  330         line_no = zend_get_executed_lineno(TSRMLS_C1(E));
  331         func_name = get_active_function_name(TSRMLS_C0);
  332     } else if (zend_is_compiling(TSRMLS_C0)) {
  333         TSRMLS_FETCH1_NOP(C);
  334         mod_name = zend_get_compiled_filename(TSRMLS_C1(C));
  335         line_no = zend_get_compiled_lineno(TSRMLS_C1(C));
  336         func_name = NULL;
  337     }
  338     else {
  339         mod_name = DBG(curr_mod_name);
  340         line_no = DBG(curr_line_no);
  341         func_name = NULL;
  342     }
  343 
  344     mod_no = DBG_FINDMODULE_ADD(mod_name);
  345     depth = CURLOC_SCOPE_ID;
  346     stk.mod_no = mod_no;
  347     stk.line_no = line_no;
  348     stk.scope_id = CURLOC_SCOPE_ID;
  349     
  350     if (func_name!=NULL && stricmp(func_name,"main") != 0) {
  351         snprintf(descr, sizeof(descr)-1, "%s()", func_name);
  352     } else if (mod_name!=NULL) {
  353         snprintf(descr, sizeof(descr)-1, "%s::main()", mod_name);
  354     } else {
  355         descr[0]='\0';
  356     }
  357     stk.idescr = dbg_packet_add_string(pack, descr);
  358 
  359     dbg_packet_add_frame(pack, FRAME_STACK, &stk, sizeof(stk));
  360     sz = sizeof(stk);
  361 
  362     depth = DBG(back_trace_count);  
  363     
  364 /*stacked location(s)*/
  365     LLIST_RFOREACH(DBG(back_trace), back_trace_item,
  366         depth--;
  367         stk.line_no = data->line_no;
  368         stk.mod_no = data->mod_no;
  369         stk.idescr = dbg_packet_add_string(pack, data->descr);
  370         stk.scope_id = INC_SCOPEID(depth);
  371         dbg_packet_add_frame(pack, FRAME_STACK, &stk, sizeof(stk));
  372         sz+=sizeof(stk);
  373     );
  374 
  375     return sz;
  376 }                           
  377 
  378 int handler_add_mod_list_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  379     dbg_src_tree_body body;
  380     int idx = 1;
  381 
  382     LLIST_FOREACH(DBG(mod_list), mod_item,
  383         body.mod_no = idx;
  384         body.rsrv1 = 0;
  385         body.rsrv2 = 0;
  386         body.imod_name = dbg_packet_add_string(pack, data->mod_name);
  387         dbg_packet_add_frame(pack, FRAME_SRC_TREE, &body, sizeof(body));
  388         idx++;
  389     );
  390     return ((idx-1) * sizeof(body));
  391 }
  392 
  393 int handler_add_bpl_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  394     int cnt = 0;
  395     dbg_bpl_request *req = FRAME_DATA_PTR(dbg_bpl_request, frame);
  396 
  397     LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
  398         if (req->bp_no == 0 || data->bp_no == req->bp_no) {
  399             cnt+=listout_bp_item(pack, data, data->bp_no);
  400         }
  401     });
  402     return (cnt);
  403 }
  404 
  405 int handler_set_breakpoint(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  406     dbg_bps_request* req = FRAME_DATA_PTR(dbg_bps_request, frame);
  407     return dbg_set_breakpoint(req, pack, inpack TSRMLS_CC2(DBG, E));
  408 }
  409 
  410 int handler_add_srclinesinfo_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  411     dbg_srclinesinfo_request *req = FRAME_DATA_PTR(dbg_srclinesinfo_request, frame);
  412     int mod_no = req->mod_no;
  413     dbg_srclinesinfo_body body;
  414     int cnt=0;
  415     
  416     LLIST_FOREACH(DBG(ctxlines_list), ctxlines_item,        
  417         if (mod_no==0 || mod_no == data->mod_no) {
  418             body.ctx_id = data->ctx_id;
  419             body.mod_no = data->mod_no;
  420             body.lines_count = data->lines_cnt;
  421             body.start_line_no = data->start_line_no;
  422             dbg_packet_add_frame(pack, FRAME_SRCLINESINFO, &body, sizeof(body));
  423             cnt++;
  424         }
  425     );
  426     return (cnt * sizeof(body));
  427 }
  428 
  429 int handler_add_srcctxinfo_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  430     dbg_srcctxinfo_body body;
  431     int cnt=0, imod_no;
  432     dbg_srcctxinfo_request *req = FRAME_DATA_PTR(dbg_srcctxinfo_request, frame);
  433     int mod_no = req->mod_no;
  434     
  435     body.mod_no = mod_no;
  436     LLIST_FOREACH(DBG(ctx_list), ctx_item,
  437         imod_no = DBG_FINDMODULE(data->mod_name);
  438         if (mod_no==0 || mod_no == imod_no) {
  439             body.ctx_id = data->ctx_id;
  440             body.mod_no = imod_no;
  441             body.ifunction_name = dbg_packet_add_string(pack, data->function_name);
  442             dbg_packet_add_frame(pack, FRAME_SRCCTXINFO, &body, sizeof(body));
  443             cnt++;
  444         }
  445     );
  446     return (cnt * sizeof(body));
  447 }
  448 
  449 int handler_add_profdata_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  450     dbg_prof_body body;
  451     profdata_item *it;
  452     int i, cnt=0;
  453     dbg_prof_request *req = FRAME_DATA_PTR(dbg_prof_request, frame);
  454     int mod_no = req->mod_no;
  455 
  456     LLIST_FOREACH(DBG(mod_list), mod_item,
  457         if (data->mod_no == mod_no || mod_no==0) {
  458             body.mod_no = data->mod_no;
  459             for (i=0; i< data->profdata_items-1; i++) {
  460                 it=&(data->profdata_arr[i]);
  461                 if (it->hitcount > 0) {
  462                     body.hit_count = it->hitcount;
  463                     body.line_no = i;
  464                     body.tm_max_hi = (long)(it->tm_max >> 32);
  465                     body.tm_max_lo = (long)(it->tm_max & 0xFFFFFFFF);
  466                     body.tm_min_hi = (long)(it->tm_min >> 32);
  467                     body.tm_min_lo = (long)(it->tm_min & 0xFFFFFFFF);
  468                     body.tm_sum_hi = (long)(it->tm_sum >> 32);
  469                     body.tm_sum_lo = (long)(it->tm_sum & 0xFFFFFFFF);
  470                     dbg_packet_add_frame(pack, FRAME_PROF, &body, sizeof(body));
  471                     cnt++;
  472                 }
  473             }
  474         }
  475     );
  476     return 1;
  477 }
  478 
  479 int handler_add_proffreq_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  480     dbg_prof_c_body body;
  481     dbgint64 f;
  482     dbgint64 v, sum1=0, sum2=0, mv, cnt1=0, cnt2=0, minv, maxv;
  483     int i, loopc;
  484     dbg_prof_c_request *req = FRAME_DATA_PTR(dbg_prof_c_request, frame);
  485 
  486     PROF_PERF_FREQ(f);
  487     body.tm_freq_lo = (unsigned dbgint)(f & 0xFFFFFFFF);
  488     body.tm_freq_hi = (unsigned dbgint)(f >> 32);
  489 
  490     loopc = req->test_loops;
  491     if (loopc<2) loopc = 2;
  492     minv = 0;
  493     maxv = 0;
  494     for (i=0; i<loopc/2; i++) {
  495         PROF_DOUBLE_SNAP(v);
  496         if (i==0) {
  497             minv=v;
  498             maxv=v;
  499         } else {
  500             if (v<minv) minv=v;
  501             if (v>maxv) maxv=v;
  502         }
  503         sum1 +=v;
  504         cnt1++;
  505     }
  506     mv=sum1/cnt1;
  507     for (i = 0; i < loopc/2; i++) {
  508         PROF_DOUBLE_SNAP(v);
  509         if (v<minv) minv=v;
  510         if (v>maxv) maxv=v;
  511         if (v <= 3*mv) {
  512             sum2 +=v;
  513             cnt2++;
  514         }
  515     }
  516     mv=sum2/cnt2;
  517     if (maxv > MAXINT32T) maxv = MAXINT32T;
  518     if (minv > MAXINT32T) minv = MAXINT32T;
  519     if (mv > MAXINT32T) mv = MAXINT32T;
  520     body.tm_diff_max = (long)maxv;
  521     body.tm_diff_min = (long)minv;
  522     body.tm_diff_m = (long)mv;
  523     dbg_packet_add_frame(pack, FRAME_PROF_C, &body, sizeof(body));
  524     return 1;
  525 }
  526 
  527 int dbg_add_version_reply(dbg_packet *pack TSRMLS_DC1(DBG)) {
  528     dbg_version_body body;
  529 
  530     body.idescription = dbg_packet_add_string(pack, DBG_API_DESCRIPTION);
  531     body.major_version = DBG_API_MAJOR_VERSION;
  532     body.minor_version = DBG_API_MINOR_VERSION;
  533     dbg_packet_add_frame(pack, FRAME_VER, &body, sizeof(body));
  534     return sizeof(body);
  535 }
  536 
  537 int handler_add_sid_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  538     dbg_sid_body body;
  539 
  540     body.isid = dbg_packet_add_string(pack, DBG(session_id));
  541     body.sesstype = DBG(sesstype);
  542     dbg_packet_add_frame(pack, FRAME_SID, &body, sizeof(body));
  543     return sizeof(body);
  544 }
  545 
  546 int handler_add_ver_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  547     dbg_version_body *client_ver = FRAME_DATA_PTR(dbg_version_body, frame); 
  548 
  549     DBG(clientversion) = ((client_ver->major_version & 0xFF) << 8) | (client_ver->minor_version & 0xFF);
  550     dbg_add_version_reply(pack TSRMLS_CC1(DBG));
  551     return (sizeof(dbg_version_body));
  552 }
  553 
  554 
  555 /*         E V A L    E F F O R T        */
  556 
  557 
  558 static void dbg_get_context_sym_table(long scope_id, HashTable **ht, zval **zthis  TSRMLS_DC2(DBG, E)) {
  559     back_trace_item *bt_item;
  560     int depth;
  561     int scope_count;
  562 
  563     if (scope_id == CURLOC_SCOPE_ID) {
  564         *ht = EG(active_symbol_table);
  565         *zthis = EG_THIS;
  566         return;
  567     }
  568     else {
  569         scope_count = DBG(back_trace_count);
  570         if (scope_id == GLOBAL_SCOPE_ID) {
  571             depth = 0;
  572             if (scope_count == 0) {
  573                 *ht = EG(active_symbol_table);
  574                 *zthis = EG_THIS;
  575                 return;
  576             }
  577         }
  578         else {
  579             depth =  DEC_SCOPEID(scope_id);
  580         }
  581 
  582         if (depth >= 0 && depth < scope_count) {
  583             LLIST_ITEM_AT(DBG(back_trace), depth, bt_item, back_trace_item*);
  584             *ht = bt_item->active_sym_table;
  585             *zthis = bt_item->active_this;
  586             return;
  587         }
  588     }
  589     *ht = NULL;
  590     *zthis = NULL;
  591     return;
  592 }
  593 
  594 void dbg_full_eval(char *str, HashTable *active_sym_table, zval *buf) {
  595     HashTable *ast;
  596     zval data;
  597     TSRMLS_FETCH3(DBG, E, C);
  598 
  599     ast = EG(active_symbol_table);
  600     EG(active_symbol_table) = active_sym_table;
  601     
  602     memset(&data, 0, sizeof(data));
  603     Z_TYPE_P(&data) = IS_STRING;
  604     data.refcount++;
  605 
  606     if (DBG(eval_error)) {
  607         efree(DBG(eval_error));
  608         DBG(eval_error) = NULL;
  609     }
  610 
  611     if (zend_eval_string(str, &data, "dbg_eval()" TSRMLS_CC2(C, E)) == SUCCESS && !DBG(eval_error)) {
  612         dbg_serialize_zval(&data, buf, 0 TSRMLS_CC2(DBG, E));
  613     }
  614     if (data.value.str.val) zval_dtor(&data);
  615     EG(active_symbol_table) = ast;
  616 }
  617 
  618 int handler_add_eval_reply(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  619     char *str = NULL;
  620     int sz = 0, ret_val = 0;
  621     HashTable *active_sym_table = NULL;
  622     zval **data;
  623     zval buf;
  624     zval *active_this;
  625     dbg_eval_body body;
  626     dbg_eval_request *req = FRAME_DATA_PTR(dbg_eval_request, frame);
  627 
  628     memset(&buf, 0, sizeof(buf));
  629     Z_TYPE_P(&buf) = IS_STRING;
  630     buf.refcount++;
  631 
  632     if (req->istr!=0 && (!dbg_packet_findstring(inpack, req->istr, &str, &sz) || sz<=0)) return 0;
  633     if (str && strlen(str)==0) str = NULL;
  634 
  635 
  636     DBG(in_eval)++;
  637     {
  638         DBG_CTX_SAVE
  639         DBG_CTX_TRY {
  640             if (DBG(eval_error)) {
  641                 efree(DBG(eval_error));
  642                 DBG(eval_error) = NULL;
  643             }
  644             dbg_get_context_sym_table(req->scope_id, &active_sym_table, &active_this TSRMLS_CC2(DBG, E));
  645             if (active_sym_table) {
  646                 if (!str) {
  647                     dbg_serialize_hash(active_sym_table, active_this, &buf, DSER_ADD_DSIGN TSRMLS_CC2(DBG, E));
  648                 } 
  649                 else if (str &&
  650                     sz > 1 && 
  651                     str[0]=='$' && 
  652                     zend_hash_find(active_sym_table, &str[1], sz-1, (void **) &data) == SUCCESS) {
  653                     dbg_serialize_zval(*data, &buf, 0 TSRMLS_CC2(DBG, E));
  654                 } 
  655                 else if (str && strcmp(str,"$GLOBALS")==0) {
  656                     dbg_get_context_sym_table(GLOBAL_SCOPE_ID, &active_sym_table, &active_this TSRMLS_CC2(DBG, E));
  657                     dbg_serialize_hash(active_sym_table, active_this, &buf, DSER_ADD_DSIGN TSRMLS_CC2(DBG, E));
  658                 }
  659                 else {
  660                     dbg_full_eval(str, active_sym_table, &buf);
  661                 }
  662             }
  663 
  664         } DBG_CTX_CATCH {
  665             DBG_TRACE(("eval: zend_catch\n"));
  666             DBG_TRACE(("dbg_full_eval(!)<<\n"));
  667             if (buf.value.str.val) 
  668                 zval_dtor(&buf);
  669             memset(&buf, 0, sizeof(buf));
  670             DBG_CTX_RESTORE
  671         } DBG_CTX_ENDTRY
  672     }
  673 
  674     DBG(in_eval)--;
  675 
  676     ret_val = buf.value.str.len;
  677     body.iresult = dbg_packet_add_rawdata(pack, Z_STRVAL(buf), Z_STRLEN(buf)+1);
  678     body.istr = str ? dbg_packet_add_string(pack, str) : 0;
  679     body.ierror = DBG(eval_error) ? dbg_packet_add_string(pack, DBG(eval_error)) : 0;
  680     dbg_packet_add_frame(pack, FRAME_EVAL, &body, sizeof(body));
  681     if (DBG(eval_error)) {
  682         efree(DBG(eval_error));
  683         DBG(eval_error) = NULL;
  684     }
  685     if (buf.value.str.val) zval_dtor(&buf);
  686     return ret_val;
  687 }
  688 
  689 int handler_set_options(dbg_packet *pack, dbg_packet *inpack, dbg_frame *frame TSRMLS_DC2(DBG, E)) {
  690     dbg_set_options_request *req = FRAME_DATA_PTR(dbg_set_options_request, frame);
  691     DBG(opt_flags) = req->opt_flags;
  692     switch ((req->opt_flags & SOF_ERR_LEVEL_MASK) >> SOF_ERR_LEVEL_SHIFT) {
  693         case 0:
  694             DBG(error_filter) = ERR_LEVEL0_MASK; 
  695             break;
  696         case 1:
  697             DBG(error_filter) = ERR_LEVEL1_MASK; 
  698             break;
  699         case 2:
  700             DBG(error_filter) = ERR_LEVEL2_MASK; 
  701             break;
  702         case 4:
  703             DBG(error_filter) = ERR_LEVEL4_MASK; 
  704             break;
  705         default:
  706             DBG(error_filter) = ERR_LEVEL3_MASK; 
  707             break;
  708     }
  709     return 1;
  710 }
  711 
  712 /*     H A N D L E    R E Q U E S T ( S )      */
  713 
  714 cmddef cmdlist[] = {
  715     {FRAME_STACK,           handler_add_stack_reply},
  716     {FRAME_SRC_TREE,        handler_add_mod_list_reply},
  717     {FRAME_EVAL,            handler_add_eval_reply},
  718     {FRAME_BPL,             handler_add_bpl_reply},
  719     {FRAME_BPS,             handler_set_breakpoint},
  720     {FRAME_SRCLINESINFO,    handler_add_srclinesinfo_reply},
  721     {FRAME_SRCCTXINFO,      handler_add_srcctxinfo_reply},
  722     {FRAME_PROF,            handler_add_profdata_reply},
  723     {FRAME_PROF_C,          handler_add_proffreq_reply},
  724     {FRAME_SID,             handler_add_sid_reply},
  725     {FRAME_VER,             handler_add_ver_reply},
  726     {FRAME_SET_OPT,         handler_set_options},
  727     {FRAME_SOURCE,          handler_add_source_reply},
  728     {0, NULL}
  729 };
  730 
  731 
  732 void dbg_handle_request(dbg_header_struct *hdr, dbg_packet *inpack  TSRMLS_DC2(DBG, E)) {
  733     dbg_frame *p;
  734     dbg_packet outpack;
  735     cmddef *pcmd;
  736 
  737     if (!hdr->flags & DBGF_WAITACK) return;
  738 
  739     dbg_packet_new(&outpack);
  740 
  741     p = dbg_packet_firstframe(inpack);
  742     while (p){
  743         DBG_TRACE(("request %ld\n",p->name));
  744         pcmd = cmdlist;
  745         while (pcmd->name != 0) {
  746             if (pcmd->name == p->name) {
  747                 pcmd->handler(&outpack, inpack, p TSRMLS_CC2(DBG, E));
  748                 break;
  749             }
  750             pcmd++;
  751         }
  752         p = dbg_packet_nextframe(inpack,p);
  753     }
  754 
  755     dbg_packet_send(DBGC_REPLY, &outpack, DBG(debug_socket), DBG(debugger_flags));
  756     dbg_packet_free(&outpack);
  757 }
  758 
  759 
  760 /* debugger host may ask to provide some information (DBGA_REQUEST) 
  761   or urge to continue run (DBGA_xxxx) */
  762 /* main way from the Listener to the DBG module */
  763 
  764 void dbg_process_ack(dbg_header_struct *hdr, dbg_packet *pack TSRMLS_DC2(DBG, E)) {
  765 
  766     DBG_TRACE(("ack %d\n",hdr->cmd));
  767     switch (hdr->cmd) {
  768         case DBGC_PAUSE: /* ignore */
  769             break;
  770         case DBGA_CONTINUE:
  771             DBG(debugger_flags)&=~DBGF_WAITACK;
  772             break;
  773         case DBGA_STOP:
  774             DBG(debugger_flags)&=~DBGF_WAITACK;
  775             DBG(debugger_flags) |= DBGF_ABORT;
  776             zend_bailout();
  777             break;
  778         case DBGA_STEPINTO:
  779             DBG(debugger_flags) |= DBGF_STEPINTO;
  780             DBG(debugger_flags) &= ~DBGF_WAITACK;
  781             DBG(debugger_step_depth) = DBG(back_trace_count);
  782             break;
  783         case DBGA_STEPOVER:
  784             DBG(debugger_flags) |= DBGF_STEPOVER;
  785             DBG(debugger_flags) &= ~DBGF_WAITACK;
  786             DBG(debugger_step_depth) = DBG(back_trace_count);
  787             break; 
  788         case DBGA_STEPOUT:
  789             DBG(debugger_flags) |= DBGF_STEPOUT;
  790             DBG(debugger_flags) &= ~DBGF_WAITACK;
  791             DBG(debugger_step_depth) = DBG(back_trace_count);
  792             break; 
  793         case DBGA_REQUEST:
  794             dbg_handle_request(hdr, pack  TSRMLS_CC2(DBG, E));
  795             break;
  796         default:
  797             DBG(debugger_flags)&=~DBGF_WAITACK;
  798             if (hdr->flags & DBGF_WAITACK) {
  799                 dbg_packet_send(DBGC_REPLY, NULL, DBG(debug_socket), DBG(debugger_flags));
  800             }
  801     }
  802 }
  803 
  804 /* waiting and looking for debugger host responce */
  805 inline void dbg_ack_loop(TSRMLS_D2(DBG, E)) {
  806     int ret_val = 0, wcnt = 0;  
  807     dbg_header_struct hdr;
  808     dbg_packet pack;
  809 
  810     if (!dbg_packet_new(&pack)) {
  811         DBG(debugger_flags)&=~DBGF_WAITACK;
  812         return;
  813     }
  814     
  815     dbg_mark_del_temp_breakpoints(TSRMLS_C1(DBG));
  816 
  817     zend_unset_timeout(TSRMLS_C0);
  818     while (DBGF(DBGF_WAITACK)) {
  819         dbg_packet_clear(&pack);
  820         ret_val = dbg_packet_recv(&hdr, &pack, DBG(debug_socket), DBG(cfgprm_timeout_seconds) * 1000);
  821         if (ret_val == 0) continue;     /* socket is not closed, but we haven't data received, so continue wait */
  822         if (ret_val < 0) break;         /*socket just closed*/
  823         dbg_process_ack(&hdr,&pack TSRMLS_CC2(DBG, E));
  824         if (DBG(breakpoint_list_inv)) {
  825             dbg_rebuild_bplist(TSRMLS_C1(DBG));
  826         }
  827     }
  828 
  829     zend_set_timeout(EG(timeout_seconds));
  830 
  831     dbg_packet_free(&pack);
  832     if (ret_val < 0) {
  833         DBG(debugger_flags)|=DBGF_UNSYNC;
  834         DBG_TRACE(("session dropped. Closing socket(%d)\n", DBG(debug_socket)));
  835         SCLOSE(DBG(debug_socket));
  836         DBG(debug_socket) = ret_val;
  837     }
  838     DBG(debugger_flags)&=~DBGF_WAITACK;
  839     dbg_flush_log(TSRMLS_C2(DBG, E));
  840 }
  841 
  842 
  843 /* inform the debugger host that it is debugging event has been fired */
  844 inline int dbg_send_command(int cmd, dbg_packet *pack, char bWaitAck TSRMLS_DC2(DBG, E)) {
  845     int ret_val;
  846 
  847     if (DBG(debug_socket) <= 0 || DBG(is_failed_connection)) return 0; 
  848     if (DBGF(DBGF_WAITACK)) return 0; /*something wrong, go out*/
  849 
  850     if (!DBGF(DBGF_UNSYNC) && bWaitAck) {
  851         DBG(debugger_flags)|=DBGF_WAITACK;      
  852     }   
  853     
  854     zend_unset_timeout(TSRMLS_C0);
  855     ret_val = dbg_packet_send(cmd, pack, DBG(debug_socket), DBG(debugger_flags));
  856     zend_set_timeout(EG(timeout_seconds));
  857 
  858     if (bWaitAck) {
  859         DBG(debugger_flags) &= ~(DBGF_STEPINTO | DBGF_STEPOVER | DBGF_STEPOUT);
  860         if (ret_val <= 0) {
  861             DBG(debugger_flags)|=DBGF_UNSYNC;
  862             DBG(debugger_flags)&=~DBGF_WAITACK;
  863             return 0;
  864         }
  865     /* wait for debugger host responce. */
  866         if (DBGF(DBGF_WAITACK)) {
  867             dbg_ack_loop(TSRMLS_C2(DBG, E));
  868         }
  869     } else {
  870         if (ret_val <= 0) {
  871             DBG(debugger_flags)|=DBGF_UNSYNC;
  872             return 0;
  873         }
  874     }
  875     return ret_val;
  876 }
  877 
  878 /* send an event such as startup/breakpoint to the debugger host */
  879 inline int dbg_send_std_action(int cmd, int hitcnt TSRMLS_DC2(DBG, E)) {
  880     dbg_packet pack;
  881     int ret_val;
  882     
  883     if (cmd != DBGC_STARTUP) dbg_flush_log(TSRMLS_C2(DBG, E));
  884 
  885     if (!dbg_packet_new(&pack)) return 0;
  886 
  887     ret_val = handler_add_stack_reply(&pack, NULL, NULL TSRMLS_CC2(DBG, E));
  888     if (cmd == DBGC_STARTUP && ret_val)
  889         ret_val = dbg_add_version_reply(&pack TSRMLS_CC1(DBG));
  890     
  891     if (ret_val) {
  892         dbg_add_bp_reply(&pack TSRMLS_CC1(DBG));
  893         ret_val = dbg_send_command(cmd, &pack, 1 TSRMLS_CC2(DBG, E));
  894     }
  895     
  896     dbg_packet_free(&pack);
  897 
  898     dbg_reset_bp_isunderhit(TSRMLS_C1(DBG));
  899     return ret_val;
  900 }
  901 
  902 inline int dbg_send_error(char *message, int type, const char *mod_name, int line_no TSRMLS_DC2(DBG, E)) {
  903     dbg_packet pack;
  904     dbg_error_body body;
  905     int ret_val = 0;
  906     
  907     
  908     dbg_flush_log(TSRMLS_C2(DBG, E));
  909 
  910     if (!dbg_packet_new(&pack)) return 0;
  911     body.imessage = dbg_packet_add_string(&pack, message);
  912     body.type = type;
  913     if (dbg_packet_add_frame(&pack, FRAME_ERROR, &body, sizeof(body)) &&
  914         handler_add_stack_reply(&pack, NULL, NULL TSRMLS_CC2(DBG, E))) {
  915         ret_val = dbg_send_command(DBGC_ERROR, &pack, 1 TSRMLS_CC2(DBG, E));
  916     }
  917     dbg_packet_free(&pack);
  918     return ret_val;
  919 }
  920 
  921 
  922 void dbg_flush_log(TSRMLS_D2(DBG, E)) {
  923 
  924     if (DBG(output_str_nd_len) > 0 && DBG(output_str_nd)) {
  925         dbg_log_body body;
  926         body.ext_info = 0;
  927         body.ilog = dbg_packet_add_stringlen(&DBG(logpack), DBG(output_str_nd), DBG(output_str_nd_len));
  928         body.imod_name = 0;
  929         body.line_no = 0;
  930         body.mod_no = 0;
  931         body.type = LT_OUTPUT;
  932         dbg_packet_add_frame(&DBG(logpack), FRAME_LOG, &body, sizeof(body));        
  933         DBG(output_str_nd_len) = 0;
  934     }   
  935 
  936     if (DBG(logpack).size <= 0 || DBG(debug_socket)<=0) return;
  937 
  938     if (dbg_send_command(DBGC_LOG, &DBG(logpack), 0 TSRMLS_CC2(DBG, E))!=0) {
  939         DBG(logpack).size = 0;
  940         DBG(logpack).lastrawid = 0;
  941     }
  942 }
  943 
  944 inline int dbg_send_log(char *log, int len, int type, const char *mod_name, const int line_no, int ext_info TSRMLS_DC2(DBG, E)) {
  945     dbg_log_body body;
  946     int ret_val = 0;
  947     char const *amod_name;
  948     int aline_no;
  949 
  950     if (DBG(deactivate_inprocess)) return 0;  /* should not activate connection by dbg_send_log() */
  951     {
  952 
  953         body.type = type;
  954         body.ext_info = ext_info;
  955 
  956         if (type!=LT_OUTPUT || DBGO(SOF_SEND_OUTPUT_DETAILED)) {
  957             amod_name = mod_name;
  958             aline_no = line_no;
  959             if (amod_name == NULL) {
  960                 if (zend_is_executing(TSRMLS_C0)) {
  961                     amod_name = zend_get_executed_filename(TSRMLS_C1(E));
  962                     aline_no = zend_get_executed_lineno(TSRMLS_C1(E));
  963                 } else if (zend_is_compiling(TSRMLS_C0)) {
  964                     TSRMLS_FETCH1_NOP(C);
  965                     amod_name = zend_get_compiled_filename(TSRMLS_C1(C));
  966                     aline_no = zend_get_compiled_lineno(TSRMLS_C1(C));
  967                 } else {
  968                     amod_name = NULL;
  969                     aline_no = 0;
  970                 }
  971             }
  972             body.line_no = aline_no;
  973             body.mod_no = DBG_FINDMODULE_ADD(amod_name);
  974             body.imod_name = dbg_packet_add_string(&DBG(logpack), amod_name);
  975             body.ilog = dbg_packet_add_stringlen(&DBG(logpack), log, len);
  976             dbg_packet_add_frame(&DBG(logpack), FRAME_LOG, &body, sizeof(body));
  977             if (DBG(logpack).size >= 16300 || DBG(logpack).lastrawid > 512 || type == LT_FATALERROR)
  978                 dbg_flush_log(TSRMLS_C2(DBG, E));
  979         } else { /* non-detailed output */
  980             int newlen;
  981             if (!DBG(output_str_nd)) {
  982                 newlen = len;
  983                 DBG(output_str_nd_len) = 0;
  984                 DBG(output_str_nd_limit) = (len > 8192) ? len : 8192;
  985                 DBG(output_str_nd) = emalloc(DBG(output_str_nd_limit));
  986             } else {
  987                 newlen = DBG(output_str_nd_len) + len;
  988             }
  989             if (newlen > DBG(output_str_nd_limit)) {
  990                 DBG(output_str_nd_limit) = (newlen + 4096) & (~4095);
  991                 DBG(output_str_nd) = erealloc(DBG(output_str_nd), DBG(output_str_nd_limit));
  992             }
  993             if (DBG(output_str_nd)) {
  994                 memcpy((char*)DBG(output_str_nd)+DBG(output_str_nd_len), log, len);
  995             } else {
  996                 newlen = 0;
  997                 DBG(output_str_nd_limit) = 0;
  998             }
  999             DBG(output_str_nd_len) = newlen;
 1000             if (newlen > 4096 || type == LT_FATALERROR) 
 1001                 dbg_flush_log(TSRMLS_C2(DBG, E));
 1002         }
 1003         ret_val = 1;
 1004     }
 1005     return ret_val;
 1006 }
 1007 
 1008 void add_session_cookie(TSRMLS_D2(DBG, S)) {
 1009     char buf[256];
 1010     if (SG(headers_sent) || SG(request_info).no_headers) return;
 1011     if (DBG(cfgprm_session_cookie) && 
 1012         !DBG(session_cookie_added) && 
 1013         DBG(req_sess_var) != NULL && 
 1014         strlen(DBG(req_sess_var)) != 0) {
 1015         DBG(session_cookie_added) = 1;
 1016         snprintf(buf, sizeof(buf) - 1, "Set-Cookie: %s;path=/;", DBG(req_sess_var));
 1017         buf[sizeof(buf) - 1] = 0;
 1018         DBG_TRACE(("adding '%s'\n", buf));
 1019         ADD_HDR(buf);
 1020     }
 1021 }
 1022 
 1023 int hex2digits_toi(char *s2) {
 1024     int ret_val;
 1025     int c;
 1026 
 1027     c = s2[0];
 1028     if (isupper(c))
 1029         c = tolower(c);
 1030     ret_val = ((c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10)) * 16;
 1031 
 1032     c = s2[1];
 1033     if (isupper(c))
 1034         c = tolower(c);
 1035     ret_val += (c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10);
 1036 
 1037     return (ret_val);
 1038 }
 1039 
 1040 int urldecode(char *str, int len) {
 1041     char *dest = str, *src = str;
 1042 
 1043     while (len--) {
 1044         if (*src == '+')
 1045             *dest = ' ';
 1046         else if (*src == '%' && len >= 2 && isxdigit((int) *(src + 1)) && isxdigit((int) *(src + 2))) {
 1047             *dest = (char) hex2digits_toi(src + 1);
 1048             src += 2;
 1049             len -= 2;
 1050         } else
 1051             *dest = *src;
 1052         src++;
 1053         dest++;
 1054     }
 1055     *dest = '\0';
 1056     return (dest - str);
 1057 }
 1058 
 1059 int parse_session_request(char *str, int len, char delimiter TSRMLS_DC1(DBG)) {
 1060     char *psid, *phost, *pport = NULL, *p;
 1061     int nsid, nhost, nport;
 1062     char numbuf[10], reqbuf[512];
 1063 
 1064 
 1065     DBG_TRACE(("parse_session_request '%s'\n", SON(str)));
 1066     if (str == NULL || len < 1) return 0;
 1067 
 1068     if (len > sizeof(reqbuf)-1) len = sizeof(reqbuf)-1;
 1069     strncpy(reqbuf, str, len);
 1070     reqbuf[len] = 0;
 1071     p = strchr(reqbuf, delimiter);
 1072     if (p) p[0] = 0;
 1073     len = urldecode(reqbuf, strlen(reqbuf));
 1074 
 1075     str = reqbuf;
 1076 
 1077     DBG_TRACE(("req '%s'\n", SON(str)));
 1078 
 1079     if (DBG(req_sess_var)) {
 1080         efree(DBG(req_sess_var));
 1081         DBG(req_sess_var) = NULL;
 1082     }
 1083     if (DBG(req_client_ip_address)) {
 1084         efree(DBG(req_client_ip_address));
 1085         DBG(req_client_ip_address) = NULL;
 1086     }
 1087     if (DBG(session_id)) {
 1088         efree(DBG(session_id));
 1089         DBG(session_id) = NULL;
 1090     }
 1091 
 1092     
 1093     phost = strchr(str, '@');
 1094     if (phost!=NULL) {
 1095         psid = str;
 1096         nsid = phost - psid;
 1097         phost++;
 1098         pport = strchr(phost, ':');
 1099         if (pport) {
 1100             nhost = pport - phost;
 1101             if ((p = strchr(phost, ',')) != NULL && p < pport) {
 1102                 nhost = p - phost;
 1103             }
 1104             pport++;
 1105             nport = strlen(pport);
 1106         } else {
 1107             nhost = strlen(phost);
 1108             nport = 0;
 1109         }
 1110         DBG(req_client_ip_address) = nhost > 0 ? estrndup(phost, nhost) : NULL;
 1111         DBG(session_id) = estrndup(psid, nsid);
 1112         if (pport != NULL && nport > 0) {
 1113             if (nport >= sizeof(numbuf)) nport = sizeof(numbuf) - 1;
 1114             strncpy(numbuf, pport, nport);
 1115             numbuf[nport]='\0';
 1116             DBG(req_client_port) = atol(numbuf);
 1117             if (DBG(req_client_port) <= 0 || DBG(req_client_port) > 32767) DBG(req_client_port) = DEFAULT_PORT;
 1118         }
 1119         snprintf(reqbuf, sizeof(reqbuf), DBGSESSVAR "=%s@%s:%d", DBG(session_id), DBG(req_client_ip_address), DBG(req_client_port));
 1120         DBG(req_sess_var) = estrdup(reqbuf);
 1121         DBG_TRACE(("parsed req IP=%s, PORT=%ld (%s), SID=%s\n", SON(DBG(req_client_ip_address)), DBG(req_client_port), numbuf, SON(DBG(session_id))));
 1122     } else {
 1123         DBG(session_id) = estrndup(str, len);
 1124         DBG(req_client_port) = 0;
 1125         snprintf(reqbuf, sizeof(reqbuf), DBGSESSVAR "=%s", DBG(session_id));
 1126         DBG(req_sess_var) = estrdup(reqbuf);
 1127         DBG_TRACE(("parsed req SID=%s\n", SON(DBG(session_id))));
 1128         return -1;
 1129     }
 1130     return 1;
 1131 }
 1132 
 1133 int chk_session_request(char *str, int len, char delimiter TSRMLS_DC1(DBG)) {
 1134     char *p, *e;
 1135     int ret_val;
 1136 
 1137     if (str == NULL) {
 1138         DBG_TRACE(("chk_session_request NULL\n"));
 1139         return 0;
 1140     }
 1141     DBG_TRACE(("chk_session_request '%s'\n", SON(str)));
 1142     if (len == -1) len = strlen(str);
 1143     p = str;
 1144     e = p + len;
 1145     while (p < e) {
 1146         while (p < e && (p[0] == ' ' || p[0] == '\t')) p++;
 1147         if ((e-p) < sizeof(DBGSESSVAR)-1) break;
 1148         if (strncmp(p, DBGSESSVAR, sizeof(DBGSESSVAR)-1) == 0) {
 1149             p += sizeof(DBGSESSVAR)-1;
 1150             if (p >= e-1) return 0;
 1151             if (*p == '=') {
 1152                 p++;
 1153                 ret_val = parse_session_request(p, e-p, delimiter TSRMLS_CC1(DBG));
 1154                 DBG_TRACE(("parsed result=%d\n", ret_val));
 1155                 return (ret_val);
 1156             }
 1157         }
 1158         while (p < e && p[0] != delimiter) p++;
 1159         if (p[0] != delimiter) return 0;
 1160         p++;
 1161     }
 1162     return 0;
 1163 }
 1164 
 1165 int dbg_send_sid(TSRMLS_D2(DBG, E)) {
 1166     dbg_packet pack;
 1167     int ret_val;
 1168 
 1169     if (!dbg_packet_new(&pack)) return 0;
 1170 
 1171     ret_val = handler_add_sid_reply(&pack, NULL, NULL TSRMLS_CC2(DBG, E));
 1172     if (ret_val) ret_val = dbg_send_command(DBGC_SID, &pack, 0 TSRMLS_CC2(DBG, E));
 1173     
 1174     dbg_packet_free(&pack);
 1175     return ret_val;
 1176 }
 1177 
 1178 
 1179 int dbg_start_session(SESSTYPE sesstype TSRMLS_DC3(DBG, E, S)) {
 1180     int ret_val;
 1181 
 1182     DBG_TRACE(("dbg_start_session req %d\n", sesstype));
 1183 
 1184 
 1185     if ((DBGF(DBGF_REJECTIONFOUND) && (sesstype != DBG_EMB)) ||
 1186         DBG(debug_socket) != 0 ||
 1187         DBG(is_failed_connection) ||
 1188         !DBG(cfgprm_enabled) ||
 1189         DBG(deactivate_inprocess)) return ESESS_NOREASON;
 1190 
 1191     add_session_cookie(TSRMLS_C2(DBG, S));
 1192     DBG(debug_socket) = create_debugger_socket(sesstype TSRMLS_CC2(DBG, E));
 1193     DBG(is_failed_connection) = (DBG(debug_socket) > 0) ? 0:1;
 1194     if (DBG(is_failed_connection)) return DBG(debug_socket);
 1195 
 1196     DBG(debugger_flags) = DBGF_STARTED;
 1197     DBG(sesstype) = sesstype;
 1198 
 1199     ret_val = dbg_send_sid(TSRMLS_C2(DBG, E));
 1200     if (ret_val > 0)
 1201         ret_val = dbg_send_std_action(DBGC_STARTUP, 0 TSRMLS_CC2(DBG, E));
 1202     if (ret_val > 0 && DBG(session_id) && strlen(DBG(session_id)) > 0) {
 1203         if (DBG(cfgprm_session_nocache) &&
 1204             !SG(headers_sent) && 
 1205             !SG(request_info).no_headers) {
 1206             ADD_HDR("Expires: Thu, 19 Nov 1981 08:52:00 GMT");
 1207             ADD_HDR("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
 1208             ADD_HDR("Pragma: no-cache");
 1209         }
 1210     }
 1211 
 1212     DBG_TRACE(("dbg_start_session ret_val=%d\n", ret_val));
 1213     return ret_val;
 1214 }
 1215 
 1216 int dbg_stop_session(TSRMLS_D2(DBG, E)) {
 1217     int ret_val = 0;
 1218     
 1219     if (!DBG(is_failed_connection) && DBG(debug_socket) > 0) {
 1220         ret_val = dbg_send_std_action(DBGC_END, 0 TSRMLS_CC2(DBG, E));
 1221     }
 1222     DBG(debugger_flags) = DBGF_FINISHED;
 1223     DBG(sesstype) = 0;
 1224     return ret_val;
 1225 }
 1226 
 1227 
 1228 inline int dbg_checkpausereq(TSRMLS_D1(DBG)) {
 1229     fd_set rset, eset;
 1230     struct timeval timeout;
 1231     int ret_val;
 1232     dbg_header_struct hdr;
 1233     dbg_packet pack;
 1234     int socket = DBG(debug_socket);
 1235 
 1236     if (socket <= 0) {
 1237         return 0;
 1238     }
 1239     FD_ZERO(&rset);
 1240     FD_SET((unsigned int)socket, &rset);
 1241     FD_ZERO(&eset);
 1242     FD_SET((unsigned int)socket, &eset);
 1243     timeout.tv_sec = 0;
 1244     timeout.tv_usec = 0;
 1245     ret_val = select(socket + 1, &rset, NULL, &eset, &timeout);
 1246     if (ret_val != 1 || !FD_ISSET((unsigned int)socket, &rset)) 
 1247         return 0;
 1248     
 1249     if (!dbg_packet_new(&pack)) return 0;
 1250     ret_val = dbg_packet_recv(&hdr, &pack, socket, 0);
 1251     if (ret_val > 0) {
 1252         ret_val = (hdr.cmd == DBGC_PAUSE);
 1253     }
 1254     dbg_packet_free(&pack);
 1255     return ret_val;
 1256 }
 1257