Bug Summary

File:rootdir/src/webserver/src/php_core_lib.cpp
Warning:line 453, column 3
This statement is never executed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name php_core_lib.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src/webserver/src -fcoverage-compilation-dir=/rootdir/src/webserver/src -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I ../../.. -I ../.. -I ../../../src -I ../../../src/libs -I ../../../src/include -D USE_WX_EXTENSIONS -D WITH_LIBPNG -D HAVE_BFD -I /usr/lib/x86_64-linux-gnu/wx/include/gtk3-unicode-3.2 -I /usr/include/wx-3.2 -D _FILE_OFFSET_BITS=64 -D WXUSINGDLL -D __WXGTK__ -D wxUSE_GUI=0 -D WEBSERVERDIR="/usr/share/amule/webserver" -D YY_NO_INPUT -I /usr/include/upnp -D ENABLE_UPNP=1 -I /usr/include/libpng16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-register -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-01-17-081402-14897-1 -x c++ php_core_lib.cpp
1//
2// This file is part of the aMule Project.
3
4// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5// Copyright (c) 2005-2011 Froenchenko Leonid ( lfroen@gmail.com / http://www.amule.org )
6//
7// Any parts of this program derived from the xMule, lMule or eMule project,
8// or contributed by third-party developers are copyrighted by their
9// respective authors.
10//
11// This program is free software; you can redistribute it and/or modify
12// it under the terms of the GNU General Public License as published by
13// the Free Software Foundation; either version 2 of the License, or
14// (at your option) any later version.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24//
25
26#include "config.h"
27
28#include <string> // Do_not_auto_remove (g++-4.0.1)
29
30#ifdef HAVE_SYS_TYPES_H1
31# include <sys/types.h>
32#endif
33
34#ifdef PHP_STANDALONE_EN
35# include <map>
36# include <string>
37# include <list>
38# include <regex.h>
39#else
40# include "WebServer.h"
41# include <ec/cpp/ECSpecialTags.h>
42# include <wx/regex.h>
43# include <wx/datetime.h>
44#endif
45
46#include "php_syntree.h"
47#include "php_core_lib.h"
48#include <stdarg.h>
49
50#ifdef ENABLE_NLS1
51#include <libintl.h>
52#endif
53
54/*
55 * Built-in php functions. Those are both library and core internals.
56 *
57 * I'm not going event to get near to what Zend provide, but
58 * at least base things must be here
59 */
60
61/*
62 * Print info about variable: php var_dump()
63 */
64void php_var_dump(PHP_VALUE_NODE *node, int ident, int ref)
65{
66 for(int i = 0; i < ident;i++) {
67 printf("\t");
68 }
69 if ( ref ) printf("&");
70 switch(node->type) {
71 case PHP_VAL_BOOL: printf("bool(%s)\n", node->int_val ? "true" : "false"); break;
72 case PHP_VAL_INT: printf("int(%" PRIu64"l" "u" ")\n", node->int_val); break;
73 case PHP_VAL_FLOAT: printf("float(%f)\n", node->float_val); break;
74 case PHP_VAL_STRING: printf("string(%d) \"%s\"\n", (int)strlen(node->str_val), node->str_val); break;
75 case PHP_VAL_OBJECT: printf("Object(%s)\n", node->obj_val.class_name); break;
76 case PHP_VAL_ARRAY: {
77 int arr_size = array_get_size(node);
78 printf("array(%d) {\n", arr_size);
79 for(int i = 0; i < arr_size;i++) {
80 const std::string &curr_key = array_get_ith_key(node, i);
81 PHP_VAR_NODE *curr_val = array_get_by_str_key(node, curr_key);
82 printf("\t[%s]=>\n", curr_key.c_str());
83 php_var_dump(&curr_val->value, ident+1, curr_val->ref_count > 1);
84 }
85 for(int i = 0; i < ident;i++) {
86 printf("\t");
87 }
88 printf("}\n");
89 break;
90 }
91 case PHP_VAL_NONE: printf("NULL\n"); break;
92 case PHP_VAL_VAR_NODE:
93 case PHP_VAL_INT_DATA: assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
; break;
94 }
95}
96
97void php_native_var_dump(PHP_VALUE_NODE *)
98{
99 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
100 if ( si ) {
101 assert((si->type == PHP_SCOPE_VAR)||(si->type == PHP_SCOPE_PARAM))(static_cast <bool> ((si->type == PHP_SCOPE_VAR)||(si
->type == PHP_SCOPE_PARAM)) ? void (0) : __assert_fail ("(si->type == PHP_SCOPE_VAR)||(si->type == PHP_SCOPE_PARAM)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
102 php_var_dump(&si->var->value, 0, 0);
103 } else {
104 php_report_error(PHP_ERROR, "Invalid or missing argument");
105 }
106}
107
108
109/*
110 * Sorting stl-way requires operator ">"
111 */
112class SortElem {
113 public:
114 SortElem() {}
115 SortElem(PHP_VAR_NODE *p) { obj = p; }
116
117 PHP_VAR_NODE *obj;
118 static PHP_SYN_FUNC_DECL_NODE *callback;
119
120 friend bool operator<(const SortElem &o1, const SortElem &o2);
121};
122
123PHP_SYN_FUNC_DECL_NODE *SortElem::callback = 0;
124
125bool operator<(const SortElem &o1, const SortElem &o2)
126{
127 PHP_VALUE_NODE result;
128
129 value_value_assign(&SortElem::callback->params[0].si_var->var->value, &o1.obj->value);
130 value_value_assign(&SortElem::callback->params[1].si_var->var->value, &o2.obj->value);
131
132 switch_push_scope_table((PHP_SCOPE_TABLE_TYPE *)SortElem::callback->scope);
133
134 //
135 // params passed by-value, all & notations ignored
136 //
137 result.type = PHP_VAL_NONE;
138 php_execute(SortElem::callback->code, &result);
139 cast_value_dnum(&result);
140 //
141 // restore stack, free arg list
142 //
143 switch_pop_scope_table(0);
144
145 value_value_free(&SortElem::callback->params[0].si_var->var->value);
146 value_value_free(&SortElem::callback->params[1].si_var->var->value);
147
148 return result.int_val != 0;
149}
150
151void php_native_usort(PHP_VALUE_NODE *)
152{
153 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
154 if ( !si || (si->var->value.type != PHP_VAL_ARRAY)) {
155 php_report_error(PHP_ERROR, "Invalid or missing argument (array)");
156 return;
157 }
158 PHP_VAR_NODE *array = si->var;
159 si = get_scope_item(g_current_scope, "__param_1");
160 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
161 php_report_error(PHP_ERROR, "Invalid or missing argument (func name)");
162 return;
163 }
164 char *cmp_func_name = si->var->value.str_val;
165 si = get_scope_item(g_global_scope, cmp_func_name);
166 if ( !si || (si->type != PHP_SCOPE_FUNC)) {
167 php_report_error(PHP_ERROR, "Compare function [%s] not found", cmp_func_name);
168 return;
169 }
170 PHP_SYN_FUNC_DECL_NODE *func_decl = si->func->func_decl;
171
172 //
173 // usort invalidates keys, and sorts values
174 //
175 PHP_ARRAY_TYPE *arr_obj = (PHP_ARRAY_TYPE *)array->value.ptr_val;
176 //
177 // create vector of values
178 //
179 if ( arr_obj->array.empty() ) {
180 php_report_error(PHP_WARNING, "Sorting array of size 0");
181 return;
182 }
183
184 std::list<SortElem> sort_list;
185 for(PHP_ARRAY_ITER_TYPE i = arr_obj->array.begin(); i != arr_obj->array.end(); ++i) {
186 sort_list.push_back(SortElem(i->second));
187 }
188 SortElem::callback = func_decl;
189 sort_list.sort();
190
191 arr_obj->array.clear();
192 arr_obj->sorted_keys.clear();
193 unsigned int key = 0;
194 for(std::list<SortElem>::iterator i = sort_list.begin(); i != sort_list.end(); ++i) {
195 array_add_to_int_key(&array->value, key++, i->obj);
196 }
197
198}
199
200
201/*
202 * String functions
203 */
204void php_native_strlen(PHP_VALUE_NODE *result)
205{
206 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
207 if ( si ) {
208 PHP_VALUE_NODE *param = &si->var->value;
209 cast_value_str(param);
210 if ( result ) {
211 cast_value_dnum(result);
212 result->int_val = strlen(param->str_val);
213 }
214 } else {
215 php_report_error(PHP_ERROR, "Invalid or missing argument");
216 }
217}
218
219void php_native_count(PHP_VALUE_NODE *result)
220{
221 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
222 if ( si ) {
223 PHP_VALUE_NODE *param = &si->var->value;
224 if ( result ) {
225 cast_value_dnum(result);
226 if ( si->var->value.type != PHP_VAL_ARRAY ) {
227 result->int_val = 0;
228 } else {
229 result->int_val = array_get_size(param);
230 }
231 }
232 } else {
233 php_report_error(PHP_ERROR, "Invalid or missing argument");
234 }
235}
236
237void php_native_isset(PHP_VALUE_NODE *result)
238{
239 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
240 if ( si ) {
241 PHP_VALUE_NODE *param = &si->var->value;
242 cast_value_str(param);
243 if ( result ) {
244 cast_value_bool(result);
245 result->int_val = (si->var->value.type == PHP_VAL_NONE) ? 0 : 1;
246 }
247 } else {
248 php_report_error(PHP_ERROR, "Invalid or missing argument");
249 }
250}
251
252void php_native_substr(PHP_VALUE_NODE * /*result*/)
253{
254 PHP_SCOPE_ITEM *si_str = get_scope_item(g_current_scope, "__param_0");
255 PHP_VALUE_NODE *str = &si_str->var->value;
256 if ( si_str ) {
257 cast_value_str(str);
258 } else {
259 php_report_error(PHP_ERROR, "Invalid or missing argument 'str' for 'substr'");
260 return;
261 }
262 PHP_SCOPE_ITEM *si_start = get_scope_item(g_current_scope, "__param_1");
263 PHP_VALUE_NODE *start = &si_start->var->value;
264 if ( si_start ) {
265 cast_value_dnum(start);
266 } else {
267 php_report_error(PHP_ERROR, "Invalid or missing argument 'start' for 'substr'");
268 return;
269 }
270 // 3-rd is optional
271 PHP_SCOPE_ITEM *si_end = get_scope_item(g_current_scope, "__param_2");
272 PHP_VALUE_NODE end = { PHP_VAL_INT, { 0 } };
273 if ( si_end ) {
274 end = si_end->var->value;
275 }
276 cast_value_dnum(&end);
277
278
279}
280
281
282void php_native_split(PHP_VALUE_NODE *result)
283{
284 if ( result ) {
285 cast_value_array(result);
286 } else {
287 return;
288 }
289 PHP_VALUE_NODE *pattern, *string_to_split;
290 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
291 if ( si ) {
292 pattern = &si->var->value;
293 cast_value_str(pattern);
294 } else {
295 php_report_error(PHP_ERROR, "Invalid or missing argument: pattern");
296 return;
297 }
298 si = get_scope_item(g_current_scope, "__param_1");
299 if ( si ) {
300 string_to_split = &si->var->value;
301 cast_value_str(string_to_split);
302 } else {
303 php_report_error(PHP_ERROR, "Invalid or missing argument: string");
304 return;
305 }
306 si = get_scope_item(g_current_scope, "__param_2");
307 if ( si ) {
308 PHP_VALUE_NODE *split_limit = &si->var->value;
309 cast_value_dnum(split_limit);
310 } else {
311 php_report_error(PHP_ERROR, "Invalid or missing argument: string");
312 return;
313 }
314#ifdef PHP_STANDALONE_EN
315 regex_t preg;
316 int reg_result = regcomp(&preg, pattern->str_val, REG_EXTENDED);
317 if ( reg_result ) {
318 char error_buff[256];
319 regerror(reg_result, &preg, error_buff, sizeof(error_buff));
320 php_report_error(PHP_ERROR, "Failed in regcomp: %s", error_buff);
321#else
322 wxRegEx preg;
323 if (!preg.Compile(wxString(char2unicode(pattern->str_val)), wxRE_EXTENDED)) {
324 php_report_error(PHP_ERROR, "Failed in Compile of: %s", pattern->str_val);
325#endif
326 return;
327 }
328
329#ifdef PHP_STANDALONE_EN
330 size_t nmatch = strlen(string_to_split->str_val);
331 regmatch_t *pmatch = new regmatch_t[nmatch];
332#endif
333 char *str_2_match = string_to_split->str_val;
334 char *tmp_buff = new char[strlen(string_to_split->str_val)+1];
335
336 while ( 1 ) {
337// printf("matching: %s\n", str_2_match);
338#ifdef PHP_STANDALONE_EN
339 reg_result = regexec(&preg, str_2_match, nmatch, pmatch, 0);
340 if ( reg_result ) {
341#else
342 if (!preg.Matches(wxString(char2unicode(str_2_match)))) {
343#endif
344 // no match
345 break;
346 }
347#ifndef PHP_STANDALONE_EN
348 // get matching position
349 size_t start, len;
350 if (!preg.GetMatch(&start, &len)) {
351 break; // shouldn't happen
352 }
353#endif
354 /*
355 * I will use only first match, since I don't see any sense to have more
356 * then 1 match in split() call
357 */
358#ifdef PHP_STANDALONE_EN
359 for(int i = 0; i < pmatch[0].rm_so; i++) {
360#else
361 for(size_t i = 0; i < start; i++) {
362#endif
363 tmp_buff[i] = str_2_match[i];
364 }
365#ifdef PHP_STANDALONE_EN
366 tmp_buff[pmatch[0].rm_so] = 0;
367#else
368 tmp_buff[start] = 0;
369#endif
370// printf("Match added [%s]\n", tmp_buff);
371
372 PHP_VAR_NODE *match_val = array_push_back(result);
373 match_val->value.type = PHP_VAL_STRING;
374 match_val->value.str_val = strdup(tmp_buff);
375
376#ifdef PHP_STANDALONE_EN
377 str_2_match += pmatch[0].rm_eo;
378#else
379 str_2_match += start + len;
380#endif
381 }
382
383 PHP_VAR_NODE *match_val = array_push_back(result);
384 match_val->value.type = PHP_VAL_STRING;
385 match_val->value.str_val = strdup(str_2_match);
386
387 delete [] tmp_buff;
388#ifdef PHP_STANDALONE_EN
389 delete [] pmatch;
390 regfree(&preg);
391#endif
392}
393
394#ifdef ENABLE_NLS1
395
396void php_native_gettext(PHP_VALUE_NODE *result)
397{
398 PHP_SCOPE_ITEM *si_str = get_scope_item(g_current_scope, "__param_0");
399 PHP_VALUE_NODE *str = &si_str->var->value;
400 if ( si_str ) {
401 cast_value_str(str);
402 } else {
403 php_report_error(PHP_ERROR, "Invalid or missing argument 'msgid' for 'gettext'");
404 return;
405 }
406 if ( result ) {
407 cast_value_dnum(result);
408 result->type = PHP_VAL_STRING;
409 result->str_val = strdup(gettext(str->str_val));
410 }
411}
412
413void php_native_gettext_noop(PHP_VALUE_NODE *result)
414{
415 PHP_SCOPE_ITEM *si_str = get_scope_item(g_current_scope, "__param_0");
416 PHP_VALUE_NODE *str = &si_str->var->value;
417 if ( si_str ) {
418 cast_value_str(str);
419 } else {
420 php_report_error(PHP_ERROR, "Invalid or missing argument 'msgid' for 'gettext_noop'");
421 return;
422 }
423 if ( result ) {
424 cast_value_dnum(result);
425 result->type = PHP_VAL_STRING;
426 result->str_val = strdup(str->str_val);
427 }
428}
429
430void php_native_ngettext(PHP_VALUE_NODE *result)
431{
432 PHP_SCOPE_ITEM *si_msgid = get_scope_item(g_current_scope, "__param_0");
433 PHP_VALUE_NODE *msgid = &si_msgid->var->value;
434 if ( si_msgid ) {
435 cast_value_str(msgid);
436 } else {
437 php_report_error(PHP_ERROR, "Invalid or missing argument 'msgid' for 'ngettext'");
438 return;
439 }
440 PHP_SCOPE_ITEM *si_msgid_plural = get_scope_item(g_current_scope, "__param_1");
441 PHP_VALUE_NODE *msgid_plural = &si_msgid_plural->var->value;
442 if ( si_msgid_plural ) {
443 cast_value_str(msgid_plural);
444 } else {
445 php_report_error(PHP_ERROR, "Invalid or missing argument 'msgid_plural' for 'ngettext'");
446 return;
447 }
448 PHP_SCOPE_ITEM *si_count = get_scope_item(g_current_scope, "__param_2");
449 PHP_VALUE_NODE *count = &si_count->var->value;
450 if ( si_count ) {
451 cast_value_dnum(count);
452 } else {
453 php_report_error(PHP_ERROR, "Invalid or missing argument 'count' for 'ngettext'");
This statement is never executed
454 return;
455 }
456 if ( result ) {
457 cast_value_dnum(result);
458 result->type = PHP_VAL_STRING;
459 result->str_val = strdup(ngettext(msgid->str_val, msgid_plural->str_val, count->int_val));
460 }
461}
462#endif
463
464PHP_BLTIN_FUNC_DEF core_lib_funcs[] = {
465 {
466 "var_dump",
467 1,
468 php_native_var_dump,
469 },
470 {
471 "strlen",
472 1, php_native_strlen,
473 },
474 {
475 "count",
476 1, php_native_count,
477 },
478 {
479 "isset",
480 1, php_native_isset,
481 },
482 {
483 "usort",
484 2,
485 php_native_usort,
486 },
487 {
488 "split",
489 3,
490 php_native_split,
491 },
492#ifdef ENABLE_NLS1
493 {
494 "_",
495 1, php_native_gettext,
496 },
497 {
498 "gettext",
499 1, php_native_gettext,
500 },
501 {
502 "gettext_noop",
503 1, php_native_gettext_noop,
504 },
505 {
506 "ngettext",
507 3, php_native_ngettext,
508 },
509#endif
510 { 0, 0, 0, },
511};
512
513void php_init_core_lib()
514{
515 // load function definitions
516 PHP_BLTIN_FUNC_DEF *curr_def = core_lib_funcs;
517 while ( curr_def->name ) {
518 php_add_native_func(curr_def);
519 curr_def++;
520 }
521}
522
523//
524// lexer has no include file
525//
526extern "C"
527void php_set_input_buffer(char *buf, int len);
528
529CPhPLibContext::CPhPLibContext(CWebServerBase *server, const char *file)
530{
531 g_curr_context = this;
532
533 m_server = server;
534
535 php_engine_init();
536 phpin = fopen(file, "r");
537 if ( !phpin ) {
538 return;
539 }
540
541 phpparse();
542
543 m_syn_tree_top = g_syn_tree_top;
544 m_global_scope = g_global_scope;
545}
546
547CPhPLibContext::CPhPLibContext(CWebServerBase *server, char *php_buf, int len)
548{
549 g_curr_context = this;
550
551 m_server = server;
552
553 php_engine_init();
554
555 m_global_scope = g_global_scope;
556
557 php_set_input_buffer(php_buf, len);
558 phpparse();
559
560 m_syn_tree_top = g_syn_tree_top;
561}
562
563CPhPLibContext::~CPhPLibContext()
564{
565 SetContext();
566 php_engine_free();
567}
568
569void CPhPLibContext::SetContext()
570{
571 g_syn_tree_top = m_syn_tree_top;
572 g_global_scope = m_global_scope;
573}
574
575void CPhPLibContext::Execute(CWriteStrBuffer *buf)
576{
577 m_curr_str_buffer = buf;
578
579 PHP_VALUE_NODE val;
580 php_execute(g_syn_tree_top, &val);
581}
582
583CPhPLibContext *CPhPLibContext::g_curr_context = 0;
584
585/*
586 * For simplicity and performance sake, this function can
587 * only handle limited-length printf's. In should be NOT be used
588 * for string concatenation like printf("xyz %s %s", s1, s2).
589 *
590 * Engine will call Print for "print" and "echo"
591 */
592void CPhPLibContext::Printf(const char *str, ...)
593{
594 va_list args;
595
596 va_start(args, str)__builtin_va_start(args, str);
597 if ( !g_curr_context || !g_curr_context->m_curr_str_buffer ) {
598 vprintf(str, args);
599 } else {
600 char buf[4096];
601 vsnprintf(buf, sizeof(buf), str, args);
602 g_curr_context->m_curr_str_buffer->Write(buf);
603 }
604 va_end(args)__builtin_va_end(args);
605}
606
607void CPhPLibContext::Print(const char *str)
608{
609 if ( !g_curr_context || !g_curr_context->m_curr_str_buffer ) {
610 printf("%s", str);
611 } else {
612 g_curr_context->m_curr_str_buffer->Write(str);
613 }
614}
615
616
617CPhpFilter::CPhpFilter(CWebServerBase *server, CSession *sess,
618 const char *file, CWriteStrBuffer *buff)
619{
620 FILE *f = fopen(file, "r");
621 if ( !f ) {
622 printf("ERROR: php can not open source file [%s]\n", file);
623 return;
624 }
625 if ( fseek(f, 0, SEEK_END2) != 0 ) {
626 printf("ERROR: fseek failed on php source file [%s]\n", file);
627 fclose(f);
628 return;
629 }
630 int size = ftell(f);
631 char *buf = new char [size+1];
632 rewind(f);
633 // fread may actually read less if it is a CR-LF-file in Windows
634 size = fread(buf, 1, size, f);
635 buf[size] = 0;
636 fclose(f);
637 char *scan_ptr = buf;
638 char *curr_code_end = buf;
639 while ( strlen(scan_ptr) ) {
640 scan_ptr = strstr(scan_ptr, "<?php");
641 if ( !scan_ptr ) {
642 buff->Write(curr_code_end);
643 break;
644 }
645 if ( scan_ptr != curr_code_end ) {
646 buff->Write(curr_code_end, scan_ptr - curr_code_end);
647 }
648 curr_code_end = strstr(scan_ptr, "?>");
649 if ( !curr_code_end ) {
650 break;
651 }
652 curr_code_end += 2; // include "?>" in buffer
653
654 int len = curr_code_end - scan_ptr;
655
656 CPhPLibContext *context = new CPhPLibContext(server, scan_ptr, len);
657
658#ifndef PHP_STANDALONE_EN
659 load_session_vars("HTTP_GET_VARS", sess->m_get_vars);
660 load_session_vars("_SESSION", sess->m_vars);
661#endif
662
663 context->Execute(buff);
664
665#ifndef PHP_STANDALONE_EN
666 save_session_vars(sess->m_vars);
667#endif
668
669 delete context;
670
671 scan_ptr = curr_code_end;
672 }
673
674#ifndef PHP_STANDALONE_EN
675 sess->m_get_vars.clear();
676#endif
677
678 delete [] buf;
679}
680
681
682/*
683 * String buffer: almost same as regular 'string' class, but,
684 * without reallocation when full. Instead, new buffer is
685 * allocated, and added to list
686 */
687CWriteStrBuffer::CWriteStrBuffer()
688{
689 m_alloc_size = 1024;
690 m_total_length = 0;
691
692 AllocBuf();
693}
694
695CWriteStrBuffer::~CWriteStrBuffer()
696{
697 for(std::list<char *>::iterator i = m_buf_list.begin(); i != m_buf_list.end(); ++i) {
698 delete [] *i;
699 }
700 delete [] m_curr_buf;
701}
702
703void CWriteStrBuffer::AllocBuf()
704{
705 m_curr_buf = new char [m_alloc_size];
706 m_buf_ptr = m_curr_buf;
707 m_curr_buf_left = m_alloc_size;
708}
709
710void CWriteStrBuffer::Write(const char *s, int len)
711{
712 if ( len == -1 ) {
713 len = strlen(s);
714 }
715 m_total_length += len;
716
717 while ( len ) {
718 if ( (len + 1) <= m_curr_buf_left ) {
719 strncpy(m_buf_ptr, s, len);
720 m_buf_ptr += len;
721 m_curr_buf_left -= len;
722 len = 0;
723 } else {
724 memcpy(m_buf_ptr, s, m_curr_buf_left);
725 int rem_len = len - m_curr_buf_left;
726 s += m_curr_buf_left;
727
728 len = rem_len;
729 m_buf_list.push_back(m_curr_buf);
730 AllocBuf();
731 }
732 }
733}
734
735void CWriteStrBuffer::CopyAll(char *dst_buffer)
736{
737 char *curr_ptr = dst_buffer;
738 int rem_size = m_total_length;
739 for(std::list<char *>::iterator i = m_buf_list.begin(); i != m_buf_list.end(); ++i) {
740 memcpy(curr_ptr, *i, m_alloc_size);
741 rem_size -= m_alloc_size;
742 curr_ptr += m_alloc_size;
743 }
744 if ( rem_size ) {
745 memcpy(curr_ptr, m_curr_buf, rem_size);
746 }
747 *(curr_ptr + rem_size) = 0;
748}
749
750void load_session_vars(const char *target, std::map<std::string, std::string> &varmap)
751{
752 PHP_EXP_NODE *sess_vars_exp_node = get_var_node(target);
753 PHP_VAR_NODE *sess_vars = sess_vars_exp_node->var_si_node->var;
754 // i'm not building exp tree, node not needed
755 delete sess_vars_exp_node;
756 cast_value_array(&sess_vars->value);
757 for(std::map<std::string, std::string>::iterator i = varmap.begin(); i != varmap.end(); ++i) {
758 PHP_VAR_NODE *curr_var = array_get_by_str_key(&sess_vars->value, i->first);
759 PHP_VALUE_NODE val;
760 val.type = PHP_VAL_STRING;
761 val.str_val = const_cast<char *>(i->second.c_str());
762 value_value_assign(&curr_var->value, &val);
763 }
764}
765
766void save_session_vars(std::map<std::string, std::string> &varmap)
767{
768 PHP_EXP_NODE *sess_vars_exp_node = get_var_node("_SESSION");
769 PHP_VAR_NODE *sess_vars = sess_vars_exp_node->var_si_node->var;
770
771 delete sess_vars_exp_node;
772 if ( sess_vars->value.type != PHP_VAL_ARRAY ) {
773 return;
774 }
775
776 for(int i = 0; i < array_get_size(&sess_vars->value); i++) {
777 std::string s = array_get_ith_key(&sess_vars->value, i);
778 PHP_VAR_NODE *var = array_get_by_str_key(&sess_vars->value, s);
779 cast_value_str(&var->value);
780 varmap[s] = var->value.str_val;
781 }
782}
783// File_checked_for_headers