PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/mysqlnd - mysqlnd_bt.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 0 95 0.0 %
Date: 2014-04-10 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 5                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 2006-2014 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Authors: Georg Richter <georg@mysql.com>                             |
      16             :   |          Andrey Hristov <andrey@mysql.com>                           |
      17             :   |          Ulf Wendel <uwendel@mysql.com>                              |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id: mysqlnd_debug.c 309303 2011-03-16 12:42:59Z andrey $ */
      22             : 
      23             : #include "php.h"
      24             : #include "Zend/zend_builtin_functions.h"
      25             : 
      26             : /* Follows code borrowed from zend_builtin_functions.c because the functions there are static */
      27             : 
      28             : #if MYSQLND_UNICODE
      29             : /* {{{ gettraceasstring() macros */
      30             : #define TRACE_APPEND_CHR(chr)                                            \
      31             :         *str = (char*)erealloc(*str, *len + 1 + 1);                          \
      32             :         (*str)[(*len)++] = chr
      33             : 
      34             : #define TRACE_APPEND_STRL(val, vallen)                                   \
      35             :         {                                                                    \
      36             :                 int l = vallen;                                                  \
      37             :                 *str = (char*)erealloc(*str, *len + l + 1);                      \
      38             :                 memcpy((*str) + *len, val, l);                                   \
      39             :                 *len += l;                                                       \
      40             :         }
      41             : 
      42             : #define TRACE_APPEND_USTRL(val, vallen) \
      43             :         { \
      44             :                 zval tmp, copy; \
      45             :                 int use_copy; \
      46             :                 ZVAL_UNICODEL(&tmp, val, vallen, 1); \
      47             :                 zend_make_printable_zval(&tmp, &copy, &use_copy); \
      48             :                 TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
      49             :                 zval_dtor(&copy); \
      50             :                 zval_dtor(&tmp); \
      51             :         }
      52             : 
      53             : #define TRACE_APPEND_ZVAL(zv) \
      54             :         if (Z_TYPE_P((zv)) == IS_UNICODE) { \
      55             :                 zval copy; \
      56             :                 int use_copy; \
      57             :                 zend_make_printable_zval((zv), &copy, &use_copy); \
      58             :                 TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
      59             :                 zval_dtor(&copy); \
      60             :         } else { \
      61             :                 TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \
      62             :         }
      63             : 
      64             : #define TRACE_APPEND_STR(val)                                            \
      65             :         TRACE_APPEND_STRL(val, sizeof(val)-1)
      66             : 
      67             : #define TRACE_APPEND_KEY(key)                                            \
      68             :         if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
      69             :                 if (Z_TYPE_PP(tmp) == IS_UNICODE) { \
      70             :                         zval copy; \
      71             :                         int use_copy; \
      72             :                         zend_make_printable_zval(*tmp, &copy, &use_copy); \
      73             :                         TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
      74             :                         zval_dtor(&copy); \
      75             :                 } else { \
      76             :                 TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \
      77             :                 } \
      78             :         }
      79             : /* }}} */
      80             : 
      81             : 
      82             : /* {{{ mysqlnd_build_trace_args */
      83             : static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
      84             : {
      85             :         char **str;
      86             :         int *len;
      87             : 
      88             :         str = va_arg(args, char**);
      89             :         len = va_arg(args, int*);
      90             : 
      91             :         /* the trivial way would be to do:
      92             :          * conver_to_string_ex(arg);
      93             :          * append it and kill the now tmp arg.
      94             :          * but that could cause some E_NOTICE and also damn long lines.
      95             :          */
      96             : 
      97             :         switch (Z_TYPE_PP(arg)) {
      98             :                 case IS_NULL:
      99             :                         TRACE_APPEND_STR("NULL, ");
     100             :                         break;
     101             :                 case IS_STRING: {
     102             :                         int l_added;
     103             :                         TRACE_APPEND_CHR('\'');
     104             :                         if (Z_STRLEN_PP(arg) > 15) {
     105             :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
     106             :                                 TRACE_APPEND_STR("...', ");
     107             :                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
     108             :                         } else {
     109             :                                 l_added = Z_STRLEN_PP(arg);
     110             :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
     111             :                                 TRACE_APPEND_STR("', ");
     112             :                                 l_added += 3 + 1;
     113             :                         }
     114             :                         while (--l_added) {
     115             :                                 if ((unsigned char)(*str)[*len - l_added] < 32) {
     116             :                                         (*str)[*len - l_added] = '?';
     117             :                                 }
     118             :                         }
     119             :                         break;
     120             :                 }
     121             :                 case IS_UNICODE: {
     122             :                         int l_added;
     123             : 
     124             :                         /*
     125             :                          * We do not want to apply current error mode here, since
     126             :                          * zend_make_printable_zval() uses output encoding converter.
     127             :                          * Temporarily set output encoding converter to escape offending
     128             :                          * chars with \uXXXX notation.
     129             :                          */
     130             :                         zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA);
     131             :                         TRACE_APPEND_CHR('\'');
     132             :                         if (Z_USTRLEN_PP(arg) > 15) {
     133             :                                 TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15);
     134             :                                 TRACE_APPEND_STR("...', ");
     135             :                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
     136             :                         } else {
     137             :                                 l_added = Z_USTRLEN_PP(arg);
     138             :                                 TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added);
     139             :                                 TRACE_APPEND_STR("', ");
     140             :                                 l_added += 3 + 1;
     141             :                         }
     142             :                         /*
     143             :                          * Reset output encoding converter error mode.
     144             :                          */
     145             :                         zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode));
     146             :                         while (--l_added) {
     147             :                                 if ((unsigned char)(*str)[*len - l_added] < 32) {
     148             :                                         (*str)[*len - l_added] = '?';
     149             :                                 }
     150             :                         }
     151             :                         break;
     152             :                 }
     153             :                 case IS_BOOL:
     154             :                         if (Z_LVAL_PP(arg)) {
     155             :                                 TRACE_APPEND_STR("true, ");
     156             :                         } else {
     157             :                                 TRACE_APPEND_STR("false, ");
     158             :                         }
     159             :                         break;
     160             :                 case IS_RESOURCE:
     161             :                         TRACE_APPEND_STR("Resource id #");
     162             :                         /* break; */
     163             :                 case IS_LONG: {
     164             :                         long lval = Z_LVAL_PP(arg);
     165             :                         char s_tmp[MAX_LENGTH_OF_LONG + 1];
     166             :                         int l_tmp = zend_sprintf(s_tmp, "%ld", lval);  /* SAFE */
     167             :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
     168             :                         TRACE_APPEND_STR(", ");
     169             :                         break;
     170             :                 }
     171             :                 case IS_DOUBLE: {
     172             :                         double dval = Z_DVAL_PP(arg);
     173             :                         char *s_tmp;
     174             :                         int l_tmp;
     175             : 
     176             :                         s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
     177             :                         l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);  /* SAFE */
     178             :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
     179             :                         /* %G already handles removing trailing zeros from the fractional part, yay */
     180             :                         efree(s_tmp);
     181             :                         TRACE_APPEND_STR(", ");
     182             :                         break;
     183             :                 }
     184             :                 case IS_ARRAY:
     185             :                         TRACE_APPEND_STR("Array, ");
     186             :                         break;
     187             :                 case IS_OBJECT: {
     188             :                         zval tmp;
     189             :                         zstr class_name;
     190             :                         zend_uint class_name_len;
     191             :                         int dup;
     192             : 
     193             :                         TRACE_APPEND_STR("Object(");
     194             : 
     195             :                         dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
     196             : 
     197             :                         ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1);
     198             :                         convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv)));
     199             :                         TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp));
     200             :                         zval_dtor(&tmp);
     201             : 
     202             :                         if(!dup) {
     203             :                                 efree(class_name.v);
     204             :                         }
     205             : 
     206             :                         TRACE_APPEND_STR("), ");
     207             :                         break;
     208             :                 }
     209             :                 default:
     210             :                         break;
     211             :         }
     212             :         return ZEND_HASH_APPLY_KEEP;
     213             : }
     214             : /* }}} */
     215             : 
     216             : 
     217             : static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
     218             : {
     219             :         char *s_tmp, **str;
     220             :         int *len, *num;
     221             :         long line;
     222             :         HashTable *ht = Z_ARRVAL_PP(frame);
     223             :         zval **file, **tmp;
     224             :         uint * level;
     225             : 
     226             :         level = va_arg(args, uint *);
     227             :         str = va_arg(args, char**);
     228             :         len = va_arg(args, int*);
     229             :         num = va_arg(args, int*);
     230             : 
     231             :         if (!*level) {
     232             :                 return ZEND_HASH_APPLY_KEEP;
     233             :         }
     234             :         --*level;
     235             : 
     236             :         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
     237             :         sprintf(s_tmp, "#%d ", (*num)++);
     238             :         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     239             :         efree(s_tmp);
     240             :         if (zend_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
     241             :                 if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
     242             :                         line = Z_LVAL_PP(tmp);
     243             :                 } else {
     244             :                         line = 0;
     245             :                 }
     246             :                 TRACE_APPEND_ZVAL(*file);
     247             :                 s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1);
     248             :                 sprintf(s_tmp, "(%ld): ", line);
     249             :                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     250             :                 efree(s_tmp);
     251             :         } else {
     252             :                 TRACE_APPEND_STR("[internal function]: ");
     253             :         }
     254             :         TRACE_APPEND_KEY("class");
     255             :         TRACE_APPEND_KEY("type");
     256             :         TRACE_APPEND_KEY("function");
     257             :         TRACE_APPEND_CHR('(');
     258             :         if (zend_ascii_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
     259             :                 int last_len = *len;
     260             :                 zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
     261             :                 if (last_len != *len) {
     262             :                         *len -= 2; /* remove last ', ' */
     263             :                 }
     264             :         }
     265             :         TRACE_APPEND_STR(")\n");
     266             :         return ZEND_HASH_APPLY_KEEP;
     267             : }
     268             : /* }}} */
     269             : 
     270             : 
     271             : #else /* PHP 5*/
     272             : 
     273             : 
     274             : /* {{{ gettraceasstring() macros */
     275             : #define TRACE_APPEND_CHR(chr)                                            \
     276             :         *str = (char*)erealloc(*str, *len + 1 + 1);                          \
     277             :         (*str)[(*len)++] = chr
     278             : 
     279             : #define TRACE_APPEND_STRL(val, vallen)                                   \
     280             :         {                                                                    \
     281             :                 int l = vallen;                                                  \
     282             :                 *str = (char*)erealloc(*str, *len + l + 1);                      \
     283             :                 memcpy((*str) + *len, val, l);                                   \
     284             :                 *len += l;                                                       \
     285             :         }
     286             : 
     287             : #define TRACE_APPEND_STR(val)                                            \
     288             :         TRACE_APPEND_STRL(val, sizeof(val)-1)
     289             : 
     290             : #define TRACE_APPEND_KEY(key)                                            \
     291             :         if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
     292             :             TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \
     293             :         }
     294             : 
     295             : /* }}} */
     296             : 
     297             : 
     298           0 : static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
     299             : {
     300             :         char **str;
     301             :         int *len;
     302             : 
     303           0 :         str = va_arg(args, char**);
     304           0 :         len = va_arg(args, int*);
     305             : 
     306             :         /* the trivial way would be to do:
     307             :          * conver_to_string_ex(arg);
     308             :          * append it and kill the now tmp arg.
     309             :          * but that could cause some E_NOTICE and also damn long lines.
     310             :          */
     311             : 
     312           0 :         switch (Z_TYPE_PP(arg)) {
     313             :                 case IS_NULL:
     314           0 :                         TRACE_APPEND_STR("NULL, ");
     315           0 :                         break;
     316             :                 case IS_STRING: {
     317             :                         int l_added;
     318           0 :                         TRACE_APPEND_CHR('\'');
     319           0 :                         if (Z_STRLEN_PP(arg) > 15) {
     320           0 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
     321           0 :                                 TRACE_APPEND_STR("...', ");
     322           0 :                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
     323             :                         } else {
     324           0 :                                 l_added = Z_STRLEN_PP(arg);
     325           0 :                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
     326           0 :                                 TRACE_APPEND_STR("', ");
     327           0 :                                 l_added += 3 + 1;
     328             :                         }
     329           0 :                         while (--l_added) {
     330           0 :                                 if ((*str)[*len - l_added] < 32) {
     331           0 :                                         (*str)[*len - l_added] = '?';
     332             :                                 }
     333             :                         }
     334           0 :                         break;
     335             :                 }
     336             :                 case IS_BOOL:
     337           0 :                         if (Z_LVAL_PP(arg)) {
     338           0 :                                 TRACE_APPEND_STR("true, ");
     339             :                         } else {
     340           0 :                                 TRACE_APPEND_STR("false, ");
     341             :                         }
     342           0 :                         break;
     343             :                 case IS_RESOURCE:
     344           0 :                         TRACE_APPEND_STR("Resource id #");
     345             :                         /* break; */
     346             :                 case IS_LONG: {
     347           0 :                         long lval = Z_LVAL_PP(arg);
     348             :                         char s_tmp[MAX_LENGTH_OF_LONG + 1];
     349           0 :                         int l_tmp = zend_sprintf(s_tmp, "%ld", lval);  /* SAFE */
     350           0 :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
     351           0 :                         TRACE_APPEND_STR(", ");
     352           0 :                         break;
     353             :                 }
     354             :                 case IS_DOUBLE: {
     355           0 :                         double dval = Z_DVAL_PP(arg);
     356             :                         char *s_tmp;
     357             :                         int l_tmp;
     358             : 
     359           0 :                         s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
     360           0 :                         l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);  /* SAFE */
     361           0 :                         TRACE_APPEND_STRL(s_tmp, l_tmp);
     362             :                         /* %G already handles removing trailing zeros from the fractional part, yay */
     363           0 :                         efree(s_tmp);
     364           0 :                         TRACE_APPEND_STR(", ");
     365           0 :                         break;
     366             :                 }
     367             :                 case IS_ARRAY:
     368           0 :                         TRACE_APPEND_STR("Array, ");
     369           0 :                         break;
     370             :                 case IS_OBJECT: {
     371             :                         char *class_name;
     372             :                         zend_uint class_name_len;
     373             :                         int dupl;
     374             : 
     375           0 :                         TRACE_APPEND_STR("Object(");
     376             : 
     377           0 :                         dupl = zend_get_object_classname(*arg, (const char **)&class_name, &class_name_len TSRMLS_CC);
     378             : 
     379           0 :                         TRACE_APPEND_STRL(class_name, class_name_len);
     380           0 :                         if (!dupl) {
     381           0 :                                 efree(class_name);
     382             :                         }
     383             : 
     384           0 :                         TRACE_APPEND_STR("), ");
     385             :                         break;
     386             :                 }
     387             :                 default:
     388             :                         break;
     389             :         }
     390           0 :         return ZEND_HASH_APPLY_KEEP;
     391             : }
     392             : /* }}} */
     393             : 
     394           0 : static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
     395             : {
     396             :         char *s_tmp, **str;
     397             :         int *len, *num;
     398             :         long line;
     399           0 :         HashTable *ht = Z_ARRVAL_PP(frame);
     400             :         zval **file, **tmp;
     401             :         uint * level;
     402             : 
     403           0 :         level = va_arg(args, uint *);
     404           0 :         str = va_arg(args, char**);
     405           0 :         len = va_arg(args, int*);
     406           0 :         num = va_arg(args, int*);
     407             : 
     408           0 :         if (!*level) {
     409           0 :                 return ZEND_HASH_APPLY_KEEP;
     410             :         }
     411           0 :         --*level;
     412             : 
     413           0 :         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
     414           0 :         sprintf(s_tmp, "#%d ", (*num)++);
     415           0 :         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     416           0 :         efree(s_tmp);
     417           0 :         if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
     418           0 :                 if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
     419           0 :                         line = Z_LVAL_PP(tmp);
     420             :                 } else {
     421           0 :                         line = 0;
     422             :                 }
     423           0 :                 s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
     424           0 :                 sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
     425           0 :                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     426           0 :                 efree(s_tmp);
     427             :         } else {
     428           0 :                 TRACE_APPEND_STR("[internal function]: ");
     429             :         }
     430           0 :         TRACE_APPEND_KEY("class");
     431           0 :         TRACE_APPEND_KEY("type");
     432           0 :         TRACE_APPEND_KEY("function");
     433           0 :         TRACE_APPEND_CHR('(');
     434           0 :         if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
     435           0 :                 int last_len = *len;
     436           0 :                 zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
     437           0 :                 if (last_len != *len) {
     438           0 :                         *len -= 2; /* remove last ', ' */
     439             :                 }
     440             :         }
     441           0 :         TRACE_APPEND_STR(")\n");
     442           0 :         return ZEND_HASH_APPLY_KEEP;
     443             : }
     444             : /* }}} */
     445             : #endif
     446             : 
     447             : 
     448           0 : PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC)
     449             : {
     450             :         zval *trace;
     451           0 :         char *res = estrdup(""), **str = &res, *s_tmp;
     452           0 :         int res_len = 0, *len = &res_len, num = 0;
     453           0 :         if (max_levels == 0) {
     454           0 :                 max_levels = 99999;
     455             :         }
     456             : 
     457           0 :         MAKE_STD_ZVAL(trace);
     458           0 :         zend_fetch_debug_backtrace(trace, 0, 0, 0 TSRMLS_CC);
     459             : 
     460           0 :         zend_hash_apply_with_arguments(Z_ARRVAL_P(trace) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_string, 4, &max_levels, str, len, &num);
     461           0 :         zval_ptr_dtor(&trace);
     462             : 
     463           0 :         if (max_levels) {
     464           0 :                 s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
     465           0 :                 sprintf(s_tmp, "#%d {main}", num);
     466           0 :                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
     467           0 :                 efree(s_tmp);
     468             :         }
     469             : 
     470           0 :         res[res_len] = '\0';
     471           0 :         *length = res_len;
     472             : 
     473           0 :         return res;
     474             : }
     475             : 
     476             : 
     477             : /*
     478             :  * Local variables:
     479             :  * tab-width: 4
     480             :  * c-basic-offset: 4
     481             :  * End:
     482             :  * vim600: noet sw=4 ts=4 fdm=marker
     483             :  * vim<600: noet sw=4 ts=4
     484             :  */

Generated by: LCOV version 1.10

Generated at Thu, 10 Apr 2014 08:53:52 +0000 (8 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.