summaryrefslogtreecommitdiff
path: root/0.3.2
diff options
context:
space:
mode:
Diffstat (limited to '0.3.2')
-rw-r--r--0.3.2/hardening-patch-4.3.11-0.3.2.patch12205
-rw-r--r--0.3.2/hardening-patch-4.4.0RC2-0.3.2.patch4959
-rw-r--r--0.3.2/hardening-patch-5.0.4-0.3.2.patch11892
3 files changed, 29056 insertions, 0 deletions
diff --git a/0.3.2/hardening-patch-4.3.11-0.3.2.patch b/0.3.2/hardening-patch-4.3.11-0.3.2.patch
new file mode 100644
index 0000000..f3ecb0f
--- /dev/null
+++ b/0.3.2/hardening-patch-4.3.11-0.3.2.patch
@@ -0,0 +1,12205 @@
1diff -Naur php-4.3.11/acinclude.m4 hardening-patch-4.3.11-0.3.2/acinclude.m4
2--- php-4.3.11/acinclude.m4 2005-01-25 14:03:06.000000000 +0100
3+++ hardening-patch-4.3.11-0.3.2/acinclude.m4 2005-07-09 08:53:02.427369648 +0200
4@@ -1173,6 +1173,36 @@
5 fi
6 ])
7
8+dnl
9+dnl Check for broken realpath()
10+dnl
11+dnl realpath("/etc/hosts/../passwd",XXX) should not return
12+dnl "/etc/passwd"
13+dnl
14+AC_DEFUN([PHP_AC_BROKEN_REALPATH],[
15+ AC_CACHE_CHECK(whether realpath is broken, ac_cv_broken_realpath,[
16+ AC_TRY_RUN([
17+main() {
18+ char buf[4096+1];
19+ buf[0] = 0;
20+ realpath("/etc/hosts/../passwd", buf);
21+ exit(strcmp(buf, "/etc/passwd")==0);
22+}
23+ ],[
24+ ac_cv_broken_realpath=no
25+ ],[
26+ ac_cv_broken_realpath=yes
27+ ],[
28+ ac_cv_broken_realpath=no
29+ ])
30+ ])
31+ if test "$ac_cv_broken_realpath" = "yes"; then
32+ AC_DEFINE(PHP_BROKEN_REALPATH, 1, [Whether realpath is broken])
33+ else
34+ AC_DEFINE(PHP_BROKEN_REALPATH, 0, [Whether realpath is broken])
35+ fi
36+])
37+
38 dnl PHP_SHARED_MODULE(module-name, object-var, build-dir, cxx)
39 dnl
40 dnl Basically sets up the link-stage for building module-name
41diff -Naur php-4.3.11/configure hardening-patch-4.3.11-0.3.2/configure
42--- php-4.3.11/configure 2005-03-30 16:35:34.000000000 +0200
43+++ hardening-patch-4.3.11-0.3.2/configure 2005-07-09 08:53:02.464364024 +0200
44@@ -394,6 +394,16 @@
45 ac_default_prefix=/usr/local
46 # Any additions from configure.in:
47 ac_help="$ac_help
48+ --disable-hardening-patch-mm-protect Disable the Memory Manager protection."
49+ac_help="$ac_help
50+ --disable-hardening-patch-ll-protect Disable the Linked List protection."
51+ac_help="$ac_help
52+ --disable-hardening-patch-inc-protect Disable include/require protection."
53+ac_help="$ac_help
54+ --disable-hardening-patch-fmt-protect Disable format string protection."
55+ac_help="$ac_help
56+ --disable-hardening-patch-hash-protect Disable Zend HashTable DTOR protection."
57+ac_help="$ac_help
58
59 SAPI modules:
60 "
61@@ -846,6 +856,8 @@
62 ac_help="$ac_help
63 --disable-tokenizer Disable tokenizer support"
64 ac_help="$ac_help
65+ --disable-varfilter Disable Hardening-Patch's variable filter"
66+ac_help="$ac_help
67 --enable-wddx Enable WDDX support."
68 ac_help="$ac_help
69 --disable-xml Disable XML support using bundled expat lib"
70@@ -2669,6 +2681,157 @@
71
72
73
74+# Check whether --enable-hardening-patch-mm-protect or --disable-hardening-patch-mm-protect was given.
75+if test "${enable_hardening_patch_mm_protect+set}" = set; then
76+ enableval="$enable_hardening_patch_mm_protect"
77+
78+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
79+
80+else
81+
82+ DO_HARDENING_PATCH_MM_PROTECT=yes
83+
84+fi
85+
86+
87+# Check whether --enable-hardening-patch-ll-protect or --disable-hardening-patch-ll-protect was given.
88+if test "${enable_hardening_patch_ll_protect+set}" = set; then
89+ enableval="$enable_hardening_patch_ll_protect"
90+
91+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
92+
93+else
94+
95+ DO_HARDENING_PATCH_LL_PROTECT=yes
96+
97+fi
98+
99+
100+# Check whether --enable-hardening-patch-inc-protect or --disable-hardening-patch-inc-protect was given.
101+if test "${enable_hardening_patch_inc_protect+set}" = set; then
102+ enableval="$enable_hardening_patch_inc_protect"
103+
104+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
105+
106+else
107+
108+ DO_HARDENING_PATCH_INC_PROTECT=yes
109+
110+fi
111+
112+
113+# Check whether --enable-hardening-patch-fmt-protect or --disable-hardening-patch-fmt-protect was given.
114+if test "${enable_hardening_patch_fmt_protect+set}" = set; then
115+ enableval="$enable_hardening_patch_fmt_protect"
116+
117+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
118+
119+else
120+
121+ DO_HARDENING_PATCH_FMT_PROTECT=yes
122+
123+fi
124+
125+
126+# Check whether --enable-hardening-patch-hash-protect or --disable-hardening-patch-hash-protect was given.
127+if test "${enable_hardening_patch_hash_protect+set}" = set; then
128+ enableval="$enable_hardening_patch_hash_protect"
129+
130+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
131+
132+else
133+
134+ DO_HARDENING_PATCH_HASH_PROTECT=yes
135+
136+fi
137+
138+
139+echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6
140+echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5
141+echo "$ac_t""$DO_HARDENING_PATCH_MM_PROTECT" 1>&6
142+
143+echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6
144+echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5
145+echo "$ac_t""$DO_HARDENING_PATCH_LL_PROTECT" 1>&6
146+
147+echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6
148+echo "configure:2733: checking whether to protect include/require statements" >&5
149+echo "$ac_t""$DO_HARDENING_PATCH_INC_PROTECT" 1>&6
150+
151+echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6
152+echo "configure:2737: checking whether to protect PHP Format String functions" >&5
153+echo "$ac_t""$DO_HARDENING_PATCH_FMT_PROTECT" 1>&6
154+
155+echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6
156+echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5
157+echo "$ac_t""$DO_HARDENING_PATCH_HASH_PROTECT" 1>&6
158+
159+
160+cat >> confdefs.h <<\EOF
161+#define HARDENING_PATCH 1
162+EOF
163+
164+
165+
166+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
167+ cat >> confdefs.h <<\EOF
168+#define HARDENING_PATCH_MM_PROTECT 1
169+EOF
170+
171+else
172+ cat >> confdefs.h <<\EOF
173+#define HARDENING_PATCH_MM_PROTECT 0
174+EOF
175+
176+fi
177+
178+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
179+ cat >> confdefs.h <<\EOF
180+#define HARDENING_PATCH_LL_PROTECT 1
181+EOF
182+
183+else
184+ cat >> confdefs.h <<\EOF
185+#define HARDENING_PATCH_LL_PROTECT 0
186+EOF
187+
188+fi
189+
190+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
191+ cat >> confdefs.h <<\EOF
192+#define HARDENING_PATCH_INC_PROTECT 1
193+EOF
194+
195+else
196+ cat >> confdefs.h <<\EOF
197+#define HARDENING_PATCH_INC_PROTECT 0
198+EOF
199+
200+fi
201+
202+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
203+ cat >> confdefs.h <<\EOF
204+#define HARDENING_PATCH_FMT_PROTECT 1
205+EOF
206+
207+else
208+ cat >> confdefs.h <<\EOF
209+#define HARDENING_PATCH_FMT_PROTECT 0
210+EOF
211+
212+fi
213+
214+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
215+ cat >> confdefs.h <<\EOF
216+#define HARDENING_PATCH_HASH_PROTECT 1
217+EOF
218+
219+else
220+ cat >> confdefs.h <<\EOF
221+#define HARDENING_PATCH_HASH_PROTECT 0
222+EOF
223+
224+fi
225
226
227
228@@ -15486,6 +15649,62 @@
229 fi
230
231
232+ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6
233+echo "configure:14928: checking whether realpath is broken" >&5
234+if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then
235+ echo $ac_n "(cached) $ac_c" 1>&6
236+else
237+
238+ if test "$cross_compiling" = yes; then
239+
240+ ac_cv_broken_realpath=no
241+
242+else
243+ cat > conftest.$ac_ext <<EOF
244+#line 14939 "configure"
245+#include "confdefs.h"
246+
247+main() {
248+ char buf[4096+1];
249+ buf[0] = 0;
250+ realpath("/etc/hosts/../passwd", buf);
251+ exit(strcmp(buf, "/etc/passwd")==0);
252+}
253+
254+EOF
255+if { (eval echo configure:14958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
256+then
257+
258+ ac_cv_broken_realpath=no
259+
260+else
261+ echo "configure: failed program was:" >&5
262+ cat conftest.$ac_ext >&5
263+ rm -fr conftest*
264+
265+ ac_cv_broken_realpath=yes
266+
267+fi
268+rm -fr conftest*
269+fi
270+
271+
272+fi
273+
274+echo "$ac_t""$ac_cv_broken_realpath" 1>&6
275+ if test "$ac_cv_broken_realpath" = "yes"; then
276+ cat >> confdefs.h <<\EOF
277+#define PHP_BROKEN_REALPATH 1
278+EOF
279+
280+ else
281+ cat >> confdefs.h <<\EOF
282+#define PHP_BROKEN_REALPATH 0
283+EOF
284+
285+ fi
286+
287+
288 echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
289 echo "configure:15491: checking for declared timezone" >&5
290 if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then
291@@ -85975,6 +86194,265 @@
292 fi
293
294
295+echo $ac_n "checking whether to enable Hardening-Patch's variable filter""... $ac_c" 1>&6
296+echo "configure:82041: checking whether to enable Hardening-Patch's variable filter" >&5
297+# Check whether --enable-varfilter or --disable-varfilter was given.
298+if test "${enable_varfilter+set}" = set; then
299+ enableval="$enable_varfilter"
300+ PHP_VARFILTER=$enableval
301+else
302+
303+ PHP_VARFILTER=yes
304+
305+ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then
306+ PHP_VARFILTER=$PHP_ENABLE_ALL
307+ fi
308+
309+fi
310+
311+
312+
313+ext_output="yes, shared"
314+ext_shared=yes
315+case $PHP_VARFILTER in
316+shared,*)
317+ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'`
318+ ;;
319+shared)
320+ PHP_VARFILTER=yes
321+ ;;
322+no)
323+ ext_output=no
324+ ext_shared=no
325+ ;;
326+*)
327+ ext_output=yes
328+ ext_shared=no
329+ ;;
330+esac
331+
332+
333+
334+echo "$ac_t""$ext_output" 1>&6
335+
336+
337+
338+
339+if test "$PHP_VARFILTER" != "no"; then
340+ cat >> confdefs.h <<\EOF
341+#define HAVE_VARFILTER 1
342+EOF
343+
344+
345+ ext_builddir=ext/varfilter
346+ ext_srcdir=$abs_srcdir/ext/varfilter
347+
348+ ac_extra=
349+
350+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then
351+
352+
353+
354+ case ext/varfilter in
355+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
356+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
357+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
358+ esac
359+
360+
361+
362+ b_c_pre=$php_c_pre
363+ b_cxx_pre=$php_cxx_pre
364+ b_c_meta=$php_c_meta
365+ b_cxx_meta=$php_cxx_meta
366+ b_c_post=$php_c_post
367+ b_cxx_post=$php_cxx_post
368+ b_lo=$php_lo
369+
370+
371+ old_IFS=$IFS
372+ for ac_src in varfilter.c; do
373+
374+ IFS=.
375+ set $ac_src
376+ ac_obj=$1
377+ IFS=$old_IFS
378+
379+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
380+
381+ case $ac_src in
382+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
383+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
384+ esac
385+
386+ cat >>Makefile.objects<<EOF
387+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
388+ $ac_comp
389+EOF
390+ done
391+
392+
393+ EXT_STATIC="$EXT_STATIC varfilter"
394+ if test "$ext_shared" != "nocli"; then
395+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
396+ fi
397+ else
398+ if test "$ext_shared" = "shared" || test "$ext_shared" = "yes"; then
399+
400+ case ext/varfilter in
401+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
402+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
403+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
404+ esac
405+
406+
407+
408+ b_c_pre=$shared_c_pre
409+ b_cxx_pre=$shared_cxx_pre
410+ b_c_meta=$shared_c_meta
411+ b_cxx_meta=$shared_cxx_meta
412+ b_c_post=$shared_c_post
413+ b_cxx_post=$shared_cxx_post
414+ b_lo=$shared_lo
415+
416+
417+ old_IFS=$IFS
418+ for ac_src in varfilter.c; do
419+
420+ IFS=.
421+ set $ac_src
422+ ac_obj=$1
423+ IFS=$old_IFS
424+
425+ shared_objects_varfilter="$shared_objects_varfilter $ac_bdir$ac_obj.lo"
426+
427+ case $ac_src in
428+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
429+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
430+ esac
431+
432+ cat >>Makefile.objects<<EOF
433+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
434+ $ac_comp
435+EOF
436+ done
437+
438+
439+ install_modules="install-modules"
440+ PHP_MODULES="$PHP_MODULES \$(phplibdir)/varfilter.la"
441+
442+ PHP_VAR_SUBST="$PHP_VAR_SUBST shared_objects_varfilter"
443+
444+ cat >>Makefile.objects<<EOF
445+\$(phplibdir)/varfilter.la: $ext_builddir/varfilter.la
446+ \$(LIBTOOL) --mode=install cp $ext_builddir/varfilter.la \$(phplibdir)
447+
448+$ext_builddir/varfilter.la: \$(shared_objects_varfilter) \$(VARFILTER_SHARED_DEPENDENCIES)
449+ \$(LIBTOOL) --mode=link \$(CC) \$(COMMON_FLAGS) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(LDFLAGS) -o \$@ -export-dynamic -avoid-version -prefer-pic -module -rpath \$(phplibdir) \$(EXTRA_LDFLAGS) \$(shared_objects_varfilter) \$(VARFILTER_SHARED_LIBADD)
450+
451+EOF
452+
453+ cat >> confdefs.h <<EOF
454+#define COMPILE_DL_VARFILTER 1
455+EOF
456+
457+ fi
458+ fi
459+
460+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" = "cli"; then
461+ if test "$PHP_SAPI" = "cgi"; then
462+
463+
464+ case ext/varfilter in
465+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
466+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
467+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
468+ esac
469+
470+
471+
472+ b_c_pre=$php_c_pre
473+ b_cxx_pre=$php_cxx_pre
474+ b_c_meta=$php_c_meta
475+ b_cxx_meta=$php_cxx_meta
476+ b_c_post=$php_c_post
477+ b_cxx_post=$php_cxx_post
478+ b_lo=$php_lo
479+
480+
481+ old_IFS=$IFS
482+ for ac_src in varfilter.c; do
483+
484+ IFS=.
485+ set $ac_src
486+ ac_obj=$1
487+ IFS=$old_IFS
488+
489+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
490+
491+ case $ac_src in
492+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
493+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
494+ esac
495+
496+ cat >>Makefile.objects<<EOF
497+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
498+ $ac_comp
499+EOF
500+ done
501+
502+
503+ EXT_STATIC="$EXT_STATIC varfilter"
504+ else
505+
506+
507+ case ext/varfilter in
508+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
509+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
510+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
511+ esac
512+
513+
514+
515+ b_c_pre=$php_c_pre
516+ b_cxx_pre=$php_cxx_pre
517+ b_c_meta=$php_c_meta
518+ b_cxx_meta=$php_cxx_meta
519+ b_c_post=$php_c_post
520+ b_cxx_post=$php_cxx_post
521+ b_lo=$php_lo
522+
523+
524+ old_IFS=$IFS
525+ for ac_src in varfilter.c; do
526+
527+ IFS=.
528+ set $ac_src
529+ ac_obj=$1
530+ IFS=$old_IFS
531+
532+ PHP_CLI_OBJS="$PHP_CLI_OBJS $ac_bdir$ac_obj.lo"
533+
534+ case $ac_src in
535+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
536+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
537+ esac
538+
539+ cat >>Makefile.objects<<EOF
540+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
541+ $ac_comp
542+EOF
543+ done
544+
545+
546+ fi
547+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
548+ fi
549+
550+ BUILD_DIR="$BUILD_DIR $ext_builddir"
551+
552+
553+fi
554
555
556 echo $ac_n "checking whether to enable WDDX support""... $ac_c" 1>&6
557@@ -98629,7 +99107,7 @@
558 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
559 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
560 streams.c network.c php_open_temporary_file.c php_logos.c \
561- output.c memory_streams.c user_streams.c; do
562+ output.c memory_streams.c user_streams.c hardening_patch.c; do
563
564 IFS=.
565 set $ac_src
566@@ -98802,7 +99280,7 @@
567 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
568 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
569 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
570- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c; do
571+ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c; do
572
573 IFS=.
574 set $ac_src
575diff -Naur php-4.3.11/configure.in hardening-patch-4.3.11-0.3.2/configure.in
576--- php-4.3.11/configure.in 2005-03-30 16:18:36.000000000 +0200
577+++ hardening-patch-4.3.11-0.3.2/configure.in 2005-07-09 08:53:02.466363720 +0200
578@@ -227,7 +227,7 @@
579 sinclude(Zend/acinclude.m4)
580 sinclude(Zend/Zend.m4)
581 sinclude(TSRM/tsrm.m4)
582-
583+sinclude(main/hardening_patch.m4)
584
585
586 divert(2)
587@@ -595,6 +595,7 @@
588 AC_FUNC_ALLOCA
589 dnl PHP_AC_BROKEN_SPRINTF
590 dnl PHP_AC_BROKEN_SNPRINTF
591+PHP_AC_BROKEN_REALPATH
592 PHP_DECLARED_TIMEZONE
593 PHP_TIME_R_TYPE
594 PHP_READDIR_R_TYPE
595@@ -1224,7 +1225,7 @@
596 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
597 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
598 streams.c network.c php_open_temporary_file.c php_logos.c \
599- output.c memory_streams.c user_streams.c)
600+ output.c memory_streams.c user_streams.c hardening_patch.c)
601 PHP_ADD_SOURCES(/main, internal_functions.c,, sapi)
602 PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli)
603
604@@ -1237,7 +1238,7 @@
605 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
606 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
607 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
608- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c)
609+ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c )
610
611 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
612 PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c)
613diff -Naur php-4.3.11/ext/calendar/calendar.c hardening-patch-4.3.11-0.3.2/ext/calendar/calendar.c
614--- php-4.3.11/ext/calendar/calendar.c 2003-08-28 22:01:24.000000000 +0200
615+++ hardening-patch-4.3.11-0.3.2/ext/calendar/calendar.c 2005-07-09 08:53:02.466363720 +0200
616@@ -300,7 +300,7 @@
617 {
618 pval **julday;
619 int year, month, day;
620- char date[10];
621+ char date[16];
622
623 if (zend_get_parameters_ex(1, &julday) != SUCCESS) {
624 WRONG_PARAM_COUNT;
625@@ -341,7 +341,7 @@
626 {
627 pval **julday;
628 int year, month, day;
629- char date[10];
630+ char date[16];
631
632 if (zend_get_parameters_ex(1, &julday) != SUCCESS) {
633 WRONG_PARAM_COUNT;
634@@ -453,7 +453,7 @@
635 {
636 long julday, fl;
637 int year, month, day;
638- char date[10], hebdate[25];
639+ char date[16], hebdate[25];
640 char *dayp, *yearp;
641
642 if (ZEND_NUM_ARGS() == 1) {
643@@ -521,7 +521,7 @@
644 {
645 pval **julday;
646 int year, month, day;
647- char date[10];
648+ char date[16];
649
650 if (zend_get_parameters_ex(1, &julday) != SUCCESS) {
651 WRONG_PARAM_COUNT;
652diff -Naur php-4.3.11/ext/fbsql/php_fbsql.c hardening-patch-4.3.11-0.3.2/ext/fbsql/php_fbsql.c
653--- php-4.3.11/ext/fbsql/php_fbsql.c 2005-02-09 20:33:32.000000000 +0100
654+++ hardening-patch-4.3.11-0.3.2/ext/fbsql/php_fbsql.c 2005-07-09 08:53:02.468363416 +0200
655@@ -1797,8 +1797,24 @@
656 }
657 else if (fbcmdErrorsFound(md))
658 {
659+#if HARDENING_PATCH
660+ char* query_copy;
661+ int i;
662+#endif
663 FBCErrorMetaData* emd = fbcdcErrorMetaData(c, md);
664 char* emg = fbcemdAllErrorMessages(emd);
665+#if HARDENING_PATCH
666+ query_copy=estrdup(query_copy);
667+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
668+ php_security_log(S_SQL, "fbsql error: %s - query: %s", emg, query_copy);
669+ efree(query_copy);
670+ if (HG(hphp_sql_bailout_on_error)) {
671+ free(emg);
672+ fbcemdRelease(emd);
673+ result = 0;
674+ zend_bailout();
675+ }
676+#endif
677 if (FB_SQL_G(generateWarnings))
678 {
679 if (emg)
680diff -Naur php-4.3.11/ext/mbstring/mbstring.c hardening-patch-4.3.11-0.3.2/ext/mbstring/mbstring.c
681--- php-4.3.11/ext/mbstring/mbstring.c 2005-02-21 09:03:47.000000000 +0100
682+++ hardening-patch-4.3.11-0.3.2/ext/mbstring/mbstring.c 2005-07-09 08:53:02.469363264 +0200
683@@ -1487,6 +1487,7 @@
684 char *strtok_buf = NULL, **val_list;
685 zval *array_ptr = (zval *) arg;
686 int n, num, val_len, *len_list;
687+ unsigned int new_val_len;
688 enum mbfl_no_encoding from_encoding;
689 mbfl_string string, resvar, resval;
690 mbfl_encoding_detector *identd = NULL;
691@@ -1609,8 +1610,14 @@
692 val_len = len_list[n];
693 }
694 n++;
695- /* add variable to symbol table */
696- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
697+ /* we need val to be emalloc()ed */
698+ val = estrndup(val, val_len);
699+ if (sapi_module.input_filter(info->data_type, var, &val, val_len, &new_val_len TSRMLS_CC)) {
700+ /* add variable to symbol table */
701+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
702+ }
703+ efree(val);
704+
705 if (convd != NULL){
706 mbfl_string_clear(&resvar);
707 mbfl_string_clear(&resval);
708diff -Naur php-4.3.11/ext/mysql/php_mysql.c hardening-patch-4.3.11-0.3.2/ext/mysql/php_mysql.c
709--- php-4.3.11/ext/mysql/php_mysql.c 2005-02-22 16:00:49.000000000 +0100
710+++ hardening-patch-4.3.11-0.3.2/ext/mysql/php_mysql.c 2005-07-09 08:53:02.471362960 +0200
711@@ -1215,6 +1215,8 @@
712 {
713 php_mysql_conn *mysql;
714 MYSQL_RES *mysql_result;
715+ char *copy_query;
716+ int i;
717
718 ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, link_id, "MySQL-Link", le_link, le_plink);
719
720@@ -1265,6 +1267,13 @@
721 php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
722 }
723 }
724+ copy_query = estrdup(Z_STRVAL_PP(query));
725+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
726+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
727+ efree(copy_query);
728+ if (HG(hphp_sql_bailout_on_error)) {
729+ zend_bailout();
730+ }
731 RETURN_FALSE;
732 }
733 #else
734@@ -1272,12 +1281,20 @@
735 /* check possible error */
736 if (MySG(trace_mode)){
737 if (mysql_errno(&mysql->conn)){
738- php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, mysql_error(&mysql->conn));
739+ php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
740 }
741 }
742+ copy_query = estrdup(Z_STRVAL_PP(query));
743+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
744+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
745+ efree(copy_query);
746+ if (HG(hphp_sql_bailout_on_error)) {
747+ zend_bailout();
748+ }
749 RETURN_FALSE;
750 }
751 #endif
752+
753 if(use_store == MYSQL_USE_RESULT) {
754 mysql_result=mysql_use_result(&mysql->conn);
755 } else {
756diff -Naur php-4.3.11/ext/pgsql/pgsql.c hardening-patch-4.3.11-0.3.2/ext/pgsql/pgsql.c
757--- php-4.3.11/ext/pgsql/pgsql.c 2004-05-12 18:49:56.000000000 +0200
758+++ hardening-patch-4.3.11-0.3.2/ext/pgsql/pgsql.c 2005-07-09 08:53:02.473362656 +0200
759@@ -997,10 +997,28 @@
760 case PGRES_EMPTY_QUERY:
761 case PGRES_BAD_RESPONSE:
762 case PGRES_NONFATAL_ERROR:
763- case PGRES_FATAL_ERROR:
764- PHP_PQ_ERROR("Query failed: %s", pgsql);
765- PQclear(pgsql_result);
766- RETURN_FALSE;
767+ case PGRES_FATAL_ERROR:
768+ {
769+#if HARDENING_PATCH
770+ int i;
771+ char *query_copy;
772+#endif
773+ char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
774+ PQclear(pgsql_result);
775+#if HARDENING_PATCH
776+ query_copy = estrdup(Z_STRVAL_PP(query));
777+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
778+ php_security_log(S_SQL, "PgSQL error: %s - query: %s", msgbuf, query_copy);
779+ efree(query_copy);
780+ if (HG(hphp_sql_bailout_on_error)) {
781+ efree(msgbuf);
782+ zend_bailout();
783+ }
784+#endif
785+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", msgbuf);
786+ efree(msgbuf);
787+ RETURN_FALSE;
788+ }
789 break;
790 case PGRES_COMMAND_OK: /* successful command that did not return rows */
791 default:
792diff -Naur php-4.3.11/ext/standard/array.c hardening-patch-4.3.11-0.3.2/ext/standard/array.c
793--- php-4.3.11/ext/standard/array.c 2004-12-23 17:40:03.000000000 +0100
794+++ hardening-patch-4.3.11-0.3.2/ext/standard/array.c 2005-07-09 08:53:02.474362504 +0200
795@@ -1153,6 +1153,32 @@
796 }
797 }
798 }
799+
800+ if (var_name[0] == 'H') {
801+ if ((strcmp(var_name, "HTTP_GET_VARS")==0)||
802+ (strcmp(var_name, "HTTP_POST_VARS")==0)||
803+ (strcmp(var_name, "HTTP_POST_FILES")==0)||
804+ (strcmp(var_name, "HTTP_ENV_VARS")==0)||
805+ (strcmp(var_name, "HTTP_SERVER_VARS")==0)||
806+ (strcmp(var_name, "HTTP_SESSION_VARS")==0)||
807+ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)||
808+ (strcmp(var_name, "HTTP_RAW_POST_DATA")==0)) {
809+ return 0;
810+ }
811+ } else if (var_name[0] == '_') {
812+ if ((strcmp(var_name, "_COOKIE")==0)||
813+ (strcmp(var_name, "_ENV")==0)||
814+ (strcmp(var_name, "_FILES")==0)||
815+ (strcmp(var_name, "_GET")==0)||
816+ (strcmp(var_name, "_POST")==0)||
817+ (strcmp(var_name, "_REQUEST")==0)||
818+ (strcmp(var_name, "_SESSION")==0)||
819+ (strcmp(var_name, "_SERVER")==0)) {
820+ return 0;
821+ }
822+ } else if (strcmp(var_name, "GLOBALS")==0) {
823+ return 0;
824+ }
825
826 return 1;
827 }
828diff -Naur php-4.3.11/ext/standard/basic_functions.c hardening-patch-4.3.11-0.3.2/ext/standard/basic_functions.c
829--- php-4.3.11/ext/standard/basic_functions.c 2005-01-18 12:01:20.000000000 +0100
830+++ hardening-patch-4.3.11-0.3.2/ext/standard/basic_functions.c 2005-07-09 08:53:02.476362200 +0200
831@@ -687,7 +687,7 @@
832 PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL)
833
834 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
835- PHP_FE(realpath, NULL)
836+ PHP_STATIC_FE("realpath", zif_real_path, NULL)
837 #endif
838
839 #ifdef HAVE_FNMATCH
840@@ -3020,6 +3020,35 @@
841 memcpy(new_key, prefix, prefix_len);
842 memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength);
843
844+ if (new_key[0] == 'H') {
845+ if ((strcmp(new_key, "HTTP_GET_VARS")==0)||
846+ (strcmp(new_key, "HTTP_POST_VARS")==0)||
847+ (strcmp(new_key, "HTTP_POST_FILES")==0)||
848+ (strcmp(new_key, "HTTP_ENV_VARS")==0)||
849+ (strcmp(new_key, "HTTP_SERVER_VARS")==0)||
850+ (strcmp(new_key, "HTTP_SESSION_VARS")==0)||
851+ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)||
852+ (strcmp(new_key, "HTTP_RAW_POST_DATA")==0)) {
853+ efree(new_key);
854+ return 0;
855+ }
856+ } else if (new_key[0] == '_') {
857+ if ((strcmp(new_key, "_COOKIE")==0)||
858+ (strcmp(new_key, "_ENV")==0)||
859+ (strcmp(new_key, "_FILES")==0)||
860+ (strcmp(new_key, "_GET")==0)||
861+ (strcmp(new_key, "_POST")==0)||
862+ (strcmp(new_key, "_REQUEST")==0)||
863+ (strcmp(new_key, "_SESSION")==0)||
864+ (strcmp(new_key, "_SERVER")==0)) {
865+ efree(new_key);
866+ return 0;
867+ }
868+ } else if (strcmp(new_key, "GLOBALS")==0) {
869+ efree(new_key);
870+ return 0;
871+ }
872+
873 zend_hash_del(&EG(symbol_table), new_key, new_key_len);
874 ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0);
875
876diff -Naur php-4.3.11/ext/standard/file.c hardening-patch-4.3.11-0.3.2/ext/standard/file.c
877--- php-4.3.11/ext/standard/file.c 2005-03-27 17:53:59.000000000 +0200
878+++ hardening-patch-4.3.11-0.3.2/ext/standard/file.c 2005-07-09 08:53:02.478361896 +0200
879@@ -2469,7 +2469,7 @@
880 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
881 /* {{{ proto string realpath(string path)
882 Return the resolved path */
883-PHP_FUNCTION(realpath)
884+PHP_FUNCTION(real_path)
885 {
886 zval **path;
887 char resolved_path_buff[MAXPATHLEN];
888diff -Naur php-4.3.11/ext/standard/file.h hardening-patch-4.3.11-0.3.2/ext/standard/file.h
889--- php-4.3.11/ext/standard/file.h 2004-06-21 21:33:47.000000000 +0200
890+++ hardening-patch-4.3.11-0.3.2/ext/standard/file.h 2005-07-09 08:53:02.478361896 +0200
891@@ -64,7 +64,7 @@
892 PHP_FUNCTION(fd_set);
893 PHP_FUNCTION(fd_isset);
894 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
895-PHP_FUNCTION(realpath);
896+PHP_FUNCTION(real_path);
897 #endif
898 #ifdef HAVE_FNMATCH
899 PHP_FUNCTION(fnmatch);
900diff -Naur php-4.3.11/ext/standard/ftp_fopen_wrapper.c hardening-patch-4.3.11-0.3.2/ext/standard/ftp_fopen_wrapper.c
901--- php-4.3.11/ext/standard/ftp_fopen_wrapper.c 2003-08-26 00:26:37.000000000 +0200
902+++ hardening-patch-4.3.11-0.3.2/ext/standard/ftp_fopen_wrapper.c 2005-07-09 08:53:02.479361744 +0200
903@@ -17,7 +17,7 @@
904 | Hartmut Holzgraefe <hholzgra@php.net> |
905 +----------------------------------------------------------------------+
906 */
907-/* $Id: ftp_fopen_wrapper.c,v 1.38.2.6 2003/08/25 22:26:37 pollita Exp $ */
908+/* $Id: ftp_fopen_wrapper.c,v 1.38.2.8.2.1 2005/06/27 08:27:23 sesser Exp $ */
909
910 #include "php.h"
911 #include "php_globals.h"
912@@ -142,7 +142,7 @@
913 unsigned short portno;
914 char *scratch;
915 int result;
916- int i, use_ssl;
917+ int i, use_ssl, tmp_len;
918 #ifdef HAVE_OPENSSL_EXT
919 int use_ssl_on_data=0;
920 php_stream *reuseid=NULL;
921@@ -243,10 +243,25 @@
922
923 #endif
924
925+#define PHP_FTP_CNTRL_CHK(val, val_len, err_msg) { \
926+ unsigned char *s = val, *e = s + val_len; \
927+ while (s < e) { \
928+ if (iscntrl(*s)) { \
929+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, err_msg, val); \
930+ goto errexit; \
931+ } \
932+ s++; \
933+ } \
934+}
935+
936 /* send the user name */
937 php_stream_write_string(stream, "USER ");
938 if (resource->user != NULL) {
939- php_raw_url_decode(resource->user, strlen(resource->user));
940+ unsigned char *s, *e;
941+ tmp_len = php_raw_url_decode(resource->user, strlen(resource->user));
942+
943+ PHP_FTP_CNTRL_CHK(resource->user, tmp_len, "Invalid login %s")
944+
945 php_stream_write_string(stream, resource->user);
946 } else {
947 php_stream_write_string(stream, "anonymous");
948@@ -262,7 +277,10 @@
949
950 php_stream_write_string(stream, "PASS ");
951 if (resource->pass != NULL) {
952- php_raw_url_decode(resource->pass, strlen(resource->pass));
953+ tmp_len = php_raw_url_decode(resource->pass, strlen(resource->pass));
954+
955+ PHP_FTP_CNTRL_CHK(resource->pass, tmp_len, "Invalid password %s")
956+
957 php_stream_write_string(stream, resource->pass);
958 } else {
959 /* if the user has configured who they are,
960diff -Naur php-4.3.11/ext/standard/head.c hardening-patch-4.3.11-0.3.2/ext/standard/head.c
961--- php-4.3.11/ext/standard/head.c 2005-01-07 22:14:23.000000000 +0100
962+++ hardening-patch-4.3.11-0.3.2/ext/standard/head.c 2005-07-09 08:53:02.479361744 +0200
963@@ -45,10 +45,31 @@
964 {
965 zend_bool rep = 1;
966 sapi_header_line ctr = {0};
967+#if HARDENING_PATCH
968+ int i;
969+#endif
970
971 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &ctr.line,
972 &ctr.line_len, &rep, &ctr.response_code) == FAILURE)
973 return;
974+
975+#if HARDENING_PATCH
976+ if (!HG(hphp_multiheader)) {
977+ for (i=0; i<ctr.line_len; i++) {
978+ if (ctr.line[i]==0) {
979+ php_security_log(S_MISC, "header(): headerline truncated by an ASCII-NUL char");
980+ ctr.line_len=i;
981+ break;
982+ } else if (ctr.line[i]=='\n') {
983+ if (i>0 && (i<ctr.line_len-1) && (ctr.line[i+1]==' ' || ctr.line[i+1]=='\t')) {
984+ continue;
985+ }
986+ php_security_log(S_MISC, "header(): headerline contains more than one header");
987+ ctr.line_len=i;
988+ }
989+ }
990+ }
991+#endif
992
993 sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr TSRMLS_CC);
994 }
995diff -Naur php-4.3.11/ext/standard/info.c hardening-patch-4.3.11-0.3.2/ext/standard/info.c
996--- php-4.3.11/ext/standard/info.c 2004-06-09 17:10:19.000000000 +0200
997+++ hardening-patch-4.3.11-0.3.2/ext/standard/info.c 2005-07-09 08:53:02.480361592 +0200
998@@ -397,7 +397,7 @@
999
1000 if (flag & PHP_INFO_GENERAL) {
1001 char *zend_version = get_zend_version();
1002- char temp_api[9];
1003+ char temp_api[11];
1004
1005 php_uname = php_get_uname('a');
1006
1007@@ -417,11 +417,22 @@
1008 }
1009 }
1010
1011+#if HARDENING_PATCH
1012+ if (!sapi_module.phpinfo_as_text) {
1013+ php_printf("<h1 class=\"p\">PHP Version %s with Hardening-Patch %s</h1>\n", PHP_VERSION, HARDENING_PATCH_VERSION);
1014+ } else {
1015+ char temp_ver[40];
1016+
1017+ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENING_PATCH_VERSION);
1018+ php_info_print_table_row(2, "PHP/Hardening-Patch Version", temp_ver);
1019+ }
1020+#else
1021 if (!sapi_module.phpinfo_as_text) {
1022 php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
1023 } else {
1024 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1025 }
1026+#endif
1027 php_info_print_box_end();
1028 php_info_print_table_start();
1029 php_info_print_table_row(2, "System", php_uname );
1030diff -Naur php-4.3.11/ext/standard/syslog.c hardening-patch-4.3.11-0.3.2/ext/standard/syslog.c
1031--- php-4.3.11/ext/standard/syslog.c 2004-07-30 16:38:29.000000000 +0200
1032+++ hardening-patch-4.3.11-0.3.2/ext/standard/syslog.c 2005-07-09 08:53:02.480361592 +0200
1033@@ -42,6 +42,7 @@
1034 */
1035 PHP_MINIT_FUNCTION(syslog)
1036 {
1037+#if !HARDENING_PATCH
1038 /* error levels */
1039 REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
1040 REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
1041@@ -97,7 +98,7 @@
1042 /* AIX doesn't have LOG_PERROR */
1043 REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
1044 #endif
1045-
1046+#endif
1047 return SUCCESS;
1048 }
1049 /* }}} */
1050diff -Naur php-4.3.11/ext/varfilter/config.m4 hardening-patch-4.3.11-0.3.2/ext/varfilter/config.m4
1051--- php-4.3.11/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100
1052+++ hardening-patch-4.3.11-0.3.2/ext/varfilter/config.m4 2005-07-09 08:53:02.481361440 +0200
1053@@ -0,0 +1,11 @@
1054+dnl
1055+dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $
1056+dnl
1057+
1058+PHP_ARG_ENABLE(varfilter, whether to enable Hardening-Patch's variable filter,
1059+[ --disable-varfilter Disable Hardening-Patch's variable filter], yes)
1060+
1061+if test "$PHP_VARFILTER" != "no"; then
1062+ AC_DEFINE(HAVE_VARFILTER, 1, [ ])
1063+ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared)
1064+fi
1065diff -Naur php-4.3.11/ext/varfilter/CREDITS hardening-patch-4.3.11-0.3.2/ext/varfilter/CREDITS
1066--- php-4.3.11/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100
1067+++ hardening-patch-4.3.11-0.3.2/ext/varfilter/CREDITS 2005-07-09 08:53:02.481361440 +0200
1068@@ -0,0 +1,2 @@
1069+varfilter
1070+Stefan Esser
1071\ Kein Zeilenumbruch am Dateiende.
1072diff -Naur php-4.3.11/ext/varfilter/php_varfilter.h hardening-patch-4.3.11-0.3.2/ext/varfilter/php_varfilter.h
1073--- php-4.3.11/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100
1074+++ hardening-patch-4.3.11-0.3.2/ext/varfilter/php_varfilter.h 2005-07-09 08:53:02.481361440 +0200
1075@@ -0,0 +1,111 @@
1076+/*
1077+ +----------------------------------------------------------------------+
1078+ | Hardened-PHP Project's varfilter extension |
1079+ +----------------------------------------------------------------------+
1080+ | Copyright (c) 2004-2005 Stefan Esser |
1081+ +----------------------------------------------------------------------+
1082+ | This source file is subject to version 2.02 of the PHP license, |
1083+ | that is bundled with this package in the file LICENSE, and is |
1084+ | available at through the world-wide-web at |
1085+ | http://www.php.net/license/2_02.txt. |
1086+ | If you did not receive a copy of the PHP license and are unable to |
1087+ | obtain it through the world-wide-web, please send a note to |
1088+ | license@php.net so we can mail you a copy immediately. |
1089+ +----------------------------------------------------------------------+
1090+ | Author: Stefan Esser <sesser@hardened-php.net> |
1091+ +----------------------------------------------------------------------+
1092+
1093+ $Id: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $
1094+*/
1095+
1096+#ifndef PHP_VARFILTER_H
1097+#define PHP_VARFILTER_H
1098+
1099+extern zend_module_entry varfilter_module_entry;
1100+#define phpext_varfilter_ptr &varfilter_module_entry
1101+
1102+#ifdef PHP_WIN32
1103+#define PHP_VARFILTER_API __declspec(dllexport)
1104+#else
1105+#define PHP_VARFILTER_API
1106+#endif
1107+
1108+#ifdef ZTS
1109+#include "TSRM.h"
1110+#endif
1111+
1112+#include "SAPI.h"
1113+
1114+#include "php_variables.h"
1115+
1116+
1117+PHP_MINIT_FUNCTION(varfilter);
1118+PHP_MSHUTDOWN_FUNCTION(varfilter);
1119+PHP_RINIT_FUNCTION(varfilter);
1120+PHP_RSHUTDOWN_FUNCTION(varfilter);
1121+PHP_MINFO_FUNCTION(varfilter);
1122+
1123+
1124+ZEND_BEGIN_MODULE_GLOBALS(varfilter)
1125+// request variables
1126+ long max_request_variables;
1127+ long cur_request_variables;
1128+ long max_varname_length;
1129+ long max_totalname_length;
1130+ long max_value_length;
1131+ long max_array_depth;
1132+ long max_array_index_length;
1133+// cookie variables
1134+ long max_cookie_vars;
1135+ long cur_cookie_vars;
1136+ long max_cookie_name_length;
1137+ long max_cookie_totalname_length;
1138+ long max_cookie_value_length;
1139+ long max_cookie_array_depth;
1140+ long max_cookie_array_index_length;
1141+// get variables
1142+ long max_get_vars;
1143+ long cur_get_vars;
1144+ long max_get_name_length;
1145+ long max_get_totalname_length;
1146+ long max_get_value_length;
1147+ long max_get_array_depth;
1148+ long max_get_array_index_length;
1149+// post variables
1150+ long max_post_vars;
1151+ long cur_post_vars;
1152+ long max_post_name_length;
1153+ long max_post_totalname_length;
1154+ long max_post_value_length;
1155+ long max_post_array_depth;
1156+ long max_post_array_index_length;
1157+// fileupload
1158+ long max_uploads;
1159+ long cur_uploads;
1160+ zend_bool disallow_elf_files;
1161+ char *verification_script;
1162+
1163+ZEND_END_MODULE_GLOBALS(varfilter)
1164+
1165+
1166+#ifdef ZTS
1167+#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v)
1168+#else
1169+#define VARFILTER_G(v) (varfilter_globals.v)
1170+#endif
1171+
1172+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter);
1173+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter);
1174+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter);
1175+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter);
1176+
1177+#endif /* PHP_VARFILTER_H */
1178+
1179+
1180+/*
1181+ * Local variables:
1182+ * tab-width: 4
1183+ * c-basic-offset: 4
1184+ * indent-tabs-mode: t
1185+ * End:
1186+ */
1187diff -Naur php-4.3.11/ext/varfilter/varfilter.c hardening-patch-4.3.11-0.3.2/ext/varfilter/varfilter.c
1188--- php-4.3.11/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100
1189+++ hardening-patch-4.3.11-0.3.2/ext/varfilter/varfilter.c 2005-07-09 08:57:24.526524520 +0200
1190@@ -0,0 +1,604 @@
1191+/*
1192+ +----------------------------------------------------------------------+
1193+ | Hardened-PHP Project's varfilter extension |
1194+ +----------------------------------------------------------------------+
1195+ | Copyright (c) 2004-2005 Stefan Esser |
1196+ +----------------------------------------------------------------------+
1197+ | This source file is subject to version 2.02 of the PHP license, |
1198+ | that is bundled with this package in the file LICENSE, and is |
1199+ | available at through the world-wide-web at |
1200+ | http://www.php.net/license/2_02.txt. |
1201+ | If you did not receive a copy of the PHP license and are unable to |
1202+ | obtain it through the world-wide-web, please send a note to |
1203+ | license@php.net so we can mail you a copy immediately. |
1204+ +----------------------------------------------------------------------+
1205+ | Author: Stefan Esser <sesser@hardened-php.net> |
1206+ +----------------------------------------------------------------------+
1207+
1208+ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $
1209+*/
1210+
1211+#ifdef HAVE_CONFIG_H
1212+#include "config.h"
1213+#endif
1214+
1215+#include "php.h"
1216+#include "php_ini.h"
1217+#include "ext/standard/info.h"
1218+#include "php_varfilter.h"
1219+#include "hardening_patch.h"
1220+
1221+ZEND_DECLARE_MODULE_GLOBALS(varfilter)
1222+
1223+/* True global resources - no need for thread safety here */
1224+static int le_varfilter;
1225+
1226+/* {{{ varfilter_module_entry
1227+ */
1228+zend_module_entry varfilter_module_entry = {
1229+#if ZEND_MODULE_API_NO >= 20010901
1230+ STANDARD_MODULE_HEADER,
1231+#endif
1232+ "varfilter",
1233+ NULL,
1234+ PHP_MINIT(varfilter),
1235+ PHP_MSHUTDOWN(varfilter),
1236+ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */
1237+ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */
1238+ PHP_MINFO(varfilter),
1239+#if ZEND_MODULE_API_NO >= 20010901
1240+ "0.3.2", /* Replace with version number for your extension */
1241+#endif
1242+ STANDARD_MODULE_PROPERTIES
1243+};
1244+/* }}} */
1245+
1246+#ifdef COMPILE_DL_VARFILTER
1247+ZEND_GET_MODULE(varfilter)
1248+#endif
1249+
1250+/* {{{ PHP_INI
1251+ */
1252+PHP_INI_BEGIN()
1253+ /* for backward compatibility */
1254+ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
1255+ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
1256+ STD_PHP_INI_ENTRY("varfilter.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
1257+ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
1258+ STD_PHP_INI_ENTRY("varfilter.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
1259+ STD_PHP_INI_ENTRY("varfilter.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
1260+
1261+ STD_PHP_INI_ENTRY("hphp.request.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
1262+ STD_PHP_INI_ENTRY("hphp.request.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
1263+ STD_PHP_INI_ENTRY("hphp.request.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
1264+ STD_PHP_INI_ENTRY("hphp.request.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
1265+ STD_PHP_INI_ENTRY("hphp.request.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
1266+ STD_PHP_INI_ENTRY("hphp.request.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
1267+
1268+ STD_PHP_INI_ENTRY("hphp.cookie.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_vars, zend_varfilter_globals, varfilter_globals)
1269+ STD_PHP_INI_ENTRY("hphp.cookie.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_name_length, zend_varfilter_globals, varfilter_globals)
1270+ STD_PHP_INI_ENTRY("hphp.cookie.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_cookie_totalname_length, zend_varfilter_globals, varfilter_globals)
1271+ STD_PHP_INI_ENTRY("hphp.cookie.max_value_length", "10000", PHP_INI_PERDIR, OnUpdateLong, max_cookie_value_length, zend_varfilter_globals, varfilter_globals)
1272+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_depth, zend_varfilter_globals, varfilter_globals)
1273+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_index_length, zend_varfilter_globals, varfilter_globals)
1274+
1275+ STD_PHP_INI_ENTRY("hphp.get.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_get_vars, zend_varfilter_globals, varfilter_globals)
1276+ STD_PHP_INI_ENTRY("hphp.get.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_name_length, zend_varfilter_globals, varfilter_globals)
1277+ STD_PHP_INI_ENTRY("hphp.get.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_get_totalname_length, zend_varfilter_globals, varfilter_globals)
1278+ STD_PHP_INI_ENTRY("hphp.get.max_value_length", "512", PHP_INI_PERDIR, OnUpdateLong, max_get_value_length, zend_varfilter_globals, varfilter_globals)
1279+ STD_PHP_INI_ENTRY("hphp.get.max_array_depth", "50", PHP_INI_PERDIR, OnUpdateLong, max_get_array_depth, zend_varfilter_globals, varfilter_globals)
1280+ STD_PHP_INI_ENTRY("hphp.get.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_array_index_length, zend_varfilter_globals, varfilter_globals)
1281+
1282+ STD_PHP_INI_ENTRY("hphp.post.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_post_vars, zend_varfilter_globals, varfilter_globals)
1283+ STD_PHP_INI_ENTRY("hphp.post.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_name_length, zend_varfilter_globals, varfilter_globals)
1284+ STD_PHP_INI_ENTRY("hphp.post.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_post_totalname_length, zend_varfilter_globals, varfilter_globals)
1285+ STD_PHP_INI_ENTRY("hphp.post.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_post_value_length, zend_varfilter_globals, varfilter_globals)
1286+ STD_PHP_INI_ENTRY("hphp.post.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_post_array_depth, zend_varfilter_globals, varfilter_globals)
1287+ STD_PHP_INI_ENTRY("hphp.post.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_array_index_length, zend_varfilter_globals, varfilter_globals)
1288+
1289+ STD_PHP_INI_ENTRY("hphp.upload.max_uploads", "25", PHP_INI_PERDIR, OnUpdateLong, max_uploads, zend_varfilter_globals, varfilter_globals)
1290+ STD_PHP_INI_ENTRY("hphp.upload.disallow_elf_files", "1", PHP_INI_SYSTEM, OnUpdateBool, disallow_elf_files, zend_varfilter_globals, varfilter_globals)
1291+ STD_PHP_INI_ENTRY("hphp.upload.verification_script", NULL, PHP_INI_SYSTEM, OnUpdateString, verification_script, zend_varfilter_globals, varfilter_globals)
1292+
1293+
1294+PHP_INI_END()
1295+/* }}} */
1296+
1297+/* {{{ php_varfilter_init_globals
1298+ */
1299+static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals)
1300+{
1301+ varfilter_globals->max_request_variables = 200;
1302+ varfilter_globals->max_varname_length = 64;
1303+ varfilter_globals->max_value_length = 10000;
1304+ varfilter_globals->max_array_depth = 100;
1305+ varfilter_globals->max_totalname_length = 256;
1306+ varfilter_globals->max_array_index_length = 64;
1307+
1308+ varfilter_globals->max_cookie_vars = 100;
1309+ varfilter_globals->max_cookie_name_length = 64;
1310+ varfilter_globals->max_cookie_totalname_length = 256;
1311+ varfilter_globals->max_cookie_value_length = 10000;
1312+ varfilter_globals->max_cookie_array_depth = 100;
1313+ varfilter_globals->max_cookie_array_index_length = 64;
1314+
1315+ varfilter_globals->max_get_vars = 100;
1316+ varfilter_globals->max_get_name_length = 64;
1317+ varfilter_globals->max_get_totalname_length = 256;
1318+ varfilter_globals->max_get_value_length = 512;
1319+ varfilter_globals->max_get_array_depth = 50;
1320+ varfilter_globals->max_get_array_index_length = 64;
1321+
1322+ varfilter_globals->max_post_vars = 200;
1323+ varfilter_globals->max_post_name_length = 64;
1324+ varfilter_globals->max_post_totalname_length = 256;
1325+ varfilter_globals->max_post_value_length = 65000;
1326+ varfilter_globals->max_post_array_depth = 100;
1327+ varfilter_globals->max_post_array_index_length = 64;
1328+
1329+ varfilter_globals->max_uploads = 25;
1330+ varfilter_globals->disallow_elf_files = 1;
1331+ varfilter_globals->verification_script = NULL;
1332+}
1333+/* }}} */
1334+
1335+/* {{{ PHP_MINIT_FUNCTION
1336+ */
1337+PHP_MINIT_FUNCTION(varfilter)
1338+{
1339+ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL);
1340+ REGISTER_INI_ENTRIES();
1341+
1342+ sapi_register_input_filter(varfilter_input_filter);
1343+ sapi_register_pre_upload_filter(varfilter_pre_upload_filter);
1344+ sapi_register_upload_content_filter(varfilter_upload_content_filter);
1345+ sapi_register_post_upload_filter(varfilter_post_upload_filter);
1346+
1347+ return SUCCESS;
1348+}
1349+/* }}} */
1350+
1351+/* {{{ PHP_MSHUTDOWN_FUNCTION
1352+ */
1353+PHP_MSHUTDOWN_FUNCTION(varfilter)
1354+{
1355+// zend_hash_apply_with_arguments(&HG(lists.functionlists), (apply_func_args_t) show_stuff, 0);
1356+
1357+ UNREGISTER_INI_ENTRIES();
1358+
1359+ return SUCCESS;
1360+}
1361+/* }}} */
1362+
1363+/* Remove if there's nothing to do at request start */
1364+/* {{{ PHP_RINIT_FUNCTION
1365+ */
1366+PHP_RINIT_FUNCTION(varfilter)
1367+{
1368+ VARFILTER_G(cur_request_variables) = 0;
1369+ VARFILTER_G(cur_get_vars) = 0;
1370+ VARFILTER_G(cur_post_vars) = 0;
1371+ VARFILTER_G(cur_cookie_vars) = 0;
1372+
1373+ VARFILTER_G(cur_uploads) = 0;
1374+
1375+ return SUCCESS;
1376+}
1377+/* }}} */
1378+
1379+/* Remove if there's nothing to do at request end */
1380+/* {{{ PHP_RSHUTDOWN_FUNCTION
1381+ */
1382+PHP_RSHUTDOWN_FUNCTION(varfilter)
1383+{
1384+ return SUCCESS;
1385+}
1386+/* }}} */
1387+
1388+/* {{{ PHP_MINFO_FUNCTION
1389+ */
1390+PHP_MINFO_FUNCTION(varfilter)
1391+{
1392+ php_info_print_table_start();
1393+ php_info_print_table_header(2, "Hardening-Patch's variable filter support", "enabled");
1394+ php_info_print_table_end();
1395+
1396+ DISPLAY_INI_ENTRIES();
1397+}
1398+/* }}} */
1399+
1400+/* {{{ normalize_varname
1401+ */
1402+static void normalize_varname(char *varname)
1403+{
1404+ char *s=varname, *index=NULL, *indexend=NULL, *p;
1405+
1406+ /* overjump leading space */
1407+ while (*s == ' ') {
1408+ s++;
1409+ }
1410+
1411+ /* and remove it */
1412+ if (s != varname) {
1413+ memmove(varname, s, strlen(s)+1);
1414+ }
1415+
1416+ for (p=varname; *p && *p != '['; p++) {
1417+ switch(*p) {
1418+ case ' ':
1419+ case '.':
1420+ *p='_';
1421+ break;
1422+ }
1423+ }
1424+
1425+ /* find index */
1426+ index = strchr(varname, '[');
1427+ if (index) {
1428+ index++;
1429+ s=index;
1430+ } else {
1431+ return;
1432+ }
1433+
1434+ /* done? */
1435+ while (index) {
1436+
1437+ while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
1438+ index++;
1439+ }
1440+ indexend = strchr(index, ']');
1441+ indexend = indexend ? indexend + 1 : index + strlen(index);
1442+
1443+ if (s != index) {
1444+ memmove(s, index, strlen(index)+1);
1445+ s += indexend-index;
1446+ } else {
1447+ s = indexend;
1448+ }
1449+
1450+ if (*s == '[') {
1451+ s++;
1452+ index = s;
1453+ } else {
1454+ index = NULL;
1455+ }
1456+ }
1457+ *s++='\0';
1458+}
1459+/* }}} */
1460+
1461+/* {{{ SAPI_PRE_UPLOAD_FILTER_FUNC
1462+ */
1463+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter)
1464+{
1465+ /* Drop this fileupload if the limit is reached */
1466+ if (VARFILTER_G(max_uploads) && VARFILTER_G(max_uploads) <= VARFILTER_G(cur_uploads)) {
1467+ php_security_log(S_FILES, "configured fileupload limit exceeded - file dropped");
1468+ return FAILURE;
1469+ }
1470+
1471+ return SUCCESS;
1472+}
1473+/* }}} */
1474+
1475+/* {{{ SAPI_UPLOAD_CONTENT_FILTER_FUNC
1476+ */
1477+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter)
1478+{
1479+
1480+ if (VARFILTER_G(disallow_elf_files)) {
1481+
1482+ if (offset == 0 && buffer_len > 10) {
1483+
1484+ if (buffer[0] == 0x7F && buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'F') {
1485+ php_security_log(S_FILES, "uploaded file is an ELF executable - file dropped");
1486+ return FAILURE;
1487+ }
1488+ }
1489+
1490+ }
1491+
1492+ return SUCCESS;
1493+}
1494+/* }}} */
1495+
1496+/* {{{ SAPI_POST_UPLOAD_FILTER_FUNC
1497+ */
1498+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter)
1499+{
1500+ int retval = SUCCESS;
1501+
1502+ if (VARFILTER_G(verification_script)) {
1503+ char cmd[8192];
1504+ FILE *in;
1505+ int first=1;
1506+
1507+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s", VARFILTER_G(verification_script), tmpfilename);
1508+
1509+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
1510+ php_security_log(S_FILES, "unable to execute fileupload verification script - file dropped");
1511+ return FAILURE;
1512+ }
1513+
1514+ retval = FAILURE;
1515+
1516+ /* read and forget the result */
1517+ while (1) {
1518+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
1519+ if (readbytes<=0) {
1520+ break;
1521+ }
1522+ if (first) {
1523+ retval = atoi(cmd) == 1 ? SUCCESS : FAILURE;
1524+ first = 0;
1525+ }
1526+ }
1527+ pclose(in);
1528+ }
1529+
1530+ if (retval != SUCCESS) {
1531+ php_security_log(S_FILES, "fileupload verification script disallows file - file dropped");
1532+ return FAILURE;
1533+ }
1534+
1535+ VARFILTER_G(cur_uploads)++;
1536+ return SUCCESS;
1537+}
1538+/* }}} */
1539+
1540+/* {{{ SAPI_INPUT_FILTER_FUNC
1541+ */
1542+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter)
1543+{
1544+ char *index, *prev_index = NULL, *copy_var;
1545+ unsigned int var_len, total_len, depth = 0, rv;
1546+
1547+ /* Drop this variable if the limit is reached */
1548+ if (VARFILTER_G(max_request_variables) && VARFILTER_G(max_request_variables) <= VARFILTER_G(cur_request_variables)) {
1549+ php_security_log(S_VARS, "configured request variable limit exceeded - dropped %s", var);
1550+ return 0;
1551+ }
1552+ switch (arg) {
1553+ case PARSE_GET:
1554+ if (VARFILTER_G(max_get_vars) && VARFILTER_G(max_get_vars) <= VARFILTER_G(cur_get_vars)) {
1555+ php_security_log(S_VARS, "configured GET variable limit exceeded - dropped %s", var);
1556+ return 0;
1557+ }
1558+ break;
1559+ case PARSE_COOKIE:
1560+ if (VARFILTER_G(max_cookie_vars) && VARFILTER_G(max_cookie_vars) <= VARFILTER_G(cur_cookie_vars)) {
1561+ php_security_log(S_VARS, "configured COOKIE variable limit exceeded - dropped %s", var);
1562+ return 0;
1563+ }
1564+ break;
1565+ case PARSE_POST:
1566+ if (VARFILTER_G(max_post_vars) && VARFILTER_G(max_post_vars) <= VARFILTER_G(cur_post_vars)) {
1567+ php_security_log(S_VARS, "configured POST variable limit exceeded - dropped %s", var);
1568+ return 0;
1569+ }
1570+ break;
1571+ }
1572+
1573+
1574+ /* Drop this variable if it exceeds the value length limit */
1575+ if (VARFILTER_G(max_value_length) && VARFILTER_G(max_value_length) < val_len) {
1576+ php_security_log(S_VARS, "configured request variable value length limit exceeded - dropped %s", var);
1577+ return 0;
1578+ }
1579+ switch (arg) {
1580+ case PARSE_GET:
1581+ if (VARFILTER_G(max_get_value_length) && VARFILTER_G(max_get_value_length) < val_len) {
1582+ php_security_log(S_VARS, "configured GET variable value length limit exceeded - dropped %s", var);
1583+ return 0;
1584+ }
1585+ break;
1586+ case PARSE_COOKIE:
1587+ if (VARFILTER_G(max_cookie_value_length) && VARFILTER_G(max_cookie_value_length) < val_len) {
1588+ php_security_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped %s", var);
1589+ return 0;
1590+ }
1591+ break;
1592+ case PARSE_POST:
1593+ if (VARFILTER_G(max_post_value_length) && VARFILTER_G(max_post_value_length) < val_len) {
1594+ php_security_log(S_VARS, "configured POST variable value length limit exceeded - dropped %s", var);
1595+ return 0;
1596+ }
1597+ break;
1598+ }
1599+
1600+ /* Normalize the variable name */
1601+ normalize_varname(var);
1602+
1603+ /* Find length of variable name */
1604+ index = strchr(var, '[');
1605+ total_len = strlen(var);
1606+ var_len = index ? index-var : total_len;
1607+
1608+ /* Drop this variable if it exceeds the varname/total length limit */
1609+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
1610+ php_security_log(S_VARS, "configured request variable name length limit exceeded - dropped %s", var);
1611+ return 0;
1612+ }
1613+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
1614+ php_security_log(S_VARS, "configured request variable total name length limit exceeded - dropped %s", var);
1615+ return 0;
1616+ }
1617+ switch (arg) {
1618+ case PARSE_GET:
1619+ if (VARFILTER_G(max_get_name_length) && VARFILTER_G(max_get_name_length) < var_len) {
1620+ php_security_log(S_VARS, "configured GET variable name length limit exceeded - dropped %s", var);
1621+ return 0;
1622+ }
1623+ if (VARFILTER_G(max_get_totalname_length) && VARFILTER_G(max_get_totalname_length) < var_len) {
1624+ php_security_log(S_VARS, "configured GET variable total name length limit exceeded - dropped %s", var);
1625+ return 0;
1626+ }
1627+ break;
1628+ case PARSE_COOKIE:
1629+ if (VARFILTER_G(max_cookie_name_length) && VARFILTER_G(max_cookie_name_length) < var_len) {
1630+ php_security_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped %s", var);
1631+ return 0;
1632+ }
1633+ if (VARFILTER_G(max_cookie_totalname_length) && VARFILTER_G(max_cookie_totalname_length) < var_len) {
1634+ php_security_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped %s", var);
1635+ return 0;
1636+ }
1637+ break;
1638+ case PARSE_POST:
1639+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
1640+ php_security_log(S_VARS, "configured POST variable name length limit exceeded - dropped %s", var);
1641+ return 0;
1642+ }
1643+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
1644+ php_security_log(S_VARS, "configured POST variable total name length limit exceeded - dropped %s", var);
1645+ return 0;
1646+ }
1647+ break;
1648+ }
1649+
1650+ /* Find out array depth */
1651+ while (index) {
1652+ unsigned int index_length;
1653+
1654+ depth++;
1655+ index = strchr(index+1, '[');
1656+
1657+ if (prev_index) {
1658+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
1659+
1660+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
1661+ php_security_log(S_VARS, "configured request variable array index length limit exceeded - dropped %s", var);
1662+ return 0;
1663+ }
1664+ switch (arg) {
1665+ case PARSE_GET:
1666+ if (VARFILTER_G(max_get_array_index_length) && VARFILTER_G(max_get_array_index_length) < index_length) {
1667+ php_security_log(S_VARS, "configured GET variable array index length limit exceeded - dropped %s", var);
1668+ return 0;
1669+ }
1670+ break;
1671+ case PARSE_COOKIE:
1672+ if (VARFILTER_G(max_cookie_array_index_length) && VARFILTER_G(max_cookie_array_index_length) < index_length) {
1673+ php_security_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped %s", var);
1674+ return 0;
1675+ }
1676+ break;
1677+ case PARSE_POST:
1678+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
1679+ php_security_log(S_VARS, "configured POST variable array index length limit exceeded - dropped %s", var);
1680+ return 0;
1681+ }
1682+ break;
1683+ }
1684+ prev_index = index;
1685+ }
1686+
1687+ }
1688+
1689+ /* Drop this variable if it exceeds the array depth limit */
1690+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
1691+ php_security_log(S_VARS, "configured request variable array depth limit exceeded - dropped %s", var);
1692+ return 0;
1693+ }
1694+ switch (arg) {
1695+ case PARSE_GET:
1696+ if (VARFILTER_G(max_get_array_depth) && VARFILTER_G(max_get_array_depth) < depth) {
1697+ php_security_log(S_VARS, "configured GET variable array depth limit exceeded - dropped %s", var);
1698+ return 0;
1699+ }
1700+ break;
1701+ case PARSE_COOKIE:
1702+ if (VARFILTER_G(max_cookie_array_depth) && VARFILTER_G(max_cookie_array_depth) < depth) {
1703+ php_security_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped %s", var);
1704+ return 0;
1705+ }
1706+ break;
1707+ case PARSE_POST:
1708+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
1709+ php_security_log(S_VARS, "configured POST variable array depth limit exceeded - dropped %s", var);
1710+ return 0;
1711+ }
1712+ break;
1713+ }
1714+
1715+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
1716+ /* This is to protect several silly scripts that do globalizing themself */
1717+
1718+ switch (var_len) {
1719+ case 18:
1720+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname;
1721+ break;
1722+ case 17:
1723+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname;
1724+ break;
1725+ case 16:
1726+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname;
1727+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname;
1728+ break;
1729+ case 15:
1730+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname;
1731+ break;
1732+ case 14:
1733+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname;
1734+ break;
1735+ case 13:
1736+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname;
1737+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname;
1738+ break;
1739+ case 8:
1740+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname;
1741+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname;
1742+ break;
1743+ case 7:
1744+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname;
1745+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname;
1746+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname;
1747+ break;
1748+ case 6:
1749+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname;
1750+ break;
1751+ case 5:
1752+ if (memcmp(var, "_POST", 5)==0) goto protected_varname;
1753+ break;
1754+ case 4:
1755+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname;
1756+ if (memcmp(var, "_GET", 4)==0) goto protected_varname;
1757+ break;
1758+ }
1759+
1760+ /* Okay let PHP register this variable */
1761+ VARFILTER_G(cur_request_variables)++;
1762+ switch (arg) {
1763+ case PARSE_GET:
1764+ VARFILTER_G(cur_get_vars)++;
1765+ break;
1766+ case PARSE_COOKIE:
1767+ VARFILTER_G(cur_cookie_vars)++;
1768+ break;
1769+ case PARSE_POST:
1770+ VARFILTER_G(cur_post_vars)++;
1771+ break;
1772+ }
1773+
1774+ if (new_val_len) {
1775+ *new_val_len = val_len;
1776+ }
1777+
1778+ return 1;
1779+protected_varname:
1780+ php_security_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
1781+ return 0;
1782+}
1783+/* }}} */
1784+
1785+/*
1786+ * Local variables:
1787+ * tab-width: 4
1788+ * c-basic-offset: 4
1789+ * End:
1790+ * vim600: noet sw=4 ts=4 fdm=marker
1791+ * vim<600: noet sw=4 ts=4
1792+ */
1793+
1794+
1795diff -Naur php-4.3.11/main/fopen_wrappers.c hardening-patch-4.3.11-0.3.2/main/fopen_wrappers.c
1796--- php-4.3.11/main/fopen_wrappers.c 2005-02-03 00:44:07.000000000 +0100
1797+++ hardening-patch-4.3.11-0.3.2/main/fopen_wrappers.c 2005-07-09 08:53:02.483361136 +0200
1798@@ -166,6 +166,21 @@
1799 char *pathbuf;
1800 char *ptr;
1801 char *end;
1802+ char path_copy[MAXPATHLEN];
1803+ int path_len;
1804+
1805+ /* Special case path ends with a trailing slash */
1806+ path_len = strlen(path);
1807+ if (path_len >= MAXPATHLEN) {
1808+ errno = EPERM; /* we deny permission to open it */
1809+ return -1;
1810+ }
1811+ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) {
1812+ memcpy(path_copy, path, path_len+1);
1813+ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--;
1814+ path_copy[path_len] = '\0';
1815+ path = (const char *)&path_copy;
1816+ }
1817
1818 pathbuf = estrdup(PG(open_basedir));
1819
1820diff -Naur php-4.3.11/main/hardened_globals.h hardening-patch-4.3.11-0.3.2/main/hardened_globals.h
1821--- php-4.3.11/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100
1822+++ hardening-patch-4.3.11-0.3.2/main/hardened_globals.h 2005-07-09 08:53:02.483361136 +0200
1823@@ -0,0 +1,56 @@
1824+/*
1825+ +----------------------------------------------------------------------+
1826+ | Hardening-Patch for PHP |
1827+ +----------------------------------------------------------------------+
1828+ | Copyright (c) 2004-2005 Stefan Esser |
1829+ +----------------------------------------------------------------------+
1830+ | This source file is subject to version 2.02 of the PHP license, |
1831+ | that is bundled with this package in the file LICENSE, and is |
1832+ | available at through the world-wide-web at |
1833+ | http://www.php.net/license/2_02.txt. |
1834+ | If you did not receive a copy of the PHP license and are unable to |
1835+ | obtain it through the world-wide-web, please send a note to |
1836+ | license@php.net so we can mail you a copy immediately. |
1837+ +----------------------------------------------------------------------+
1838+ | Author: Stefan Esser <sesser@hardened-php.net> |
1839+ +----------------------------------------------------------------------+
1840+ */
1841+
1842+#ifndef HARDENED_GLOBALS_H
1843+#define HARDENED_GLOBALS_H
1844+
1845+typedef struct _hardened_globals hardened_globals_struct;
1846+
1847+#ifdef ZTS
1848+# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v)
1849+extern int hardened_globals_id;
1850+#else
1851+# define HG(v) (hardened_globals.v)
1852+extern struct _hardened_globals hardened_globals;
1853+#endif
1854+
1855+
1856+struct _hardened_globals {
1857+#if HARDENING_PATCH_MM_PROTECT
1858+ unsigned int canary_1;
1859+ unsigned int canary_2;
1860+#endif
1861+#if HARDENING_PATCH_LL_PROTECT
1862+ unsigned int canary_3;
1863+ unsigned int canary_4;
1864+ unsigned int ll_canary_inited;
1865+#endif
1866+ zend_bool hphp_sql_bailout_on_error;
1867+ zend_bool hphp_multiheader;
1868+ unsigned int dummy;
1869+};
1870+
1871+
1872+#endif /* HARDENED_GLOBALS_H */
1873+
1874+/*
1875+ * Local variables:
1876+ * tab-width: 4
1877+ * c-basic-offset: 4
1878+ * End:
1879+ */
1880diff -Naur php-4.3.11/main/hardening_patch.c hardening-patch-4.3.11-0.3.2/main/hardening_patch.c
1881--- php-4.3.11/main/hardening_patch.c 1970-01-01 01:00:00.000000000 +0100
1882+++ hardening-patch-4.3.11-0.3.2/main/hardening_patch.c 2005-07-09 08:53:02.484360984 +0200
1883@@ -0,0 +1,322 @@
1884+/*
1885+ +----------------------------------------------------------------------+
1886+ | Hardening Patch for PHP |
1887+ +----------------------------------------------------------------------+
1888+ | Copyright (c) 2004-2005 Stefan Esser |
1889+ +----------------------------------------------------------------------+
1890+ | This source file is subject to version 2.02 of the PHP license, |
1891+ | that is bundled with this package in the file LICENSE, and is |
1892+ | available at through the world-wide-web at |
1893+ | http://www.php.net/license/2_02.txt. |
1894+ | If you did not receive a copy of the PHP license and are unable to |
1895+ | obtain it through the world-wide-web, please send a note to |
1896+ | license@php.net so we can mail you a copy immediately. |
1897+ +----------------------------------------------------------------------+
1898+ | Author: Stefan Esser <sesser@hardened-php.net> |
1899+ +----------------------------------------------------------------------+
1900+ */
1901+/* $Id: hardening_patch.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */
1902+
1903+#include "php.h"
1904+
1905+#include <stdio.h>
1906+#include <stdlib.h>
1907+
1908+#if HAVE_UNISTD_H
1909+#include <unistd.h>
1910+#endif
1911+#include "SAPI.h"
1912+#include "php_globals.h"
1913+
1914+#if HARDENING_PATCH
1915+
1916+#ifdef HAVE_SYS_SOCKET_H
1917+#include <sys/socket.h>
1918+#endif
1919+
1920+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
1921+#undef AF_UNIX
1922+#endif
1923+
1924+#if defined(AF_UNIX)
1925+#include <sys/un.h>
1926+#endif
1927+
1928+#define SYSLOG_PATH "/dev/log"
1929+
1930+#include "snprintf.h"
1931+
1932+#include "hardening_patch.h"
1933+
1934+#ifdef ZTS
1935+#include "hardened_globals.h"
1936+int hardened_globals_id;
1937+#else
1938+struct _hardened_globals hardened_globals;
1939+#endif
1940+
1941+static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC)
1942+{
1943+ memset(hardened_globals, 0, sizeof(*hardened_globals));
1944+}
1945+
1946+
1947+PHPAPI void hardened_startup()
1948+{
1949+#ifdef ZTS
1950+ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL);
1951+#else
1952+ hardened_globals_ctor(&hardened_globals TSRMLS_CC);
1953+#endif
1954+}
1955+
1956+char *loglevel2string(int loglevel)
1957+{
1958+ switch (loglevel) {
1959+ case S_FILES:
1960+ return "FILES";
1961+ case S_INCLUDE:
1962+ return "INCLUDE";
1963+ case S_MEMORY:
1964+ return "MEMORY";
1965+ case S_MISC:
1966+ return "MISC";
1967+ case S_SQL:
1968+ return "SQL";
1969+ case S_EXECUTOR:
1970+ return "EXECUTOR";
1971+ case S_VARS:
1972+ return "VARS";
1973+ default:
1974+ return "UNKNOWN";
1975+ }
1976+}
1977+
1978+PHPAPI void php_security_log(int loglevel, char *fmt, ...)
1979+{
1980+#if defined(AF_UNIX)
1981+ int s, r, i=0;
1982+ struct sockaddr_un saun;
1983+ char buf[4096+64];
1984+ char error[4096+100];
1985+ char *ip_address;
1986+ char *fname;
1987+ int lineno;
1988+ va_list ap;
1989+ TSRMLS_FETCH();
1990+
1991+ if (EG(hphp_log_use_x_forwarded_for)) {
1992+ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
1993+ if (ip_address == NULL) {
1994+ ip_address = "X-FORWARDED-FOR not set";
1995+ }
1996+ } else {
1997+ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
1998+ if (ip_address == NULL) {
1999+ ip_address = "REMOTE_ADDR not set";
2000+ }
2001+ }
2002+
2003+
2004+ va_start(ap, fmt);
2005+ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
2006+ va_end(ap);
2007+ while (error[i]) {
2008+ if (error[i] < 32) error[i] = '.';
2009+ i++;
2010+ }
2011+
2012+ if (zend_is_executing(TSRMLS_C)) {
2013+ lineno = zend_get_executed_lineno(TSRMLS_C);
2014+ fname = zend_get_executed_filename(TSRMLS_C);
2015+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s', line %u)", error, ip_address, fname, lineno);
2016+ } else {
2017+ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
2018+ if (fname==NULL) {
2019+ fname = "unknown";
2020+ }
2021+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s')", error, ip_address, fname);
2022+ }
2023+
2024+ /* Syslog-Logging disabled? */
2025+ if ((EG(hphp_log_syslog) & loglevel)==0) {
2026+ goto log_sapi;
2027+ }
2028+
2029+ ap_php_snprintf(error, sizeof(error), "<%u>hphp[%u]: %s\n", EG(hphp_log_syslog_facility)|EG(hphp_log_syslog_priority),getpid(),buf);
2030+
2031+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
2032+ if (s == -1) {
2033+ goto log_sapi;
2034+ }
2035+
2036+ memset(&saun, 0, sizeof(saun));
2037+ saun.sun_family = AF_UNIX;
2038+ strcpy(saun.sun_path, SYSLOG_PATH);
2039+ /*saun.sun_len = sizeof(saun);*/
2040+
2041+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
2042+ if (r) {
2043+ close(s);
2044+ s = socket(AF_UNIX, SOCK_STREAM, 0);
2045+ if (s == -1) {
2046+ goto log_sapi;
2047+ }
2048+
2049+ memset(&saun, 0, sizeof(saun));
2050+ saun.sun_family = AF_UNIX;
2051+ strcpy(saun.sun_path, SYSLOG_PATH);
2052+ /*saun.sun_len = sizeof(saun);*/
2053+
2054+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
2055+ if (r) {
2056+ close(s);
2057+ goto log_sapi;
2058+ }
2059+ }
2060+ send(s, error, strlen(error), 0);
2061+
2062+ close(s);
2063+
2064+log_sapi:
2065+ /* SAPI Logging activated? */
2066+ if ((EG(hphp_log_syslog) & loglevel)!=0) {
2067+ sapi_module.log_message(buf);
2068+ }
2069+
2070+log_script:
2071+ /* script logging activaed? */
2072+ if (((EG(hphp_log_script) & loglevel)!=0) && EG(hphp_log_scriptname)!=NULL) {
2073+ char cmd[8192], *cmdpos, *bufpos;
2074+ FILE *in;
2075+ int space;
2076+
2077+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", EG(hphp_log_scriptname), loglevel2string(loglevel));
2078+ space = sizeof(cmd) - strlen(cmd);
2079+ cmdpos = cmd + strlen(cmd);
2080+ bufpos = buf;
2081+ if (space <= 1) return;
2082+ while (space > 2 && *bufpos) {
2083+ if (*bufpos == '\'') {
2084+ if (space<=5) break;
2085+ *cmdpos++ = '\'';
2086+ *cmdpos++ = '\\';
2087+ *cmdpos++ = '\'';
2088+ *cmdpos++ = '\'';
2089+ bufpos++;
2090+ space-=4;
2091+ } else {
2092+ *cmdpos++ = *bufpos++;
2093+ space--;
2094+ }
2095+ }
2096+ *cmdpos++ = '\'';
2097+ *cmdpos = 0;
2098+
2099+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
2100+ return;
2101+ }
2102+ /* read and forget the result */
2103+ while (1) {
2104+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
2105+ if (readbytes<=0) {
2106+ break;
2107+ }
2108+ }
2109+ pclose(in);
2110+ }
2111+
2112+#endif
2113+}
2114+#endif
2115+
2116+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
2117+
2118+/* will be replaced later with more compatible method */
2119+PHPAPI unsigned int php_canary()
2120+{
2121+ time_t t;
2122+ unsigned int canary;
2123+ int fd;
2124+
2125+ fd = open("/dev/urandom", 0);
2126+ if (fd != -1) {
2127+ int r = read(fd, &canary, sizeof(canary));
2128+ close(fd);
2129+ if (r == sizeof(canary)) {
2130+ return (canary);
2131+ }
2132+ }
2133+ /* not good but we never want to do this */
2134+ time(&t);
2135+ canary = *(unsigned int *)&t + getpid() << 16;
2136+ return (canary);
2137+}
2138+#endif
2139+
2140+#if HARDENING_PATCH_INC_PROTECT
2141+
2142+PHPAPI int php_is_valid_include(zval *z)
2143+{
2144+ char *filename;
2145+ int len, i;
2146+ TSRMLS_FETCH();
2147+
2148+ /* must be of type string */
2149+ if (z->type != IS_STRING || z->value.str.val == NULL) {
2150+ return (0);
2151+ }
2152+
2153+ /* short cut */
2154+ filename = z->value.str.val;
2155+ len = z->value.str.len;
2156+
2157+ /* 1. must be shorter than MAXPATHLEN */
2158+ if (len > MAXPATHLEN) {
2159+ char *fname = estrndup(filename, len);
2160+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
2161+ php_security_log(S_INCLUDE, "Include filename ('%s') longer than MAXPATHLEN chars", fname);
2162+ efree(fname);
2163+ return (0);
2164+ }
2165+
2166+ /* 2. must not be cutted */
2167+ if (len != strlen(filename)) {
2168+ char *fname = estrndup(filename, len);
2169+ for (i=0; fname[i]; i++) if (fname[i] < 32) fname[i]='.';
2170+ php_security_log(S_INCLUDE, "Include filename truncated by a \\0 after '%s'", fname);
2171+ efree(fname);
2172+ return (0);
2173+ }
2174+
2175+ /* 3. must not be a URL */
2176+ if (strstr(filename, "://")) {
2177+ char *fname = estrndup(filename, len);
2178+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
2179+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL", fname);
2180+ efree(fname);
2181+ return (0);
2182+ }
2183+
2184+ /* 4. must not be an uploaded file */
2185+ if (SG(rfc1867_uploaded_files)) {
2186+ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) {
2187+ php_security_log(S_INCLUDE, "Include filename is an uploaded file");
2188+ return (0);
2189+ }
2190+ }
2191+
2192+ /* passed all tests */
2193+ return (1);
2194+}
2195+
2196+#endif
2197+
2198+/*
2199+ * Local variables:
2200+ * tab-width: 4
2201+ * c-basic-offset: 4
2202+ * End:
2203+ * vim600: sw=4 ts=4 fdm=marker
2204+ * vim<600: sw=4 ts=4
2205+ */
2206diff -Naur php-4.3.11/main/hardening_patch.h hardening-patch-4.3.11-0.3.2/main/hardening_patch.h
2207--- php-4.3.11/main/hardening_patch.h 1970-01-01 01:00:00.000000000 +0100
2208+++ hardening-patch-4.3.11-0.3.2/main/hardening_patch.h 2005-07-09 08:57:24.527524368 +0200
2209@@ -0,0 +1,46 @@
2210+/*
2211+ +----------------------------------------------------------------------+
2212+ | Hardening Patch for PHP |
2213+ +----------------------------------------------------------------------+
2214+ | Copyright (c) 2004-2005 Stefan Esser |
2215+ +----------------------------------------------------------------------+
2216+ | This source file is subject to version 2.02 of the PHP license, |
2217+ | that is bundled with this package in the file LICENSE, and is |
2218+ | available at through the world-wide-web at |
2219+ | http://www.php.net/license/2_02.txt. |
2220+ | If you did not receive a copy of the PHP license and are unable to |
2221+ | obtain it through the world-wide-web, please send a note to |
2222+ | license@php.net so we can mail you a copy immediately. |
2223+ +----------------------------------------------------------------------+
2224+ | Author: Stefan Esser <sesser@hardened-php.net> |
2225+ +----------------------------------------------------------------------+
2226+ */
2227+
2228+#ifndef HARDENING_PATCH_H
2229+#define HARDENING_PATCH_H
2230+
2231+#include "zend.h"
2232+
2233+#if HARDENING_PATCH
2234+PHPAPI void php_security_log(int loglevel, char *fmt, ...);
2235+PHPAPI void hardened_startup();
2236+#define HARDENING_PATCH_VERSION "0.3.2"
2237+
2238+#endif
2239+
2240+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
2241+PHPAPI unsigned int php_canary();
2242+#endif
2243+
2244+#if HARDENING_PATCH_INC_PROTECT
2245+PHPAPI int php_is_valid_include(zval *z);
2246+#endif
2247+
2248+#endif /* HARDENING_PATCH_H */
2249+
2250+/*
2251+ * Local variables:
2252+ * tab-width: 4
2253+ * c-basic-offset: 4
2254+ * End:
2255+ */
2256diff -Naur php-4.3.11/main/hardening_patch.m4 hardening-patch-4.3.11-0.3.2/main/hardening_patch.m4
2257--- php-4.3.11/main/hardening_patch.m4 1970-01-01 01:00:00.000000000 +0100
2258+++ hardening-patch-4.3.11-0.3.2/main/hardening_patch.m4 2005-07-09 08:53:02.485360832 +0200
2259@@ -0,0 +1,95 @@
2260+dnl
2261+dnl $Id: hardening_patch.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $
2262+dnl
2263+dnl This file contains Hardening Patch for PHP specific autoconf functions.
2264+dnl
2265+
2266+AC_ARG_ENABLE(hardening-patch-mm-protect,
2267+[ --disable-hardening-patch-mm-protect Disable the Memory Manager protection.],[
2268+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
2269+],[
2270+ DO_HARDENING_PATCH_MM_PROTECT=yes
2271+])
2272+
2273+AC_ARG_ENABLE(hardening-patch-ll-protect,
2274+[ --disable-hardening-patch-ll-protect Disable the Linked List protection.],[
2275+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
2276+],[
2277+ DO_HARDENING_PATCH_LL_PROTECT=yes
2278+])
2279+
2280+AC_ARG_ENABLE(hardening-patch-inc-protect,
2281+[ --disable-hardening-patch-inc-protect Disable include/require protection.],[
2282+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
2283+],[
2284+ DO_HARDENING_PATCH_INC_PROTECT=yes
2285+])
2286+
2287+AC_ARG_ENABLE(hardening-patch-fmt-protect,
2288+[ --disable-hardening-patch-fmt-protect Disable format string protection.],[
2289+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
2290+],[
2291+ DO_HARDENING_PATCH_FMT_PROTECT=yes
2292+])
2293+
2294+AC_ARG_ENABLE(hardening-patch-hash-protect,
2295+[ --disable-hardening-patch-hash-protect Disable HashTable destructor protection.],[
2296+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
2297+],[
2298+ DO_HARDENING_PATCH_HASH_PROTECT=yes
2299+])
2300+
2301+AC_MSG_CHECKING(whether to protect the Zend Memory Manager)
2302+AC_MSG_RESULT($DO_HARDENING_PATCH_MM_PROTECT)
2303+
2304+AC_MSG_CHECKING(whether to protect the Zend Linked Lists)
2305+AC_MSG_RESULT($DO_HARDENING_PATCH_LL_PROTECT)
2306+
2307+AC_MSG_CHECKING(whether to protect include/require statements)
2308+AC_MSG_RESULT($DO_HARDENING_PATCH_INC_PROTECT)
2309+
2310+AC_MSG_CHECKING(whether to protect PHP Format String functions)
2311+AC_MSG_RESULT($DO_HARDENING_PATCH_FMT_PROTECT)
2312+
2313+AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables)
2314+AC_MSG_RESULT($DO_HARDENING_PATCH_HASH_PROTECT)
2315+
2316+
2317+AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2318+
2319+
2320+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
2321+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2322+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 1, [Memory Manager Protection])
2323+else
2324+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 0, [Memory Manager Protection])
2325+fi
2326+
2327+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
2328+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2329+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 1, [Linked List Protection])
2330+else
2331+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 0, [Linked List Protection])
2332+fi
2333+
2334+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
2335+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2336+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 1, [Include/Require Protection])
2337+else
2338+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 0, [Include/Require Protection])
2339+fi
2340+
2341+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
2342+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2343+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 1, [Fmt String Protection])
2344+else
2345+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 0, [Fmt String Protection])
2346+fi
2347+
2348+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
2349+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2350+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 1, [HashTable DTOR Protection])
2351+else
2352+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 0, [HashTable DTOR Protection])
2353+fi
2354+
2355diff -Naur php-4.3.11/main/main.c hardening-patch-4.3.11-0.3.2/main/main.c
2356--- php-4.3.11/main/main.c 2005-03-08 22:45:51.000000000 +0100
2357+++ hardening-patch-4.3.11-0.3.2/main/main.c 2005-07-09 08:53:02.486360680 +0200
2358@@ -100,6 +100,10 @@
2359 PHPAPI int core_globals_id;
2360 #endif
2361
2362+#if HARDENING_PATCH
2363+#include "hardened_globals.h"
2364+#endif
2365+
2366 #define ERROR_BUF_LEN 1024
2367
2368 typedef struct {
2369@@ -150,10 +154,33 @@
2370 */
2371 static PHP_INI_MH(OnChangeMemoryLimit)
2372 {
2373+#if HARDENING_PATCH
2374+ long orig_memory_limit;
2375+
2376+ if (entry->modified) {
2377+ orig_memory_limit = zend_atoi(entry->orig_value, entry->orig_value_length);
2378+ } else {
2379+ orig_memory_limit = 1<<30;
2380+ }
2381+ if (orig_memory_limit < 0 || orig_memory_limit > (1<<30)) {
2382+ orig_memory_limit = 1<<30;
2383+ }
2384+#endif
2385 if (new_value) {
2386 PG(memory_limit) = zend_atoi(new_value, new_value_length);
2387+#if HARDENING_PATCH
2388+ if (PG(memory_limit) > orig_memory_limit) {
2389+ PG(memory_limit) = orig_memory_limit;
2390+ php_security_log(S_MISC, "script tried to increase memory_limit above allowed value");
2391+ return FAILURE;
2392+ }
2393+#endif
2394 } else {
2395+#if HARDENING_PATCH
2396+ PG(memory_limit) = orig_memory_limit;
2397+#else
2398 PG(memory_limit) = 1<<30; /* effectively, no limit */
2399+#endif
2400 }
2401 return zend_set_memory_limit(PG(memory_limit));
2402 }
2403@@ -1092,6 +1119,10 @@
2404 tsrm_ls = ts_resource(0);
2405 #endif
2406
2407+#if HARDENING_PATCH
2408+ hardened_startup();
2409+#endif
2410+
2411 sapi_initialize_empty_request(TSRMLS_C);
2412 sapi_activate(TSRMLS_C);
2413
2414@@ -1104,6 +1135,12 @@
2415 php_output_startup();
2416 php_output_activate(TSRMLS_C);
2417
2418+#if HARDENING_PATCH_INC_PROTECT
2419+ zuf.is_valid_include = php_is_valid_include;
2420+#endif
2421+#if HARDENING_PATCH
2422+ zuf.security_log_function = php_security_log;
2423+#endif
2424 zuf.error_function = php_error_cb;
2425 zuf.printf_function = php_printf;
2426 zuf.write_function = php_body_write_wrapper;
2427@@ -1205,6 +1242,10 @@
2428 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, sizeof(PHP_CONFIG_FILE_PATH)-1, CONST_PERSISTENT | CONST_CS);
2429 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
2430 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
2431+#if HARDENING_PATCH
2432+ REGISTER_MAIN_LONG_CONSTANT("HARDENING_PATCH", 1, CONST_PERSISTENT | CONST_CS);
2433+ REGISTER_MAIN_STRINGL_CONSTANT("HARDENING_PATCH_VERSION", HARDENING_PATCH_VERSION, sizeof(HARDENING_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
2434+#endif
2435 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
2436 php_output_register_constants(TSRMLS_C);
2437 php_rfc1867_register_constants(TSRMLS_C);
2438@@ -1310,7 +1351,7 @@
2439 */
2440 static inline void php_register_server_variables(TSRMLS_D)
2441 {
2442- zval *array_ptr=NULL;
2443+ zval *array_ptr=NULL, *vptr;
2444
2445 ALLOC_ZVAL(array_ptr);
2446 array_init(array_ptr);
2447@@ -1320,6 +1361,16 @@
2448 /* Server variables */
2449 if (sapi_module.register_server_variables) {
2450 sapi_module.register_server_variables(array_ptr TSRMLS_CC);
2451+ if (zend_hash_find(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"), (void **)&vptr)==SUCCESS) {
2452+ char *str;
2453+ if (vptr->type != IS_STRING) {
2454+ str = "Array";
2455+ } else {
2456+ str = vptr->value.str.val;
2457+ }
2458+ php_security_log(S_VARS, "Attacker tried to overwrite HTTP_RAW_POST_DATA with '%s' through a HTTP header", str);
2459+ zend_hash_del(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
2460+ }
2461 }
2462
2463 /* PHP Authentication support */
2464diff -Naur php-4.3.11/main/php_config.h.in hardening-patch-4.3.11-0.3.2/main/php_config.h.in
2465--- php-4.3.11/main/php_config.h.in 2005-03-30 16:35:47.000000000 +0200
2466+++ hardening-patch-4.3.11-0.3.2/main/php_config.h.in 2005-07-09 08:53:02.487360528 +0200
2467@@ -839,6 +839,39 @@
2468 /* Enabling BIND8 compatibility for Panther */
2469 #undef BIND_8_COMPAT
2470
2471+/* Hardening-Patch */
2472+#undef HARDENING_PATCH
2473+
2474+/* Memory Manager Protection */
2475+#undef HARDENING_PATCH_MM_PROTECT
2476+
2477+/* Memory Manager Protection */
2478+#undef HARDENING_PATCH_MM_PROTECT
2479+
2480+/* Linked List Protection */
2481+#undef HARDENING_PATCH_LL_PROTECT
2482+
2483+/* Linked List Protection */
2484+#undef HARDENING_PATCH_LL_PROTECT
2485+
2486+/* Include/Require Protection */
2487+#undef HARDENING_PATCH_INC_PROTECT
2488+
2489+/* Include/Require Protection */
2490+#undef HARDENING_PATCH_INC_PROTECT
2491+
2492+/* Fmt String Protection */
2493+#undef HARDENING_PATCH_FMT_PROTECT
2494+
2495+/* Fmt String Protection */
2496+#undef HARDENING_PATCH_FMT_PROTECT
2497+
2498+/* HashTable DTOR Protection */
2499+#undef HARDENING_PATCH_HASH_PROTECT
2500+
2501+/* HashTable DTOR Protection */
2502+#undef HARDENING_PATCH_HASH_PROTECT
2503+
2504 /* Whether you have AOLserver */
2505 #undef HAVE_AOLSERVER
2506
2507@@ -1122,6 +1155,12 @@
2508 /* Define if you have the getaddrinfo function */
2509 #undef HAVE_GETADDRINFO
2510
2511+/* Whether realpath is broken */
2512+#undef PHP_BROKEN_REALPATH
2513+
2514+/* Whether realpath is broken */
2515+#undef PHP_BROKEN_REALPATH
2516+
2517 /* Whether system headers declare timezone */
2518 #undef HAVE_DECLARED_TIMEZONE
2519
2520diff -Naur php-4.3.11/main/php_content_types.c hardening-patch-4.3.11-0.3.2/main/php_content_types.c
2521--- php-4.3.11/main/php_content_types.c 2002-12-31 17:26:14.000000000 +0100
2522+++ hardening-patch-4.3.11-0.3.2/main/php_content_types.c 2005-07-09 08:53:02.487360528 +0200
2523@@ -77,6 +77,7 @@
2524 sapi_register_post_entries(php_post_entries);
2525 sapi_register_default_post_reader(php_default_post_reader);
2526 sapi_register_treat_data(php_default_treat_data);
2527+ sapi_register_input_filter(php_default_input_filter);
2528 return SUCCESS;
2529 }
2530 /* }}} */
2531diff -Naur php-4.3.11/main/php.h hardening-patch-4.3.11-0.3.2/main/php.h
2532--- php-4.3.11/main/php.h 2005-03-08 22:45:51.000000000 +0100
2533+++ hardening-patch-4.3.11-0.3.2/main/php.h 2005-07-09 08:53:02.488360376 +0200
2534@@ -26,7 +26,7 @@
2535 #include <dmalloc.h>
2536 #endif
2537
2538-#define PHP_API_VERSION 20020918
2539+#define PHP_API_VERSION 1020050626
2540 #define PHP_HAVE_STREAMS
2541 #define YYDEBUG 0
2542
2543@@ -35,11 +35,19 @@
2544 #include "zend_qsort.h"
2545 #include "php_compat.h"
2546
2547+
2548 #include "zend_API.h"
2549
2550 #undef sprintf
2551 #define sprintf php_sprintf
2552
2553+#if HARDENING_PATCH
2554+#if HAVE_REALPATH
2555+#undef realpath
2556+#define realpath php_realpath
2557+#endif
2558+#endif
2559+
2560 /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */
2561 #undef PHP_DEBUG
2562 #define PHP_DEBUG ZEND_DEBUG
2563@@ -436,6 +444,10 @@
2564 #endif
2565 #endif /* !XtOffsetOf */
2566
2567+#if HARDENING_PATCH
2568+#include "hardening_patch.h"
2569+#endif
2570+
2571 #endif
2572
2573 /*
2574diff -Naur php-4.3.11/main/php_variables.c hardening-patch-4.3.11-0.3.2/main/php_variables.c
2575--- php-4.3.11/main/php_variables.c 2004-10-18 17:08:46.000000000 +0200
2576+++ hardening-patch-4.3.11-0.3.2/main/php_variables.c 2005-07-09 08:53:02.488360376 +0200
2577@@ -211,17 +211,28 @@
2578 while (var) {
2579 val = strchr(var, '=');
2580 if (val) { /* have a value */
2581- int val_len;
2582+ unsigned int val_len, new_val_len;
2583
2584 *val++ = '\0';
2585 php_url_decode(var, strlen(var));
2586 val_len = php_url_decode(val, strlen(val));
2587- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
2588+ val = estrndup(val, val_len);
2589+ if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) {
2590+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
2591+ }
2592+ efree(val);
2593 }
2594 var = php_strtok_r(NULL, "&", &strtok_buf);
2595 }
2596 }
2597
2598+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter)
2599+{
2600+ /* TODO: check .ini setting here and apply user-defined input filter */
2601+ *new_val_len = val_len;
2602+ return 1;
2603+}
2604+
2605 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
2606 {
2607 char *res = NULL, *var, *val, *separator=NULL;
2608@@ -299,15 +310,26 @@
2609 while (var) {
2610 val = strchr(var, '=');
2611 if (val) { /* have a value */
2612- int val_len;
2613+ unsigned int val_len, new_val_len;
2614
2615 *val++ = '\0';
2616 php_url_decode(var, strlen(var));
2617 val_len = php_url_decode(val, strlen(val));
2618- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
2619+ val = estrndup(val, val_len);
2620+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
2621+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
2622+ }
2623+ efree(val);
2624 } else {
2625+ unsigned int val_len, new_val_len;
2626+
2627 php_url_decode(var, strlen(var));
2628- php_register_variable_safe(var, "", 0, array_ptr TSRMLS_CC);
2629+ val_len = 0;
2630+ val = estrndup("", 0);
2631+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
2632+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
2633+ }
2634+ efree(val);
2635 }
2636 var = php_strtok_r(NULL, separator, &strtok_buf);
2637 }
2638diff -Naur php-4.3.11/main/rfc1867.c hardening-patch-4.3.11-0.3.2/main/rfc1867.c
2639--- php-4.3.11/main/rfc1867.c 2005-02-15 01:28:39.000000000 +0100
2640+++ hardening-patch-4.3.11-0.3.2/main/rfc1867.c 2005-07-09 08:53:02.489360224 +0200
2641@@ -127,6 +127,7 @@
2642 #define UPLOAD_ERROR_C 3 /* Partially uploaded */
2643 #define UPLOAD_ERROR_D 4 /* No file uploaded */
2644 #define UPLOAD_ERROR_E 6 /* Missing /tmp or similar directory */
2645+#define UPLOAD_ERROR_F 7 /* Filter forbids upload */
2646
2647 void php_rfc1867_register_constants(TSRMLS_D)
2648 {
2649@@ -136,6 +137,7 @@
2650 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_PARTIAL", UPLOAD_ERROR_C, CONST_CS | CONST_PERSISTENT);
2651 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE", UPLOAD_ERROR_D, CONST_CS | CONST_PERSISTENT);
2652 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E, CONST_CS | CONST_PERSISTENT);
2653+ REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FILTER", UPLOAD_ERROR_F, CONST_CS | CONST_PERSISTENT);
2654 }
2655
2656 static void normalize_protected_variable(char *varname TSRMLS_DC)
2657@@ -844,6 +846,7 @@
2658 char buff[FILLUNIT];
2659 char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL;
2660 int blen=0, wlen=0;
2661+ unsigned long offset;
2662
2663 zend_llist_clean(&header);
2664
2665@@ -891,21 +894,24 @@
2666 if (!filename && param) {
2667
2668 char *value = multipart_buffer_read_body(mbuff TSRMLS_CC);
2669+ unsigned int new_val_len; /* Dummy variable */
2670
2671 if (!value) {
2672 value = estrdup("");
2673 }
2674
2675+ if (sapi_module.input_filter(PARSE_POST, param, &value, strlen(value), &new_val_len TSRMLS_CC)) {
2676 #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
2677- if (php_mb_encoding_translation(TSRMLS_C)) {
2678- php_mb_gpc_stack_variable(param, value, &val_list, &len_list,
2679- &num_vars, &num_vars_max TSRMLS_CC);
2680- } else {
2681- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2682- }
2683+ if (php_mb_encoding_translation(TSRMLS_C)) {
2684+ php_mb_gpc_stack_variable(param, value, &val_list, &len_list,
2685+ &num_vars, &num_vars_max TSRMLS_CC);
2686+ } else {
2687+ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2688+ }
2689 #else
2690- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2691+ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2692 #endif
2693+ }
2694 if (!strcasecmp(param, "MAX_FILE_SIZE")) {
2695 max_file_size = atol(value);
2696 }
2697@@ -981,6 +987,11 @@
2698 cancel_upload = UPLOAD_ERROR_D;
2699 }
2700
2701+ if (sapi_module.pre_upload_filter && sapi_module.pre_upload_filter(param, filename TSRMLS_CC)==FAILURE) {
2702+ cancel_upload = UPLOAD_ERROR_F;
2703+ }
2704+
2705+ offset = 0;
2706 while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff) TSRMLS_CC)))
2707 {
2708 if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) {
2709@@ -990,6 +1001,11 @@
2710 sapi_module.sapi_error(E_WARNING, "MAX_FILE_SIZE of %ld bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename);
2711 cancel_upload = UPLOAD_ERROR_B;
2712 } else if (blen > 0) {
2713+
2714+ if (sapi_module.upload_content_filter && sapi_module.upload_content_filter(offset, buff, blen, &blen TSRMLS_CC)==FAILURE) {
2715+ cancel_upload = UPLOAD_ERROR_F;
2716+ }
2717+
2718 wlen = fwrite(buff, 1, blen, fp);
2719
2720 if (wlen < blen) {
2721@@ -997,6 +1013,7 @@
2722 cancel_upload = UPLOAD_ERROR_C;
2723 } else {
2724 total_bytes += wlen;
2725+ offset += wlen;
2726 }
2727 }
2728 }
2729@@ -1011,6 +1028,10 @@
2730 }
2731 #endif
2732
2733+ if (!cancel_upload && sapi_module.post_upload_filter && sapi_module.post_upload_filter(temp_filename TSRMLS_CC)==FAILURE) {
2734+ cancel_upload = UPLOAD_ERROR_F;
2735+ }
2736+
2737 if (cancel_upload) {
2738 if (temp_filename) {
2739 if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
2740diff -Naur php-4.3.11/main/SAPI.c hardening-patch-4.3.11-0.3.2/main/SAPI.c
2741--- php-4.3.11/main/SAPI.c 2005-02-22 15:46:24.000000000 +0100
2742+++ hardening-patch-4.3.11-0.3.2/main/SAPI.c 2005-07-09 08:53:02.490360072 +0200
2743@@ -831,6 +831,31 @@
2744 return SUCCESS;
2745 }
2746
2747+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
2748+{
2749+ sapi_module.input_filter = input_filter;
2750+ return SUCCESS;
2751+}
2752+
2753+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC))
2754+{
2755+ sapi_module.pre_upload_filter = pre_upload_filter;
2756+ return SUCCESS;
2757+}
2758+
2759+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC))
2760+{
2761+ sapi_module.upload_content_filter = upload_content_filter;
2762+ return SUCCESS;
2763+}
2764+
2765+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC))
2766+{
2767+ sapi_module.post_upload_filter = post_upload_filter;
2768+ return SUCCESS;
2769+}
2770+
2771+
2772
2773 SAPI_API int sapi_flush(TSRMLS_D)
2774 {
2775diff -Naur php-4.3.11/main/SAPI.h hardening-patch-4.3.11-0.3.2/main/SAPI.h
2776--- php-4.3.11/main/SAPI.h 2003-04-09 22:27:55.000000000 +0200
2777+++ hardening-patch-4.3.11-0.3.2/main/SAPI.h 2005-07-09 08:53:02.491359920 +0200
2778@@ -101,9 +101,10 @@
2779 char *current_user;
2780 int current_user_length;
2781
2782- /* this is necessary for CLI module */
2783- int argc;
2784- char **argv;
2785+ /* this is necessary for CLI module */
2786+ int argc;
2787+ char **argv;
2788+
2789 } sapi_request_info;
2790
2791
2792@@ -177,6 +178,10 @@
2793 SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry);
2794 SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D));
2795 SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC));
2796+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC));
2797+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC));
2798+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC));
2799+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC));
2800
2801 SAPI_API int sapi_flush(TSRMLS_D);
2802 SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
2803@@ -238,8 +243,15 @@
2804 int (*get_target_uid)(uid_t * TSRMLS_DC);
2805 int (*get_target_gid)(gid_t * TSRMLS_DC);
2806
2807+ unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
2808+
2809+ unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC);
2810+ unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC);
2811+ unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC);
2812+
2813 void (*ini_defaults)(HashTable *configuration_hash);
2814 int phpinfo_as_text;
2815+
2816 };
2817
2818
2819@@ -262,16 +274,26 @@
2820
2821 #define SAPI_DEFAULT_MIMETYPE "text/html"
2822 #define SAPI_DEFAULT_CHARSET ""
2823+
2824+#if HARDENING_PATCH
2825+#define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION " with Hardening-Patch"
2826+#else
2827 #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION
2828+#endif
2829
2830 #define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D)
2831 #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC)
2832
2833 #define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC)
2834+#define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
2835+#define SAPI_PRE_UPLOAD_FILTER_FUNC(pre_upload_filter) unsigned int pre_upload_filter(char *varname, char *filename TSRMLS_DC)
2836+#define SAPI_UPLOAD_CONTENT_FILTER_FUNC(upload_content_filter) unsigned int upload_content_filter(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC)
2837+#define SAPI_POST_UPLOAD_FILTER_FUNC(post_upload_filter) unsigned int post_upload_filter(char *tmpfilename TSRMLS_DC)
2838
2839 SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
2840 SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader);
2841 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data);
2842+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter);
2843
2844 #define STANDARD_SAPI_MODULE_PROPERTIES
2845
2846diff -Naur php-4.3.11/main/snprintf.c hardening-patch-4.3.11-0.3.2/main/snprintf.c
2847--- php-4.3.11/main/snprintf.c 2004-11-16 00:27:26.000000000 +0100
2848+++ hardening-patch-4.3.11-0.3.2/main/snprintf.c 2005-07-09 08:53:02.491359920 +0200
2849@@ -850,7 +850,11 @@
2850
2851
2852 case 'n':
2853+#if HARDENING_PATCH_FMT_PROTECT
2854+ php_security_log(S_MISC, "'n' specifier within format string");
2855+#else
2856 *(va_arg(ap, int *)) = cc;
2857+#endif
2858 break;
2859
2860 /*
2861diff -Naur php-4.3.11/main/spprintf.c hardening-patch-4.3.11-0.3.2/main/spprintf.c
2862--- php-4.3.11/main/spprintf.c 2003-09-29 03:09:36.000000000 +0200
2863+++ hardening-patch-4.3.11-0.3.2/main/spprintf.c 2005-07-09 08:53:02.492359768 +0200
2864@@ -531,7 +531,11 @@
2865
2866
2867 case 'n':
2868+#if HARDENING_PATCH_FMT_PROTECT
2869+ php_security_log(S_MISC, "'n' specifier within format string");
2870+#else
2871 *(va_arg(ap, int *)) = cc;
2872+#endif
2873 break;
2874
2875 /*
2876diff -Naur php-4.3.11/pear/go-pear-list.php hardening-patch-4.3.11-0.3.2/pear/go-pear-list.php
2877--- php-4.3.11/pear/go-pear-list.php 2005-03-18 02:58:20.000000000 +0100
2878+++ hardening-patch-4.3.11-0.3.2/pear/go-pear-list.php 2005-07-09 08:53:02.492359768 +0200
2879@@ -8,7 +8,7 @@
2880 $packages = array(
2881 // required packages for the installer
2882 "PEAR" => "1.3.5",
2883-"XML_RPC" => "1.2.2",
2884+"XML_RPC" => "1.3.1",
2885 "Console_Getopt" => "1.2",
2886 "Archive_Tar" => "1.3.1",
2887
2888diff -Naur php-4.3.11/pear/packages/XML_RPC-1.2.2.tar hardening-patch-4.3.11-0.3.2/pear/packages/XML_RPC-1.2.2.tar
2889--- php-4.3.11/pear/packages/XML_RPC-1.2.2.tar 2005-03-28 19:02:28.000000000 +0200
2890+++ hardening-patch-4.3.11-0.3.2/pear/packages/XML_RPC-1.2.2.tar 1970-01-01 01:00:00.000000000 +0100
2891@@ -1,3393 +0,0 @@
2892-package2.xml
2893-<package packagerversion="1.4.0a1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
2894- <name>XML_RPC</name>
2895- <channel>pear.php.net</channel>
2896- <summary>PHP implementation of the XML-RPC protocol</summary>
2897- <description>A PEAR-ified version of Useful Inc&apos;s XML-RPC for PHP.
2898-
2899-It has support for HTTP/HTTPS transport, proxies and authentication.</description>
2900- <lead>
2901- <name>Stig Bakken</name>
2902- <user>ssb</user>
2903- <email>stig@php.net</email>
2904- <active>no</active>
2905- </lead>
2906- <lead>
2907- <name>Daniel Convissor</name>
2908- <user>danielc</user>
2909- <email>danielc@php.net</email>
2910- <active>yes</active>
2911- </lead>
2912- <date>2005-03-07</date>
2913- <time>12:54:49</time>
2914- <version>
2915- <release>1.2.2</release>
2916- <api>1.2.0</api>
2917- </version>
2918- <stability>
2919- <release>stable</release>
2920- <api>stable</api>
2921- </stability>
2922- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2923- <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.</notes>
2924- <contents>
2925- <dir name="/">
2926- <file md5sum="9aca4434f486b517a75c7f2878fb1e9c" name="tests/protoport.php" role="test">
2927- <tasks:replace from="@package_version@" to="version" type="package-info" />
2928- </file>
2929- <file md5sum="49639b76a2296777a1dfa076ae41024a" name="tests/test_Dump.php" role="test">
2930- <tasks:replace from="@package_version@" to="version" type="package-info" />
2931- </file>
2932- <file baseinstalldir="XML/RPC" md5sum="2fb141b1f8927ef27ab0c222f2117d77" name="Dump.php" role="php">
2933- <tasks:replace from="@package_version@" to="version" type="package-info" />
2934- </file>
2935- <file baseinstalldir="XML" md5sum="fbfa3c674175786cc95893cc5192d910" name="RPC.php" role="php">
2936- <tasks:replace from="@package_version@" to="version" type="package-info" />
2937- </file>
2938- <file baseinstalldir="XML/RPC" md5sum="6fc2498def65f09d4ae535fa5f987f62" name="Server.php" role="php">
2939- <tasks:replace from="@package_version@" to="version" type="package-info" />
2940- </file>
2941- </dir>
2942- </contents>
2943- <compatible>
2944- <name>PEAR</name>
2945- <channel>pear.php.net</channel>
2946- <min>1.4.0a1</min>
2947- <max>1.4.0a4</max>
2948- </compatible>
2949- <dependencies>
2950- <required>
2951- <php>
2952- <min>4.2.0</min>
2953- <max>6.0.0</max>
2954- </php>
2955- <pearinstaller>
2956- <min>1.4.0a1</min>
2957- </pearinstaller>
2958- </required>
2959- </dependencies>
2960- <phprelease />
2961- <changelog>
2962- <release>
2963- <version>
2964- <release>1.2.1</release>
2965- <api>1.2.0</api>
2966- </version>
2967- <stability>
2968- <release>stable</release>
2969- <api>stable</api>
2970- </stability>
2971- <date>2005-03-01</date>
2972- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2973- <notes>* Add isset() check before examining the dispatch map. Bug 3658.</notes>
2974- </release>
2975- <release>
2976- <version>
2977- <release>1.2.0</release>
2978- <api>1.2.0</api>
2979- </version>
2980- <stability>
2981- <release>stable</release>
2982- <api>stable</api>
2983- </stability>
2984- <date>2005-02-27</date>
2985- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2986- <notes>* Provide the &quot;stable&quot; release.
2987-* Add package2.xml for compatibility with PEAR 1.4.0.
2988-* For changes since 1.1.0, see the changelogs for the various RC releases.</notes>
2989- </release>
2990- <release>
2991- <version>
2992- <release>1.2.0RC7</release>
2993- <api>1.2.0RC7</api>
2994- </version>
2995- <stability>
2996- <release>beta</release>
2997- <api>beta</api>
2998- </stability>
2999- <date>2005-02-22</date>
3000- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3001- <notes>* Add the setSendEncoding() method and $send_encoding
3002- property to XML_RPC_Message. Request 3537.
3003-* Allow class methods to be mapped using either syntax:
3004- &apos;function&apos; =&gt; &apos;hello::sayHello&apos;,
3005- or
3006- &apos;function&apos; =&gt; array(&apos;hello&apos;, &apos;sayhello&apos;),
3007- Bug 3363.
3008-* Use 8192 instead of 32768 for bytes in fread()
3009- in parseResponseFile(). Bug 3340.</notes>
3010- </release>
3011- <release>
3012- <version>
3013- <release>1.2.0RC6</release>
3014- <api>1.2.0RC6</api>
3015- </version>
3016- <stability>
3017- <release>beta</release>
3018- <api>beta</api>
3019- </stability>
3020- <date>2005-01-25</date>
3021- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3022- <notes>* Don&apos;t put the protocol in the Host field of the POST data. (danielc)</notes>
3023- </release>
3024- <release>
3025- <version>
3026- <release>1.2.0RC5</release>
3027- <api>1.2.0RC5</api>
3028- </version>
3029- <stability>
3030- <release>beta</release>
3031- <api>beta</api>
3032- </stability>
3033- <date>2005-01-24</date>
3034- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3035- <notes>* If $port is 443 but a protocol isn&apos;t specified in $server, assume ssl:// is the protocol.</notes>
3036- </release>
3037- <release>
3038- <version>
3039- <release>1.2.0RC4</release>
3040- <api>1.2.0RC4</api>
3041- </version>
3042- <stability>
3043- <release>beta</release>
3044- <api>beta</api>
3045- </stability>
3046- <date>2005-01-24</date>
3047- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3048- <notes>* When a connection attempt fails, have the method return 0. (danielc)
3049-* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
3050-* Add tests for setting the client properties. (danielc)
3051-* Remove $GLOBALS[&apos;XML_RPC_twoslash&apos;] since it&apos;s not used. (danielc)
3052-* Bundle the tests with the package. (danielc)</notes>
3053- </release>
3054- <release>
3055- <version>
3056- <release>1.2.0RC3</release>
3057- <api>1.2.0RC3</api>
3058- </version>
3059- <stability>
3060- <release>beta</release>
3061- <api>beta</api>
3062- </stability>
3063- <date>2005-01-19</date>
3064- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3065- <notes>* ssl uses port 443, not 445.</notes>
3066- </release>
3067- <release>
3068- <version>
3069- <release>1.2.0RC2</release>
3070- <api>1.2.0RC2</api>
3071- </version>
3072- <stability>
3073- <release>beta</release>
3074- <api>beta</api>
3075- </stability>
3076- <date>2005-01-11</date>
3077- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3078- <notes>* Handle ssl:// in the $server string. (danielc)
3079-* Also default to port 445 for ssl:// requests as well. (danielc)
3080-* Enhance debugging in the server. (danielc)</notes>
3081- </release>
3082- <release>
3083- <version>
3084- <release>1.2.0RC1</release>
3085- <api>1.2.0RC1</api>
3086- </version>
3087- <stability>
3088- <release>beta</release>
3089- <api>beta</api>
3090- </stability>
3091- <date>2004-12-30</date>
3092- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3093- <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
3094-* Allow array function callbacks (Matt Kane)
3095-* Some minor speed-ups (Matt Kane)
3096-* Add Dump.php to the package (Christian Weiske)
3097-* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
3098-* Silence fsockopen() errors. Bug 1714. (danielc)
3099-* Encode empty arrays as an array. Bug 1493. (danielc)
3100-* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
3101-* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
3102-* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()&apos;ing error messages. (danielc)
3103-* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
3104-* Allow raiseError() to be called statically. (danielc)
3105-* Stop double escaping of character entities. Bug 987. (danielc)
3106- NOTICE: the following have been removed:
3107- * XML_RPC_dh()
3108- * $GLOBALS[&apos;XML_RPC_entities&apos;]
3109- * XML_RPC_entity_decode()
3110- * XML_RPC_lookup_entity()
3111-* Determine the XML&apos;s encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)</notes>
3112- </release>
3113- <release>
3114- <version>
3115- <release>1.1.0</release>
3116- <api>1.1.0</api>
3117- </version>
3118- <stability>
3119- <release>stable</release>
3120- <api>stable</api>
3121- </stability>
3122- <date>2004-03-15</date>
3123- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3124- <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
3125-* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
3126-* Remove &quot;require_once &apos;PEAR.php&apos;&quot;, include only when needed to raise an error
3127-* Replace echo and error_log() with raiseError() (mroch)
3128-* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
3129-* be tolerant of junk after methodResponse (Luca Mariano, mroch)
3130-* Silent notice even in the error log (pierre)
3131-* fix include of shared xml extension on win32 (pierre)</notes>
3132- </release>
3133- <release>
3134- <version>
3135- <release>1.0.4</release>
3136- <api>1.0.4</api>
3137- </version>
3138- <stability>
3139- <release>stable</release>
3140- <api>stable</api>
3141- </stability>
3142- <date>2002-10-02</date>
3143- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3144- <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)</notes>
3145- </release>
3146- <release>
3147- <version>
3148- <release>1.0.3</release>
3149- <api>1.0.3</api>
3150- </version>
3151- <stability>
3152- <release>stable</release>
3153- <api>stable</api>
3154- </stability>
3155- <date>2002-05-19</date>
3156- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3157- <notes>* fix bug when parsing responses with boolean types</notes>
3158- </release>
3159- <release>
3160- <version>
3161- <release>1.0.2</release>
3162- <api>1.0.2</api>
3163- </version>
3164- <stability>
3165- <release>stable</release>
3166- <api>stable</api>
3167- </stability>
3168- <date>2002-04-16</date>
3169- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3170- <notes>* E_ALL fixes
3171-* fix HTTP response header parsing</notes>
3172- </release>
3173- <release>
3174- <version>
3175- <release>1.0.1</release>
3176- <api>1.0.1</api>
3177- </version>
3178- <stability>
3179- <release>stable</release>
3180- <api>stable</api>
3181- </stability>
3182- <date>2001-09-25</date>
3183- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3184- <notes>This is a PEAR-ified version of Useful Inc&apos;s 1.0.1 release.
3185-Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.</notes>
3186- </release>
3187- </changelog>
3188-</package>
3189-
3190-/**
3191- * Tests that properties of XML_RPC_Client get properly set
3192- *
3193- * Any individual tests that fail will have their name, expected result
3194- * and actual result printed out. So seeing no output when executing
3195- * this file is a good thing.
3196- *
3197- * Can be run via CLI or a web server.
3198- *
3199- * PHP versions 4 and 5
3200- *
3201- * LICENSE: This source file is subject to version 3.0 of the PHP license
3202- * that is available through the world-wide-web at the following URI:
3203- * http://www.php.net/license/3_0.txt. If you did not receive a copy of
3204- * the PHP License and are unable to obtain it through the web, please
3205- * send a note to license@php.net so we can mail you a copy immediately.
3206- *
3207- * @category Web Services
3208- * @package XML_RPC
3209- * @author Daniel Convissor <danielc@php.net>
3210- * @copyright 2005 The PHP Group
3211- * @license http://www.php.net/license/3_0.txt PHP License
3212- * @version CVS: $Id: protoport.php,v 1.4 2005/01/24 17:48:47 danielc Exp $
3213- * @link http://pear.php.net/package/XML_RPC
3214- * @since File available since Release 1.2
3215- */
3216-
3217-/*
3218- * If the package version number is found in the left hand
3219- * portion of the if() expression below, that means this file has
3220- * come from the PEAR installer. Therefore, let's test the
3221- * installed version of XML_RPC which should be in the include path.
3222- *
3223- * If the version has not been substituted in the if() expression,
3224- * this file has likely come from a CVS checkout or a .tar file.
3225- * Therefore, we'll assume the tests should use the version of
3226- * XML_RPC that has come from there as well.
3227- */
3228-if ('1.2.2' != '@'.'package_version'.'@') {
3229- /**
3230- * Get the needed class from the PEAR installation
3231- */
3232- require_once 'XML/RPC.php';
3233-} else {
3234- /**
3235- * Get the needed class from the parent directory
3236- */
3237- require_once '../RPC.php';
3238-}
3239-
3240-/**
3241- * Compare the test result to the expected result
3242- *
3243- * If the test fails, echo out the results.
3244- *
3245- * @param array $expect the array of object properties you expect
3246- * from the test
3247- * @param object $actual the object results from the test
3248- * @param string $test_name the name of the test
3249- *
3250- * @return void
3251- */
3252-function compare($expect, $actual, $test_name) {
3253- $actual = get_object_vars($actual);
3254- if (count(array_diff($actual, $expect))) {
3255- echo "$test_name failed.\nExpect: ";
3256- print_r($expect);
3257- echo "Actual: ";
3258- print_r($actual);
3259- echo "\n";
3260- }
3261-}
3262-
3263-if (php_sapi_name() != 'cli') {
3264- echo "<pre>\n";
3265-}
3266-
3267-
3268-$x = array(
3269- 'path' => 'thepath',
3270- 'server' => 'theserver',
3271- 'protocol' => 'http://',
3272- 'port' => 80,
3273- 'proxy' => '',
3274- 'proxy_protocol' => 'http://',
3275- 'proxy_port' => 8080,
3276- 'proxy_user' => '',
3277- 'proxy_pass' => '',
3278- 'errno' => 0,
3279- 'errstring' => '',
3280- 'debug' => 0,
3281- 'username' => '',
3282- 'password' => '',
3283-);
3284-$c = new XML_RPC_Client('thepath', 'theserver');
3285-compare($x, $c, 'defaults');
3286-
3287-$x = array(
3288- 'path' => 'thepath',
3289- 'server' => 'theserver',
3290- 'protocol' => 'http://',
3291- 'port' => 80,
3292- 'proxy' => '',
3293- 'proxy_protocol' => 'http://',
3294- 'proxy_port' => 8080,
3295- 'proxy_user' => '',
3296- 'proxy_pass' => '',
3297- 'errno' => 0,
3298- 'errstring' => '',
3299- 'debug' => 0,
3300- 'username' => '',
3301- 'password' => '',
3302-);
3303-$c = new XML_RPC_Client('thepath', 'http://theserver');
3304-compare($x, $c, 'defaults with http');
3305-
3306-$x = array(
3307- 'path' => 'thepath',
3308- 'server' => 'theserver',
3309- 'protocol' => 'ssl://',
3310- 'port' => 443,
3311- 'proxy' => '',
3312- 'proxy_protocol' => 'http://',
3313- 'proxy_port' => 8080,
3314- 'proxy_user' => '',
3315- 'proxy_pass' => '',
3316- 'errno' => 0,
3317- 'errstring' => '',
3318- 'debug' => 0,
3319- 'username' => '',
3320- 'password' => '',
3321-);
3322-$c = new XML_RPC_Client('thepath', 'https://theserver');
3323-compare($x, $c, 'defaults with https');
3324-
3325-$x = array(
3326- 'path' => 'thepath',
3327- 'server' => 'theserver',
3328- 'protocol' => 'ssl://',
3329- 'port' => 443,
3330- 'proxy' => '',
3331- 'proxy_protocol' => 'http://',
3332- 'proxy_port' => 8080,
3333- 'proxy_user' => '',
3334- 'proxy_pass' => '',
3335- 'errno' => 0,
3336- 'errstring' => '',
3337- 'debug' => 0,
3338- 'username' => '',
3339- 'password' => '',
3340-);
3341-$c = new XML_RPC_Client('thepath', 'ssl://theserver');
3342-compare($x, $c, 'defaults with ssl');
3343-
3344-
3345-$x = array(
3346- 'path' => 'thepath',
3347- 'server' => 'theserver',
3348- 'protocol' => 'http://',
3349- 'port' => 65,
3350- 'proxy' => '',
3351- 'proxy_protocol' => 'http://',
3352- 'proxy_port' => 8080,
3353- 'proxy_user' => '',
3354- 'proxy_pass' => '',
3355- 'errno' => 0,
3356- 'errstring' => '',
3357- 'debug' => 0,
3358- 'username' => '',
3359- 'password' => '',
3360-);
3361-$c = new XML_RPC_Client('thepath', 'theserver', 65);
3362-compare($x, $c, 'port 65');
3363-
3364-$x = array(
3365- 'path' => 'thepath',
3366- 'server' => 'theserver',
3367- 'protocol' => 'http://',
3368- 'port' => 65,
3369- 'proxy' => '',
3370- 'proxy_protocol' => 'http://',
3371- 'proxy_port' => 8080,
3372- 'proxy_user' => '',
3373- 'proxy_pass' => '',
3374- 'errno' => 0,
3375- 'errstring' => '',
3376- 'debug' => 0,
3377- 'username' => '',
3378- 'password' => '',
3379-);
3380-$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
3381-compare($x, $c, 'port 65 with http');
3382-
3383-$x = array(
3384- 'path' => 'thepath',
3385- 'server' => 'theserver',
3386- 'protocol' => 'ssl://',
3387- 'port' => 65,
3388- 'proxy' => '',
3389- 'proxy_protocol' => 'http://',
3390- 'proxy_port' => 8080,
3391- 'proxy_user' => '',
3392- 'proxy_pass' => '',
3393- 'errno' => 0,
3394- 'errstring' => '',
3395- 'debug' => 0,
3396- 'username' => '',
3397- 'password' => '',
3398-);
3399-$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
3400-compare($x, $c, 'port 65 with https');
3401-
3402-$x = array(
3403- 'path' => 'thepath',
3404- 'server' => 'theserver',
3405- 'protocol' => 'ssl://',
3406- 'port' => 65,
3407- 'proxy' => '',
3408- 'proxy_protocol' => 'http://',
3409- 'proxy_port' => 8080,
3410- 'proxy_user' => '',
3411- 'proxy_pass' => '',
3412- 'errno' => 0,
3413- 'errstring' => '',
3414- 'debug' => 0,
3415- 'username' => '',
3416- 'password' => '',
3417-);
3418-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
3419-compare($x, $c, 'port 65 with ssl');
3420-
3421-
3422-$x = array(
3423- 'path' => 'thepath',
3424- 'server' => 'theserver',
3425- 'protocol' => 'http://',
3426- 'port' => 80,
3427- 'proxy' => 'theproxy',
3428- 'proxy_protocol' => 'http://',
3429- 'proxy_port' => 8080,
3430- 'proxy_user' => '',
3431- 'proxy_pass' => '',
3432- 'errno' => 0,
3433- 'errstring' => '',
3434- 'debug' => 0,
3435- 'username' => '',
3436- 'password' => '',
3437-);
3438-$c = new XML_RPC_Client('thepath', 'theserver', 0,
3439- 'theproxy');
3440-compare($x, $c, 'defaults proxy');
3441-
3442-$x = array(
3443- 'path' => 'thepath',
3444- 'server' => 'theserver',
3445- 'protocol' => 'http://',
3446- 'port' => 80,
3447- 'proxy' => 'theproxy',
3448- 'proxy_protocol' => 'http://',
3449- 'proxy_port' => 8080,
3450- 'proxy_user' => '',
3451- 'proxy_pass' => '',
3452- 'errno' => 0,
3453- 'errstring' => '',
3454- 'debug' => 0,
3455- 'username' => '',
3456- 'password' => '',
3457-);
3458-$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
3459- 'http://theproxy');
3460-compare($x, $c, 'defaults with http proxy');
3461-
3462-$x = array(
3463- 'path' => 'thepath',
3464- 'server' => 'theserver',
3465- 'protocol' => 'ssl://',
3466- 'port' => 443,
3467- 'proxy' => 'theproxy',
3468- 'proxy_protocol' => 'ssl://',
3469- 'proxy_port' => 443,
3470- 'proxy_user' => '',
3471- 'proxy_pass' => '',
3472- 'errno' => 0,
3473- 'errstring' => '',
3474- 'debug' => 0,
3475- 'username' => '',
3476- 'password' => '',
3477-);
3478-$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
3479- 'https://theproxy');
3480-compare($x, $c, 'defaults with https proxy');
3481-
3482-$x = array(
3483- 'path' => 'thepath',
3484- 'server' => 'theserver',
3485- 'protocol' => 'ssl://',
3486- 'port' => 443,
3487- 'proxy' => 'theproxy',
3488- 'proxy_protocol' => 'ssl://',
3489- 'proxy_port' => 443,
3490- 'proxy_user' => '',
3491- 'proxy_pass' => '',
3492- 'errno' => 0,
3493- 'errstring' => '',
3494- 'debug' => 0,
3495- 'username' => '',
3496- 'password' => '',
3497-);
3498-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
3499- 'ssl://theproxy');
3500-compare($x, $c, 'defaults with ssl proxy');
3501-
3502-
3503-$x = array(
3504- 'path' => 'thepath',
3505- 'server' => 'theserver',
3506- 'protocol' => 'http://',
3507- 'port' => 65,
3508- 'proxy' => 'theproxy',
3509- 'proxy_protocol' => 'http://',
3510- 'proxy_port' => 6565,
3511- 'proxy_user' => '',
3512- 'proxy_pass' => '',
3513- 'errno' => 0,
3514- 'errstring' => '',
3515- 'debug' => 0,
3516- 'username' => '',
3517- 'password' => '',
3518-);
3519-$c = new XML_RPC_Client('thepath', 'theserver', 65,
3520- 'theproxy', 6565);
3521-compare($x, $c, 'port 65 proxy 6565');
3522-
3523-$x = array(
3524- 'path' => 'thepath',
3525- 'server' => 'theserver',
3526- 'protocol' => 'http://',
3527- 'port' => 65,
3528- 'proxy' => 'theproxy',
3529- 'proxy_protocol' => 'http://',
3530- 'proxy_port' => 6565,
3531- 'proxy_user' => '',
3532- 'proxy_pass' => '',
3533- 'errno' => 0,
3534- 'errstring' => '',
3535- 'debug' => 0,
3536- 'username' => '',
3537- 'password' => '',
3538-);
3539-$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
3540- 'http://theproxy', 6565);
3541-compare($x, $c, 'port 65 with http proxy 6565');
3542-
3543-$x = array(
3544- 'path' => 'thepath',
3545- 'server' => 'theserver',
3546- 'protocol' => 'ssl://',
3547- 'port' => 65,
3548- 'proxy' => 'theproxy',
3549- 'proxy_protocol' => 'ssl://',
3550- 'proxy_port' => 6565,
3551- 'proxy_user' => '',
3552- 'proxy_pass' => '',
3553- 'errno' => 0,
3554- 'errstring' => '',
3555- 'debug' => 0,
3556- 'username' => '',
3557- 'password' => '',
3558-);
3559-$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
3560- 'https://theproxy', 6565);
3561-compare($x, $c, 'port 65 with https proxy 6565');
3562-
3563-$x = array(
3564- 'path' => 'thepath',
3565- 'server' => 'theserver',
3566- 'protocol' => 'ssl://',
3567- 'port' => 65,
3568- 'proxy' => 'theproxy',
3569- 'proxy_protocol' => 'ssl://',
3570- 'proxy_port' => 6565,
3571- 'proxy_user' => '',
3572- 'proxy_pass' => '',
3573- 'errno' => 0,
3574- 'errstring' => '',
3575- 'debug' => 0,
3576- 'username' => '',
3577- 'password' => '',
3578-);
3579-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
3580- 'ssl://theproxy', 6565);
3581-compare($x, $c, 'port 65 with ssl proxy 6565');
3582-
3583-
3584-$x = array(
3585- 'path' => 'thepath',
3586- 'server' => 'theserver',
3587- 'protocol' => 'ssl://',
3588- 'port' => 443,
3589- 'proxy' => 'theproxy',
3590- 'proxy_protocol' => 'ssl://',
3591- 'proxy_port' => 443,
3592- 'proxy_user' => '',
3593- 'proxy_pass' => '',
3594- 'errno' => 0,
3595- 'errstring' => '',
3596- 'debug' => 0,
3597- 'username' => '',
3598- 'password' => '',
3599-);
3600-$c = new XML_RPC_Client('thepath', 'theserver', 443,
3601- 'theproxy', 443);
3602-compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
3603-
3604-$x = array(
3605- 'path' => 'thepath',
3606- 'server' => 'theserver',
3607- 'protocol' => 'http://',
3608- 'port' => 80,
3609- 'proxy' => 'theproxy',
3610- 'proxy_protocol' => 'ssl://',
3611- 'proxy_port' => 6565,
3612- 'proxy_user' => '',
3613- 'proxy_pass' => '',
3614- 'errno' => 0,
3615- 'errstring' => '',
3616- 'debug' => 0,
3617- 'username' => '',
3618- 'password' => '',
3619-);
3620-$c = new XML_RPC_Client('thepath', 'theserver', 0,
3621- 'ssl://theproxy', 6565);
3622-compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
3623-
3624-
3625-/*
3626- * If the package version number is found in the left hand
3627- * portion of the if() expression below, that means this file has
3628- * come from the PEAR installer. Therefore, let's test the
3629- * installed version of XML_RPC which should be in the include path.
3630- *
3631- * If the version has not been substituted in the if() expression,
3632- * this file has likely come from a CVS checkout or a .tar file.
3633- * Therefore, we'll assume the tests should use the version of
3634- * XML_RPC that has come from there as well.
3635- */
3636-if ('1.2.2' != '@'.'package_version'.'@') {
3637- /**
3638- * Get the needed class from the PEAR installation
3639- */
3640- require_once 'XML/RPC/Dump.php';
3641-} else {
3642- /**
3643- * Get the needed class from the parent directory
3644- */
3645- require_once '../Dump.php';
3646-}
3647-
3648-$val = new XML_RPC_Value(array(
3649- 'title' =>new XML_RPC_Value('das ist der Titel', 'string'),
3650- 'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
3651- 'endDate' =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
3652- 'error' =>'string',
3653- 'arkey' => new XML_RPC_Value( array(
3654- new XML_RPC_Value('simple string'),
3655- new XML_RPC_Value(12345, 'int')
3656- ), 'array')
3657- )
3658- ,'struct');
3659-
3660-XML_RPC_Dump($val);
3661-
3662-echo '==============' . "\r\n";
3663-$val2 = new XML_RPC_Value(44353, 'int');
3664-XML_RPC_Dump($val2);
3665-
3666-echo '==============' . "\r\n";
3667-$val3 = new XML_RPC_Value('this should be a string', 'string');
3668-XML_RPC_Dump($val3);
3669-
3670-echo '==============' . "\r\n";
3671-$val4 = new XML_RPC_Value(true, 'boolean');
3672-XML_RPC_Dump($val4);
3673-
3674-
3675-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3676-
3677-/**
3678- * Function and class to dump XML_RPC_Value objects in a nice way
3679- *
3680- * Should be helpful as a normal var_dump(..) displays all internals which
3681- * doesn't really give you an overview due to too much information.
3682- *
3683- * @category Web Services
3684- * @package XML_RPC
3685- * @author Christian Weiske <cweiske@php.net>
3686- * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $
3687- * @link http://pear.php.net/package/XML_RPC
3688- */
3689-
3690-
3691-/**
3692- * Pull in the XML_RPC class
3693- */
3694-require_once 'XML/RPC.php';
3695-
3696-
3697-/**
3698- * Generates the dump of the XML_RPC_Value and echoes it
3699- *
3700- * @param object $value the XML_RPC_Value object to dump
3701- *
3702- * @return void
3703- */
3704-function XML_RPC_Dump($value)
3705-{
3706- $dumper = new XML_RPC_Dump();
3707- echo $dumper->generateDump($value);
3708-}
3709-
3710-
3711-/**
3712- * Class which generates a dump of a XML_RPC_Value object
3713- *
3714- * @category Web Services
3715- * @package XML_RPC
3716- * @author Christian Weiske <cweiske@php.net>
3717- * @version Release: 1.2.2
3718- * @link http://pear.php.net/package/XML_RPC
3719- */
3720-class XML_RPC_Dump
3721-{
3722- /**
3723- * The indentation array cache
3724- * @var array
3725- */
3726- var $arIndent = array();
3727-
3728- /**
3729- * The spaces used for indenting the XML
3730- * @var string
3731- */
3732- var $strBaseIndent = ' ';
3733-
3734- /**
3735- * Returns the dump in XML format without printing it out
3736- *
3737- * @param object $value the XML_RPC_Value object to dump
3738- * @param int $nLevel the level of indentation
3739- *
3740- * @return string the dump
3741- */
3742- function generateDump($value, $nLevel = 0)
3743- {
3744- if (!is_object($value) && get_class($value) != 'xml_rpc_value') {
3745- require_once 'PEAR.php';
3746- PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n",
3747- 0, PEAR_ERROR_PRINT);
3748- if (is_object($value)) {
3749- $strType = get_class($value);
3750- } else {
3751- $strType = gettype($value);
3752- }
3753- return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: '
3754- . $strType . "\r\n";
3755- }
3756-
3757- switch ($value->kindOf()) {
3758- case 'struct':
3759- $ret = $this->genStruct($value, $nLevel);
3760- break;
3761- case 'array':
3762- $ret = $this->genArray($value, $nLevel);
3763- break;
3764- case 'scalar':
3765- $ret = $this->genScalar($value->scalarval(), $nLevel);
3766- break;
3767- default:
3768- require_once 'PEAR.php';
3769- PEAR::raiseError('Illegal type "' . $value->kindOf()
3770- . '" in XML_RPC_Value' . "\r\n", 0,
3771- PEAR_ERROR_PRINT);
3772- }
3773-
3774- return $ret;
3775- }
3776-
3777- /**
3778- * Returns the scalar value dump
3779- *
3780- * @param object $value the scalar XML_RPC_Value object to dump
3781- * @param int $nLevel the level of indentation
3782- *
3783- * @return string Dumped version of the scalar value
3784- */
3785- function genScalar($value, $nLevel)
3786- {
3787- if (gettype($value) == 'object') {
3788- $strClass = ' ' . get_class($value);
3789- } else {
3790- $strClass = '';
3791- }
3792- return $this->getIndent($nLevel) . gettype($value) . $strClass
3793- . ' ' . $value . "\r\n";
3794- }
3795-
3796- /**
3797- * Returns the dump of a struct
3798- *
3799- * @param object $value the struct XML_RPC_Value object to dump
3800- * @param int $nLevel the level of indentation
3801- *
3802- * @return string Dumped version of the scalar value
3803- */
3804- function genStruct($value, $nLevel)
3805- {
3806- $value->structreset();
3807- $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n";
3808- while (list($key, $keyval) = $value->structeach()) {
3809- $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n";
3810- $strOutput .= $this->generateDump($keyval, $nLevel + 2);
3811- }
3812- return $strOutput;
3813- }
3814-
3815- /**
3816- * Returns the dump of an array
3817- *
3818- * @param object $value the array XML_RPC_Value object to dump
3819- * @param int $nLevel the level of indentation
3820- *
3821- * @return string Dumped version of the scalar value
3822- */
3823- function genArray($value, $nLevel)
3824- {
3825- $nSize = $value->arraysize();
3826- $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n";
3827- for($nA = 0; $nA < $nSize; $nA++) {
3828- $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n";
3829- $strOutput .= $this->generateDump($value->arraymem($nA),
3830- $nLevel + 2);
3831- }
3832- return $strOutput;
3833- }
3834-
3835- /**
3836- * Returns the indent for a specific level and caches it for faster use
3837- *
3838- * @param int $nLevel the level
3839- *
3840- * @return string the indented string
3841- */
3842- function getIndent($nLevel)
3843- {
3844- if (!isset($this->arIndent[$nLevel])) {
3845- $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel);
3846- }
3847- return $this->arIndent[$nLevel];
3848- }
3849-}
3850-
3851-/*
3852- * Local variables:
3853- * tab-width: 4
3854- * c-basic-offset: 4
3855- * c-hanging-comment-ender-p: nil
3856- * End:
3857- */
3858-
3859-?>
3860-
3861-
3862-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3863-
3864-/**
3865- * PHP implementation of the XML-RPC protocol
3866- *
3867- * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
3868- * It has support for HTTP transport, proxies and authentication.
3869- *
3870- * PHP versions 4 and 5
3871- *
3872- * LICENSE: License is granted to use or modify this software
3873- * ("XML-RPC for PHP") for commercial or non-commercial use provided the
3874- * copyright of the author is preserved in any distributed or derivative work.
3875- *
3876- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
3877- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3878- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3879- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3880- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3881- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3882- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3883- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3884- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3885- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3886- *
3887- * @category Web Services
3888- * @package XML_RPC
3889- * @author Edd Dumbill <edd@usefulinc.com>
3890- * @author Stig Bakken <stig@php.net>
3891- * @author Martin Jansen <mj@php.net>
3892- * @author Daniel Convissor <danielc@php.net>
3893- * @copyright 1999-2001 Edd Dumbill
3894- * @version CVS: $Id: RPC.php,v 1.60 2005/03/07 17:45:08 danielc Exp $
3895- * @link http://pear.php.net/package/XML_RPC
3896- */
3897-
3898-
3899-if (!function_exists('xml_parser_create')) {
3900- // Win 32 fix. From: "Leo West" <lwest@imaginet.fr>
3901- if ($WINDIR) {
3902- dl('php_xml.dll');
3903- } else {
3904- dl('xml.so');
3905- }
3906-}
3907-
3908-/**#@+
3909- * Error constants
3910- */
3911-define('XML_RPC_ERROR_INVALID_TYPE', 101);
3912-define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
3913-define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
3914-define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
3915-/**#@-*/
3916-
3917-
3918-/**
3919- * Data types
3920- * @global string $GLOBALS['XML_RPC_I4']
3921- */
3922-$GLOBALS['XML_RPC_I4'] = 'i4';
3923-
3924-/**
3925- * Data types
3926- * @global string $GLOBALS['XML_RPC_Int']
3927- */
3928-$GLOBALS['XML_RPC_Int'] = 'int';
3929-
3930-/**
3931- * Data types
3932- * @global string $GLOBALS['XML_RPC_Boolean']
3933- */
3934-$GLOBALS['XML_RPC_Boolean'] = 'boolean';
3935-
3936-/**
3937- * Data types
3938- * @global string $GLOBALS['XML_RPC_Double']
3939- */
3940-$GLOBALS['XML_RPC_Double'] = 'double';
3941-
3942-/**
3943- * Data types
3944- * @global string $GLOBALS['XML_RPC_String']
3945- */
3946-$GLOBALS['XML_RPC_String'] = 'string';
3947-
3948-/**
3949- * Data types
3950- * @global string $GLOBALS['XML_RPC_DateTime']
3951- */
3952-$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601';
3953-
3954-/**
3955- * Data types
3956- * @global string $GLOBALS['XML_RPC_Base64']
3957- */
3958-$GLOBALS['XML_RPC_Base64'] = 'base64';
3959-
3960-/**
3961- * Data types
3962- * @global string $GLOBALS['XML_RPC_Array']
3963- */
3964-$GLOBALS['XML_RPC_Array'] = 'array';
3965-
3966-/**
3967- * Data types
3968- * @global string $GLOBALS['XML_RPC_Struct']
3969- */
3970-$GLOBALS['XML_RPC_Struct'] = 'struct';
3971-
3972-
3973-/**
3974- * Data type meta-types
3975- * @global array $GLOBALS['XML_RPC_Types']
3976- */
3977-$GLOBALS['XML_RPC_Types'] = array(
3978- $GLOBALS['XML_RPC_I4'] => 1,
3979- $GLOBALS['XML_RPC_Int'] => 1,
3980- $GLOBALS['XML_RPC_Boolean'] => 1,
3981- $GLOBALS['XML_RPC_String'] => 1,
3982- $GLOBALS['XML_RPC_Double'] => 1,
3983- $GLOBALS['XML_RPC_DateTime'] => 1,
3984- $GLOBALS['XML_RPC_Base64'] => 1,
3985- $GLOBALS['XML_RPC_Array'] => 2,
3986- $GLOBALS['XML_RPC_Struct'] => 3,
3987-);
3988-
3989-
3990-/**
3991- * Error message numbers
3992- * @global array $GLOBALS['XML_RPC_err']
3993- */
3994-$GLOBALS['XML_RPC_err'] = array(
3995- 'unknown_method' => 1,
3996- 'invalid_return' => 2,
3997- 'incorrect_params' => 3,
3998- 'introspect_unknown' => 4,
3999- 'http_error' => 5,
4000-);
4001-
4002-/**
4003- * Error message strings
4004- * @global array $GLOBALS['XML_RPC_str']
4005- */
4006-$GLOBALS['XML_RPC_str'] = array(
4007- 'unknown_method' => 'Unknown method',
4008- 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload',
4009- 'incorrect_params' => 'Incorrect parameters passed to method',
4010- 'introspect_unknown' => 'Can\'t introspect: method unknown',
4011- 'http_error' => 'Didn\'t receive 200 OK from remote server.',
4012-);
4013-
4014-
4015-/**
4016- * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII)
4017- * @global string $GLOBALS['XML_RPC_defencoding']
4018- */
4019-$GLOBALS['XML_RPC_defencoding'] = 'UTF-8';
4020-
4021-/**
4022- * User error codes start at 800
4023- * @global int $GLOBALS['XML_RPC_erruser']
4024- */
4025-$GLOBALS['XML_RPC_erruser'] = 800;
4026-
4027-/**
4028- * XML parse error codes start at 100
4029- * @global int $GLOBALS['XML_RPC_errxml']
4030- */
4031-$GLOBALS['XML_RPC_errxml'] = 100;
4032-
4033-
4034-/**
4035- * Compose backslashes for escaping regexp
4036- * @global string $GLOBALS['XML_RPC_backslash']
4037- */
4038-$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92);
4039-
4040-
4041-/**
4042- * Stores state during parsing
4043- *
4044- * quick explanation of components:
4045- * + st = builds up a string for evaluation
4046- * + ac = accumulates values
4047- * + qt = decides if quotes are needed for evaluation
4048- * + cm = denotes struct or array (comma needed)
4049- * + isf = indicates a fault
4050- * + lv = indicates "looking for a value": implements the logic
4051- * to allow values with no types to be strings
4052- * + params = stores parameters in method calls
4053- * + method = stores method name
4054- *
4055- * @global array $GLOBALS['XML_RPC_xh']
4056- */
4057-$GLOBALS['XML_RPC_xh'] = array();
4058-
4059-
4060-/**
4061- * Start element handler for the XML parser
4062- *
4063- * @return void
4064- */
4065-function XML_RPC_se($parser, $name, $attrs)
4066-{
4067- global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String;
4068-
4069- switch ($name) {
4070- case 'STRUCT':
4071- case 'ARRAY':
4072- $XML_RPC_xh[$parser]['st'] .= 'array(';
4073- $XML_RPC_xh[$parser]['cm']++;
4074- // this last line turns quoting off
4075- // this means if we get an empty array we'll
4076- // simply get a bit of whitespace in the eval
4077- $XML_RPC_xh[$parser]['qt'] = 0;
4078- break;
4079-
4080- case 'NAME':
4081- $XML_RPC_xh[$parser]['st'] .= "'";
4082- $XML_RPC_xh[$parser]['ac'] = '';
4083- break;
4084-
4085- case 'FAULT':
4086- $XML_RPC_xh[$parser]['isf'] = 1;
4087- break;
4088-
4089- case 'PARAM':
4090- $XML_RPC_xh[$parser]['st'] = '';
4091- break;
4092-
4093- case 'VALUE':
4094- $XML_RPC_xh[$parser]['st'] .= 'new XML_RPC_Value(';
4095- $XML_RPC_xh[$parser]['lv'] = 1;
4096- $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String;
4097- $XML_RPC_xh[$parser]['ac'] = '';
4098- $XML_RPC_xh[$parser]['qt'] = 0;
4099- // look for a value: if this is still 1 by the
4100- // time we reach the first data segment then the type is string
4101- // by implication and we need to add in a quote
4102- break;
4103-
4104- case 'I4':
4105- case 'INT':
4106- case 'STRING':
4107- case 'BOOLEAN':
4108- case 'DOUBLE':
4109- case 'DATETIME.ISO8601':
4110- case 'BASE64':
4111- $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator
4112-
4113- if ($name == 'DATETIME.ISO8601' || $name == 'STRING') {
4114- $XML_RPC_xh[$parser]['qt'] = 1;
4115-
4116- if ($name == 'DATETIME.ISO8601') {
4117- $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime;
4118- }
4119-
4120- } elseif ($name == 'BASE64') {
4121- $XML_RPC_xh[$parser]['qt'] = 2;
4122- } else {
4123- // No quoting is required here -- but
4124- // at the end of the element we must check
4125- // for data format errors.
4126- $XML_RPC_xh[$parser]['qt'] = 0;
4127- }
4128- break;
4129-
4130- case 'MEMBER':
4131- $XML_RPC_xh[$parser]['ac'] = '';
4132- }
4133-
4134- if ($name != 'VALUE') {
4135- $XML_RPC_xh[$parser]['lv'] = 0;
4136- }
4137-}
4138-
4139-/**
4140- * End element handler for the XML parser
4141- *
4142- * @return void
4143- */
4144-function XML_RPC_ee($parser, $name)
4145-{
4146- global $XML_RPC_xh, $XML_RPC_Types, $XML_RPC_String;
4147-
4148- switch ($name) {
4149- case 'STRUCT':
4150- case 'ARRAY':
4151- if ($XML_RPC_xh[$parser]['cm']
4152- && substr($XML_RPC_xh[$parser]['st'], -1) == ',')
4153- {
4154- $XML_RPC_xh[$parser]['st'] = substr($XML_RPC_xh[$parser]['st'], 0, -1);
4155- }
4156-
4157- $XML_RPC_xh[$parser]['st'] .= ')';
4158- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4159- $XML_RPC_xh[$parser]['cm']--;
4160- break;
4161-
4162- case 'NAME':
4163- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . "' => ";
4164- break;
4165-
4166- case 'BOOLEAN':
4167- // special case here: we translate boolean 1 or 0 into PHP
4168- // constants true or false
4169- if ($XML_RPC_xh[$parser]['ac'] == '1') {
4170- $XML_RPC_xh[$parser]['ac'] = 'true';
4171- } else {
4172- $XML_RPC_xh[$parser]['ac'] = 'false';
4173- }
4174-
4175- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4176- // Drop through intentionally.
4177-
4178- case 'I4':
4179- case 'INT':
4180- case 'STRING':
4181- case 'DOUBLE':
4182- case 'DATETIME.ISO8601':
4183- case 'BASE64':
4184- if ($XML_RPC_xh[$parser]['qt'] == 1) {
4185- // we use double quotes rather than single so backslashification works OK
4186- $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
4187- } elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
4188- $XML_RPC_xh[$parser]['st'] .= "base64_decode('"
4189- . $XML_RPC_xh[$parser]['ac'] . "')";
4190- } elseif ($name == 'BOOLEAN') {
4191- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
4192- } else {
4193- // we have an I4, INT or a DOUBLE
4194- // we must check that only 0123456789-.<space> are characters here
4195- if (!ereg("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) {
4196- XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE',
4197- XML_RPC_ERROR_NON_NUMERIC_FOUND);
4198- $XML_RPC_xh[$parser]['st'] .= 'XML_RPC_ERROR_NON_NUMERIC_FOUND';
4199- } else {
4200- // it's ok, add it on
4201- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
4202- }
4203- }
4204-
4205- $XML_RPC_xh[$parser]['ac'] = '';
4206- $XML_RPC_xh[$parser]['qt'] = 0;
4207- $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value
4208- break;
4209-
4210- case 'VALUE':
4211- // deal with a string value
4212- if (strlen($XML_RPC_xh[$parser]['ac']) > 0 &&
4213- $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) {
4214-
4215- $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
4216- }
4217-
4218- // This if () detects if no scalar was inside <VALUE></VALUE>
4219- // and pads an empty "".
4220- if ($XML_RPC_xh[$parser]['st'][strlen($XML_RPC_xh[$parser]['st'])-1] == '(') {
4221- $XML_RPC_xh[$parser]['st'] .= '""';
4222- }
4223- $XML_RPC_xh[$parser]['st'] .= ", '" . $XML_RPC_xh[$parser]['vt'] . "')";
4224- if ($XML_RPC_xh[$parser]['cm']) {
4225- $XML_RPC_xh[$parser]['st'] .= ',';
4226- }
4227- break;
4228-
4229- case 'MEMBER':
4230- $XML_RPC_xh[$parser]['ac'] = '';
4231- $XML_RPC_xh[$parser]['qt'] = 0;
4232- break;
4233-
4234- case 'DATA':
4235- $XML_RPC_xh[$parser]['ac'] = '';
4236- $XML_RPC_xh[$parser]['qt'] = 0;
4237- break;
4238-
4239- case 'PARAM':
4240- $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['st'];
4241- break;
4242-
4243- case 'METHODNAME':
4244- $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", '',
4245- $XML_RPC_xh[$parser]['ac']);
4246- break;
4247-
4248- case 'BOOLEAN':
4249- // special case here: we translate boolean 1 or 0 into PHP
4250- // constants true or false
4251- if ($XML_RPC_xh[$parser]['ac'] == '1') {
4252- $XML_RPC_xh[$parser]['ac'] = 'true';
4253- } else {
4254- $XML_RPC_xh[$parser]['ac'] = 'false';
4255- }
4256-
4257- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4258- }
4259-
4260- // if it's a valid type name, set the type
4261- if (isset($XML_RPC_Types[strtolower($name)])) {
4262- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4263- }
4264-}
4265-
4266-/**
4267- * Character data handler for the XML parser
4268- *
4269- * @return void
4270- */
4271-function XML_RPC_cd($parser, $data)
4272-{
4273- global $XML_RPC_xh, $XML_RPC_backslash;
4274-
4275- if ($XML_RPC_xh[$parser]['lv'] != 3) {
4276- // "lookforvalue==3" means that we've found an entire value
4277- // and should discard any further character data
4278-
4279- if ($XML_RPC_xh[$parser]['lv'] == 1) {
4280- // if we've found text and we're just in a <value> then
4281- // turn quoting on, as this will be a string
4282- $XML_RPC_xh[$parser]['qt'] = 1;
4283- // and say we've found a value
4284- $XML_RPC_xh[$parser]['lv'] = 2;
4285- }
4286-
4287- // replace characters that eval would
4288- // do special things with
4289- if (!isset($XML_RPC_xh[$parser]['ac'])) {
4290- $XML_RPC_xh[$parser]['ac'] = '';
4291- }
4292- $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$',
4293- str_replace('"', '\"', str_replace(chr(92),
4294- $XML_RPC_backslash, $data)));
4295- }
4296-}
4297-
4298-/**
4299- * Base class
4300- *
4301- * This class provides common functions for all of the XML_RPC classes.
4302- *
4303- * @category Web Services
4304- * @package XML_RPC
4305- * @author Edd Dumbill <edd@usefulinc.com>
4306- * @author Stig Bakken <stig@php.net>
4307- * @author Martin Jansen <mj@php.net>
4308- * @copyright 1999-2001 Edd Dumbill
4309- * @version Release: 1.2.2
4310- * @link http://pear.php.net/package/XML_RPC
4311- */
4312-class XML_RPC_Base {
4313-
4314- /**
4315- * PEAR Error handling
4316- *
4317- * @return object PEAR_Error object
4318- */
4319- function raiseError($msg, $code)
4320- {
4321- include_once 'PEAR.php';
4322- if (is_object(@$this)) {
4323- return PEAR::raiseError(get_class($this) . ': ' . $msg, $code);
4324- } else {
4325- return PEAR::raiseError('XML_RPC: ' . $msg, $code);
4326- }
4327- }
4328-
4329- /**
4330- * Tell whether something is a PEAR_Error object
4331- *
4332- * @param mixed $value the item to check
4333- *
4334- * @return bool whether $value is a PEAR_Error object or not
4335- *
4336- * @access public
4337- */
4338- function isError($value)
4339- {
4340- return is_a($value, 'PEAR_Error');
4341- }
4342-}
4343-
4344-/**
4345- *
4346- *
4347- * @category Web Services
4348- * @package XML_RPC
4349- * @author Edd Dumbill <edd@usefulinc.com>
4350- * @author Stig Bakken <stig@php.net>
4351- * @author Martin Jansen <mj@php.net>
4352- * @author Daniel Convissor <danielc@php.net>
4353- * @copyright 1999-2001 Edd Dumbill
4354- * @version Release: 1.2.2
4355- * @link http://pear.php.net/package/XML_RPC
4356- */
4357-class XML_RPC_Client extends XML_RPC_Base {
4358-
4359- /**
4360- * The path and name of the RPC server script you want the request to go to
4361- * @var string
4362- */
4363- var $path = '';
4364-
4365- /**
4366- * The name of the remote server to connect to
4367- * @var string
4368- */
4369- var $server = '';
4370-
4371- /**
4372- * The protocol to use in contacting the remote server
4373- * @var string
4374- */
4375- var $protocol = 'http://';
4376-
4377- /**
4378- * The port for connecting to the remote server
4379- *
4380- * The default is 80 for http:// connections
4381- * and 443 for https:// and ssl:// connections.
4382- *
4383- * @var integer
4384- */
4385- var $port = 80;
4386-
4387- /**
4388- * A user name for accessing the RPC server
4389- * @var string
4390- * @see XML_RPC_Client::setCredentials()
4391- */
4392- var $username = '';
4393-
4394- /**
4395- * A password for accessing the RPC server
4396- * @var string
4397- * @see XML_RPC_Client::setCredentials()
4398- */
4399- var $password = '';
4400-
4401- /**
4402- * The name of the proxy server to use, if any
4403- * @var string
4404- */
4405- var $proxy = '';
4406-
4407- /**
4408- * The protocol to use in contacting the proxy server, if any
4409- * @var string
4410- */
4411- var $proxy_protocol = 'http://';
4412-
4413- /**
4414- * The port for connecting to the proxy server
4415- *
4416- * The default is 8080 for http:// connections
4417- * and 443 for https:// and ssl:// connections.
4418- *
4419- * @var integer
4420- */
4421- var $proxy_port = 8080;
4422-
4423- /**
4424- * A user name for accessing the proxy server
4425- * @var string
4426- */
4427- var $proxy_user = '';
4428-
4429- /**
4430- * A password for accessing the proxy server
4431- * @var string
4432- */
4433- var $proxy_pass = '';
4434-
4435- /**
4436- * The error number, if any
4437- * @var integer
4438- */
4439- var $errno = 0;
4440-
4441- /**
4442- * The error message, if any
4443- * @var string
4444- */
4445- var $errstring = '';
4446-
4447- /**
4448- * The current debug mode (1 = on, 0 = off)
4449- * @var integer
4450- */
4451- var $debug = 0;
4452-
4453-
4454- /**
4455- * Sets the object's properties
4456- *
4457- * @param string $path the path and name of the RPC server script
4458- * you want the request to go to
4459- * @param string $server the URL of the remote server to connect to.
4460- * If this parameter doesn't specify a
4461- * protocol and $port is 443, ssl:// is
4462- * assumed.
4463- * @param integer $port a port for connecting to the remote server.
4464- * Defaults to 80 for http:// connections and
4465- * 443 for https:// and ssl:// connections.
4466- * @param string $proxy the URL of the proxy server to use, if any.
4467- * If this parameter doesn't specify a
4468- * protocol and $port is 443, ssl:// is
4469- * assumed.
4470- * @param integer $proxy_port a port for connecting to the remote server.
4471- * Defaults to 8080 for http:// connections and
4472- * 443 for https:// and ssl:// connections.
4473- * @param string $proxy_user a user name for accessing the proxy server
4474- * @param string $proxy_pass a password for accessing the proxy server
4475- *
4476- * @return void
4477- */
4478- function XML_RPC_Client($path, $server, $port = 0,
4479- $proxy = '', $proxy_port = 0,
4480- $proxy_user = '', $proxy_pass = '')
4481- {
4482- $this->path = $path;
4483- $this->proxy_user = $proxy_user;
4484- $this->proxy_pass = $proxy_pass;
4485-
4486- preg_match('@^(http://|https://|ssl://)?(.*)$@', $server, $match);
4487- if ($match[1] == '') {
4488- if ($port == 443) {
4489- $this->server = $match[2];
4490- $this->protocol = 'ssl://';
4491- $this->port = 443;
4492- } else {
4493- $this->server = $match[2];
4494- if ($port) {
4495- $this->port = $port;
4496- }
4497- }
4498- } elseif ($match[1] == 'http://') {
4499- $this->server = $match[2];
4500- if ($port) {
4501- $this->port = $port;
4502- }
4503- } else {
4504- $this->server = $match[2];
4505- $this->protocol = 'ssl://';
4506- if ($port) {
4507- $this->port = $port;
4508- } else {
4509- $this->port = 443;
4510- }
4511- }
4512-
4513- if ($proxy) {
4514- preg_match('@^(http://|https://|ssl://)?(.*)$@', $proxy, $match);
4515- if ($match[1] == '') {
4516- if ($proxy_port == 443) {
4517- $this->proxy = $match[2];
4518- $this->proxy_protocol = 'ssl://';
4519- $this->proxy_port = 443;
4520- } else {
4521- $this->proxy = $match[2];
4522- if ($proxy_port) {
4523- $this->proxy_port = $proxy_port;
4524- }
4525- }
4526- } elseif ($match[1] == 'http://') {
4527- $this->proxy = $match[2];
4528- if ($proxy_port) {
4529- $this->proxy_port = $proxy_port;
4530- }
4531- } else {
4532- $this->proxy = $match[2];
4533- $this->proxy_protocol = 'ssl://';
4534- if ($proxy_port) {
4535- $this->proxy_port = $proxy_port;
4536- } else {
4537- $this->proxy_port = 443;
4538- }
4539- }
4540- }
4541- }
4542-
4543- /**
4544- * Change the current debug mode
4545- *
4546- * @param int $in where 1 = on, 0 = off
4547- *
4548- * @return void
4549- */
4550- function setDebug($in)
4551- {
4552- if ($in) {
4553- $this->debug = 1;
4554- } else {
4555- $this->debug = 0;
4556- }
4557- }
4558-
4559- /**
4560- * Set username and password properties for connecting to the RPC server
4561- *
4562- * @param string $u the user name
4563- * @param string $p the password
4564- *
4565- * @return void
4566- *
4567- * @see XML_RPC_Client::$username, XML_RPC_Client::$password
4568- */
4569- function setCredentials($u, $p)
4570- {
4571- $this->username = $u;
4572- $this->password = $p;
4573- }
4574-
4575- /**
4576- * Transmit the RPC request via HTTP 1.0 protocol
4577- *
4578- * @param object $msg the XML_RPC_Message object
4579- * @param int $timeout how many seconds to wait for the request
4580- *
4581- * @return object an XML_RPC_Response object. 0 is returned if any
4582- * problems happen.
4583- *
4584- * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(),
4585- * XML_RPC_Client::setCredentials()
4586- */
4587- function send($msg, $timeout = 0)
4588- {
4589- $msg->debug = $this->debug;
4590- return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
4591- $timeout, $this->username,
4592- $this->password);
4593- }
4594-
4595- /**
4596- * Transmit the RPC request via HTTP 1.0 protocol
4597- *
4598- * Requests should be sent using XML_RPC_Client send() rather than
4599- * calling this method directly.
4600- *
4601- * @param object $msg the XML_RPC_Message object
4602- * @param string $server the server to send the request to
4603- * @param int $port the server port send the request to
4604- * @param int $timeout how many seconds to wait for the request
4605- * before giving up
4606- * @param string $username a user name for accessing the RPC server
4607- * @param string $password a password for accessing the RPC server
4608- *
4609- * @return object an XML_RPC_Response object. 0 is returned if any
4610- * problems happen.
4611- *
4612- * @see XML_RPC_Client::send()
4613- */
4614- function sendPayloadHTTP10($msg, $server, $port, $timeout = 0,
4615- $username = '', $password = '')
4616- {
4617- /*
4618- * If we're using a proxy open a socket to the proxy server
4619- * instead to the xml-rpc server
4620- */
4621- if ($this->proxy) {
4622- if ($this->proxy_protocol == 'http://') {
4623- $protocol = '';
4624- } else {
4625- $protocol = $this->proxy_protocol;
4626- }
4627- if ($timeout > 0) {
4628- $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
4629- $this->errno, $this->errstr, $timeout);
4630- } else {
4631- $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
4632- $this->errno, $this->errstr);
4633- }
4634- } else {
4635- if ($this->protocol == 'http://') {
4636- $protocol = '';
4637- } else {
4638- $protocol = $this->protocol;
4639- }
4640- if ($timeout > 0) {
4641- $fp = @fsockopen($protocol . $server, $port,
4642- $this->errno, $this->errstr, $timeout);
4643- } else {
4644- $fp = @fsockopen($protocol . $server, $port,
4645- $this->errno, $this->errstr);
4646- }
4647- }
4648-
4649- /*
4650- * Just raising the error without returning it is strange,
4651- * but keep it here for backwards compatibility.
4652- */
4653- if (!$fp && $this->proxy) {
4654- $this->raiseError('Connection to proxy server '
4655- . $this->proxy . ':' . $this->proxy_port
4656- . ' failed. ' . $this->errstr,
4657- XML_RPC_ERROR_CONNECTION_FAILED);
4658- return 0;
4659- } elseif (!$fp) {
4660- $this->raiseError('Connection to RPC server '
4661- . $server . ':' . $port
4662- . ' failed. ' . $this->errstr,
4663- XML_RPC_ERROR_CONNECTION_FAILED);
4664- return 0;
4665- }
4666-
4667- // Only create the payload if it was not created previously
4668- if (empty($msg->payload)) {
4669- $msg->createPayload();
4670- }
4671-
4672- // thanks to Grant Rauscher <grant7@firstworld.net> for this
4673- $credentials = '';
4674- if ($username != '') {
4675- $credentials = 'Authorization: Basic ' .
4676- base64_encode($username . ':' . $password) . "\r\n";
4677- }
4678-
4679- if ($this->proxy) {
4680- $op = 'POST ' . $this->protocol . $server;
4681- if ($this->proxy_port) {
4682- $op .= ':' . $this->port;
4683- }
4684- } else {
4685- $op = 'POST ';
4686- }
4687-
4688- $op .= $this->path. " HTTP/1.0\r\n" .
4689- "User-Agent: PEAR XML_RPC\r\n" .
4690- 'Host: ' . $server . "\r\n";
4691- if ($this->proxy && $this->proxy_user != '') {
4692- $op .= 'Proxy-Authorization: Basic ' .
4693- base64_encode($this->proxy_user . ':' . $this->proxy_pass) .
4694- "\r\n";
4695- }
4696- $op .= $credentials .
4697- "Content-Type: text/xml\r\n" .
4698- 'Content-Length: ' . strlen($msg->payload) . "\r\n\r\n" .
4699- $msg->payload;
4700-
4701- if (!fputs($fp, $op, strlen($op))) {
4702- $this->errstr = 'Write error';
4703- return 0;
4704- }
4705- $resp = $msg->parseResponseFile($fp);
4706- fclose($fp);
4707- return $resp;
4708- }
4709-}
4710-
4711-/**
4712- *
4713- *
4714- * @category Web Services
4715- * @package XML_RPC
4716- * @author Edd Dumbill <edd@usefulinc.com>
4717- * @author Stig Bakken <stig@php.net>
4718- * @author Martin Jansen <mj@php.net>
4719- * @copyright 1999-2001 Edd Dumbill
4720- * @version Release: 1.2.2
4721- * @link http://pear.php.net/package/XML_RPC
4722- */
4723-class XML_RPC_Response extends XML_RPC_Base
4724-{
4725- var $xv;
4726- var $fn;
4727- var $fs;
4728- var $hdrs;
4729-
4730- /**
4731- * @return void
4732- */
4733- function XML_RPC_Response($val, $fcode = 0, $fstr = '')
4734- {
4735- if ($fcode != 0) {
4736- $this->fn = $fcode;
4737- $this->fs = htmlspecialchars($fstr);
4738- } else {
4739- $this->xv = $val;
4740- }
4741- }
4742-
4743- /**
4744- * @return int the error code
4745- */
4746- function faultCode()
4747- {
4748- if (isset($this->fn)) {
4749- return $this->fn;
4750- } else {
4751- return 0;
4752- }
4753- }
4754-
4755- /**
4756- * @return string the error string
4757- */
4758- function faultString()
4759- {
4760- return $this->fs;
4761- }
4762-
4763- /**
4764- * @return mixed the value
4765- */
4766- function value()
4767- {
4768- return $this->xv;
4769- }
4770-
4771- /**
4772- * @return string the error message in XML format
4773- */
4774- function serialize()
4775- {
4776- $rs = "<methodResponse>\n";
4777- if ($this->fn) {
4778- $rs .= "<fault>
4779- <value>
4780- <struct>
4781- <member>
4782- <name>faultCode</name>
4783- <value><int>" . $this->fn . "</int></value>
4784- </member>
4785- <member>
4786- <name>faultString</name>
4787- <value><string>" . $this->fs . "</string></value>
4788- </member>
4789- </struct>
4790- </value>
4791-</fault>";
4792- } else {
4793- $rs .= "<params>\n<param>\n" . $this->xv->serialize() .
4794- "</param>\n</params>";
4795- }
4796- $rs .= "\n</methodResponse>";
4797- return $rs;
4798- }
4799-}
4800-
4801-/**
4802- *
4803- *
4804- * @category Web Services
4805- * @package XML_RPC
4806- * @author Edd Dumbill <edd@usefulinc.com>
4807- * @author Stig Bakken <stig@php.net>
4808- * @author Martin Jansen <mj@php.net>
4809- * @author Daniel Convissor <danielc@php.net>
4810- * @copyright 1999-2001 Edd Dumbill
4811- * @version Release: 1.2.2
4812- * @link http://pear.php.net/package/XML_RPC
4813- */
4814-class XML_RPC_Message extends XML_RPC_Base
4815-{
4816- /**
4817- * The current debug mode (1 = on, 0 = off)
4818- * @var integer
4819- */
4820- var $debug = 0;
4821-
4822- /**
4823- * The encoding to be used for outgoing messages
4824- *
4825- * Defaults to the value of <var>$GLOBALS['XML_RPC_defencoding']</var>
4826- *
4827- * @var string
4828- * @see XML_RPC_Message::setSendEncoding(),
4829- * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header()
4830- */
4831- var $send_encoding = '';
4832-
4833- /**
4834- * The method presently being evaluated
4835- * @var string
4836- */
4837- var $methodname = '';
4838-
4839- /**
4840- * @var array
4841- */
4842- var $params = array();
4843-
4844- /**
4845- * The XML message being generated
4846- * @var string
4847- */
4848- var $payload = '';
4849-
4850- /**
4851- * @return void
4852- */
4853- function XML_RPC_Message($meth, $pars = 0)
4854- {
4855- $this->methodname = $meth;
4856- if (is_array($pars) && sizeof($pars) > 0) {
4857- for ($i = 0; $i < sizeof($pars); $i++) {
4858- $this->addParam($pars[$i]);
4859- }
4860- }
4861- }
4862-
4863- /**
4864- * Produces the XML declaration including the encoding attribute
4865- *
4866- * The encoding is determined by this class' <var>$send_encoding</var>
4867- * property. If the <var>$send_encoding</var> property is not set, use
4868- * <var>$GLOBALS['XML_RPC_defencoding']</var>.
4869- *
4870- * @return string the XML declaration and <methodCall> element
4871- *
4872- * @see XML_RPC_Message::setSendEncoding(),
4873- * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding']
4874- */
4875- function xml_header()
4876- {
4877- global $XML_RPC_defencoding;
4878- if (!$this->send_encoding) {
4879- $this->send_encoding = $XML_RPC_defencoding;
4880- }
4881- return '<?xml version="1.0" encoding="' . $this->send_encoding . '"?>'
4882- . "\n<methodCall>\n";
4883- }
4884-
4885- /**
4886- * @return string the closing </methodCall> tag
4887- */
4888- function xml_footer()
4889- {
4890- return "</methodCall>\n";
4891- }
4892-
4893- /**
4894- * @return void
4895- *
4896- * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer()
4897- */
4898- function createPayload()
4899- {
4900- $this->payload = $this->xml_header();
4901- $this->payload .= '<methodName>' . $this->methodname . "</methodName>\n";
4902- $this->payload .= "<params>\n";
4903- for ($i = 0; $i < sizeof($this->params); $i++) {
4904- $p = $this->params[$i];
4905- $this->payload .= "<param>\n" . $p->serialize() . "</param>\n";
4906- }
4907- $this->payload .= "</params>\n";
4908- $this->payload .= $this->xml_footer();
4909- $this->payload = ereg_replace("[\r\n]+", "\r\n", $this->payload);
4910- }
4911-
4912- /**
4913- * @return string the name of the method
4914- */
4915- function method($meth = '')
4916- {
4917- if ($meth != '') {
4918- $this->methodname = $meth;
4919- }
4920- return $this->methodname;
4921- }
4922-
4923- /**
4924- * @return string the payload
4925- */
4926- function serialize()
4927- {
4928- $this->createPayload();
4929- return $this->payload;
4930- }
4931-
4932- /**
4933- * @return void
4934- */
4935- function addParam($par)
4936- {
4937- $this->params[] = $par;
4938- }
4939-
4940- /**
4941- * @return void
4942- */
4943- function getParam($i)
4944- {
4945- return $this->params[$i];
4946- }
4947-
4948- /**
4949- * @return int the number of parameters
4950- */
4951- function getNumParams()
4952- {
4953- return sizeof($this->params);
4954- }
4955-
4956- /**
4957- * Sets the XML declaration's encoding attribute
4958- *
4959- * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII)
4960- *
4961- * @return void
4962- *
4963- * @see XML_RPC_Message::$send_encoding, XML_RPC_Message::xml_header()
4964- * @since Method available since Release 1.2.0
4965- */
4966- function setSendEncoding($type)
4967- {
4968- $this->send_encoding = $type;
4969- }
4970-
4971- /**
4972- * Determine the XML's encoding via the encoding attribute
4973- * in the XML declaration
4974- *
4975- * If the encoding parameter is not set or is not ISO-8859-1, UTF-8
4976- * or US-ASCII, $XML_RPC_defencoding will be returned.
4977- *
4978- * @param string $data the XML that will be parsed
4979- *
4980- * @return string the encoding to be used
4981- *
4982- * @link http://php.net/xml_parser_create
4983- * @since Method available since Release 1.2.0
4984- */
4985- function getEncoding($data)
4986- {
4987- global $XML_RPC_defencoding;
4988-
4989- if (preg_match('/<\?xml[^>]*\s*encoding\s*=\s*[\'"]([^"\']*)[\'"]/i',
4990- $data, $match))
4991- {
4992- $match[1] = trim(strtoupper($match[1]));
4993- switch ($match[1]) {
4994- case 'ISO-8859-1':
4995- case 'UTF-8':
4996- case 'US-ASCII':
4997- return $match[1];
4998- break;
4999-
5000- default:
5001- return $XML_RPC_defencoding;
5002- }
5003- } else {
5004- return $XML_RPC_defencoding;
5005- }
5006- }
5007-
5008- /**
5009- * @return object a new XML_RPC_Response object
5010- */
5011- function parseResponseFile($fp)
5012- {
5013- $ipd = '';
5014- while ($data = @fread($fp, 8192)) {
5015- $ipd .= $data;
5016- }
5017- return $this->parseResponse($ipd);
5018- }
5019-
5020- /**
5021- * @return object a new XML_RPC_Response object
5022- */
5023- function parseResponse($data = '')
5024- {
5025- global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding;
5026-
5027- $encoding = $this->getEncoding($data);
5028- $parser = xml_parser_create($encoding);
5029-
5030- $XML_RPC_xh[$parser] = array();
5031-
5032- $XML_RPC_xh[$parser]['st'] = '';
5033- $XML_RPC_xh[$parser]['cm'] = 0;
5034- $XML_RPC_xh[$parser]['isf'] = 0;
5035- $XML_RPC_xh[$parser]['ac'] = '';
5036- $XML_RPC_xh[$parser]['qt'] = '';
5037-
5038- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
5039- xml_set_element_handler($parser, 'XML_RPC_se', 'XML_RPC_ee');
5040- xml_set_character_data_handler($parser, 'XML_RPC_cd');
5041-
5042- $hdrfnd = 0;
5043- if ($this->debug) {
5044- print "<PRE>---GOT---\n";
5045- print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
5046- print "\n---END---\n</PRE>";
5047- }
5048-
5049- // see if we got an HTTP 200 OK, else bomb
5050- // but only do this if we're using the HTTP protocol.
5051- if (ereg('^HTTP', $data) &&
5052- !ereg('^HTTP/[0-9\.]+ 200 ', $data)) {
5053- $errstr = substr($data, 0, strpos($data, "\n") - 1);
5054- error_log('HTTP error, got response: ' . $errstr);
5055- $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'],
5056- $XML_RPC_str['http_error'] . ' (' .
5057- $errstr . ')');
5058- xml_parser_free($parser);
5059- return $r;
5060- }
5061- // gotta get rid of headers here
5062-
5063-
5064- if ((!$hdrfnd) && ($brpos = strpos($data,"\r\n\r\n"))) {
5065- $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
5066- $data = substr($data, $brpos + 4);
5067- $hdrfnd = 1;
5068- }
5069-
5070- /*
5071- * be tolerant of junk after methodResponse
5072- * (e.g. javascript automatically inserted by free hosts)
5073- * thanks to Luca Mariano <luca.mariano@email.it>
5074- */
5075- $data = substr($data, 0, strpos($data, "</methodResponse>") + 17);
5076-
5077- if (!xml_parse($parser, $data, sizeof($data))) {
5078- // thanks to Peter Kocks <peter.kocks@baygate.com>
5079- if ((xml_get_current_line_number($parser)) == 1) {
5080- $errstr = 'XML error at line 1, check URL';
5081- } else {
5082- $errstr = sprintf('XML error: %s at line %d',
5083- xml_error_string(xml_get_error_code($parser)),
5084- xml_get_current_line_number($parser));
5085- }
5086- error_log($errstr);
5087- $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
5088- $XML_RPC_str['invalid_return']);
5089- xml_parser_free($parser);
5090- return $r;
5091- }
5092- xml_parser_free($parser);
5093- if ($this->debug) {
5094- print '<PRE>---EVALING---[' .
5095- strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
5096- htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---</PRE>";
5097- }
5098- if (strlen($XML_RPC_xh[$parser]['st']) == 0) {
5099- // then something odd has happened
5100- // and it's time to generate a client side error
5101- // indicating something odd went on
5102- $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
5103- $XML_RPC_str['invalid_return']);
5104- } else {
5105- eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;');
5106- if ($XML_RPC_xh[$parser]['isf']) {
5107- $f = $v->structmem('faultCode');
5108- $fs = $v->structmem('faultString');
5109- $r = new XML_RPC_Response($v, $f->scalarval(),
5110- $fs->scalarval());
5111- } else {
5112- $r = new XML_RPC_Response($v);
5113- }
5114- }
5115- $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
5116- return $r;
5117- }
5118-}
5119-
5120-/**
5121- *
5122- *
5123- * @category Web Services
5124- * @package XML_RPC
5125- * @author Edd Dumbill <edd@usefulinc.com>
5126- * @author Stig Bakken <stig@php.net>
5127- * @author Martin Jansen <mj@php.net>
5128- * @copyright 1999-2001 Edd Dumbill
5129- * @version Release: 1.2.2
5130- * @link http://pear.php.net/package/XML_RPC
5131- */
5132-class XML_RPC_Value extends XML_RPC_Base
5133-{
5134- var $me = array();
5135- var $mytype = 0;
5136-
5137- /**
5138- * @return void
5139- */
5140- function XML_RPC_Value($val = -1, $type = '')
5141- {
5142- global $XML_RPC_Types;
5143- $this->me = array();
5144- $this->mytype = 0;
5145- if ($val != -1 || $type != '') {
5146- if ($type == '') {
5147- $type = 'string';
5148- }
5149- if (!array_key_exists($type, $XML_RPC_Types)) {
5150- // XXX
5151- // need some way to report this error
5152- } elseif ($XML_RPC_Types[$type] == 1) {
5153- $this->addScalar($val, $type);
5154- } elseif ($XML_RPC_Types[$type] == 2) {
5155- $this->addArray($val);
5156- } elseif ($XML_RPC_Types[$type] == 3) {
5157- $this->addStruct($val);
5158- }
5159- }
5160- }
5161-
5162- /**
5163- * @return int returns 1 if successful or 0 if there are problems
5164- */
5165- function addScalar($val, $type = 'string')
5166- {
5167- global $XML_RPC_Types, $XML_RPC_Boolean;
5168-
5169- if ($this->mytype == 1) {
5170- $this->raiseError('Scalar can have only one value',
5171- XML_RPC_ERROR_INVALID_TYPE);
5172- return 0;
5173- }
5174- $typeof = $XML_RPC_Types[$type];
5175- if ($typeof != 1) {
5176- $this->raiseError("Not a scalar type (${typeof})",
5177- XML_RPC_ERROR_INVALID_TYPE);
5178- return 0;
5179- }
5180-
5181- if ($type == $XML_RPC_Boolean) {
5182- if (strcasecmp($val, 'true') == 0
5183- || $val == 1
5184- || ($val == true && strcasecmp($val, 'false')))
5185- {
5186- $val = 1;
5187- } else {
5188- $val = 0;
5189- }
5190- }
5191-
5192- if ($this->mytype == 2) {
5193- // we're adding to an array here
5194- $ar = $this->me['array'];
5195- $ar[] = new XML_RPC_Value($val, $type);
5196- $this->me['array'] = $ar;
5197- } else {
5198- // a scalar, so set the value and remember we're scalar
5199- $this->me[$type] = $val;
5200- $this->mytype = $typeof;
5201- }
5202- return 1;
5203- }
5204-
5205- /**
5206- * @return int returns 1 if successful or 0 if there are problems
5207- */
5208- function addArray($vals)
5209- {
5210- global $XML_RPC_Types;
5211- if ($this->mytype != 0) {
5212- $this->raiseError(
5213- 'Already initialized as a [' . $this->kindOf() . ']',
5214- XML_RPC_ERROR_ALREADY_INITIALIZED);
5215- return 0;
5216- }
5217- $this->mytype = $XML_RPC_Types['array'];
5218- $this->me['array'] = $vals;
5219- return 1;
5220- }
5221-
5222- /**
5223- * @return int returns 1 if successful or 0 if there are problems
5224- */
5225- function addStruct($vals)
5226- {
5227- global $XML_RPC_Types;
5228- if ($this->mytype != 0) {
5229- $this->raiseError(
5230- 'Already initialized as a [' . $this->kindOf() . ']',
5231- XML_RPC_ERROR_ALREADY_INITIALIZED);
5232- return 0;
5233- }
5234- $this->mytype = $XML_RPC_Types['struct'];
5235- $this->me['struct'] = $vals;
5236- return 1;
5237- }
5238-
5239- /**
5240- * @return void
5241- */
5242- function dump($ar)
5243- {
5244- reset($ar);
5245- while (list($key, $val) = each($ar)) {
5246- echo "$key => $val<br>";
5247- if ($key == 'array') {
5248- while (list($key2, $val2) = each($val)) {
5249- echo "-- $key2 => $val2<br>";
5250- }
5251- }
5252- }
5253- }
5254-
5255- /**
5256- * @return string the data type of the current value
5257- */
5258- function kindOf()
5259- {
5260- switch ($this->mytype) {
5261- case 3:
5262- return 'struct';
5263-
5264- case 2:
5265- return 'array';
5266-
5267- case 1:
5268- return 'scalar';
5269-
5270- default:
5271- return 'undef';
5272- }
5273- }
5274-
5275- /**
5276- * @return string the data in XML format
5277- */
5278- function serializedata($typ, $val)
5279- {
5280- $rs = '';
5281- global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
5282- if (!array_key_exists($typ, $XML_RPC_Types)) {
5283- // XXX
5284- // need some way to report this error
5285- return;
5286- }
5287- switch ($XML_RPC_Types[$typ]) {
5288- case 3:
5289- // struct
5290- $rs .= "<struct>\n";
5291- reset($val);
5292- while (list($key2, $val2) = each($val)) {
5293- $rs .= "<member><name>${key2}</name>\n";
5294- $rs .= $this->serializeval($val2);
5295- $rs .= "</member>\n";
5296- }
5297- $rs .= '</struct>';
5298- break;
5299-
5300- case 2:
5301- // array
5302- $rs .= "<array>\n<data>\n";
5303- for ($i = 0; $i < sizeof($val); $i++) {
5304- $rs .= $this->serializeval($val[$i]);
5305- }
5306- $rs .= "</data>\n</array>";
5307- break;
5308-
5309- case 1:
5310- switch ($typ) {
5311- case $XML_RPC_Base64:
5312- $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
5313- break;
5314- case $XML_RPC_Boolean:
5315- $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
5316- break;
5317- case $XML_RPC_String:
5318- $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
5319- break;
5320- default:
5321- $rs .= "<${typ}>${val}</${typ}>";
5322- }
5323- }
5324- return $rs;
5325- }
5326-
5327- /**
5328- * @return string the data in XML format
5329- */
5330- function serialize()
5331- {
5332- return $this->serializeval($this);
5333- }
5334-
5335- /**
5336- * @return string the data in XML format
5337- */
5338- function serializeval($o)
5339- {
5340- $rs = '';
5341- $ar = $o->me;
5342- reset($ar);
5343- list($typ, $val) = each($ar);
5344- $rs .= '<value>';
5345- $rs .= $this->serializedata($typ, $val);
5346- $rs .= "</value>\n";
5347- return $rs;
5348- }
5349-
5350- /**
5351- * @return mixed the contents of the element requested
5352- */
5353- function structmem($m)
5354- {
5355- return $this->me['struct'][$m];
5356- }
5357-
5358- /**
5359- * @return void
5360- */
5361- function structreset()
5362- {
5363- reset($this->me['struct']);
5364- }
5365-
5366- /**
5367- * @return the key/value pair of the struct's current element
5368- */
5369- function structeach()
5370- {
5371- return each($this->me['struct']);
5372- }
5373-
5374- /**
5375- * @return mixed the current value
5376- */
5377- function getval() {
5378- // UNSTABLE
5379- global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
5380-
5381- reset($this->me);
5382- list($a, $b) = each($this->me);
5383-
5384- // contributed by I Sofer, 2001-03-24
5385- // add support for nested arrays to scalarval
5386- // i've created a new method here, so as to
5387- // preserve back compatibility
5388-
5389- if (is_array($b)) {
5390- foreach ($b as $id => $cont) {
5391- $b[$id] = $cont->scalarval();
5392- }
5393- }
5394-
5395- // add support for structures directly encoding php objects
5396- if (is_object($b)) {
5397- $t = get_object_vars($b);
5398- foreach ($t as $id => $cont) {
5399- $t[$id] = $cont->scalarval();
5400- }
5401- foreach ($t as $id => $cont) {
5402- eval('$b->'.$id.' = $cont;');
5403- }
5404- }
5405-
5406- // end contrib
5407- return $b;
5408- }
5409-
5410- /**
5411- * @return mixed
5412- */
5413- function scalarval()
5414- {
5415- global $XML_RPC_Boolean, $XML_RPC_Base64;
5416- reset($this->me);
5417- list($a, $b) = each($this->me);
5418- return $b;
5419- }
5420-
5421- /**
5422- * @return string
5423- */
5424- function scalartyp()
5425- {
5426- global $XML_RPC_I4, $XML_RPC_Int;
5427- reset($this->me);
5428- list($a, $b) = each($this->me);
5429- if ($a == $XML_RPC_I4) {
5430- $a = $XML_RPC_Int;
5431- }
5432- return $a;
5433- }
5434-
5435- /**
5436- * @return mixed the struct's current element
5437- */
5438- function arraymem($m)
5439- {
5440- return $this->me['array'][$m];
5441- }
5442-
5443- /**
5444- * @return int the number of elements in the array
5445- */
5446- function arraysize()
5447- {
5448- reset($this->me);
5449- list($a, $b) = each($this->me);
5450- return sizeof($b);
5451- }
5452-}
5453-
5454-/**
5455- * Return an ISO8601 encoded string
5456- *
5457- * While timezones ought to be supported, the XML-RPC spec says:
5458- *
5459- * "Don't assume a timezone. It should be specified by the server in its
5460- * documentation what assumptions it makes about timezones."
5461- *
5462- * This routine always assumes localtime unless $utc is set to 1, in which
5463- * case UTC is assumed and an adjustment for locale is made when encoding.
5464- *
5465- * @return string the formatted date
5466- */
5467-function XML_RPC_iso8601_encode($timet, $utc = 0) {
5468- if (!$utc) {
5469- $t = strftime('%Y%m%dT%H:%M:%S', $timet);
5470- } else {
5471- if (function_exists('gmstrftime')) {
5472- // gmstrftime doesn't exist in some versions
5473- // of PHP
5474- $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet);
5475- } else {
5476- $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z'));
5477- }
5478- }
5479- return $t;
5480-}
5481-
5482-/**
5483- * Convert a datetime string into a Unix timestamp
5484- *
5485- * While timezones ought to be supported, the XML-RPC spec says:
5486- *
5487- * "Don't assume a timezone. It should be specified by the server in its
5488- * documentation what assumptions it makes about timezones."
5489- *
5490- * This routine always assumes localtime unless $utc is set to 1, in which
5491- * case UTC is assumed and an adjustment for locale is made when encoding.
5492- *
5493- * @return int the unix timestamp of the date submitted
5494- */
5495-function XML_RPC_iso8601_decode($idate, $utc = 0) {
5496- $t = 0;
5497- if (ereg('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) {
5498- if ($utc) {
5499- $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
5500- } else {
5501- $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
5502- }
5503- }
5504- return $t;
5505-}
5506-
5507-/**
5508- * Takes a message in PHP XML_RPC object format and translates it into
5509- * native PHP types
5510- *
5511- * @return mixed
5512- *
5513- * @author Dan Libby <dan@libby.com>
5514- */
5515-function XML_RPC_decode($XML_RPC_val)
5516-{
5517- $kind = $XML_RPC_val->kindOf();
5518-
5519- if ($kind == 'scalar') {
5520- return $XML_RPC_val->scalarval();
5521-
5522- } elseif ($kind == 'array') {
5523- $size = $XML_RPC_val->arraysize();
5524- $arr = array();
5525- for ($i = 0; $i < $size; $i++) {
5526- $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i));
5527- }
5528- return $arr;
5529-
5530- } elseif ($kind == 'struct') {
5531- $XML_RPC_val->structreset();
5532- $arr = array();
5533- while (list($key, $value) = $XML_RPC_val->structeach()) {
5534- $arr[$key] = XML_RPC_decode($value);
5535- }
5536- return $arr;
5537- }
5538-}
5539-
5540-/**
5541- * Takes native php types and encodes them into XML_RPC PHP object format
5542- *
5543- * Feature creep -- could support more types via optional type argument.
5544- *
5545- * @return string
5546- *
5547- * @author Dan Libby <dan@libby.com>
5548- */
5549-function XML_RPC_encode($php_val) {
5550- global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double, $XML_RPC_String,
5551- $XML_RPC_Array, $XML_RPC_Struct;
5552-
5553- $type = gettype($php_val);
5554- $XML_RPC_val = new XML_RPC_Value;
5555-
5556- switch ($type) {
5557- case 'array':
5558- if (empty($php_val)) {
5559- $XML_RPC_val->addArray($php_val);
5560- break;
5561- }
5562- $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1));
5563- if (empty($tmp)) {
5564- $arr = array();
5565- foreach ($php_val as $k => $v) {
5566- $arr[$k] = XML_RPC_encode($v);
5567- }
5568- $XML_RPC_val->addArray($arr);
5569- break;
5570- }
5571- // fall though if it's not an enumerated array
5572-
5573- case 'object':
5574- $arr = array();
5575- foreach ($php_val as $k => $v) {
5576- $arr[$k] = XML_RPC_encode($v);
5577- }
5578- $XML_RPC_val->addStruct($arr);
5579- break;
5580-
5581- case 'integer':
5582- $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
5583- break;
5584-
5585- case 'double':
5586- $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
5587- break;
5588-
5589- case 'string':
5590- case 'NULL':
5591- $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
5592- break;
5593-
5594- case 'boolean':
5595- // Add support for encoding/decoding of booleans, since they
5596- // are supported in PHP
5597- // by <G_Giunta_2001-02-29>
5598- $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
5599- break;
5600-
5601- case 'unknown type':
5602- default:
5603- $XML_RPC_val = false;
5604- }
5605- return $XML_RPC_val;
5606-}
5607-
5608-/*
5609- * Local variables:
5610- * tab-width: 4
5611- * c-basic-offset: 4
5612- * c-hanging-comment-ender-p: nil
5613- * End:
5614- */
5615-
5616-?>
5617-XML_RPC-1.2.2/Server.php
5618-
5619-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5620-
5621-/**
5622- * PHP implementation of the XML-RPC protocol
5623- *
5624- * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
5625- * It has support for HTTP transport, proxies and authentication.
5626- *
5627- * PHP versions 4 and 5
5628- *
5629- * LICENSE: License is granted to use or modify this software
5630- * ("XML-RPC for PHP") for commercial or non-commercial use provided the
5631- * copyright of the author is preserved in any distributed or derivative work.
5632- *
5633- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
5634- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5635- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5636- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5637- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5638- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5639- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5640- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5641- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5642- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5643- *
5644- * @category Web Services
5645- * @package XML_RPC
5646- * @author Edd Dumbill <edd@usefulinc.com>
5647- * @author Stig Bakken <stig@php.net>
5648- * @author Martin Jansen <mj@php.net>
5649- * @copyright 1999-2001 Edd Dumbill
5650- * @version CVS: $Id: Server.php,v 1.17 2005/03/01 17:09:49 danielc Exp $
5651- * @link http://pear.php.net/package/XML_RPC
5652- */
5653-
5654-
5655-/**
5656- * Pull in the XML_RPC class
5657- */
5658-require_once 'XML/RPC.php';
5659-
5660-
5661-/**
5662- * listMethods: either a string, or nothing
5663- * @global array $GLOBALS['XML_RPC_Server_listMethods_sig']
5664- */
5665-$GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
5666- array($GLOBALS['XML_RPC_Array'],
5667- $GLOBALS['XML_RPC_String']
5668- ),
5669- array($GLOBALS['XML_RPC_Array'])
5670-);
5671-
5672-/**
5673- * @global string $GLOBALS['XML_RPC_Server_listMethods_doc']
5674- */
5675-$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the'
5676- . ' methods that the XML-RPC server knows how to dispatch';
5677-
5678-/**
5679- * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig']
5680- */
5681-$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
5682- array($GLOBALS['XML_RPC_Array'],
5683- $GLOBALS['XML_RPC_String']
5684- )
5685-);
5686-
5687-/**
5688- * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc']
5689- */
5690-$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
5691- . ' signatures (an array of arrays) for the method name passed. If'
5692- . ' no signatures are known, returns a none-array (test for type !='
5693- . ' array to detect missing signature)';
5694-
5695-/**
5696- * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig']
5697- */
5698-$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
5699- array($GLOBALS['XML_RPC_String'],
5700- $GLOBALS['XML_RPC_String']
5701- )
5702-);
5703-
5704-/**
5705- * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc']
5706- */
5707-$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined'
5708- . ' for the method passed, otherwise returns an empty string';
5709-
5710-/**
5711- * @global array $GLOBALS['XML_RPC_Server_dmap']
5712- */
5713-$GLOBALS['XML_RPC_Server_dmap'] = array(
5714- 'system.listMethods' => array(
5715- 'function' => 'XML_RPC_Server_listMethods',
5716- 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'],
5717- 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc']
5718- ),
5719- 'system.methodHelp' => array(
5720- 'function' => 'XML_RPC_Server_methodHelp',
5721- 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'],
5722- 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc']
5723- ),
5724- 'system.methodSignature' => array(
5725- 'function' => 'XML_RPC_Server_methodSignature',
5726- 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'],
5727- 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc']
5728- )
5729-);
5730-
5731-/**
5732- * @global string $GLOBALS['XML_RPC_Server_debuginfo']
5733- */
5734-$GLOBALS['XML_RPC_Server_debuginfo'] = '';
5735-
5736-
5737-/**
5738- * Lists all the methods that the XML-RPC server knows how to dispatch
5739- *
5740- * @return object a new XML_RPC_Response object
5741- */
5742-function XML_RPC_Server_listMethods($server, $m)
5743-{
5744- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
5745-
5746- $v = new XML_RPC_Value();
5747- $dmap = $server->dmap;
5748- $outAr = array();
5749- for (reset($dmap); list($key, $val) = each($dmap); ) {
5750- $outAr[] = new XML_RPC_Value($key, 'string');
5751- }
5752- $dmap = $XML_RPC_Server_dmap;
5753- for (reset($dmap); list($key, $val) = each($dmap); ) {
5754- $outAr[] = new XML_RPC_Value($key, 'string');
5755- }
5756- $v->addArray($outAr);
5757- return new XML_RPC_Response($v);
5758-}
5759-
5760-/**
5761- * Returns an array of known signatures (an array of arrays)
5762- * for the given method
5763- *
5764- * If no signatures are known, returns a none-array
5765- * (test for type != array to detect missing signature)
5766- *
5767- * @return object a new XML_RPC_Response object
5768- */
5769-function XML_RPC_Server_methodSignature($server, $m)
5770-{
5771- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
5772-
5773- $methName = $m->getParam(0);
5774- $methName = $methName->scalarval();
5775- if (strpos($methName, 'system.') === 0) {
5776- $dmap = $XML_RPC_Server_dmap;
5777- $sysCall = 1;
5778- } else {
5779- $dmap = $server->dmap;
5780- $sysCall = 0;
5781- }
5782- // print "<!-- ${methName} -->\n";
5783- if (isset($dmap[$methName])) {
5784- if ($dmap[$methName]['signature']) {
5785- $sigs = array();
5786- $thesigs = $dmap[$methName]['signature'];
5787- for ($i = 0; $i < sizeof($thesigs); $i++) {
5788- $cursig = array();
5789- $inSig = $thesigs[$i];
5790- for ($j = 0; $j < sizeof($inSig); $j++) {
5791- $cursig[] = new XML_RPC_Value($inSig[$j], 'string');
5792- }
5793- $sigs[] = new XML_RPC_Value($cursig, 'array');
5794- }
5795- $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array'));
5796- } else {
5797- $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string'));
5798- }
5799- } else {
5800- $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
5801- $XML_RPC_str['introspect_unknown']);
5802- }
5803- return $r;
5804-}
5805-
5806-/**
5807- * Returns help text if defined for the method passed, otherwise returns
5808- * an empty string
5809- *
5810- * @return object a new XML_RPC_Response object
5811- */
5812-function XML_RPC_Server_methodHelp($server, $m)
5813-{
5814- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
5815-
5816- $methName = $m->getParam(0);
5817- $methName = $methName->scalarval();
5818- if (strpos($methName, 'system.') === 0) {
5819- $dmap = $XML_RPC_Server_dmap;
5820- $sysCall = 1;
5821- } else {
5822- $dmap = $server->dmap;
5823- $sysCall = 0;
5824- }
5825- // print "<!-- ${methName} -->\n";
5826- if (isset($dmap[$methName])) {
5827- if ($dmap[$methName]['docstring']) {
5828- $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']),
5829- 'string');
5830- } else {
5831- $r = new XML_RPC_Response(new XML_RPC_Value('', 'string'));
5832- }
5833- } else {
5834- $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
5835- $XML_RPC_str['introspect_unknown']);
5836- }
5837- return $r;
5838-}
5839-
5840-/**
5841- * @return void
5842- */
5843-function XML_RPC_Server_debugmsg($m)
5844-{
5845- global $XML_RPC_Server_debuginfo;
5846- $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n";
5847-}
5848-
5849-
5850-/**
5851- *
5852- *
5853- * @category Web Services
5854- * @package XML_RPC
5855- * @author Edd Dumbill <edd@usefulinc.com>
5856- * @author Stig Bakken <stig@php.net>
5857- * @author Martin Jansen <mj@php.net>
5858- * @copyright 1999-2001 Edd Dumbill
5859- * @version Release: 1.2.2
5860- * @link http://pear.php.net/package/XML_RPC
5861- */
5862-class XML_RPC_Server
5863-{
5864- var $dmap = array();
5865- var $encoding = '';
5866- var $debug = 0;
5867-
5868- /**
5869- * @return void
5870- */
5871- function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0)
5872- {
5873- global $HTTP_RAW_POST_DATA;
5874-
5875- if ($debug) {
5876- $this->debug = 1;
5877- } else {
5878- $this->debug = 0;
5879- }
5880-
5881- // dispMap is a despatch array of methods
5882- // mapped to function names and signatures
5883- // if a method
5884- // doesn't appear in the map then an unknown
5885- // method error is generated
5886- $this->dmap = $dispMap;
5887- if ($serviceNow) {
5888- $this->service();
5889- }
5890- }
5891-
5892- /**
5893- * @return string the debug information if debug debug mode is on
5894- */
5895- function serializeDebug()
5896- {
5897- global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA;
5898-
5899- if ($this->debug) {
5900- XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n"
5901- . $HTTP_RAW_POST_DATA
5902- . "\n" . '^^^ END POST DATA ^^^');
5903- }
5904-
5905- if ($XML_RPC_Server_debuginfo != '') {
5906- return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n"
5907- . preg_replace('/-(?=-)/', '- ', $XML_RPC_Server_debuginfo)
5908- . "-->\n";
5909- } else {
5910- return '';
5911- }
5912- }
5913-
5914- /**
5915- * Print out the result
5916- *
5917- * The encoding and content-type are determined by
5918- * XML_RPC_Message::getEncoding()
5919- *
5920- * @return void
5921- *
5922- * @see XML_RPC_Message::getEncoding()
5923- */
5924- function service()
5925- {
5926- $r = $this->parseRequest();
5927- $payload = '<?xml version="1.0" encoding="'
5928- . $this->encoding . '"?>' . "\n"
5929- . $this->serializeDebug()
5930- . $r->serialize();
5931- header('Content-Length: ' . strlen($payload));
5932- header('Content-Type: text/xml; charset=' . $this->encoding);
5933- print $payload;
5934- }
5935-
5936- /**
5937- * @return array
5938- */
5939- function verifySignature($in, $sig)
5940- {
5941- for ($i = 0; $i < sizeof($sig); $i++) {
5942- // check each possible signature in turn
5943- $cursig = $sig[$i];
5944- if (sizeof($cursig) == $in->getNumParams() + 1) {
5945- $itsOK = 1;
5946- for ($n = 0; $n < $in->getNumParams(); $n++) {
5947- $p = $in->getParam($n);
5948- // print "<!-- $p -->\n";
5949- if ($p->kindOf() == 'scalar') {
5950- $pt = $p->scalartyp();
5951- } else {
5952- $pt = $p->kindOf();
5953- }
5954- // $n+1 as first type of sig is return type
5955- if ($pt != $cursig[$n+1]) {
5956- $itsOK = 0;
5957- $pno = $n+1;
5958- $wanted = $cursig[$n+1];
5959- $got = $pt;
5960- break;
5961- }
5962- }
5963- if ($itsOK) {
5964- return array(1);
5965- }
5966- }
5967- }
5968- return array(0, "Wanted ${wanted}, got ${got} at param ${pno})");
5969- }
5970-
5971- /**
5972- * @return object a new XML_RPC_Response object
5973- */
5974- function parseRequest($data = '')
5975- {
5976- global $XML_RPC_xh, $HTTP_RAW_POST_DATA,
5977- $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml,
5978- $XML_RPC_defencoding, $XML_RPC_Server_dmap;
5979-
5980- if ($data == '') {
5981- $data = $HTTP_RAW_POST_DATA;
5982- }
5983-
5984- $this->encoding = XML_RPC_Message::getEncoding($data);
5985- $parser = xml_parser_create($this->encoding);
5986-
5987- $XML_RPC_xh[$parser] = array();
5988- $XML_RPC_xh[$parser]['st'] = '';
5989- $XML_RPC_xh[$parser]['cm'] = 0;
5990- $XML_RPC_xh[$parser]['isf'] = 0;
5991- $XML_RPC_xh[$parser]['params'] = array();
5992- $XML_RPC_xh[$parser]['method'] = '';
5993-
5994- $plist = '';
5995-
5996- // decompose incoming XML into request structure
5997-
5998- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
5999- xml_set_element_handler($parser, 'XML_RPC_se', 'XML_RPC_ee');
6000- xml_set_character_data_handler($parser, 'XML_RPC_cd');
6001- if (!xml_parse($parser, $data, 1)) {
6002- // return XML error as a faultCode
6003- $r = new XML_RPC_Response(0,
6004- $XML_RPC_errxml+xml_get_error_code($parser),
6005- sprintf('XML error: %s at line %d',
6006- xml_error_string(xml_get_error_code($parser)),
6007- xml_get_current_line_number($parser)));
6008- xml_parser_free($parser);
6009- } else {
6010- xml_parser_free($parser);
6011- $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']);
6012- // now add parameters in
6013- for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) {
6014- // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n";
6015- $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n";
6016- eval('$m->addParam(' . $XML_RPC_xh[$parser]['params'][$i] . ');');
6017- }
6018- XML_RPC_Server_debugmsg($plist);
6019-
6020- // now to deal with the method
6021- $methName = $XML_RPC_xh[$parser]['method'];
6022- if (strpos($methName, 'system.') === 0) {
6023- $dmap = $XML_RPC_Server_dmap;
6024- $sysCall = 1;
6025- } else {
6026- $dmap = $this->dmap;
6027- $sysCall = 0;
6028- }
6029-
6030- if (isset($dmap[$methName]['function'])
6031- && is_string($dmap[$methName]['function'])
6032- && strpos($dmap[$methName]['function'], '::') !== false)
6033- {
6034- $dmap[$methName]['function'] =
6035- explode('::', $dmap[$methName]['function']);
6036- }
6037-
6038- if (isset($dmap[$methName]['function'])
6039- && is_callable($dmap[$methName]['function']))
6040- {
6041- // dispatch if exists
6042- if (isset($dmap[$methName]['signature'])) {
6043- $sr = $this->verifySignature($m,
6044- $dmap[$methName]['signature'] );
6045- }
6046- if ( (!isset($dmap[$methName]['signature'])) || $sr[0]) {
6047- // if no signature or correct signature
6048- if ($sysCall) {
6049- $r = call_user_func($dmap[$methName]['function'], $this, $m);
6050- } else {
6051- $r = call_user_func($dmap[$methName]['function'], $m);
6052- }
6053- } else {
6054- $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
6055- $XML_RPC_str['incorrect_params']
6056- . ': ' . $sr[1]);
6057- }
6058- } else {
6059- // else prepare error response
6060- $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'],
6061- $XML_RPC_str['unknown_method']);
6062- }
6063- }
6064- return $r;
6065- }
6066-
6067- /**
6068- * Echos back the input packet as a string value
6069- *
6070- * @return void
6071- *
6072- * Useful for debugging.
6073- */
6074- function echoInput() {
6075- global $HTTP_RAW_POST_DATA;
6076-
6077- $r = new XML_RPC_Response(0);
6078- $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string');
6079- print $r->serialize();
6080- }
6081-}
6082-
6083-/*
6084- * Local variables:
6085- * tab-width: 4
6086- * c-basic-offset: 4
6087- * c-hanging-comment-ender-p: nil
6088- * End:
6089- */
6090-
6091-?>
6092-
6093-<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
6094-<package version="1.0" packagerversion="1.4.0a1">
6095- <name>XML_RPC</name>
6096- <summary>PHP implementation of the XML-RPC protocol</summary>
6097- <description>A PEAR-ified version of Useful Inc's XML-RPC for PHP.
6098-
6099-It has support for HTTP/HTTPS transport, proxies and authentication.
6100- </description>
6101- <maintainers>
6102- <maintainer>
6103- <user>ssb</user>
6104- <name>Stig Bakken</name>
6105- <email>stig@php.net</email>
6106- <role>lead</role>
6107- </maintainer>
6108- <maintainer>
6109- <user>danielc</user>
6110- <name>Daniel Convissor</name>
6111- <email>danielc@php.net</email>
6112- <role>lead</role>
6113- </maintainer>
6114- </maintainers>
6115- <release>
6116- <version>1.2.2</version>
6117- <date>2005-03-07</date>
6118- <license>PHP License</license>
6119- <state>stable</state>
6120- <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.
6121- </notes>
6122- <filelist>
6123- <file role="php" baseinstalldir="XML" name="RPC.php">
6124- <replace from="@package_version@" to="version" type="package-info"/>
6125- </file>
6126- <file role="php" baseinstalldir="XML/RPC" name="Server.php">
6127- <replace from="@package_version@" to="version" type="package-info"/>
6128- </file>
6129- <file role="php" baseinstalldir="XML/RPC" name="Dump.php">
6130- <replace from="@package_version@" to="version" type="package-info"/>
6131- </file>
6132- <file role="test" name="tests/protoport.php">
6133- <replace from="@package_version@" to="version" type="package-info"/>
6134- </file>
6135- <file role="test" name="tests/test_Dump.php">
6136- <replace from="@package_version@" to="version" type="package-info"/>
6137- </file>
6138- </filelist>
6139- </release>
6140- <changelog>
6141- <release>
6142- <version>1.2.1</version>
6143- <date>2005-03-01</date>
6144- <state>stable</state>
6145- <notes>* Add isset() check before examining the dispatch map. Bug 3658.
6146- </notes>
6147- </release>
6148- <release>
6149- <version>1.2.0</version>
6150- <date>2005-02-27</date>
6151- <state>stable</state>
6152- <notes>* Provide the &quot;stable&quot; release.
6153-* Add package2.xml for compatibility with PEAR 1.4.0.
6154-* For changes since 1.1.0, see the changelogs for the various RC releases.
6155- </notes>
6156- </release>
6157- <release>
6158- <version>1.2.0RC7</version>
6159- <date>2005-02-22</date>
6160- <state>beta</state>
6161- <notes>* Add the setSendEncoding() method and $send_encoding
6162- property to XML_RPC_Message. Request 3537.
6163-* Allow class methods to be mapped using either syntax:
6164- 'function' =&gt; 'hello::sayHello',
6165- or
6166- 'function' =&gt; array('hello', 'sayhello'),
6167- Bug 3363.
6168-* Use 8192 instead of 32768 for bytes in fread()
6169- in parseResponseFile(). Bug 3340.
6170- </notes>
6171- </release>
6172- <release>
6173- <version>1.2.0RC6</version>
6174- <date>2005-01-25</date>
6175- <state>beta</state>
6176- <notes>* Don't put the protocol in the Host field of the POST data. (danielc)
6177- </notes>
6178- </release>
6179- <release>
6180- <version>1.2.0RC5</version>
6181- <date>2005-01-24</date>
6182- <state>beta</state>
6183- <notes>* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
6184- </notes>
6185- </release>
6186- <release>
6187- <version>1.2.0RC4</version>
6188- <date>2005-01-24</date>
6189- <state>beta</state>
6190- <notes>* When a connection attempt fails, have the method return 0. (danielc)
6191-* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
6192-* Add tests for setting the client properties. (danielc)
6193-* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc)
6194-* Bundle the tests with the package. (danielc)
6195- </notes>
6196- </release>
6197- <release>
6198- <version>1.2.0RC3</version>
6199- <date>2005-01-19</date>
6200- <state>beta</state>
6201- <notes>* ssl uses port 443, not 445.
6202- </notes>
6203- </release>
6204- <release>
6205- <version>1.2.0RC2</version>
6206- <date>2005-01-11</date>
6207- <state>beta</state>
6208- <notes>* Handle ssl:// in the $server string. (danielc)
6209-* Also default to port 445 for ssl:// requests as well. (danielc)
6210-* Enhance debugging in the server. (danielc)
6211- </notes>
6212- </release>
6213- <release>
6214- <version>1.2.0RC1</version>
6215- <date>2004-12-30</date>
6216- <state>beta</state>
6217- <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
6218-* Allow array function callbacks (Matt Kane)
6219-* Some minor speed-ups (Matt Kane)
6220-* Add Dump.php to the package (Christian Weiske)
6221-* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
6222-* Silence fsockopen() errors. Bug 1714. (danielc)
6223-* Encode empty arrays as an array. Bug 1493. (danielc)
6224-* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
6225-* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
6226-* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc)
6227-* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
6228-* Allow raiseError() to be called statically. (danielc)
6229-* Stop double escaping of character entities. Bug 987. (danielc)
6230- NOTICE: the following have been removed:
6231- * XML_RPC_dh()
6232- * $GLOBALS['XML_RPC_entities']
6233- * XML_RPC_entity_decode()
6234- * XML_RPC_lookup_entity()
6235-* Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)
6236- </notes>
6237- </release>
6238- <release>
6239- <version>1.1.0</version>
6240- <date>2004-03-15</date>
6241- <state>stable</state>
6242- <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
6243-* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
6244-* Remove &quot;require_once 'PEAR.php'&quot;, include only when needed to raise an error
6245-* Replace echo and error_log() with raiseError() (mroch)
6246-* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
6247-* be tolerant of junk after methodResponse (Luca Mariano, mroch)
6248-* Silent notice even in the error log (pierre)
6249-* fix include of shared xml extension on win32 (pierre)
6250- </notes>
6251- </release>
6252- <release>
6253- <version>1.0.4</version>
6254- <date>2002-10-02</date>
6255- <state>stable</state>
6256- <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)
6257- </notes>
6258- </release>
6259- <release>
6260- <version>1.0.3</version>
6261- <date>2002-05-19</date>
6262- <state>stable</state>
6263- <notes>* fix bug when parsing responses with boolean types
6264- </notes>
6265- </release>
6266- <release>
6267- <version>1.0.2</version>
6268- <date>2002-04-16</date>
6269- <state>stable</state>
6270- <notes>* E_ALL fixes
6271-* fix HTTP response header parsing
6272- </notes>
6273- </release>
6274- <release>
6275- <version>1.0.1</version>
6276- <date>2001-09-25</date>
6277- <state>stable</state>
6278- <notes>This is a PEAR-ified version of Useful Inc's 1.0.1 release.
6279-Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.
6280- </notes>
6281- </release>
6282- </changelog>
6283-</package>
6284-
6285\ Kein Zeilenumbruch am Dateiende.
6286diff -Naur php-4.3.11/pear/packages/XML_RPC-1.3.1.tar hardening-patch-4.3.11-0.3.2/pear/packages/XML_RPC-1.3.1.tar
6287--- php-4.3.11/pear/packages/XML_RPC-1.3.1.tar 1970-01-01 01:00:00.000000000 +0100
6288+++ hardening-patch-4.3.11-0.3.2/pear/packages/XML_RPC-1.3.1.tar 2005-07-09 08:53:02.503358096 +0200
6289@@ -0,0 +1,3733 @@
6290+package2.xml
6291+<package packagerversion="1.4.0a12" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
6292+ <name>XML_RPC</name>
6293+ <channel>pear.php.net</channel>
6294+ <summary>PHP implementation of the XML-RPC protocol</summary>
6295+ <description>A PEAR-ified version of Useful Inc&apos;s XML-RPC for PHP.
6296+
6297+It has support for HTTP/HTTPS transport, proxies and authentication.</description>
6298+ <lead>
6299+ <name>Stig Bakken</name>
6300+ <user>ssb</user>
6301+ <email>stig@php.net</email>
6302+ <active>no</active>
6303+ </lead>
6304+ <lead>
6305+ <name>Daniel Convissor</name>
6306+ <user>danielc</user>
6307+ <email>danielc@php.net</email>
6308+ <active>yes</active>
6309+ </lead>
6310+ <date>2005-06-29</date>
6311+ <time>15:09:18</time>
6312+ <version>
6313+ <release>1.3.1</release>
6314+ <api>1.3.0</api>
6315+ </version>
6316+ <stability>
6317+ <release>stable</release>
6318+ <api>stable</api>
6319+ </stability>
6320+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6321+ <notes>* Security fix. Update highly recommended!</notes>
6322+ <contents>
6323+ <dir name="/">
6324+ <file md5sum="9b06c053e8e534f8d731eb90de2d0681" name="tests/protoport.php" role="test">
6325+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6326+ </file>
6327+ <file md5sum="74d1c90ae551d28bd40030fcc0b0f38d" name="tests/test_Dump.php" role="test">
6328+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6329+ </file>
6330+ <file baseinstalldir="XML/RPC" md5sum="5e2dfc5771116965655e07b4665563ce" name="Dump.php" role="php">
6331+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6332+ </file>
6333+ <file baseinstalldir="XML" md5sum="1e79cf06ae3ada5a6603c003ac0521e3" name="RPC.php" role="php">
6334+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6335+ </file>
6336+ <file baseinstalldir="XML/RPC" md5sum="6a750e3517d25ca01e685e8afe3976d6" name="Server.php" role="php">
6337+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6338+ </file>
6339+ </dir>
6340+ </contents>
6341+ <compatible>
6342+ <name>PEAR</name>
6343+ <channel>pear.php.net</channel>
6344+ <min>1.4.0a1</min>
6345+ <max>1.4.0a12</max>
6346+ </compatible>
6347+ <dependencies>
6348+ <required>
6349+ <php>
6350+ <min>4.2.0</min>
6351+ <max>6.0.0</max>
6352+ </php>
6353+ <pearinstaller>
6354+ <min>1.4.0a1</min>
6355+ </pearinstaller>
6356+ </required>
6357+ </dependencies>
6358+ <phprelease />
6359+ <changelog>
6360+ <release>
6361+ <version>
6362+ <release>1.3.0RC3</release>
6363+ <api>1.3.0</api>
6364+ </version>
6365+ <stability>
6366+ <release>beta</release>
6367+ <api>stable</api>
6368+ </stability>
6369+ <date>2005-05-10</date>
6370+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6371+ <notes>* When verifying requests against function signatures, if the number of parameters don&apos;t match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
6372+* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
6373+* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
6374+* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
6375+* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
6376+* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().</notes>
6377+ </release>
6378+ <release>
6379+ <version>
6380+ <release>1.3.0RC2</release>
6381+ <api>1.3.0</api>
6382+ </version>
6383+ <stability>
6384+ <release>beta</release>
6385+ <api>beta</api>
6386+ </stability>
6387+ <date>2005-05-05</date>
6388+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6389+ <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
6390+* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
6391+* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
6392+* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.</notes>
6393+ </release>
6394+ <release>
6395+ <version>
6396+ <release>1.3.0RC1</release>
6397+ <api>1.3.0</api>
6398+ </version>
6399+ <stability>
6400+ <release>beta</release>
6401+ <api>beta</api>
6402+ </stability>
6403+ <date>2005-04-07</date>
6404+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6405+ <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
6406+* Add Fault Code 6: &quot;The requested method didn&apos;t return an XML_RPC_Response object.&quot; Request 4032.
6407+* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
6408+* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
6409+* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
6410+* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.</notes>
6411+ </release>
6412+ <release>
6413+ <version>
6414+ <release>1.2.2</release>
6415+ <api>1.2.0</api>
6416+ </version>
6417+ <stability>
6418+ <release>stable</release>
6419+ <api>stable</api>
6420+ </stability>
6421+ <date>2005-03-07</date>
6422+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6423+ <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.</notes>
6424+ </release>
6425+ <release>
6426+ <version>
6427+ <release>1.2.1</release>
6428+ <api>1.2.0</api>
6429+ </version>
6430+ <stability>
6431+ <release>stable</release>
6432+ <api>stable</api>
6433+ </stability>
6434+ <date>2005-03-01</date>
6435+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6436+ <notes>* Add isset() check before examining the dispatch map. Bug 3658.</notes>
6437+ </release>
6438+ <release>
6439+ <version>
6440+ <release>1.2.0</release>
6441+ <api>1.2.0</api>
6442+ </version>
6443+ <stability>
6444+ <release>stable</release>
6445+ <api>stable</api>
6446+ </stability>
6447+ <date>2005-02-27</date>
6448+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6449+ <notes>* Provide the &quot;stable&quot; release.
6450+* Add package2.xml for compatibility with PEAR 1.4.0.
6451+* For changes since 1.1.0, see the changelogs for the various RC releases.</notes>
6452+ </release>
6453+ <release>
6454+ <version>
6455+ <release>1.2.0RC7</release>
6456+ <api>1.2.0RC7</api>
6457+ </version>
6458+ <stability>
6459+ <release>beta</release>
6460+ <api>beta</api>
6461+ </stability>
6462+ <date>2005-02-22</date>
6463+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6464+ <notes>* Add the setSendEncoding() method and $send_encoding
6465+ property to XML_RPC_Message. Request 3537.
6466+* Allow class methods to be mapped using either syntax:
6467+ &apos;function&apos; =&gt; &apos;hello::sayHello&apos;,
6468+ or
6469+ &apos;function&apos; =&gt; array(&apos;hello&apos;, &apos;sayhello&apos;),
6470+ Bug 3363.
6471+* Use 8192 instead of 32768 for bytes in fread()
6472+ in parseResponseFile(). Bug 3340.</notes>
6473+ </release>
6474+ <release>
6475+ <version>
6476+ <release>1.2.0RC6</release>
6477+ <api>1.2.0RC6</api>
6478+ </version>
6479+ <stability>
6480+ <release>beta</release>
6481+ <api>beta</api>
6482+ </stability>
6483+ <date>2005-01-25</date>
6484+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6485+ <notes>* Don&apos;t put the protocol in the Host field of the POST data. (danielc)</notes>
6486+ </release>
6487+ <release>
6488+ <version>
6489+ <release>1.2.0RC5</release>
6490+ <api>1.2.0RC5</api>
6491+ </version>
6492+ <stability>
6493+ <release>beta</release>
6494+ <api>beta</api>
6495+ </stability>
6496+ <date>2005-01-24</date>
6497+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6498+ <notes>* If $port is 443 but a protocol isn&apos;t specified in $server, assume ssl:// is the protocol.</notes>
6499+ </release>
6500+ <release>
6501+ <version>
6502+ <release>1.2.0RC4</release>
6503+ <api>1.2.0RC4</api>
6504+ </version>
6505+ <stability>
6506+ <release>beta</release>
6507+ <api>beta</api>
6508+ </stability>
6509+ <date>2005-01-24</date>
6510+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6511+ <notes>* When a connection attempt fails, have the method return 0. (danielc)
6512+* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
6513+* Add tests for setting the client properties. (danielc)
6514+* Remove $GLOBALS[&apos;XML_RPC_twoslash&apos;] since it&apos;s not used. (danielc)
6515+* Bundle the tests with the package. (danielc)</notes>
6516+ </release>
6517+ <release>
6518+ <version>
6519+ <release>1.2.0RC3</release>
6520+ <api>1.2.0RC3</api>
6521+ </version>
6522+ <stability>
6523+ <release>beta</release>
6524+ <api>beta</api>
6525+ </stability>
6526+ <date>2005-01-19</date>
6527+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6528+ <notes>* ssl uses port 443, not 445.</notes>
6529+ </release>
6530+ <release>
6531+ <version>
6532+ <release>1.2.0RC2</release>
6533+ <api>1.2.0RC2</api>
6534+ </version>
6535+ <stability>
6536+ <release>beta</release>
6537+ <api>beta</api>
6538+ </stability>
6539+ <date>2005-01-11</date>
6540+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6541+ <notes>* Handle ssl:// in the $server string. (danielc)
6542+* Also default to port 445 for ssl:// requests as well. (danielc)
6543+* Enhance debugging in the server. (danielc)</notes>
6544+ </release>
6545+ <release>
6546+ <version>
6547+ <release>1.2.0RC1</release>
6548+ <api>1.2.0RC1</api>
6549+ </version>
6550+ <stability>
6551+ <release>beta</release>
6552+ <api>beta</api>
6553+ </stability>
6554+ <date>2004-12-30</date>
6555+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6556+ <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
6557+* Allow array function callbacks (Matt Kane)
6558+* Some minor speed-ups (Matt Kane)
6559+* Add Dump.php to the package (Christian Weiske)
6560+* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
6561+* Silence fsockopen() errors. Bug 1714. (danielc)
6562+* Encode empty arrays as an array. Bug 1493. (danielc)
6563+* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
6564+* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
6565+* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()&apos;ing error messages. (danielc)
6566+* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
6567+* Allow raiseError() to be called statically. (danielc)
6568+* Stop double escaping of character entities. Bug 987. (danielc)
6569+ NOTICE: the following have been removed:
6570+ * XML_RPC_dh()
6571+ * $GLOBALS[&apos;XML_RPC_entities&apos;]
6572+ * XML_RPC_entity_decode()
6573+ * XML_RPC_lookup_entity()
6574+* Determine the XML&apos;s encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)</notes>
6575+ </release>
6576+ <release>
6577+ <version>
6578+ <release>1.1.0</release>
6579+ <api>1.1.0</api>
6580+ </version>
6581+ <stability>
6582+ <release>stable</release>
6583+ <api>stable</api>
6584+ </stability>
6585+ <date>2004-03-15</date>
6586+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6587+ <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
6588+* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
6589+* Remove &quot;require_once &apos;PEAR.php&apos;&quot;, include only when needed to raise an error
6590+* Replace echo and error_log() with raiseError() (mroch)
6591+* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
6592+* be tolerant of junk after methodResponse (Luca Mariano, mroch)
6593+* Silent notice even in the error log (pierre)
6594+* fix include of shared xml extension on win32 (pierre)</notes>
6595+ </release>
6596+ <release>
6597+ <version>
6598+ <release>1.0.4</release>
6599+ <api>1.0.4</api>
6600+ </version>
6601+ <stability>
6602+ <release>stable</release>
6603+ <api>stable</api>
6604+ </stability>
6605+ <date>2002-10-02</date>
6606+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6607+ <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)</notes>
6608+ </release>
6609+ <release>
6610+ <version>
6611+ <release>1.0.3</release>
6612+ <api>1.0.3</api>
6613+ </version>
6614+ <stability>
6615+ <release>stable</release>
6616+ <api>stable</api>
6617+ </stability>
6618+ <date>2002-05-19</date>
6619+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6620+ <notes>* fix bug when parsing responses with boolean types</notes>
6621+ </release>
6622+ <release>
6623+ <version>
6624+ <release>1.0.2</release>
6625+ <api>1.0.2</api>
6626+ </version>
6627+ <stability>
6628+ <release>stable</release>
6629+ <api>stable</api>
6630+ </stability>
6631+ <date>2002-04-16</date>
6632+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6633+ <notes>* E_ALL fixes
6634+* fix HTTP response header parsing</notes>
6635+ </release>
6636+ <release>
6637+ <version>
6638+ <release>1.0.1</release>
6639+ <api>1.0.1</api>
6640+ </version>
6641+ <stability>
6642+ <release>stable</release>
6643+ <api>stable</api>
6644+ </stability>
6645+ <date>2001-09-25</date>
6646+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6647+ <notes>This is a PEAR-ified version of Useful Inc&apos;s 1.0.1 release.
6648+Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.</notes>
6649+ </release>
6650+ </changelog>
6651+</package>
6652+
6653+
6654+/**
6655+ * Tests that properties of XML_RPC_Client get properly set
6656+ *
6657+ * Any individual tests that fail will have their name, expected result
6658+ * and actual result printed out. So seeing no output when executing
6659+ * this file is a good thing.
6660+ *
6661+ * Can be run via CLI or a web server.
6662+ *
6663+ * PHP versions 4 and 5
6664+ *
6665+ * LICENSE: This source file is subject to version 3.0 of the PHP license
6666+ * that is available through the world-wide-web at the following URI:
6667+ * http://www.php.net/license/3_0.txt. If you did not receive a copy of
6668+ * the PHP License and are unable to obtain it through the web, please
6669+ * send a note to license@php.net so we can mail you a copy immediately.
6670+ *
6671+ * @category Web Services
6672+ * @package XML_RPC
6673+ * @author Daniel Convissor <danielc@php.net>
6674+ * @copyright 2005 The PHP Group
6675+ * @license http://www.php.net/license/3_0.txt PHP License
6676+ * @version CVS: $Id: protoport.php,v 1.4 2005/01/24 17:48:47 danielc Exp $
6677+ * @link http://pear.php.net/package/XML_RPC
6678+ * @since File available since Release 1.2
6679+ */
6680+
6681+/*
6682+ * If the package version number is found in the left hand
6683+ * portion of the if() expression below, that means this file has
6684+ * come from the PEAR installer. Therefore, let's test the
6685+ * installed version of XML_RPC which should be in the include path.
6686+ *
6687+ * If the version has not been substituted in the if() expression,
6688+ * this file has likely come from a CVS checkout or a .tar file.
6689+ * Therefore, we'll assume the tests should use the version of
6690+ * XML_RPC that has come from there as well.
6691+ */
6692+if ('1.3.1' != '@'.'package_version'.'@') {
6693+ /**
6694+ * Get the needed class from the PEAR installation
6695+ */
6696+ require_once 'XML/RPC.php';
6697+} else {
6698+ /**
6699+ * Get the needed class from the parent directory
6700+ */
6701+ require_once '../RPC.php';
6702+}
6703+
6704+/**
6705+ * Compare the test result to the expected result
6706+ *
6707+ * If the test fails, echo out the results.
6708+ *
6709+ * @param array $expect the array of object properties you expect
6710+ * from the test
6711+ * @param object $actual the object results from the test
6712+ * @param string $test_name the name of the test
6713+ *
6714+ * @return void
6715+ */
6716+function compare($expect, $actual, $test_name) {
6717+ $actual = get_object_vars($actual);
6718+ if (count(array_diff($actual, $expect))) {
6719+ echo "$test_name failed.\nExpect: ";
6720+ print_r($expect);
6721+ echo "Actual: ";
6722+ print_r($actual);
6723+ echo "\n";
6724+ }
6725+}
6726+
6727+if (php_sapi_name() != 'cli') {
6728+ echo "<pre>\n";
6729+}
6730+
6731+
6732+$x = array(
6733+ 'path' => 'thepath',
6734+ 'server' => 'theserver',
6735+ 'protocol' => 'http://',
6736+ 'port' => 80,
6737+ 'proxy' => '',
6738+ 'proxy_protocol' => 'http://',
6739+ 'proxy_port' => 8080,
6740+ 'proxy_user' => '',
6741+ 'proxy_pass' => '',
6742+ 'errno' => 0,
6743+ 'errstring' => '',
6744+ 'debug' => 0,
6745+ 'username' => '',
6746+ 'password' => '',
6747+);
6748+$c = new XML_RPC_Client('thepath', 'theserver');
6749+compare($x, $c, 'defaults');
6750+
6751+$x = array(
6752+ 'path' => 'thepath',
6753+ 'server' => 'theserver',
6754+ 'protocol' => 'http://',
6755+ 'port' => 80,
6756+ 'proxy' => '',
6757+ 'proxy_protocol' => 'http://',
6758+ 'proxy_port' => 8080,
6759+ 'proxy_user' => '',
6760+ 'proxy_pass' => '',
6761+ 'errno' => 0,
6762+ 'errstring' => '',
6763+ 'debug' => 0,
6764+ 'username' => '',
6765+ 'password' => '',
6766+);
6767+$c = new XML_RPC_Client('thepath', 'http://theserver');
6768+compare($x, $c, 'defaults with http');
6769+
6770+$x = array(
6771+ 'path' => 'thepath',
6772+ 'server' => 'theserver',
6773+ 'protocol' => 'ssl://',
6774+ 'port' => 443,
6775+ 'proxy' => '',
6776+ 'proxy_protocol' => 'http://',
6777+ 'proxy_port' => 8080,
6778+ 'proxy_user' => '',
6779+ 'proxy_pass' => '',
6780+ 'errno' => 0,
6781+ 'errstring' => '',
6782+ 'debug' => 0,
6783+ 'username' => '',
6784+ 'password' => '',
6785+);
6786+$c = new XML_RPC_Client('thepath', 'https://theserver');
6787+compare($x, $c, 'defaults with https');
6788+
6789+$x = array(
6790+ 'path' => 'thepath',
6791+ 'server' => 'theserver',
6792+ 'protocol' => 'ssl://',
6793+ 'port' => 443,
6794+ 'proxy' => '',
6795+ 'proxy_protocol' => 'http://',
6796+ 'proxy_port' => 8080,
6797+ 'proxy_user' => '',
6798+ 'proxy_pass' => '',
6799+ 'errno' => 0,
6800+ 'errstring' => '',
6801+ 'debug' => 0,
6802+ 'username' => '',
6803+ 'password' => '',
6804+);
6805+$c = new XML_RPC_Client('thepath', 'ssl://theserver');
6806+compare($x, $c, 'defaults with ssl');
6807+
6808+
6809+$x = array(
6810+ 'path' => 'thepath',
6811+ 'server' => 'theserver',
6812+ 'protocol' => 'http://',
6813+ 'port' => 65,
6814+ 'proxy' => '',
6815+ 'proxy_protocol' => 'http://',
6816+ 'proxy_port' => 8080,
6817+ 'proxy_user' => '',
6818+ 'proxy_pass' => '',
6819+ 'errno' => 0,
6820+ 'errstring' => '',
6821+ 'debug' => 0,
6822+ 'username' => '',
6823+ 'password' => '',
6824+);
6825+$c = new XML_RPC_Client('thepath', 'theserver', 65);
6826+compare($x, $c, 'port 65');
6827+
6828+$x = array(
6829+ 'path' => 'thepath',
6830+ 'server' => 'theserver',
6831+ 'protocol' => 'http://',
6832+ 'port' => 65,
6833+ 'proxy' => '',
6834+ 'proxy_protocol' => 'http://',
6835+ 'proxy_port' => 8080,
6836+ 'proxy_user' => '',
6837+ 'proxy_pass' => '',
6838+ 'errno' => 0,
6839+ 'errstring' => '',
6840+ 'debug' => 0,
6841+ 'username' => '',
6842+ 'password' => '',
6843+);
6844+$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
6845+compare($x, $c, 'port 65 with http');
6846+
6847+$x = array(
6848+ 'path' => 'thepath',
6849+ 'server' => 'theserver',
6850+ 'protocol' => 'ssl://',
6851+ 'port' => 65,
6852+ 'proxy' => '',
6853+ 'proxy_protocol' => 'http://',
6854+ 'proxy_port' => 8080,
6855+ 'proxy_user' => '',
6856+ 'proxy_pass' => '',
6857+ 'errno' => 0,
6858+ 'errstring' => '',
6859+ 'debug' => 0,
6860+ 'username' => '',
6861+ 'password' => '',
6862+);
6863+$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
6864+compare($x, $c, 'port 65 with https');
6865+
6866+$x = array(
6867+ 'path' => 'thepath',
6868+ 'server' => 'theserver',
6869+ 'protocol' => 'ssl://',
6870+ 'port' => 65,
6871+ 'proxy' => '',
6872+ 'proxy_protocol' => 'http://',
6873+ 'proxy_port' => 8080,
6874+ 'proxy_user' => '',
6875+ 'proxy_pass' => '',
6876+ 'errno' => 0,
6877+ 'errstring' => '',
6878+ 'debug' => 0,
6879+ 'username' => '',
6880+ 'password' => '',
6881+);
6882+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
6883+compare($x, $c, 'port 65 with ssl');
6884+
6885+
6886+$x = array(
6887+ 'path' => 'thepath',
6888+ 'server' => 'theserver',
6889+ 'protocol' => 'http://',
6890+ 'port' => 80,
6891+ 'proxy' => 'theproxy',
6892+ 'proxy_protocol' => 'http://',
6893+ 'proxy_port' => 8080,
6894+ 'proxy_user' => '',
6895+ 'proxy_pass' => '',
6896+ 'errno' => 0,
6897+ 'errstring' => '',
6898+ 'debug' => 0,
6899+ 'username' => '',
6900+ 'password' => '',
6901+);
6902+$c = new XML_RPC_Client('thepath', 'theserver', 0,
6903+ 'theproxy');
6904+compare($x, $c, 'defaults proxy');
6905+
6906+$x = array(
6907+ 'path' => 'thepath',
6908+ 'server' => 'theserver',
6909+ 'protocol' => 'http://',
6910+ 'port' => 80,
6911+ 'proxy' => 'theproxy',
6912+ 'proxy_protocol' => 'http://',
6913+ 'proxy_port' => 8080,
6914+ 'proxy_user' => '',
6915+ 'proxy_pass' => '',
6916+ 'errno' => 0,
6917+ 'errstring' => '',
6918+ 'debug' => 0,
6919+ 'username' => '',
6920+ 'password' => '',
6921+);
6922+$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
6923+ 'http://theproxy');
6924+compare($x, $c, 'defaults with http proxy');
6925+
6926+$x = array(
6927+ 'path' => 'thepath',
6928+ 'server' => 'theserver',
6929+ 'protocol' => 'ssl://',
6930+ 'port' => 443,
6931+ 'proxy' => 'theproxy',
6932+ 'proxy_protocol' => 'ssl://',
6933+ 'proxy_port' => 443,
6934+ 'proxy_user' => '',
6935+ 'proxy_pass' => '',
6936+ 'errno' => 0,
6937+ 'errstring' => '',
6938+ 'debug' => 0,
6939+ 'username' => '',
6940+ 'password' => '',
6941+);
6942+$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
6943+ 'https://theproxy');
6944+compare($x, $c, 'defaults with https proxy');
6945+
6946+$x = array(
6947+ 'path' => 'thepath',
6948+ 'server' => 'theserver',
6949+ 'protocol' => 'ssl://',
6950+ 'port' => 443,
6951+ 'proxy' => 'theproxy',
6952+ 'proxy_protocol' => 'ssl://',
6953+ 'proxy_port' => 443,
6954+ 'proxy_user' => '',
6955+ 'proxy_pass' => '',
6956+ 'errno' => 0,
6957+ 'errstring' => '',
6958+ 'debug' => 0,
6959+ 'username' => '',
6960+ 'password' => '',
6961+);
6962+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
6963+ 'ssl://theproxy');
6964+compare($x, $c, 'defaults with ssl proxy');
6965+
6966+
6967+$x = array(
6968+ 'path' => 'thepath',
6969+ 'server' => 'theserver',
6970+ 'protocol' => 'http://',
6971+ 'port' => 65,
6972+ 'proxy' => 'theproxy',
6973+ 'proxy_protocol' => 'http://',
6974+ 'proxy_port' => 6565,
6975+ 'proxy_user' => '',
6976+ 'proxy_pass' => '',
6977+ 'errno' => 0,
6978+ 'errstring' => '',
6979+ 'debug' => 0,
6980+ 'username' => '',
6981+ 'password' => '',
6982+);
6983+$c = new XML_RPC_Client('thepath', 'theserver', 65,
6984+ 'theproxy', 6565);
6985+compare($x, $c, 'port 65 proxy 6565');
6986+
6987+$x = array(
6988+ 'path' => 'thepath',
6989+ 'server' => 'theserver',
6990+ 'protocol' => 'http://',
6991+ 'port' => 65,
6992+ 'proxy' => 'theproxy',
6993+ 'proxy_protocol' => 'http://',
6994+ 'proxy_port' => 6565,
6995+ 'proxy_user' => '',
6996+ 'proxy_pass' => '',
6997+ 'errno' => 0,
6998+ 'errstring' => '',
6999+ 'debug' => 0,
7000+ 'username' => '',
7001+ 'password' => '',
7002+);
7003+$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
7004+ 'http://theproxy', 6565);
7005+compare($x, $c, 'port 65 with http proxy 6565');
7006+
7007+$x = array(
7008+ 'path' => 'thepath',
7009+ 'server' => 'theserver',
7010+ 'protocol' => 'ssl://',
7011+ 'port' => 65,
7012+ 'proxy' => 'theproxy',
7013+ 'proxy_protocol' => 'ssl://',
7014+ 'proxy_port' => 6565,
7015+ 'proxy_user' => '',
7016+ 'proxy_pass' => '',
7017+ 'errno' => 0,
7018+ 'errstring' => '',
7019+ 'debug' => 0,
7020+ 'username' => '',
7021+ 'password' => '',
7022+);
7023+$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
7024+ 'https://theproxy', 6565);
7025+compare($x, $c, 'port 65 with https proxy 6565');
7026+
7027+$x = array(
7028+ 'path' => 'thepath',
7029+ 'server' => 'theserver',
7030+ 'protocol' => 'ssl://',
7031+ 'port' => 65,
7032+ 'proxy' => 'theproxy',
7033+ 'proxy_protocol' => 'ssl://',
7034+ 'proxy_port' => 6565,
7035+ 'proxy_user' => '',
7036+ 'proxy_pass' => '',
7037+ 'errno' => 0,
7038+ 'errstring' => '',
7039+ 'debug' => 0,
7040+ 'username' => '',
7041+ 'password' => '',
7042+);
7043+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
7044+ 'ssl://theproxy', 6565);
7045+compare($x, $c, 'port 65 with ssl proxy 6565');
7046+
7047+
7048+$x = array(
7049+ 'path' => 'thepath',
7050+ 'server' => 'theserver',
7051+ 'protocol' => 'ssl://',
7052+ 'port' => 443,
7053+ 'proxy' => 'theproxy',
7054+ 'proxy_protocol' => 'ssl://',
7055+ 'proxy_port' => 443,
7056+ 'proxy_user' => '',
7057+ 'proxy_pass' => '',
7058+ 'errno' => 0,
7059+ 'errstring' => '',
7060+ 'debug' => 0,
7061+ 'username' => '',
7062+ 'password' => '',
7063+);
7064+$c = new XML_RPC_Client('thepath', 'theserver', 443,
7065+ 'theproxy', 443);
7066+compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
7067+
7068+$x = array(
7069+ 'path' => 'thepath',
7070+ 'server' => 'theserver',
7071+ 'protocol' => 'http://',
7072+ 'port' => 80,
7073+ 'proxy' => 'theproxy',
7074+ 'proxy_protocol' => 'ssl://',
7075+ 'proxy_port' => 6565,
7076+ 'proxy_user' => '',
7077+ 'proxy_pass' => '',
7078+ 'errno' => 0,
7079+ 'errstring' => '',
7080+ 'debug' => 0,
7081+ 'username' => '',
7082+ 'password' => '',
7083+);
7084+$c = new XML_RPC_Client('thepath', 'theserver', 0,
7085+ 'ssl://theproxy', 6565);
7086+compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
7087+
7088+
7089+/*
7090+ * If the package version number is found in the left hand
7091+ * portion of the if() expression below, that means this file has
7092+ * come from the PEAR installer. Therefore, let's test the
7093+ * installed version of XML_RPC which should be in the include path.
7094+ *
7095+ * If the version has not been substituted in the if() expression,
7096+ * this file has likely come from a CVS checkout or a .tar file.
7097+ * Therefore, we'll assume the tests should use the version of
7098+ * XML_RPC that has come from there as well.
7099+ */
7100+if ('1.3.1' != '@'.'package_version'.'@') {
7101+ /**
7102+ * Get the needed class from the PEAR installation
7103+ */
7104+ require_once 'XML/RPC/Dump.php';
7105+} else {
7106+ /**
7107+ * Get the needed class from the parent directory
7108+ */
7109+ require_once '../Dump.php';
7110+}
7111+
7112+$val = new XML_RPC_Value(array(
7113+ 'title' =>new XML_RPC_Value('das ist der Titel', 'string'),
7114+ 'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
7115+ 'endDate' =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
7116+ 'error' =>'string',
7117+ 'arkey' => new XML_RPC_Value( array(
7118+ new XML_RPC_Value('simple string'),
7119+ new XML_RPC_Value(12345, 'int')
7120+ ), 'array')
7121+ )
7122+ ,'struct');
7123+
7124+XML_RPC_Dump($val);
7125+
7126+echo '==============' . "\r\n";
7127+$val2 = new XML_RPC_Value(44353, 'int');
7128+XML_RPC_Dump($val2);
7129+
7130+echo '==============' . "\r\n";
7131+$val3 = new XML_RPC_Value('this should be a string', 'string');
7132+XML_RPC_Dump($val3);
7133+
7134+echo '==============' . "\r\n";
7135+$val4 = new XML_RPC_Value(true, 'boolean');
7136+XML_RPC_Dump($val4);
7137+
7138+
7139+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
7140+
7141+/**
7142+ * Function and class to dump XML_RPC_Value objects in a nice way
7143+ *
7144+ * Should be helpful as a normal var_dump(..) displays all internals which
7145+ * doesn't really give you an overview due to too much information.
7146+ *
7147+ * @category Web Services
7148+ * @package XML_RPC
7149+ * @author Christian Weiske <cweiske@php.net>
7150+ * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $
7151+ * @link http://pear.php.net/package/XML_RPC
7152+ */
7153+
7154+
7155+/**
7156+ * Pull in the XML_RPC class
7157+ */
7158+require_once 'XML/RPC.php';
7159+
7160+
7161+/**
7162+ * Generates the dump of the XML_RPC_Value and echoes it
7163+ *
7164+ * @param object $value the XML_RPC_Value object to dump
7165+ *
7166+ * @return void
7167+ */
7168+function XML_RPC_Dump($value)
7169+{
7170+ $dumper = new XML_RPC_Dump();
7171+ echo $dumper->generateDump($value);
7172+}
7173+
7174+
7175+/**
7176+ * Class which generates a dump of a XML_RPC_Value object
7177+ *
7178+ * @category Web Services
7179+ * @package XML_RPC
7180+ * @author Christian Weiske <cweiske@php.net>
7181+ * @version Release: 1.3.1
7182+ * @link http://pear.php.net/package/XML_RPC
7183+ */
7184+class XML_RPC_Dump
7185+{
7186+ /**
7187+ * The indentation array cache
7188+ * @var array
7189+ */
7190+ var $arIndent = array();
7191+
7192+ /**
7193+ * The spaces used for indenting the XML
7194+ * @var string
7195+ */
7196+ var $strBaseIndent = ' ';
7197+
7198+ /**
7199+ * Returns the dump in XML format without printing it out
7200+ *
7201+ * @param object $value the XML_RPC_Value object to dump
7202+ * @param int $nLevel the level of indentation
7203+ *
7204+ * @return string the dump
7205+ */
7206+ function generateDump($value, $nLevel = 0)
7207+ {
7208+ if (!is_object($value) && get_class($value) != 'xml_rpc_value') {
7209+ require_once 'PEAR.php';
7210+ PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n",
7211+ 0, PEAR_ERROR_PRINT);
7212+ if (is_object($value)) {
7213+ $strType = get_class($value);
7214+ } else {
7215+ $strType = gettype($value);
7216+ }
7217+ return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: '
7218+ . $strType . "\r\n";
7219+ }
7220+
7221+ switch ($value->kindOf()) {
7222+ case 'struct':
7223+ $ret = $this->genStruct($value, $nLevel);
7224+ break;
7225+ case 'array':
7226+ $ret = $this->genArray($value, $nLevel);
7227+ break;
7228+ case 'scalar':
7229+ $ret = $this->genScalar($value->scalarval(), $nLevel);
7230+ break;
7231+ default:
7232+ require_once 'PEAR.php';
7233+ PEAR::raiseError('Illegal type "' . $value->kindOf()
7234+ . '" in XML_RPC_Value' . "\r\n", 0,
7235+ PEAR_ERROR_PRINT);
7236+ }
7237+
7238+ return $ret;
7239+ }
7240+
7241+ /**
7242+ * Returns the scalar value dump
7243+ *
7244+ * @param object $value the scalar XML_RPC_Value object to dump
7245+ * @param int $nLevel the level of indentation
7246+ *
7247+ * @return string Dumped version of the scalar value
7248+ */
7249+ function genScalar($value, $nLevel)
7250+ {
7251+ if (gettype($value) == 'object') {
7252+ $strClass = ' ' . get_class($value);
7253+ } else {
7254+ $strClass = '';
7255+ }
7256+ return $this->getIndent($nLevel) . gettype($value) . $strClass
7257+ . ' ' . $value . "\r\n";
7258+ }
7259+
7260+ /**
7261+ * Returns the dump of a struct
7262+ *
7263+ * @param object $value the struct XML_RPC_Value object to dump
7264+ * @param int $nLevel the level of indentation
7265+ *
7266+ * @return string Dumped version of the scalar value
7267+ */
7268+ function genStruct($value, $nLevel)
7269+ {
7270+ $value->structreset();
7271+ $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n";
7272+ while (list($key, $keyval) = $value->structeach()) {
7273+ $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n";
7274+ $strOutput .= $this->generateDump($keyval, $nLevel + 2);
7275+ }
7276+ return $strOutput;
7277+ }
7278+
7279+ /**
7280+ * Returns the dump of an array
7281+ *
7282+ * @param object $value the array XML_RPC_Value object to dump
7283+ * @param int $nLevel the level of indentation
7284+ *
7285+ * @return string Dumped version of the scalar value
7286+ */
7287+ function genArray($value, $nLevel)
7288+ {
7289+ $nSize = $value->arraysize();
7290+ $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n";
7291+ for($nA = 0; $nA < $nSize; $nA++) {
7292+ $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n";
7293+ $strOutput .= $this->generateDump($value->arraymem($nA),
7294+ $nLevel + 2);
7295+ }
7296+ return $strOutput;
7297+ }
7298+
7299+ /**
7300+ * Returns the indent for a specific level and caches it for faster use
7301+ *
7302+ * @param int $nLevel the level
7303+ *
7304+ * @return string the indented string
7305+ */
7306+ function getIndent($nLevel)
7307+ {
7308+ if (!isset($this->arIndent[$nLevel])) {
7309+ $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel);
7310+ }
7311+ return $this->arIndent[$nLevel];
7312+ }
7313+}
7314+
7315+/*
7316+ * Local variables:
7317+ * tab-width: 4
7318+ * c-basic-offset: 4
7319+ * c-hanging-comment-ender-p: nil
7320+ * End:
7321+ */
7322+
7323+?>
7324+
7325+
7326+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
7327+
7328+/**
7329+ * PHP implementation of the XML-RPC protocol
7330+ *
7331+ * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
7332+ * It has support for HTTP transport, proxies and authentication.
7333+ *
7334+ * PHP versions 4 and 5
7335+ *
7336+ * LICENSE: License is granted to use or modify this software
7337+ * ("XML-RPC for PHP") for commercial or non-commercial use provided the
7338+ * copyright of the author is preserved in any distributed or derivative work.
7339+ *
7340+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
7341+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
7342+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
7343+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
7344+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
7345+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
7346+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7347+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7348+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
7349+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7350+ *
7351+ * @category Web Services
7352+ * @package XML_RPC
7353+ * @author Edd Dumbill <edd@usefulinc.com>
7354+ * @author Stig Bakken <stig@php.net>
7355+ * @author Martin Jansen <mj@php.net>
7356+ * @author Daniel Convissor <danielc@php.net>
7357+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7358+ * @version CVS: $Id: RPC.php,v 1.74 2005/05/09 20:51:54 danielc Exp $
7359+ * @link http://pear.php.net/package/XML_RPC
7360+ */
7361+
7362+
7363+if (!function_exists('xml_parser_create')) {
7364+ PEAR::loadExtension('xml');
7365+}
7366+
7367+/**#@+
7368+ * Error constants
7369+ */
7370+/**
7371+ * Parameter values don't match parameter types
7372+ */
7373+define('XML_RPC_ERROR_INVALID_TYPE', 101);
7374+/**
7375+ * Parameter declared to be numeric but the values are not
7376+ */
7377+define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
7378+/**
7379+ * Communication error
7380+ */
7381+define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
7382+/**
7383+ * The array or struct has already been started
7384+ */
7385+define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
7386+/**
7387+ * Incorrect parameters submitted
7388+ */
7389+define('XML_RPC_ERROR_INCORRECT_PARAMS', 105);
7390+/**
7391+ * Programming error by developer
7392+ */
7393+define('XML_RPC_ERROR_PROGRAMMING', 106);
7394+/**#@-*/
7395+
7396+
7397+/**
7398+ * Data types
7399+ * @global string $GLOBALS['XML_RPC_I4']
7400+ */
7401+$GLOBALS['XML_RPC_I4'] = 'i4';
7402+
7403+/**
7404+ * Data types
7405+ * @global string $GLOBALS['XML_RPC_Int']
7406+ */
7407+$GLOBALS['XML_RPC_Int'] = 'int';
7408+
7409+/**
7410+ * Data types
7411+ * @global string $GLOBALS['XML_RPC_Boolean']
7412+ */
7413+$GLOBALS['XML_RPC_Boolean'] = 'boolean';
7414+
7415+/**
7416+ * Data types
7417+ * @global string $GLOBALS['XML_RPC_Double']
7418+ */
7419+$GLOBALS['XML_RPC_Double'] = 'double';
7420+
7421+/**
7422+ * Data types
7423+ * @global string $GLOBALS['XML_RPC_String']
7424+ */
7425+$GLOBALS['XML_RPC_String'] = 'string';
7426+
7427+/**
7428+ * Data types
7429+ * @global string $GLOBALS['XML_RPC_DateTime']
7430+ */
7431+$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601';
7432+
7433+/**
7434+ * Data types
7435+ * @global string $GLOBALS['XML_RPC_Base64']
7436+ */
7437+$GLOBALS['XML_RPC_Base64'] = 'base64';
7438+
7439+/**
7440+ * Data types
7441+ * @global string $GLOBALS['XML_RPC_Array']
7442+ */
7443+$GLOBALS['XML_RPC_Array'] = 'array';
7444+
7445+/**
7446+ * Data types
7447+ * @global string $GLOBALS['XML_RPC_Struct']
7448+ */
7449+$GLOBALS['XML_RPC_Struct'] = 'struct';
7450+
7451+
7452+/**
7453+ * Data type meta-types
7454+ * @global array $GLOBALS['XML_RPC_Types']
7455+ */
7456+$GLOBALS['XML_RPC_Types'] = array(
7457+ $GLOBALS['XML_RPC_I4'] => 1,
7458+ $GLOBALS['XML_RPC_Int'] => 1,
7459+ $GLOBALS['XML_RPC_Boolean'] => 1,
7460+ $GLOBALS['XML_RPC_String'] => 1,
7461+ $GLOBALS['XML_RPC_Double'] => 1,
7462+ $GLOBALS['XML_RPC_DateTime'] => 1,
7463+ $GLOBALS['XML_RPC_Base64'] => 1,
7464+ $GLOBALS['XML_RPC_Array'] => 2,
7465+ $GLOBALS['XML_RPC_Struct'] => 3,
7466+);
7467+
7468+
7469+/**
7470+ * Error message numbers
7471+ * @global array $GLOBALS['XML_RPC_err']
7472+ */
7473+$GLOBALS['XML_RPC_err'] = array(
7474+ 'unknown_method' => 1,
7475+ 'invalid_return' => 2,
7476+ 'incorrect_params' => 3,
7477+ 'introspect_unknown' => 4,
7478+ 'http_error' => 5,
7479+ 'not_response_object' => 6,
7480+);
7481+
7482+/**
7483+ * Error message strings
7484+ * @global array $GLOBALS['XML_RPC_str']
7485+ */
7486+$GLOBALS['XML_RPC_str'] = array(
7487+ 'unknown_method' => 'Unknown method',
7488+ 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload',
7489+ 'incorrect_params' => 'Incorrect parameters passed to method',
7490+ 'introspect_unknown' => 'Can\'t introspect: method unknown',
7491+ 'http_error' => 'Didn\'t receive 200 OK from remote server.',
7492+ 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.',
7493+);
7494+
7495+
7496+/**
7497+ * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII)
7498+ * @global string $GLOBALS['XML_RPC_defencoding']
7499+ */
7500+$GLOBALS['XML_RPC_defencoding'] = 'UTF-8';
7501+
7502+/**
7503+ * User error codes start at 800
7504+ * @global int $GLOBALS['XML_RPC_erruser']
7505+ */
7506+$GLOBALS['XML_RPC_erruser'] = 800;
7507+
7508+/**
7509+ * XML parse error codes start at 100
7510+ * @global int $GLOBALS['XML_RPC_errxml']
7511+ */
7512+$GLOBALS['XML_RPC_errxml'] = 100;
7513+
7514+
7515+/**
7516+ * Compose backslashes for escaping regexp
7517+ * @global string $GLOBALS['XML_RPC_backslash']
7518+ */
7519+$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92);
7520+
7521+
7522+/**
7523+ * Stores state during parsing
7524+ *
7525+ * quick explanation of components:
7526+ * + st = builds up a string for evaluation
7527+ * + ac = accumulates values
7528+ * + qt = decides if quotes are needed for evaluation
7529+ * + cm = denotes struct or array (comma needed)
7530+ * + isf = indicates a fault
7531+ * + lv = indicates "looking for a value": implements the logic
7532+ * to allow values with no types to be strings
7533+ * + params = stores parameters in method calls
7534+ * + method = stores method name
7535+ *
7536+ * @global array $GLOBALS['XML_RPC_xh']
7537+ */
7538+$GLOBALS['XML_RPC_xh'] = array();
7539+
7540+
7541+/**
7542+ * Start element handler for the XML parser
7543+ *
7544+ * @return void
7545+ */
7546+function XML_RPC_se($parser_resource, $name, $attrs)
7547+{
7548+ global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String;
7549+ $parser = (int) $parser_resource;
7550+
7551+ switch ($name) {
7552+ case 'STRUCT':
7553+ case 'ARRAY':
7554+ $XML_RPC_xh[$parser]['st'] .= 'array(';
7555+ $XML_RPC_xh[$parser]['cm']++;
7556+ // this last line turns quoting off
7557+ // this means if we get an empty array we'll
7558+ // simply get a bit of whitespace in the eval
7559+ $XML_RPC_xh[$parser]['qt'] = 0;
7560+ break;
7561+
7562+ case 'NAME':
7563+ $XML_RPC_xh[$parser]['st'] .= '"';
7564+ $XML_RPC_xh[$parser]['ac'] = '';
7565+ break;
7566+
7567+ case 'FAULT':
7568+ $XML_RPC_xh[$parser]['isf'] = 1;
7569+ break;
7570+
7571+ case 'PARAM':
7572+ $XML_RPC_xh[$parser]['st'] = '';
7573+ break;
7574+
7575+ case 'VALUE':
7576+ $XML_RPC_xh[$parser]['st'] .= 'new XML_RPC_Value(';
7577+ $XML_RPC_xh[$parser]['lv'] = 1;
7578+ $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String;
7579+ $XML_RPC_xh[$parser]['ac'] = '';
7580+ $XML_RPC_xh[$parser]['qt'] = 0;
7581+ // look for a value: if this is still 1 by the
7582+ // time we reach the first data segment then the type is string
7583+ // by implication and we need to add in a quote
7584+ break;
7585+
7586+ case 'I4':
7587+ case 'INT':
7588+ case 'STRING':
7589+ case 'BOOLEAN':
7590+ case 'DOUBLE':
7591+ case 'DATETIME.ISO8601':
7592+ case 'BASE64':
7593+ $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator
7594+
7595+ if ($name == 'DATETIME.ISO8601' || $name == 'STRING') {
7596+ $XML_RPC_xh[$parser]['qt'] = 1;
7597+
7598+ if ($name == 'DATETIME.ISO8601') {
7599+ $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime;
7600+ }
7601+
7602+ } elseif ($name == 'BASE64') {
7603+ $XML_RPC_xh[$parser]['qt'] = 2;
7604+ } else {
7605+ // No quoting is required here -- but
7606+ // at the end of the element we must check
7607+ // for data format errors.
7608+ $XML_RPC_xh[$parser]['qt'] = 0;
7609+ }
7610+ break;
7611+
7612+ case 'MEMBER':
7613+ $XML_RPC_xh[$parser]['ac'] = '';
7614+ }
7615+
7616+ if ($name != 'VALUE') {
7617+ $XML_RPC_xh[$parser]['lv'] = 0;
7618+ }
7619+}
7620+
7621+/**
7622+ * End element handler for the XML parser
7623+ *
7624+ * @return void
7625+ */
7626+function XML_RPC_ee($parser_resource, $name)
7627+{
7628+ global $XML_RPC_xh, $XML_RPC_Types, $XML_RPC_String;
7629+ $parser = (int) $parser_resource;
7630+
7631+ switch ($name) {
7632+ case 'STRUCT':
7633+ case 'ARRAY':
7634+ if ($XML_RPC_xh[$parser]['cm']
7635+ && substr($XML_RPC_xh[$parser]['st'], -1) == ',')
7636+ {
7637+ $XML_RPC_xh[$parser]['st'] = substr($XML_RPC_xh[$parser]['st'], 0, -1);
7638+ }
7639+
7640+ $XML_RPC_xh[$parser]['st'] .= ')';
7641+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
7642+ $XML_RPC_xh[$parser]['cm']--;
7643+ break;
7644+
7645+ case 'NAME':
7646+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . '" => ';
7647+ break;
7648+
7649+ case 'BOOLEAN':
7650+ // special case here: we translate boolean 1 or 0 into PHP
7651+ // constants true or false
7652+ if ($XML_RPC_xh[$parser]['ac'] == '1') {
7653+ $XML_RPC_xh[$parser]['ac'] = 'true';
7654+ } else {
7655+ $XML_RPC_xh[$parser]['ac'] = 'false';
7656+ }
7657+
7658+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
7659+ // Drop through intentionally.
7660+
7661+ case 'I4':
7662+ case 'INT':
7663+ case 'STRING':
7664+ case 'DOUBLE':
7665+ case 'DATETIME.ISO8601':
7666+ case 'BASE64':
7667+ if ($XML_RPC_xh[$parser]['qt'] == 1) {
7668+ // we use double quotes rather than single so backslashification works OK
7669+ $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
7670+ } elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
7671+ $XML_RPC_xh[$parser]['st'] .= 'base64_decode("'
7672+ . $XML_RPC_xh[$parser]['ac'] . '")';
7673+ } elseif ($name == 'BOOLEAN') {
7674+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
7675+ } else {
7676+ // we have an I4, INT or a DOUBLE
7677+ // we must check that only 0123456789-.<space> are characters here
7678+ if (!ereg("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) {
7679+ XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE',
7680+ XML_RPC_ERROR_NON_NUMERIC_FOUND);
7681+ $XML_RPC_xh[$parser]['st'] .= 'XML_RPC_ERROR_NON_NUMERIC_FOUND';
7682+ } else {
7683+ // it's ok, add it on
7684+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
7685+ }
7686+ }
7687+
7688+ $XML_RPC_xh[$parser]['ac'] = '';
7689+ $XML_RPC_xh[$parser]['qt'] = 0;
7690+ $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value
7691+ break;
7692+
7693+ case 'VALUE':
7694+ // deal with a string value
7695+ if (strlen($XML_RPC_xh[$parser]['ac']) > 0 &&
7696+ $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) {
7697+
7698+ $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
7699+ }
7700+
7701+ // This if () detects if no scalar was inside <VALUE></VALUE>
7702+ // and pads an empty "".
7703+ if ($XML_RPC_xh[$parser]['st'][strlen($XML_RPC_xh[$parser]['st'])-1] == '(') {
7704+ $XML_RPC_xh[$parser]['st'] .= '""';
7705+ }
7706+ $XML_RPC_xh[$parser]['st'] .= ", '" . $XML_RPC_xh[$parser]['vt'] . "')";
7707+ if ($XML_RPC_xh[$parser]['cm']) {
7708+ $XML_RPC_xh[$parser]['st'] .= ',';
7709+ }
7710+ break;
7711+
7712+ case 'MEMBER':
7713+ $XML_RPC_xh[$parser]['ac'] = '';
7714+ $XML_RPC_xh[$parser]['qt'] = 0;
7715+ break;
7716+
7717+ case 'DATA':
7718+ $XML_RPC_xh[$parser]['ac'] = '';
7719+ $XML_RPC_xh[$parser]['qt'] = 0;
7720+ break;
7721+
7722+ case 'PARAM':
7723+ $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['st'];
7724+ break;
7725+
7726+ case 'METHODNAME':
7727+ case 'RPCMETHODNAME':
7728+ $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", '',
7729+ $XML_RPC_xh[$parser]['ac']);
7730+ break;
7731+ }
7732+
7733+ // if it's a valid type name, set the type
7734+ if (isset($XML_RPC_Types[strtolower($name)])) {
7735+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
7736+ }
7737+}
7738+
7739+/**
7740+ * Character data handler for the XML parser
7741+ *
7742+ * @return void
7743+ */
7744+function XML_RPC_cd($parser_resource, $data)
7745+{
7746+ global $XML_RPC_xh, $XML_RPC_backslash;
7747+ $parser = (int) $parser_resource;
7748+
7749+ if ($XML_RPC_xh[$parser]['lv'] != 3) {
7750+ // "lookforvalue==3" means that we've found an entire value
7751+ // and should discard any further character data
7752+
7753+ if ($XML_RPC_xh[$parser]['lv'] == 1) {
7754+ // if we've found text and we're just in a <value> then
7755+ // turn quoting on, as this will be a string
7756+ $XML_RPC_xh[$parser]['qt'] = 1;
7757+ // and say we've found a value
7758+ $XML_RPC_xh[$parser]['lv'] = 2;
7759+ }
7760+
7761+ // replace characters that eval would
7762+ // do special things with
7763+ if (!isset($XML_RPC_xh[$parser]['ac'])) {
7764+ $XML_RPC_xh[$parser]['ac'] = '';
7765+ }
7766+ $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$',
7767+ str_replace('"', '\"', str_replace(chr(92),
7768+ $XML_RPC_backslash, $data)));
7769+ }
7770+}
7771+
7772+/**
7773+ * The common methods and properties for all of the XML_RPC classes
7774+ *
7775+ * @category Web Services
7776+ * @package XML_RPC
7777+ * @author Edd Dumbill <edd@usefulinc.com>
7778+ * @author Stig Bakken <stig@php.net>
7779+ * @author Martin Jansen <mj@php.net>
7780+ * @author Daniel Convissor <danielc@php.net>
7781+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7782+ * @version Release: 1.3.1
7783+ * @link http://pear.php.net/package/XML_RPC
7784+ */
7785+class XML_RPC_Base {
7786+
7787+ /**
7788+ * PEAR Error handling
7789+ *
7790+ * @return object PEAR_Error object
7791+ */
7792+ function raiseError($msg, $code)
7793+ {
7794+ include_once 'PEAR.php';
7795+ if (is_object(@$this)) {
7796+ return PEAR::raiseError(get_class($this) . ': ' . $msg, $code);
7797+ } else {
7798+ return PEAR::raiseError('XML_RPC: ' . $msg, $code);
7799+ }
7800+ }
7801+
7802+ /**
7803+ * Tell whether something is a PEAR_Error object
7804+ *
7805+ * @param mixed $value the item to check
7806+ *
7807+ * @return bool whether $value is a PEAR_Error object or not
7808+ *
7809+ * @access public
7810+ */
7811+ function isError($value)
7812+ {
7813+ return is_a($value, 'PEAR_Error');
7814+ }
7815+}
7816+
7817+/**
7818+ * The methods and properties for submitting XML RPC requests
7819+ *
7820+ * @category Web Services
7821+ * @package XML_RPC
7822+ * @author Edd Dumbill <edd@usefulinc.com>
7823+ * @author Stig Bakken <stig@php.net>
7824+ * @author Martin Jansen <mj@php.net>
7825+ * @author Daniel Convissor <danielc@php.net>
7826+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7827+ * @version Release: 1.3.1
7828+ * @link http://pear.php.net/package/XML_RPC
7829+ */
7830+class XML_RPC_Client extends XML_RPC_Base {
7831+
7832+ /**
7833+ * The path and name of the RPC server script you want the request to go to
7834+ * @var string
7835+ */
7836+ var $path = '';
7837+
7838+ /**
7839+ * The name of the remote server to connect to
7840+ * @var string
7841+ */
7842+ var $server = '';
7843+
7844+ /**
7845+ * The protocol to use in contacting the remote server
7846+ * @var string
7847+ */
7848+ var $protocol = 'http://';
7849+
7850+ /**
7851+ * The port for connecting to the remote server
7852+ *
7853+ * The default is 80 for http:// connections
7854+ * and 443 for https:// and ssl:// connections.
7855+ *
7856+ * @var integer
7857+ */
7858+ var $port = 80;
7859+
7860+ /**
7861+ * A user name for accessing the RPC server
7862+ * @var string
7863+ * @see XML_RPC_Client::setCredentials()
7864+ */
7865+ var $username = '';
7866+
7867+ /**
7868+ * A password for accessing the RPC server
7869+ * @var string
7870+ * @see XML_RPC_Client::setCredentials()
7871+ */
7872+ var $password = '';
7873+
7874+ /**
7875+ * The name of the proxy server to use, if any
7876+ * @var string
7877+ */
7878+ var $proxy = '';
7879+
7880+ /**
7881+ * The protocol to use in contacting the proxy server, if any
7882+ * @var string
7883+ */
7884+ var $proxy_protocol = 'http://';
7885+
7886+ /**
7887+ * The port for connecting to the proxy server
7888+ *
7889+ * The default is 8080 for http:// connections
7890+ * and 443 for https:// and ssl:// connections.
7891+ *
7892+ * @var integer
7893+ */
7894+ var $proxy_port = 8080;
7895+
7896+ /**
7897+ * A user name for accessing the proxy server
7898+ * @var string
7899+ */
7900+ var $proxy_user = '';
7901+
7902+ /**
7903+ * A password for accessing the proxy server
7904+ * @var string
7905+ */
7906+ var $proxy_pass = '';
7907+
7908+ /**
7909+ * The error number, if any
7910+ * @var integer
7911+ */
7912+ var $errno = 0;
7913+
7914+ /**
7915+ * The error message, if any
7916+ * @var string
7917+ */
7918+ var $errstring = '';
7919+
7920+ /**
7921+ * The current debug mode (1 = on, 0 = off)
7922+ * @var integer
7923+ */
7924+ var $debug = 0;
7925+
7926+ /**
7927+ * The HTTP headers for the current request.
7928+ * @var string
7929+ */
7930+ var $headers = '';
7931+
7932+
7933+ /**
7934+ * Sets the object's properties
7935+ *
7936+ * @param string $path the path and name of the RPC server script
7937+ * you want the request to go to
7938+ * @param string $server the URL of the remote server to connect to.
7939+ * If this parameter doesn't specify a
7940+ * protocol and $port is 443, ssl:// is
7941+ * assumed.
7942+ * @param integer $port a port for connecting to the remote server.
7943+ * Defaults to 80 for http:// connections and
7944+ * 443 for https:// and ssl:// connections.
7945+ * @param string $proxy the URL of the proxy server to use, if any.
7946+ * If this parameter doesn't specify a
7947+ * protocol and $port is 443, ssl:// is
7948+ * assumed.
7949+ * @param integer $proxy_port a port for connecting to the remote server.
7950+ * Defaults to 8080 for http:// connections and
7951+ * 443 for https:// and ssl:// connections.
7952+ * @param string $proxy_user a user name for accessing the proxy server
7953+ * @param string $proxy_pass a password for accessing the proxy server
7954+ *
7955+ * @return void
7956+ */
7957+ function XML_RPC_Client($path, $server, $port = 0,
7958+ $proxy = '', $proxy_port = 0,
7959+ $proxy_user = '', $proxy_pass = '')
7960+ {
7961+ $this->path = $path;
7962+ $this->proxy_user = $proxy_user;
7963+ $this->proxy_pass = $proxy_pass;
7964+
7965+ preg_match('@^(http://|https://|ssl://)?(.*)$@', $server, $match);
7966+ if ($match[1] == '') {
7967+ if ($port == 443) {
7968+ $this->server = $match[2];
7969+ $this->protocol = 'ssl://';
7970+ $this->port = 443;
7971+ } else {
7972+ $this->server = $match[2];
7973+ if ($port) {
7974+ $this->port = $port;
7975+ }
7976+ }
7977+ } elseif ($match[1] == 'http://') {
7978+ $this->server = $match[2];
7979+ if ($port) {
7980+ $this->port = $port;
7981+ }
7982+ } else {
7983+ $this->server = $match[2];
7984+ $this->protocol = 'ssl://';
7985+ if ($port) {
7986+ $this->port = $port;
7987+ } else {
7988+ $this->port = 443;
7989+ }
7990+ }
7991+
7992+ if ($proxy) {
7993+ preg_match('@^(http://|https://|ssl://)?(.*)$@', $proxy, $match);
7994+ if ($match[1] == '') {
7995+ if ($proxy_port == 443) {
7996+ $this->proxy = $match[2];
7997+ $this->proxy_protocol = 'ssl://';
7998+ $this->proxy_port = 443;
7999+ } else {
8000+ $this->proxy = $match[2];
8001+ if ($proxy_port) {
8002+ $this->proxy_port = $proxy_port;
8003+ }
8004+ }
8005+ } elseif ($match[1] == 'http://') {
8006+ $this->proxy = $match[2];
8007+ if ($proxy_port) {
8008+ $this->proxy_port = $proxy_port;
8009+ }
8010+ } else {
8011+ $this->proxy = $match[2];
8012+ $this->proxy_protocol = 'ssl://';
8013+ if ($proxy_port) {
8014+ $this->proxy_port = $proxy_port;
8015+ } else {
8016+ $this->proxy_port = 443;
8017+ }
8018+ }
8019+ }
8020+ }
8021+
8022+ /**
8023+ * Change the current debug mode
8024+ *
8025+ * @param int $in where 1 = on, 0 = off
8026+ *
8027+ * @return void
8028+ */
8029+ function setDebug($in)
8030+ {
8031+ if ($in) {
8032+ $this->debug = 1;
8033+ } else {
8034+ $this->debug = 0;
8035+ }
8036+ }
8037+
8038+ /**
8039+ * Set username and password properties for connecting to the RPC server
8040+ *
8041+ * @param string $u the user name
8042+ * @param string $p the password
8043+ *
8044+ * @return void
8045+ *
8046+ * @see XML_RPC_Client::$username, XML_RPC_Client::$password
8047+ */
8048+ function setCredentials($u, $p)
8049+ {
8050+ $this->username = $u;
8051+ $this->password = $p;
8052+ }
8053+
8054+ /**
8055+ * Transmit the RPC request via HTTP 1.0 protocol
8056+ *
8057+ * @param object $msg the XML_RPC_Message object
8058+ * @param int $timeout how many seconds to wait for the request
8059+ *
8060+ * @return object an XML_RPC_Response object. 0 is returned if any
8061+ * problems happen.
8062+ *
8063+ * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(),
8064+ * XML_RPC_Client::setCredentials()
8065+ */
8066+ function send($msg, $timeout = 0)
8067+ {
8068+ if (strtolower(get_class($msg)) != 'xml_rpc_message') {
8069+ $this->errstr = 'send()\'s $msg parameter must be an'
8070+ . ' XML_RPC_Message object.';
8071+ $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING);
8072+ return 0;
8073+ }
8074+ $msg->debug = $this->debug;
8075+ return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
8076+ $timeout, $this->username,
8077+ $this->password);
8078+ }
8079+
8080+ /**
8081+ * Transmit the RPC request via HTTP 1.0 protocol
8082+ *
8083+ * Requests should be sent using XML_RPC_Client send() rather than
8084+ * calling this method directly.
8085+ *
8086+ * @param object $msg the XML_RPC_Message object
8087+ * @param string $server the server to send the request to
8088+ * @param int $port the server port send the request to
8089+ * @param int $timeout how many seconds to wait for the request
8090+ * before giving up
8091+ * @param string $username a user name for accessing the RPC server
8092+ * @param string $password a password for accessing the RPC server
8093+ *
8094+ * @return object an XML_RPC_Response object. 0 is returned if any
8095+ * problems happen.
8096+ *
8097+ * @access protected
8098+ * @see XML_RPC_Client::send()
8099+ */
8100+ function sendPayloadHTTP10($msg, $server, $port, $timeout = 0,
8101+ $username = '', $password = '')
8102+ {
8103+ /*
8104+ * If we're using a proxy open a socket to the proxy server
8105+ * instead to the xml-rpc server
8106+ */
8107+ if ($this->proxy) {
8108+ if ($this->proxy_protocol == 'http://') {
8109+ $protocol = '';
8110+ } else {
8111+ $protocol = $this->proxy_protocol;
8112+ }
8113+ if ($timeout > 0) {
8114+ $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
8115+ $this->errno, $this->errstr, $timeout);
8116+ } else {
8117+ $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
8118+ $this->errno, $this->errstr);
8119+ }
8120+ } else {
8121+ if ($this->protocol == 'http://') {
8122+ $protocol = '';
8123+ } else {
8124+ $protocol = $this->protocol;
8125+ }
8126+ if ($timeout > 0) {
8127+ $fp = @fsockopen($protocol . $server, $port,
8128+ $this->errno, $this->errstr, $timeout);
8129+ } else {
8130+ $fp = @fsockopen($protocol . $server, $port,
8131+ $this->errno, $this->errstr);
8132+ }
8133+ }
8134+
8135+ /*
8136+ * Just raising the error without returning it is strange,
8137+ * but keep it here for backwards compatibility.
8138+ */
8139+ if (!$fp && $this->proxy) {
8140+ $this->raiseError('Connection to proxy server '
8141+ . $this->proxy . ':' . $this->proxy_port
8142+ . ' failed. ' . $this->errstr,
8143+ XML_RPC_ERROR_CONNECTION_FAILED);
8144+ return 0;
8145+ } elseif (!$fp) {
8146+ $this->raiseError('Connection to RPC server '
8147+ . $server . ':' . $port
8148+ . ' failed. ' . $this->errstr,
8149+ XML_RPC_ERROR_CONNECTION_FAILED);
8150+ return 0;
8151+ }
8152+
8153+ if ($timeout) {
8154+ stream_set_timeout($fp, $timeout);
8155+ }
8156+
8157+ // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly
8158+ if ($username != $this->username) {
8159+ $this->setCredentials($username, $password);
8160+ }
8161+
8162+ // Only create the payload if it was not created previously
8163+ if (empty($msg->payload)) {
8164+ $msg->createPayload();
8165+ }
8166+ $this->createHeaders($msg);
8167+
8168+ $op = $this->headers . "\r\n\r\n";
8169+ $op .= $msg->payload;
8170+
8171+ if (!fputs($fp, $op, strlen($op))) {
8172+ $this->errstr = 'Write error';
8173+ return 0;
8174+ }
8175+ $resp = $msg->parseResponseFile($fp);
8176+
8177+ $meta = stream_get_meta_data($fp);
8178+ if ($meta['timed_out']) {
8179+ fclose($fp);
8180+ $this->errstr = 'RPC server did not send response before timeout.';
8181+ $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED);
8182+ return 0;
8183+ }
8184+
8185+ fclose($fp);
8186+ return $resp;
8187+ }
8188+
8189+ /**
8190+ * Determines the HTTP headers and puts it in the $headers property
8191+ *
8192+ * @param object $msg the XML_RPC_Message object
8193+ *
8194+ * @return boolean TRUE if okay, FALSE if the message payload isn't set.
8195+ *
8196+ * @access protected
8197+ */
8198+ function createHeaders($msg)
8199+ {
8200+ if (empty($msg->payload)) {
8201+ return false;
8202+ }
8203+ if ($this->proxy) {
8204+ $this->headers = 'POST ' . $this->protocol . $this->server;
8205+ if ($this->proxy_port) {
8206+ $this->headers .= ':' . $this->port;
8207+ }
8208+ } else {
8209+ $this->headers = 'POST ';
8210+ }
8211+ $this->headers .= $this->path. " HTTP/1.0\r\n";
8212+
8213+ $this->headers .= "User-Agent: PEAR XML_RPC\r\n";
8214+ $this->headers .= 'Host: ' . $this->server . "\r\n";
8215+
8216+ if ($this->proxy && $this->proxy_user) {
8217+ $this->headers .= 'Proxy-Authorization: Basic '
8218+ . base64_encode("$this->proxy_user:$this->proxy_pass")
8219+ . "\r\n";
8220+ }
8221+
8222+ // thanks to Grant Rauscher <grant7@firstworld.net> for this
8223+ if ($this->username) {
8224+ $this->headers .= 'Authorization: Basic '
8225+ . base64_encode("$this->username:$this->password")
8226+ . "\r\n";
8227+ }
8228+
8229+ $this->headers .= "Content-Type: text/xml\r\n";
8230+ $this->headers .= 'Content-Length: ' . strlen($msg->payload);
8231+ return true;
8232+ }
8233+}
8234+
8235+/**
8236+ * The methods and properties for interpreting responses to XML RPC requests
8237+ *
8238+ * @category Web Services
8239+ * @package XML_RPC
8240+ * @author Edd Dumbill <edd@usefulinc.com>
8241+ * @author Stig Bakken <stig@php.net>
8242+ * @author Martin Jansen <mj@php.net>
8243+ * @author Daniel Convissor <danielc@php.net>
8244+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
8245+ * @version Release: 1.3.1
8246+ * @link http://pear.php.net/package/XML_RPC
8247+ */
8248+class XML_RPC_Response extends XML_RPC_Base
8249+{
8250+ var $xv;
8251+ var $fn;
8252+ var $fs;
8253+ var $hdrs;
8254+
8255+ /**
8256+ * @return void
8257+ */
8258+ function XML_RPC_Response($val, $fcode = 0, $fstr = '')
8259+ {
8260+ if ($fcode != 0) {
8261+ $this->fn = $fcode;
8262+ $this->fs = htmlspecialchars($fstr);
8263+ } else {
8264+ $this->xv = $val;
8265+ }
8266+ }
8267+
8268+ /**
8269+ * @return int the error code
8270+ */
8271+ function faultCode()
8272+ {
8273+ if (isset($this->fn)) {
8274+ return $this->fn;
8275+ } else {
8276+ return 0;
8277+ }
8278+ }
8279+
8280+ /**
8281+ * @return string the error string
8282+ */
8283+ function faultString()
8284+ {
8285+ return $this->fs;
8286+ }
8287+
8288+ /**
8289+ * @return mixed the value
8290+ */
8291+ function value()
8292+ {
8293+ return $this->xv;
8294+ }
8295+
8296+ /**
8297+ * @return string the error message in XML format
8298+ */
8299+ function serialize()
8300+ {
8301+ $rs = "<methodResponse>\n";
8302+ if ($this->fn) {
8303+ $rs .= "<fault>
8304+ <value>
8305+ <struct>
8306+ <member>
8307+ <name>faultCode</name>
8308+ <value><int>" . $this->fn . "</int></value>
8309+ </member>
8310+ <member>
8311+ <name>faultString</name>
8312+ <value><string>" . $this->fs . "</string></value>
8313+ </member>
8314+ </struct>
8315+ </value>
8316+</fault>";
8317+ } else {
8318+ $rs .= "<params>\n<param>\n" . $this->xv->serialize() .
8319+ "</param>\n</params>";
8320+ }
8321+ $rs .= "\n</methodResponse>";
8322+ return $rs;
8323+ }
8324+}
8325+
8326+/**
8327+ * The methods and properties for composing XML RPC messages
8328+ *
8329+ * @category Web Services
8330+ * @package XML_RPC
8331+ * @author Edd Dumbill <edd@usefulinc.com>
8332+ * @author Stig Bakken <stig@php.net>
8333+ * @author Martin Jansen <mj@php.net>
8334+ * @author Daniel Convissor <danielc@php.net>
8335+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
8336+ * @version Release: 1.3.1
8337+ * @link http://pear.php.net/package/XML_RPC
8338+ */
8339+class XML_RPC_Message extends XML_RPC_Base
8340+{
8341+ /**
8342+ * The current debug mode (1 = on, 0 = off)
8343+ * @var integer
8344+ */
8345+ var $debug = 0;
8346+
8347+ /**
8348+ * The encoding to be used for outgoing messages
8349+ *
8350+ * Defaults to the value of <var>$GLOBALS['XML_RPC_defencoding']</var>
8351+ *
8352+ * @var string
8353+ * @see XML_RPC_Message::setSendEncoding(),
8354+ * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header()
8355+ */
8356+ var $send_encoding = '';
8357+
8358+ /**
8359+ * The method presently being evaluated
8360+ * @var string
8361+ */
8362+ var $methodname = '';
8363+
8364+ /**
8365+ * @var array
8366+ */
8367+ var $params = array();
8368+
8369+ /**
8370+ * The XML message being generated
8371+ * @var string
8372+ */
8373+ var $payload = '';
8374+
8375+ /**
8376+ * @return void
8377+ */
8378+ function XML_RPC_Message($meth, $pars = 0)
8379+ {
8380+ $this->methodname = $meth;
8381+ if (is_array($pars) && sizeof($pars) > 0) {
8382+ for ($i = 0; $i < sizeof($pars); $i++) {
8383+ $this->addParam($pars[$i]);
8384+ }
8385+ }
8386+ }
8387+
8388+ /**
8389+ * Produces the XML declaration including the encoding attribute
8390+ *
8391+ * The encoding is determined by this class' <var>$send_encoding</var>
8392+ * property. If the <var>$send_encoding</var> property is not set, use
8393+ * <var>$GLOBALS['XML_RPC_defencoding']</var>.
8394+ *
8395+ * @return string the XML declaration and <methodCall> element
8396+ *
8397+ * @see XML_RPC_Message::setSendEncoding(),
8398+ * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding']
8399+ */
8400+ function xml_header()
8401+ {
8402+ global $XML_RPC_defencoding;
8403+ if (!$this->send_encoding) {
8404+ $this->send_encoding = $XML_RPC_defencoding;
8405+ }
8406+ return '<?xml version="1.0" encoding="' . $this->send_encoding . '"?>'
8407+ . "\n<methodCall>\n";
8408+ }
8409+
8410+ /**
8411+ * @return string the closing </methodCall> tag
8412+ */
8413+ function xml_footer()
8414+ {
8415+ return "</methodCall>\n";
8416+ }
8417+
8418+ /**
8419+ * @return void
8420+ *
8421+ * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer()
8422+ */
8423+ function createPayload()
8424+ {
8425+ $this->payload = $this->xml_header();
8426+ $this->payload .= '<methodName>' . $this->methodname . "</methodName>\n";
8427+ $this->payload .= "<params>\n";
8428+ for ($i = 0; $i < sizeof($this->params); $i++) {
8429+ $p = $this->params[$i];
8430+ $this->payload .= "<param>\n" . $p->serialize() . "</param>\n";
8431+ }
8432+ $this->payload .= "</params>\n";
8433+ $this->payload .= $this->xml_footer();
8434+ $this->payload = ereg_replace("[\r\n]+", "\r\n", $this->payload);
8435+ }
8436+
8437+ /**
8438+ * @return string the name of the method
8439+ */
8440+ function method($meth = '')
8441+ {
8442+ if ($meth != '') {
8443+ $this->methodname = $meth;
8444+ }
8445+ return $this->methodname;
8446+ }
8447+
8448+ /**
8449+ * @return string the payload
8450+ */
8451+ function serialize()
8452+ {
8453+ $this->createPayload();
8454+ return $this->payload;
8455+ }
8456+
8457+ /**
8458+ * @return void
8459+ */
8460+ function addParam($par)
8461+ {
8462+ $this->params[] = $par;
8463+ }
8464+
8465+ /**
8466+ * Obtains an XML_RPC_Value object for the given parameter
8467+ *
8468+ * @param int $i the index number of the parameter to obtain
8469+ *
8470+ * @return object the XML_RPC_Value object.
8471+ * If the parameter doesn't exist, an XML_RPC_Response object.
8472+ *
8473+ * @since Returns XML_RPC_Response object on error since Release 1.3.0
8474+ */
8475+ function getParam($i)
8476+ {
8477+ global $XML_RPC_err, $XML_RPC_str;
8478+
8479+ if (isset($this->params[$i])) {
8480+ return $this->params[$i];
8481+ } else {
8482+ $this->raiseError('The submitted request did not contain this parameter',
8483+ XML_RPC_ERROR_INCORRECT_PARAMS);
8484+ return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
8485+ $XML_RPC_str['incorrect_params']);
8486+ }
8487+ }
8488+
8489+ /**
8490+ * @return int the number of parameters
8491+ */
8492+ function getNumParams()
8493+ {
8494+ return sizeof($this->params);
8495+ }
8496+
8497+ /**
8498+ * Sets the XML declaration's encoding attribute
8499+ *
8500+ * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII)
8501+ *
8502+ * @return void
8503+ *
8504+ * @see XML_RPC_Message::$send_encoding, XML_RPC_Message::xml_header()
8505+ * @since Method available since Release 1.2.0
8506+ */
8507+ function setSendEncoding($type)
8508+ {
8509+ $this->send_encoding = $type;
8510+ }
8511+
8512+ /**
8513+ * Determine the XML's encoding via the encoding attribute
8514+ * in the XML declaration
8515+ *
8516+ * If the encoding parameter is not set or is not ISO-8859-1, UTF-8
8517+ * or US-ASCII, $XML_RPC_defencoding will be returned.
8518+ *
8519+ * @param string $data the XML that will be parsed
8520+ *
8521+ * @return string the encoding to be used
8522+ *
8523+ * @link http://php.net/xml_parser_create
8524+ * @since Method available since Release 1.2.0
8525+ */
8526+ function getEncoding($data)
8527+ {
8528+ global $XML_RPC_defencoding;
8529+
8530+ if (preg_match('/<\?xml[^>]*\s*encoding\s*=\s*[\'"]([^"\']*)[\'"]/i',
8531+ $data, $match))
8532+ {
8533+ $match[1] = trim(strtoupper($match[1]));
8534+ switch ($match[1]) {
8535+ case 'ISO-8859-1':
8536+ case 'UTF-8':
8537+ case 'US-ASCII':
8538+ return $match[1];
8539+ break;
8540+
8541+ default:
8542+ return $XML_RPC_defencoding;
8543+ }
8544+ } else {
8545+ return $XML_RPC_defencoding;
8546+ }
8547+ }
8548+
8549+ /**
8550+ * @return object a new XML_RPC_Response object
8551+ */
8552+ function parseResponseFile($fp)
8553+ {
8554+ $ipd = '';
8555+ while ($data = @fread($fp, 8192)) {
8556+ $ipd .= $data;
8557+ }
8558+ return $this->parseResponse($ipd);
8559+ }
8560+
8561+ /**
8562+ * @return object a new XML_RPC_Response object
8563+ */
8564+ function parseResponse($data = '')
8565+ {
8566+ global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding;
8567+
8568+ $encoding = $this->getEncoding($data);
8569+ $parser_resource = xml_parser_create($encoding);
8570+ $parser = (int) $parser_resource;
8571+
8572+ $XML_RPC_xh[$parser] = array();
8573+
8574+ $XML_RPC_xh[$parser]['st'] = '';
8575+ $XML_RPC_xh[$parser]['cm'] = 0;
8576+ $XML_RPC_xh[$parser]['isf'] = 0;
8577+ $XML_RPC_xh[$parser]['ac'] = '';
8578+ $XML_RPC_xh[$parser]['qt'] = '';
8579+
8580+ xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
8581+ xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
8582+ xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
8583+
8584+ $hdrfnd = 0;
8585+ if ($this->debug) {
8586+ print "<PRE>---GOT---\n";
8587+ print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
8588+ print "\n---END---\n</PRE>";
8589+ }
8590+
8591+ // See if response is a 200 or a 100 then a 200, else raise error.
8592+ // But only do this if we're using the HTTP protocol.
8593+ if (ereg('^HTTP', $data) &&
8594+ !ereg('^HTTP/[0-9\.]+ 200 ', $data) &&
8595+ !preg_match('@^HTTP/[0-9\.]+ 10[0-9]([A-Za-z ]+)?[\r\n]+HTTP/[0-9\.]+ 200@', $data))
8596+ {
8597+ $errstr = substr($data, 0, strpos($data, "\n") - 1);
8598+ error_log('HTTP error, got response: ' . $errstr);
8599+ $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'],
8600+ $XML_RPC_str['http_error'] . ' (' .
8601+ $errstr . ')');
8602+ xml_parser_free($parser_resource);
8603+ return $r;
8604+ }
8605+ // gotta get rid of headers here
8606+
8607+
8608+ if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) {
8609+ $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
8610+ $data = substr($data, $brpos + 4);
8611+ $hdrfnd = 1;
8612+ }
8613+
8614+ /*
8615+ * be tolerant of junk after methodResponse
8616+ * (e.g. javascript automatically inserted by free hosts)
8617+ * thanks to Luca Mariano <luca.mariano@email.it>
8618+ */
8619+ $data = substr($data, 0, strpos($data, "</methodResponse>") + 17);
8620+
8621+ if (!xml_parse($parser_resource, $data, sizeof($data))) {
8622+ // thanks to Peter Kocks <peter.kocks@baygate.com>
8623+ if (xml_get_current_line_number($parser_resource) == 1) {
8624+ $errstr = 'XML error at line 1, check URL';
8625+ } else {
8626+ $errstr = sprintf('XML error: %s at line %d',
8627+ xml_error_string(xml_get_error_code($parser_resource)),
8628+ xml_get_current_line_number($parser_resource));
8629+ }
8630+ error_log($errstr);
8631+ $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
8632+ $XML_RPC_str['invalid_return']);
8633+ xml_parser_free($parser_resource);
8634+ return $r;
8635+ }
8636+ xml_parser_free($parser_resource);
8637+ if ($this->debug) {
8638+ print '<PRE>---EVALING---[' .
8639+ strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
8640+ htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---</PRE>";
8641+ }
8642+ if (strlen($XML_RPC_xh[$parser]['st']) == 0) {
8643+ // then something odd has happened
8644+ // and it's time to generate a client side error
8645+ // indicating something odd went on
8646+ $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
8647+ $XML_RPC_str['invalid_return']);
8648+ } else {
8649+ eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;');
8650+ if ($XML_RPC_xh[$parser]['isf']) {
8651+ $f = $v->structmem('faultCode');
8652+ $fs = $v->structmem('faultString');
8653+ $r = new XML_RPC_Response($v, $f->scalarval(),
8654+ $fs->scalarval());
8655+ } else {
8656+ $r = new XML_RPC_Response($v);
8657+ }
8658+ }
8659+ $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
8660+ return $r;
8661+ }
8662+}
8663+
8664+/**
8665+ * The methods and properties that represent data in XML RPC format
8666+ *
8667+ * @category Web Services
8668+ * @package XML_RPC
8669+ * @author Edd Dumbill <edd@usefulinc.com>
8670+ * @author Stig Bakken <stig@php.net>
8671+ * @author Martin Jansen <mj@php.net>
8672+ * @author Daniel Convissor <danielc@php.net>
8673+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
8674+ * @version Release: 1.3.1
8675+ * @link http://pear.php.net/package/XML_RPC
8676+ */
8677+class XML_RPC_Value extends XML_RPC_Base
8678+{
8679+ var $me = array();
8680+ var $mytype = 0;
8681+
8682+ /**
8683+ * @return void
8684+ */
8685+ function XML_RPC_Value($val = -1, $type = '')
8686+ {
8687+ global $XML_RPC_Types;
8688+ $this->me = array();
8689+ $this->mytype = 0;
8690+ if ($val != -1 || $type != '') {
8691+ if ($type == '') {
8692+ $type = 'string';
8693+ }
8694+ if (!array_key_exists($type, $XML_RPC_Types)) {
8695+ // XXX
8696+ // need some way to report this error
8697+ } elseif ($XML_RPC_Types[$type] == 1) {
8698+ $this->addScalar($val, $type);
8699+ } elseif ($XML_RPC_Types[$type] == 2) {
8700+ $this->addArray($val);
8701+ } elseif ($XML_RPC_Types[$type] == 3) {
8702+ $this->addStruct($val);
8703+ }
8704+ }
8705+ }
8706+
8707+ /**
8708+ * @return int returns 1 if successful or 0 if there are problems
8709+ */
8710+ function addScalar($val, $type = 'string')
8711+ {
8712+ global $XML_RPC_Types, $XML_RPC_Boolean;
8713+
8714+ if ($this->mytype == 1) {
8715+ $this->raiseError('Scalar can have only one value',
8716+ XML_RPC_ERROR_INVALID_TYPE);
8717+ return 0;
8718+ }
8719+ $typeof = $XML_RPC_Types[$type];
8720+ if ($typeof != 1) {
8721+ $this->raiseError("Not a scalar type (${typeof})",
8722+ XML_RPC_ERROR_INVALID_TYPE);
8723+ return 0;
8724+ }
8725+
8726+ if ($type == $XML_RPC_Boolean) {
8727+ if (strcasecmp($val, 'true') == 0
8728+ || $val == 1
8729+ || ($val == true && strcasecmp($val, 'false')))
8730+ {
8731+ $val = 1;
8732+ } else {
8733+ $val = 0;
8734+ }
8735+ }
8736+
8737+ if ($this->mytype == 2) {
8738+ // we're adding to an array here
8739+ $ar = $this->me['array'];
8740+ $ar[] = new XML_RPC_Value($val, $type);
8741+ $this->me['array'] = $ar;
8742+ } else {
8743+ // a scalar, so set the value and remember we're scalar
8744+ $this->me[$type] = $val;
8745+ $this->mytype = $typeof;
8746+ }
8747+ return 1;
8748+ }
8749+
8750+ /**
8751+ * @return int returns 1 if successful or 0 if there are problems
8752+ */
8753+ function addArray($vals)
8754+ {
8755+ global $XML_RPC_Types;
8756+ if ($this->mytype != 0) {
8757+ $this->raiseError(
8758+ 'Already initialized as a [' . $this->kindOf() . ']',
8759+ XML_RPC_ERROR_ALREADY_INITIALIZED);
8760+ return 0;
8761+ }
8762+ $this->mytype = $XML_RPC_Types['array'];
8763+ $this->me['array'] = $vals;
8764+ return 1;
8765+ }
8766+
8767+ /**
8768+ * @return int returns 1 if successful or 0 if there are problems
8769+ */
8770+ function addStruct($vals)
8771+ {
8772+ global $XML_RPC_Types;
8773+ if ($this->mytype != 0) {
8774+ $this->raiseError(
8775+ 'Already initialized as a [' . $this->kindOf() . ']',
8776+ XML_RPC_ERROR_ALREADY_INITIALIZED);
8777+ return 0;
8778+ }
8779+ $this->mytype = $XML_RPC_Types['struct'];
8780+ $this->me['struct'] = $vals;
8781+ return 1;
8782+ }
8783+
8784+ /**
8785+ * @return void
8786+ */
8787+ function dump($ar)
8788+ {
8789+ reset($ar);
8790+ foreach ($ar as $key => $val) {
8791+ echo "$key => $val<br />";
8792+ if ($key == 'array') {
8793+ foreach ($val as $key2 => $val2) {
8794+ echo "-- $key2 => $val2<br />";
8795+ }
8796+ }
8797+ }
8798+ }
8799+
8800+ /**
8801+ * @return string the data type of the current value
8802+ */
8803+ function kindOf()
8804+ {
8805+ switch ($this->mytype) {
8806+ case 3:
8807+ return 'struct';
8808+
8809+ case 2:
8810+ return 'array';
8811+
8812+ case 1:
8813+ return 'scalar';
8814+
8815+ default:
8816+ return 'undef';
8817+ }
8818+ }
8819+
8820+ /**
8821+ * @return string the data in XML format
8822+ */
8823+ function serializedata($typ, $val)
8824+ {
8825+ $rs = '';
8826+ global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
8827+ if (!array_key_exists($typ, $XML_RPC_Types)) {
8828+ // XXX
8829+ // need some way to report this error
8830+ return;
8831+ }
8832+ switch ($XML_RPC_Types[$typ]) {
8833+ case 3:
8834+ // struct
8835+ $rs .= "<struct>\n";
8836+ reset($val);
8837+ foreach ($val as $key2 => $val2) {
8838+ $rs .= "<member><name>${key2}</name>\n";
8839+ $rs .= $this->serializeval($val2);
8840+ $rs .= "</member>\n";
8841+ }
8842+ $rs .= '</struct>';
8843+ break;
8844+
8845+ case 2:
8846+ // array
8847+ $rs .= "<array>\n<data>\n";
8848+ for ($i = 0; $i < sizeof($val); $i++) {
8849+ $rs .= $this->serializeval($val[$i]);
8850+ }
8851+ $rs .= "</data>\n</array>";
8852+ break;
8853+
8854+ case 1:
8855+ switch ($typ) {
8856+ case $XML_RPC_Base64:
8857+ $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
8858+ break;
8859+ case $XML_RPC_Boolean:
8860+ $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
8861+ break;
8862+ case $XML_RPC_String:
8863+ $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
8864+ break;
8865+ default:
8866+ $rs .= "<${typ}>${val}</${typ}>";
8867+ }
8868+ }
8869+ return $rs;
8870+ }
8871+
8872+ /**
8873+ * @return string the data in XML format
8874+ */
8875+ function serialize()
8876+ {
8877+ return $this->serializeval($this);
8878+ }
8879+
8880+ /**
8881+ * @return string the data in XML format
8882+ */
8883+ function serializeval($o)
8884+ {
8885+ $rs = '';
8886+ $ar = $o->me;
8887+ reset($ar);
8888+ list($typ, $val) = each($ar);
8889+ $rs .= '<value>';
8890+ $rs .= $this->serializedata($typ, $val);
8891+ $rs .= "</value>\n";
8892+ return $rs;
8893+ }
8894+
8895+ /**
8896+ * @return mixed the contents of the element requested
8897+ */
8898+ function structmem($m)
8899+ {
8900+ return $this->me['struct'][$m];
8901+ }
8902+
8903+ /**
8904+ * @return void
8905+ */
8906+ function structreset()
8907+ {
8908+ reset($this->me['struct']);
8909+ }
8910+
8911+ /**
8912+ * @return the key/value pair of the struct's current element
8913+ */
8914+ function structeach()
8915+ {
8916+ return each($this->me['struct']);
8917+ }
8918+
8919+ /**
8920+ * @return mixed the current value
8921+ */
8922+ function getval()
8923+ {
8924+ // UNSTABLE
8925+ global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
8926+
8927+ reset($this->me);
8928+ $b = current($this->me);
8929+
8930+ // contributed by I Sofer, 2001-03-24
8931+ // add support for nested arrays to scalarval
8932+ // i've created a new method here, so as to
8933+ // preserve back compatibility
8934+
8935+ if (is_array($b)) {
8936+ foreach ($b as $id => $cont) {
8937+ $b[$id] = $cont->scalarval();
8938+ }
8939+ }
8940+
8941+ // add support for structures directly encoding php objects
8942+ if (is_object($b)) {
8943+ $t = get_object_vars($b);
8944+ foreach ($t as $id => $cont) {
8945+ $t[$id] = $cont->scalarval();
8946+ }
8947+ foreach ($t as $id => $cont) {
8948+ eval('$b->'.$id.' = $cont;');
8949+ }
8950+ }
8951+
8952+ // end contrib
8953+ return $b;
8954+ }
8955+
8956+ /**
8957+ * @return mixed
8958+ */
8959+ function scalarval()
8960+ {
8961+ global $XML_RPC_Boolean, $XML_RPC_Base64;
8962+ reset($this->me);
8963+ return current($this->me);
8964+ }
8965+
8966+ /**
8967+ * @return string
8968+ */
8969+ function scalartyp()
8970+ {
8971+ global $XML_RPC_I4, $XML_RPC_Int;
8972+ reset($this->me);
8973+ $a = key($this->me);
8974+ if ($a == $XML_RPC_I4) {
8975+ $a = $XML_RPC_Int;
8976+ }
8977+ return $a;
8978+ }
8979+
8980+ /**
8981+ * @return mixed the struct's current element
8982+ */
8983+ function arraymem($m)
8984+ {
8985+ return $this->me['array'][$m];
8986+ }
8987+
8988+ /**
8989+ * @return int the number of elements in the array
8990+ */
8991+ function arraysize()
8992+ {
8993+ reset($this->me);
8994+ list($a, $b) = each($this->me);
8995+ return sizeof($b);
8996+ }
8997+
8998+ /**
8999+ * Determines if the item submitted is an XML_RPC_Value object
9000+ *
9001+ * @param mixed $val the variable to be evaluated
9002+ *
9003+ * @return bool TRUE if the item is an XML_RPC_Value object
9004+ *
9005+ * @static
9006+ * @since Method available since Release 1.3.0
9007+ */
9008+ function isValue($val)
9009+ {
9010+ return (strtolower(get_class($val)) == 'xml_rpc_value');
9011+ }
9012+}
9013+
9014+/**
9015+ * Return an ISO8601 encoded string
9016+ *
9017+ * While timezones ought to be supported, the XML-RPC spec says:
9018+ *
9019+ * "Don't assume a timezone. It should be specified by the server in its
9020+ * documentation what assumptions it makes about timezones."
9021+ *
9022+ * This routine always assumes localtime unless $utc is set to 1, in which
9023+ * case UTC is assumed and an adjustment for locale is made when encoding.
9024+ *
9025+ * @return string the formatted date
9026+ */
9027+function XML_RPC_iso8601_encode($timet, $utc = 0)
9028+{
9029+ if (!$utc) {
9030+ $t = strftime('%Y%m%dT%H:%M:%S', $timet);
9031+ } else {
9032+ if (function_exists('gmstrftime')) {
9033+ // gmstrftime doesn't exist in some versions
9034+ // of PHP
9035+ $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet);
9036+ } else {
9037+ $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z'));
9038+ }
9039+ }
9040+ return $t;
9041+}
9042+
9043+/**
9044+ * Convert a datetime string into a Unix timestamp
9045+ *
9046+ * While timezones ought to be supported, the XML-RPC spec says:
9047+ *
9048+ * "Don't assume a timezone. It should be specified by the server in its
9049+ * documentation what assumptions it makes about timezones."
9050+ *
9051+ * This routine always assumes localtime unless $utc is set to 1, in which
9052+ * case UTC is assumed and an adjustment for locale is made when encoding.
9053+ *
9054+ * @return int the unix timestamp of the date submitted
9055+ */
9056+function XML_RPC_iso8601_decode($idate, $utc = 0)
9057+{
9058+ $t = 0;
9059+ if (ereg('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) {
9060+ if ($utc) {
9061+ $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
9062+ } else {
9063+ $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
9064+ }
9065+ }
9066+ return $t;
9067+}
9068+
9069+/**
9070+ * Converts an XML_RPC_Value object into native PHP types
9071+ *
9072+ * @param object $XML_RPC_val the XML_RPC_Value object to decode
9073+ *
9074+ * @return mixed the PHP values
9075+ */
9076+function XML_RPC_decode($XML_RPC_val)
9077+{
9078+ $kind = $XML_RPC_val->kindOf();
9079+
9080+ if ($kind == 'scalar') {
9081+ return $XML_RPC_val->scalarval();
9082+
9083+ } elseif ($kind == 'array') {
9084+ $size = $XML_RPC_val->arraysize();
9085+ $arr = array();
9086+ for ($i = 0; $i < $size; $i++) {
9087+ $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i));
9088+ }
9089+ return $arr;
9090+
9091+ } elseif ($kind == 'struct') {
9092+ $XML_RPC_val->structreset();
9093+ $arr = array();
9094+ while (list($key, $value) = $XML_RPC_val->structeach()) {
9095+ $arr[$key] = XML_RPC_decode($value);
9096+ }
9097+ return $arr;
9098+ }
9099+}
9100+
9101+/**
9102+ * Converts native PHP types into an XML_RPC_Value object
9103+ *
9104+ * @param mixed $php_val the PHP value or variable you want encoded
9105+ *
9106+ * @return object the XML_RPC_Value object
9107+ */
9108+function XML_RPC_encode($php_val)
9109+{
9110+ global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double, $XML_RPC_String,
9111+ $XML_RPC_Array, $XML_RPC_Struct;
9112+
9113+ $type = gettype($php_val);
9114+ $XML_RPC_val = new XML_RPC_Value;
9115+
9116+ switch ($type) {
9117+ case 'array':
9118+ if (empty($php_val)) {
9119+ $XML_RPC_val->addArray($php_val);
9120+ break;
9121+ }
9122+ $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1));
9123+ if (empty($tmp)) {
9124+ $arr = array();
9125+ foreach ($php_val as $k => $v) {
9126+ $arr[$k] = XML_RPC_encode($v);
9127+ }
9128+ $XML_RPC_val->addArray($arr);
9129+ break;
9130+ }
9131+ // fall though if it's not an enumerated array
9132+
9133+ case 'object':
9134+ $arr = array();
9135+ foreach ($php_val as $k => $v) {
9136+ $arr[$k] = XML_RPC_encode($v);
9137+ }
9138+ $XML_RPC_val->addStruct($arr);
9139+ break;
9140+
9141+ case 'integer':
9142+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
9143+ break;
9144+
9145+ case 'double':
9146+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
9147+ break;
9148+
9149+ case 'string':
9150+ case 'NULL':
9151+ $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
9152+ break;
9153+
9154+ case 'boolean':
9155+ // Add support for encoding/decoding of booleans, since they
9156+ // are supported in PHP
9157+ // by <G_Giunta_2001-02-29>
9158+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
9159+ break;
9160+
9161+ case 'unknown type':
9162+ default:
9163+ $XML_RPC_val = false;
9164+ }
9165+ return $XML_RPC_val;
9166+}
9167+
9168+/*
9169+ * Local variables:
9170+ * tab-width: 4
9171+ * c-basic-offset: 4
9172+ * c-hanging-comment-ender-p: nil
9173+ * End:
9174+ */
9175+
9176+?>
9177+
9178+
9179+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
9180+
9181+/**
9182+ * Server commands for our PHP implementation of the XML-RPC protocol
9183+ *
9184+ * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
9185+ * It has support for HTTP transport, proxies and authentication.
9186+ *
9187+ * PHP versions 4 and 5
9188+ *
9189+ * LICENSE: License is granted to use or modify this software
9190+ * ("XML-RPC for PHP") for commercial or non-commercial use provided the
9191+ * copyright of the author is preserved in any distributed or derivative work.
9192+ *
9193+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
9194+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
9195+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9196+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
9197+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
9198+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
9199+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9200+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9201+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
9202+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9203+ *
9204+ * @category Web Services
9205+ * @package XML_RPC
9206+ * @author Edd Dumbill <edd@usefulinc.com>
9207+ * @author Stig Bakken <stig@php.net>
9208+ * @author Martin Jansen <mj@php.net>
9209+ * @author Daniel Convissor <danielc@php.net>
9210+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
9211+ * @version CVS: $Id: Server.php,v 1.26 2005/05/09 21:39:47 danielc Exp $
9212+ * @link http://pear.php.net/package/XML_RPC
9213+ */
9214+
9215+
9216+/**
9217+ * Pull in the XML_RPC class
9218+ */
9219+require_once 'XML/RPC.php';
9220+
9221+
9222+/**
9223+ * signature for system.listMethods: return = array,
9224+ * parameters = a string or nothing
9225+ * @global array $GLOBALS['XML_RPC_Server_listMethods_sig']
9226+ */
9227+$GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
9228+ array($GLOBALS['XML_RPC_Array'],
9229+ $GLOBALS['XML_RPC_String']
9230+ ),
9231+ array($GLOBALS['XML_RPC_Array'])
9232+);
9233+
9234+/**
9235+ * docstring for system.listMethods
9236+ * @global string $GLOBALS['XML_RPC_Server_listMethods_doc']
9237+ */
9238+$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the'
9239+ . ' methods that the XML-RPC server knows how to dispatch';
9240+
9241+/**
9242+ * signature for system.methodSignature: return = array,
9243+ * parameters = string
9244+ * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig']
9245+ */
9246+$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
9247+ array($GLOBALS['XML_RPC_Array'],
9248+ $GLOBALS['XML_RPC_String']
9249+ )
9250+);
9251+
9252+/**
9253+ * docstring for system.methodSignature
9254+ * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc']
9255+ */
9256+$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
9257+ . ' signatures (an array of arrays) for the method name passed. If'
9258+ . ' no signatures are known, returns a none-array (test for type !='
9259+ . ' array to detect missing signature)';
9260+
9261+/**
9262+ * signature for system.methodHelp: return = string,
9263+ * parameters = string
9264+ * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig']
9265+ */
9266+$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
9267+ array($GLOBALS['XML_RPC_String'],
9268+ $GLOBALS['XML_RPC_String']
9269+ )
9270+);
9271+
9272+/**
9273+ * docstring for methodHelp
9274+ * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc']
9275+ */
9276+$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined'
9277+ . ' for the method passed, otherwise returns an empty string';
9278+
9279+/**
9280+ * dispatch map for the automatically declared XML-RPC methods.
9281+ * @global array $GLOBALS['XML_RPC_Server_dmap']
9282+ */
9283+$GLOBALS['XML_RPC_Server_dmap'] = array(
9284+ 'system.listMethods' => array(
9285+ 'function' => 'XML_RPC_Server_listMethods',
9286+ 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'],
9287+ 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc']
9288+ ),
9289+ 'system.methodHelp' => array(
9290+ 'function' => 'XML_RPC_Server_methodHelp',
9291+ 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'],
9292+ 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc']
9293+ ),
9294+ 'system.methodSignature' => array(
9295+ 'function' => 'XML_RPC_Server_methodSignature',
9296+ 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'],
9297+ 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc']
9298+ )
9299+);
9300+
9301+/**
9302+ * @global string $GLOBALS['XML_RPC_Server_debuginfo']
9303+ */
9304+$GLOBALS['XML_RPC_Server_debuginfo'] = '';
9305+
9306+
9307+/**
9308+ * Lists all the methods that the XML-RPC server knows how to dispatch
9309+ *
9310+ * @return object a new XML_RPC_Response object
9311+ */
9312+function XML_RPC_Server_listMethods($server, $m)
9313+{
9314+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
9315+
9316+ $v = new XML_RPC_Value();
9317+ $outAr = array();
9318+ foreach ($server->dmap as $key => $val) {
9319+ $outAr[] = new XML_RPC_Value($key, 'string');
9320+ }
9321+ foreach ($XML_RPC_Server_dmap as $key => $val) {
9322+ $outAr[] = new XML_RPC_Value($key, 'string');
9323+ }
9324+ $v->addArray($outAr);
9325+ return new XML_RPC_Response($v);
9326+}
9327+
9328+/**
9329+ * Returns an array of known signatures (an array of arrays)
9330+ * for the given method
9331+ *
9332+ * If no signatures are known, returns a none-array
9333+ * (test for type != array to detect missing signature)
9334+ *
9335+ * @return object a new XML_RPC_Response object
9336+ */
9337+function XML_RPC_Server_methodSignature($server, $m)
9338+{
9339+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
9340+
9341+ $methName = $m->getParam(0);
9342+ $methName = $methName->scalarval();
9343+ if (strpos($methName, 'system.') === 0) {
9344+ $dmap = $XML_RPC_Server_dmap;
9345+ $sysCall = 1;
9346+ } else {
9347+ $dmap = $server->dmap;
9348+ $sysCall = 0;
9349+ }
9350+ // print "<!-- ${methName} -->\n";
9351+ if (isset($dmap[$methName])) {
9352+ if ($dmap[$methName]['signature']) {
9353+ $sigs = array();
9354+ $thesigs = $dmap[$methName]['signature'];
9355+ for ($i = 0; $i < sizeof($thesigs); $i++) {
9356+ $cursig = array();
9357+ $inSig = $thesigs[$i];
9358+ for ($j = 0; $j < sizeof($inSig); $j++) {
9359+ $cursig[] = new XML_RPC_Value($inSig[$j], 'string');
9360+ }
9361+ $sigs[] = new XML_RPC_Value($cursig, 'array');
9362+ }
9363+ $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array'));
9364+ } else {
9365+ $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string'));
9366+ }
9367+ } else {
9368+ $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
9369+ $XML_RPC_str['introspect_unknown']);
9370+ }
9371+ return $r;
9372+}
9373+
9374+/**
9375+ * Returns help text if defined for the method passed, otherwise returns
9376+ * an empty string
9377+ *
9378+ * @return object a new XML_RPC_Response object
9379+ */
9380+function XML_RPC_Server_methodHelp($server, $m)
9381+{
9382+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
9383+
9384+ $methName = $m->getParam(0);
9385+ $methName = $methName->scalarval();
9386+ if (strpos($methName, 'system.') === 0) {
9387+ $dmap = $XML_RPC_Server_dmap;
9388+ $sysCall = 1;
9389+ } else {
9390+ $dmap = $server->dmap;
9391+ $sysCall = 0;
9392+ }
9393+ // print "<!-- ${methName} -->\n";
9394+ if (isset($dmap[$methName])) {
9395+ if ($dmap[$methName]['docstring']) {
9396+ $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']),
9397+ 'string');
9398+ } else {
9399+ $r = new XML_RPC_Response(new XML_RPC_Value('', 'string'));
9400+ }
9401+ } else {
9402+ $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
9403+ $XML_RPC_str['introspect_unknown']);
9404+ }
9405+ return $r;
9406+}
9407+
9408+/**
9409+ * @return void
9410+ */
9411+function XML_RPC_Server_debugmsg($m)
9412+{
9413+ global $XML_RPC_Server_debuginfo;
9414+ $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n";
9415+}
9416+
9417+
9418+/**
9419+ * A server for receiving and replying to XML RPC requests
9420+ *
9421+ * <code>
9422+ * $server = new XML_RPC_Server(
9423+ * array(
9424+ * 'isan8' =>
9425+ * array(
9426+ * 'function' => 'is_8',
9427+ * 'signature' =>
9428+ * array(
9429+ * array('boolean', 'int'),
9430+ * array('boolean', 'int', 'boolean'),
9431+ * array('boolean', 'string'),
9432+ * array('boolean', 'string', 'boolean'),
9433+ * ),
9434+ * 'docstring' => 'Is the value an 8?'
9435+ * ),
9436+ * ),
9437+ * 1,
9438+ * 0
9439+ * );
9440+ * </code>
9441+ *
9442+ * @category Web Services
9443+ * @package XML_RPC
9444+ * @author Edd Dumbill <edd@usefulinc.com>
9445+ * @author Stig Bakken <stig@php.net>
9446+ * @author Martin Jansen <mj@php.net>
9447+ * @author Daniel Convissor <danielc@php.net>
9448+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
9449+ * @version Release: 1.3.1
9450+ * @link http://pear.php.net/package/XML_RPC
9451+ */
9452+class XML_RPC_Server
9453+{
9454+ /**
9455+ * The dispatch map, listing the methods this server provides.
9456+ * @var array
9457+ */
9458+ var $dmap = array();
9459+
9460+ /**
9461+ * The present response's encoding
9462+ * @var string
9463+ * @see XML_RPC_Message::getEncoding()
9464+ */
9465+ var $encoding = '';
9466+
9467+ /**
9468+ * Debug mode (0 = off, 1 = on)
9469+ * @var integer
9470+ */
9471+ var $debug = 0;
9472+
9473+ /**
9474+ * The response's HTTP headers
9475+ * @var string
9476+ */
9477+ var $server_headers = '';
9478+
9479+ /**
9480+ * The response's XML payload
9481+ * @var string
9482+ */
9483+ var $server_payload = '';
9484+
9485+
9486+ /**
9487+ * Constructor for the XML_RPC_Server class
9488+ *
9489+ * @param array $dispMap the dispatch map. An associative array
9490+ * explaining each function. The keys of the main
9491+ * array are the procedure names used by the
9492+ * clients. The value is another associative array
9493+ * that contains up to three elements:
9494+ * + The 'function' element's value is the name
9495+ * of the function or method that gets called.
9496+ * To define a class' method: 'class::method'.
9497+ * + The 'signature' element (optional) is an
9498+ * array describing the return values and
9499+ * parameters
9500+ * + The 'docstring' element (optional) is a
9501+ * string describing what the method does
9502+ * @param int $serviceNow should the HTTP response be sent now?
9503+ * (1 = yes, 0 = no)
9504+ * @param int $debug should debug output be displayed?
9505+ * (1 = yes, 0 = no)
9506+ *
9507+ * @return void
9508+ */
9509+ function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0)
9510+ {
9511+ global $HTTP_RAW_POST_DATA;
9512+
9513+ if ($debug) {
9514+ $this->debug = 1;
9515+ } else {
9516+ $this->debug = 0;
9517+ }
9518+
9519+ $this->dmap = $dispMap;
9520+
9521+ if ($serviceNow) {
9522+ $this->service();
9523+ } else {
9524+ $this->createServerPayload();
9525+ $this->createServerHeaders();
9526+ }
9527+ }
9528+
9529+ /**
9530+ * @return string the debug information if debug debug mode is on
9531+ */
9532+ function serializeDebug()
9533+ {
9534+ global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA;
9535+
9536+ if ($this->debug) {
9537+ XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n"
9538+ . $HTTP_RAW_POST_DATA
9539+ . "\n" . '^^^ END POST DATA ^^^');
9540+ }
9541+
9542+ if ($XML_RPC_Server_debuginfo != '') {
9543+ return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n"
9544+ . preg_replace('/-(?=-)/', '- ', $XML_RPC_Server_debuginfo)
9545+ . "-->\n";
9546+ } else {
9547+ return '';
9548+ }
9549+ }
9550+
9551+ /**
9552+ * Sends the response
9553+ *
9554+ * The encoding and content-type are determined by
9555+ * XML_RPC_Message::getEncoding()
9556+ *
9557+ * @return void
9558+ *
9559+ * @uses XML_RPC_Server::createServerPayload(),
9560+ * XML_RPC_Server::createServerHeaders()
9561+ */
9562+ function service()
9563+ {
9564+ $this->createServerPayload();
9565+ $this->createServerHeaders();
9566+ header($this->server_headers);
9567+ print $this->server_payload;
9568+ }
9569+
9570+ /**
9571+ * Generates the payload and puts it in the $server_payload property
9572+ *
9573+ * @return void
9574+ *
9575+ * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding,
9576+ * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug()
9577+ */
9578+ function createServerPayload()
9579+ {
9580+ $r = $this->parseRequest();
9581+ $this->server_payload = '<?xml version="1.0" encoding="'
9582+ . $this->encoding . '"?>' . "\n"
9583+ . $this->serializeDebug()
9584+ . $r->serialize();
9585+ }
9586+
9587+ /**
9588+ * Determines the HTTP headers and puts them in the $server_headers
9589+ * property
9590+ *
9591+ * @return boolean TRUE if okay, FALSE if $server_payload isn't set.
9592+ *
9593+ * @uses XML_RPC_Server::createServerPayload(),
9594+ * XML_RPC_Server::$server_headers
9595+ */
9596+ function createServerHeaders()
9597+ {
9598+ if (!$this->server_payload) {
9599+ return false;
9600+ }
9601+ $this->server_headers = 'Content-Length: '
9602+ . strlen($this->server_payload) . "\r\n"
9603+ . 'Content-Type: text/xml;'
9604+ . ' charset=' . $this->encoding;
9605+ return true;
9606+ }
9607+
9608+ /**
9609+ * @return array
9610+ */
9611+ function verifySignature($in, $sig)
9612+ {
9613+ for ($i = 0; $i < sizeof($sig); $i++) {
9614+ // check each possible signature in turn
9615+ $cursig = $sig[$i];
9616+ if (sizeof($cursig) == $in->getNumParams() + 1) {
9617+ $itsOK = 1;
9618+ for ($n = 0; $n < $in->getNumParams(); $n++) {
9619+ $p = $in->getParam($n);
9620+ // print "<!-- $p -->\n";
9621+ if ($p->kindOf() == 'scalar') {
9622+ $pt = $p->scalartyp();
9623+ } else {
9624+ $pt = $p->kindOf();
9625+ }
9626+ // $n+1 as first type of sig is return type
9627+ if ($pt != $cursig[$n+1]) {
9628+ $itsOK = 0;
9629+ $pno = $n+1;
9630+ $wanted = $cursig[$n+1];
9631+ $got = $pt;
9632+ break;
9633+ }
9634+ }
9635+ if ($itsOK) {
9636+ return array(1);
9637+ }
9638+ }
9639+ }
9640+ if (isset($wanted)) {
9641+ return array(0, "Wanted ${wanted}, got ${got} at param ${pno}");
9642+ } else {
9643+ $allowed = array();
9644+ foreach ($sig as $val) {
9645+ end($val);
9646+ $allowed[] = key($val);
9647+ }
9648+ $allowed = array_unique($allowed);
9649+ $last = count($allowed) - 1;
9650+ if ($last > 0) {
9651+ $allowed[$last] = 'or ' . $allowed[$last];
9652+ }
9653+ return array(0,
9654+ 'Signature permits ' . implode(', ', $allowed)
9655+ . ' parameters but the request had '
9656+ . $in->getNumParams());
9657+ }
9658+ }
9659+
9660+ /**
9661+ * @return object a new XML_RPC_Response object
9662+ *
9663+ * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding
9664+ */
9665+ function parseRequest($data = '')
9666+ {
9667+ global $XML_RPC_xh, $HTTP_RAW_POST_DATA,
9668+ $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml,
9669+ $XML_RPC_defencoding, $XML_RPC_Server_dmap;
9670+
9671+ if ($data == '') {
9672+ $data = $HTTP_RAW_POST_DATA;
9673+ }
9674+
9675+ $this->encoding = XML_RPC_Message::getEncoding($data);
9676+ $parser_resource = xml_parser_create($this->encoding);
9677+ $parser = (int) $parser_resource;
9678+
9679+ $XML_RPC_xh[$parser] = array();
9680+ $XML_RPC_xh[$parser]['st'] = '';
9681+ $XML_RPC_xh[$parser]['cm'] = 0;
9682+ $XML_RPC_xh[$parser]['isf'] = 0;
9683+ $XML_RPC_xh[$parser]['params'] = array();
9684+ $XML_RPC_xh[$parser]['method'] = '';
9685+
9686+ $plist = '';
9687+
9688+ // decompose incoming XML into request structure
9689+
9690+ xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
9691+ xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
9692+ xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
9693+ if (!xml_parse($parser_resource, $data, 1)) {
9694+ // return XML error as a faultCode
9695+ $r = new XML_RPC_Response(0,
9696+ $XML_RPC_errxml+xml_get_error_code($parser_resource),
9697+ sprintf('XML error: %s at line %d',
9698+ xml_error_string(xml_get_error_code($parser_resource)),
9699+ xml_get_current_line_number($parser_resource)));
9700+ xml_parser_free($parser_resource);
9701+ } else {
9702+ xml_parser_free($parser_resource);
9703+ $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']);
9704+ // now add parameters in
9705+ for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) {
9706+ // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n";
9707+ $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n";
9708+ eval('$m->addParam(' . $XML_RPC_xh[$parser]['params'][$i] . ');');
9709+ }
9710+ XML_RPC_Server_debugmsg($plist);
9711+
9712+ // now to deal with the method
9713+ $methName = $XML_RPC_xh[$parser]['method'];
9714+ if (strpos($methName, 'system.') === 0) {
9715+ $dmap = $XML_RPC_Server_dmap;
9716+ $sysCall = 1;
9717+ } else {
9718+ $dmap = $this->dmap;
9719+ $sysCall = 0;
9720+ }
9721+
9722+ if (isset($dmap[$methName]['function'])
9723+ && is_string($dmap[$methName]['function'])
9724+ && strpos($dmap[$methName]['function'], '::') !== false)
9725+ {
9726+ $dmap[$methName]['function'] =
9727+ explode('::', $dmap[$methName]['function']);
9728+ }
9729+
9730+ if (isset($dmap[$methName]['function'])
9731+ && is_callable($dmap[$methName]['function']))
9732+ {
9733+ // dispatch if exists
9734+ if (isset($dmap[$methName]['signature'])) {
9735+ $sr = $this->verifySignature($m,
9736+ $dmap[$methName]['signature'] );
9737+ }
9738+ if (!isset($dmap[$methName]['signature']) || $sr[0]) {
9739+ // if no signature or correct signature
9740+ if ($sysCall) {
9741+ $r = call_user_func($dmap[$methName]['function'], $this, $m);
9742+ } else {
9743+ $r = call_user_func($dmap[$methName]['function'], $m);
9744+ }
9745+ if (!is_a($r, 'XML_RPC_Response')) {
9746+ $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'],
9747+ $XML_RPC_str['not_response_object']);
9748+ }
9749+ } else {
9750+ $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
9751+ $XML_RPC_str['incorrect_params']
9752+ . ': ' . $sr[1]);
9753+ }
9754+ } else {
9755+ // else prepare error response
9756+ $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'],
9757+ $XML_RPC_str['unknown_method']);
9758+ }
9759+ }
9760+ return $r;
9761+ }
9762+
9763+ /**
9764+ * Echos back the input packet as a string value
9765+ *
9766+ * @return void
9767+ *
9768+ * Useful for debugging.
9769+ */
9770+ function echoInput()
9771+ {
9772+ global $HTTP_RAW_POST_DATA;
9773+
9774+ $r = new XML_RPC_Response(0);
9775+ $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string');
9776+ print $r->serialize();
9777+ }
9778+}
9779+
9780+/*
9781+ * Local variables:
9782+ * tab-width: 4
9783+ * c-basic-offset: 4
9784+ * c-hanging-comment-ender-p: nil
9785+ * End:
9786+ */
9787+
9788+?>
9789+
9790+<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
9791+<package version="1.0" packagerversion="1.4.0a12">
9792+ <name>XML_RPC</name>
9793+ <summary>PHP implementation of the XML-RPC protocol</summary>
9794+ <description>A PEAR-ified version of Useful Inc's XML-RPC for PHP.
9795+
9796+It has support for HTTP/HTTPS transport, proxies and authentication.
9797+ </description>
9798+ <maintainers>
9799+ <maintainer>
9800+ <user>ssb</user>
9801+ <name>Stig Bakken</name>
9802+ <email>stig@php.net</email>
9803+ <role>lead</role>
9804+ </maintainer>
9805+ <maintainer>
9806+ <user>danielc</user>
9807+ <name>Daniel Convissor</name>
9808+ <email>danielc@php.net</email>
9809+ <role>lead</role>
9810+ </maintainer>
9811+ </maintainers>
9812+ <release>
9813+ <version>1.3.1</version>
9814+ <date>2005-06-29</date>
9815+ <license>PHP License</license>
9816+ <state>stable</state>
9817+ <notes>* Security fix. Update highly recommended!
9818+ </notes>
9819+ <filelist>
9820+ <file role="php" baseinstalldir="XML" name="RPC.php">
9821+ <replace from="@package_version@" to="version" type="package-info"/>
9822+ </file>
9823+ <file role="php" baseinstalldir="XML/RPC" name="Server.php">
9824+ <replace from="@package_version@" to="version" type="package-info"/>
9825+ </file>
9826+ <file role="php" baseinstalldir="XML/RPC" name="Dump.php">
9827+ <replace from="@package_version@" to="version" type="package-info"/>
9828+ </file>
9829+ <file role="test" name="tests/protoport.php">
9830+ <replace from="@package_version@" to="version" type="package-info"/>
9831+ </file>
9832+ <file role="test" name="tests/test_Dump.php">
9833+ <replace from="@package_version@" to="version" type="package-info"/>
9834+ </file>
9835+ </filelist>
9836+ </release>
9837+ <changelog>
9838+ <release>
9839+ <version>1.3.0RC3</version>
9840+ <date>2005-05-10</date>
9841+ <state>beta</state>
9842+ <notes>* When verifying requests against function signatures, if the number of parameters don't match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
9843+* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
9844+* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
9845+* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
9846+* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
9847+* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().
9848+ </notes>
9849+ </release>
9850+ <release>
9851+ <version>1.3.0RC2</version>
9852+ <date>2005-05-05</date>
9853+ <state>beta</state>
9854+ <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
9855+* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
9856+* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
9857+* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.
9858+ </notes>
9859+ </release>
9860+ <release>
9861+ <version>1.3.0RC1</version>
9862+ <date>2005-04-07</date>
9863+ <state>beta</state>
9864+ <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
9865+* Add Fault Code 6: &quot;The requested method didn't return an XML_RPC_Response object.&quot; Request 4032.
9866+* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
9867+* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
9868+* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
9869+* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.
9870+ </notes>
9871+ </release>
9872+ <release>
9873+ <version>1.2.2</version>
9874+ <date>2005-03-07</date>
9875+ <state>stable</state>
9876+ <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.
9877+ </notes>
9878+ </release>
9879+ <release>
9880+ <version>1.2.1</version>
9881+ <date>2005-03-01</date>
9882+ <state>stable</state>
9883+ <notes>* Add isset() check before examining the dispatch map. Bug 3658.
9884+ </notes>
9885+ </release>
9886+ <release>
9887+ <version>1.2.0</version>
9888+ <date>2005-02-27</date>
9889+ <state>stable</state>
9890+ <notes>* Provide the &quot;stable&quot; release.
9891+* Add package2.xml for compatibility with PEAR 1.4.0.
9892+* For changes since 1.1.0, see the changelogs for the various RC releases.
9893+ </notes>
9894+ </release>
9895+ <release>
9896+ <version>1.2.0RC7</version>
9897+ <date>2005-02-22</date>
9898+ <state>beta</state>
9899+ <notes>* Add the setSendEncoding() method and $send_encoding
9900+ property to XML_RPC_Message. Request 3537.
9901+* Allow class methods to be mapped using either syntax:
9902+ 'function' =&gt; 'hello::sayHello',
9903+ or
9904+ 'function' =&gt; array('hello', 'sayhello'),
9905+ Bug 3363.
9906+* Use 8192 instead of 32768 for bytes in fread()
9907+ in parseResponseFile(). Bug 3340.
9908+ </notes>
9909+ </release>
9910+ <release>
9911+ <version>1.2.0RC6</version>
9912+ <date>2005-01-25</date>
9913+ <state>beta</state>
9914+ <notes>* Don't put the protocol in the Host field of the POST data. (danielc)
9915+ </notes>
9916+ </release>
9917+ <release>
9918+ <version>1.2.0RC5</version>
9919+ <date>2005-01-24</date>
9920+ <state>beta</state>
9921+ <notes>* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
9922+ </notes>
9923+ </release>
9924+ <release>
9925+ <version>1.2.0RC4</version>
9926+ <date>2005-01-24</date>
9927+ <state>beta</state>
9928+ <notes>* When a connection attempt fails, have the method return 0. (danielc)
9929+* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
9930+* Add tests for setting the client properties. (danielc)
9931+* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc)
9932+* Bundle the tests with the package. (danielc)
9933+ </notes>
9934+ </release>
9935+ <release>
9936+ <version>1.2.0RC3</version>
9937+ <date>2005-01-19</date>
9938+ <state>beta</state>
9939+ <notes>* ssl uses port 443, not 445.
9940+ </notes>
9941+ </release>
9942+ <release>
9943+ <version>1.2.0RC2</version>
9944+ <date>2005-01-11</date>
9945+ <state>beta</state>
9946+ <notes>* Handle ssl:// in the $server string. (danielc)
9947+* Also default to port 445 for ssl:// requests as well. (danielc)
9948+* Enhance debugging in the server. (danielc)
9949+ </notes>
9950+ </release>
9951+ <release>
9952+ <version>1.2.0RC1</version>
9953+ <date>2004-12-30</date>
9954+ <state>beta</state>
9955+ <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
9956+* Allow array function callbacks (Matt Kane)
9957+* Some minor speed-ups (Matt Kane)
9958+* Add Dump.php to the package (Christian Weiske)
9959+* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
9960+* Silence fsockopen() errors. Bug 1714. (danielc)
9961+* Encode empty arrays as an array. Bug 1493. (danielc)
9962+* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
9963+* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
9964+* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc)
9965+* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
9966+* Allow raiseError() to be called statically. (danielc)
9967+* Stop double escaping of character entities. Bug 987. (danielc)
9968+ NOTICE: the following have been removed:
9969+ * XML_RPC_dh()
9970+ * $GLOBALS['XML_RPC_entities']
9971+ * XML_RPC_entity_decode()
9972+ * XML_RPC_lookup_entity()
9973+* Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)
9974+ </notes>
9975+ </release>
9976+ <release>
9977+ <version>1.1.0</version>
9978+ <date>2004-03-15</date>
9979+ <state>stable</state>
9980+ <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
9981+* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
9982+* Remove &quot;require_once 'PEAR.php'&quot;, include only when needed to raise an error
9983+* Replace echo and error_log() with raiseError() (mroch)
9984+* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
9985+* be tolerant of junk after methodResponse (Luca Mariano, mroch)
9986+* Silent notice even in the error log (pierre)
9987+* fix include of shared xml extension on win32 (pierre)
9988+ </notes>
9989+ </release>
9990+ <release>
9991+ <version>1.0.4</version>
9992+ <date>2002-10-02</date>
9993+ <state>stable</state>
9994+ <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)
9995+ </notes>
9996+ </release>
9997+ <release>
9998+ <version>1.0.3</version>
9999+ <date>2002-05-19</date>
10000+ <state>stable</state>
10001+ <notes>* fix bug when parsing responses with boolean types
10002+ </notes>
10003+ </release>
10004+ <release>
10005+ <version>1.0.2</version>
10006+ <date>2002-04-16</date>
10007+ <state>stable</state>
10008+ <notes>* E_ALL fixes
10009+* fix HTTP response header parsing
10010+ </notes>
10011+ </release>
10012+ <release>
10013+ <version>1.0.1</version>
10014+ <date>2001-09-25</date>
10015+ <state>stable</state>
10016+ <notes>This is a PEAR-ified version of Useful Inc's 1.0.1 release.
10017+Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.
10018+ </notes>
10019+ </release>
10020+ </changelog>
10021+</package>
10022+
10023\ Kein Zeilenumbruch am Dateiende.
10024diff -Naur php-4.3.11/php.ini-dist hardening-patch-4.3.11-0.3.2/php.ini-dist
10025--- php-4.3.11/php.ini-dist 2005-02-14 09:26:10.000000000 +0100
10026+++ hardening-patch-4.3.11-0.3.2/php.ini-dist 2005-07-09 08:53:02.504357944 +0200
10027@@ -1109,6 +1109,177 @@
10028 ;exif.decode_jis_motorola = JIS
10029 ;exif.decode_jis_intel = JIS
10030
10031+[hardening-patch]
10032+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10033+; Hardening-Patch's logging ;
10034+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10035+
10036+;
10037+; hphp.log.syslog - Configures level for alerts reported through syslog
10038+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
10039+; hphp.log.script - Configures level for alerts reported through external script
10040+;
10041+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
10042+; Or each number up to get desired Hardening-Patch's reporting level
10043+;
10044+; S_ALL - All alerts
10045+; S_MEMORY - All canary violations and the safe unlink protection use this class
10046+; S_VARS - All variable filters trigger this class
10047+; S_FILES - All violation of uploaded files filter use this class
10048+; S_INCLUDE - The protection against malicious include filenames use this class
10049+; S_SQL - Failed SQL queries in MySQL are logged with this class
10050+; S_EXECUTOR - The execution depth protection uses this logging class
10051+; S_MISC - All other log messages (f.e. format string protection) use this class
10052+;
10053+; Example:
10054+;
10055+; - Report all alerts (except memory alerts) to the SAPI errorlog,
10056+; memory alerts through syslog and SQL+Include alerts fo the script
10057+;
10058+;hphp.log.syslog = S_MEMORY
10059+;hphp.log.sapi = S_ALL & ~S_MEMORY
10060+;hphp.log.script = S_INCLUDE | S_SQL
10061+;
10062+; Syslog logging:
10063+;
10064+; - Facility configuration: one of the following facilities
10065+;
10066+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
10067+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
10068+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
10069+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
10070+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
10071+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
10072+; LOG_PERROR
10073+;
10074+; - Priority configuration: one of the followinf priorities
10075+;
10076+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
10077+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
10078+;
10079+hphp.log.syslog.priority = LOG_ALERT
10080+hphp.log.syslog.facility = LOG_USER
10081+;
10082+; Script logging:
10083+;
10084+;hphp.log.script.name = /home/hphp/log_script
10085+;
10086+; Alert configuration:
10087+;
10088+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
10089+;
10090+;hphp.log.use-x-forwarded-for = On
10091+;
10092+
10093+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10094+; Hardening-Patch's logging ;
10095+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10096+
10097+; Execution depth limit
10098+;hphp.executor.max_depth = 8000
10099+
10100+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10101+; Hardening-Patch's REQUEST variable filters ;
10102+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10103+
10104+; Limits the number of REQUEST variables
10105+hphp.request.max_vars = 200
10106+
10107+; Limits the length of variable names (without indices)
10108+hphp.request.max_varname_length = 64
10109+
10110+; Limits the length of complete variable names (with indices)
10111+hphp.request.max_totalname_length = 256
10112+
10113+; Limits the length of array indices
10114+hphp.request.max_array_index_length = 64
10115+
10116+; Limits the depth of arrays
10117+hphp.request.max_array_depth = 100
10118+
10119+; Limits the length of variable values
10120+hphp.request.max_value_length = 65000
10121+
10122+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10123+; Hardening-Patch's COOKIE variable filters ;
10124+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10125+
10126+; Limits the number of COOKIE variables
10127+hphp.cookie.max_vars = 100
10128+
10129+; Limits the length of variable names (without indices)
10130+hphp.cookie.max_name_length = 64
10131+
10132+; Limits the length of complete variable names (with indices)
10133+hphp.cookie.max_totalname_length = 256
10134+
10135+; Limits the length of array indices
10136+hphp.cookie.max_array_index_length = 64
10137+
10138+; Limits the depth of arrays
10139+hphp.cookie.max_array_depth = 100
10140+
10141+; Limits the length of variable values
10142+hphp.cookie.max_value_length = 10000
10143+
10144+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10145+; Hardening-Patch's GET variable filters ;
10146+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10147+
10148+; Limits the number of COOKIE variables
10149+hphp.get.max_vars = 100
10150+
10151+; Limits the length of variable names (without indices)
10152+hphp.get.max_name_length = 64
10153+
10154+; Limits the length of complete variable names (with indices)
10155+hphp.get.max_totalname_length = 256
10156+
10157+; Limits the length of array indices
10158+hphp.get.max_array_index_length = 64
10159+
10160+; Limits the depth of arrays
10161+hphp.get.max_array_depth = 50
10162+
10163+; Limits the length of variable values
10164+hphp.get.max_value_length = 512
10165+
10166+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10167+; Hardening-Patch's POST variable filters ;
10168+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10169+
10170+; Limits the number of POST variables
10171+hphp.post.max_vars = 200
10172+
10173+; Limits the length of variable names (without indices)
10174+hphp.post.max_name_length = 64
10175+
10176+; Limits the length of complete variable names (with indices)
10177+hphp.post.max_totalname_length = 256
10178+
10179+; Limits the length of array indices
10180+hphp.post.max_array_index_length = 64
10181+
10182+; Limits the depth of arrays
10183+hphp.post.max_array_depth = 100
10184+
10185+; Limits the length of variable values
10186+hphp.post.max_value_length = 65000
10187+
10188+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10189+; Hardening-Patch's fileupload variable filters ;
10190+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10191+
10192+; Limits the number of uploadable files
10193+hphp.upload.max_uploads = 25
10194+
10195+; Filter out the upload of ELF executables
10196+hphp.upload.disallow_elf_files = On
10197+
10198+; External filterscript for upload verification
10199+;hphp.upload.verification_script = /home/hphp/verify_script
10200+
10201+
10202 ; Local Variables:
10203 ; tab-width: 4
10204 ; End:
10205diff -Naur php-4.3.11/php.ini-recommended hardening-patch-4.3.11-0.3.2/php.ini-recommended
10206--- php-4.3.11/php.ini-recommended 2005-02-14 09:26:10.000000000 +0100
10207+++ hardening-patch-4.3.11-0.3.2/php.ini-recommended 2005-07-09 08:53:02.505357792 +0200
10208@@ -1107,6 +1107,177 @@
10209 ;exif.decode_jis_motorola = JIS
10210 ;exif.decode_jis_intel = JIS
10211
10212+[hardening-patch]
10213+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10214+; Hardening-Patch's logging ;
10215+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10216+
10217+;
10218+; hphp.log.syslog - Configures level for alerts reported through syslog
10219+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
10220+; hphp.log.script - Configures level for alerts reported through external script
10221+;
10222+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
10223+; Or each number up to get desired Hardening-Patch's reporting level
10224+;
10225+; S_ALL - All alerts
10226+; S_MEMORY - All canary violations and the safe unlink protection use this class
10227+; S_VARS - All variable filters trigger this class
10228+; S_FILES - All violation of uploaded files filter use this class
10229+; S_INCLUDE - The protection against malicious include filenames use this class
10230+; S_SQL - Failed SQL queries in MySQL are logged with this class
10231+; S_EXECUTOR - The execution depth protection uses this logging class
10232+; S_MISC - All other log messages (f.e. format string protection) use this class
10233+;
10234+; Example:
10235+;
10236+; - Report all alerts (except memory alerts) to the SAPI errorlog,
10237+; memory alerts through syslog and SQL+Include alerts fo the script
10238+;
10239+;hphp.log.syslog = S_MEMORY
10240+;hphp.log.sapi = S_ALL & ~S_MEMORY
10241+;hphp.log.script = S_INCLUDE | S_SQL
10242+;
10243+; Syslog logging:
10244+;
10245+; - Facility configuration: one of the following facilities
10246+;
10247+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
10248+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
10249+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
10250+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
10251+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
10252+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
10253+; LOG_PERROR
10254+;
10255+; - Priority configuration: one of the followinf priorities
10256+;
10257+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
10258+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
10259+;
10260+hphp.log.syslog.priority = LOG_ALERT
10261+hphp.log.syslog.facility = LOG_USER
10262+;
10263+; Script logging:
10264+;
10265+;hphp.log.script.name = /home/hphp/log_script
10266+;
10267+; Alert configuration:
10268+;
10269+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
10270+;
10271+;hphp.log.use-x-forwarded-for = On
10272+;
10273+
10274+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10275+; Hardening-Patch's logging ;
10276+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10277+
10278+; Execution depth limit
10279+;hphp.executor.max_depth = 8000
10280+
10281+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10282+; Hardening-Patch's REQUEST variable filters ;
10283+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10284+
10285+; Limits the number of REQUEST variables
10286+hphp.request.max_vars = 200
10287+
10288+; Limits the length of variable names (without indices)
10289+hphp.request.max_varname_length = 64
10290+
10291+; Limits the length of complete variable names (with indices)
10292+hphp.request.max_totalname_length = 256
10293+
10294+; Limits the length of array indices
10295+hphp.request.max_array_index_length = 64
10296+
10297+; Limits the depth of arrays
10298+hphp.request.max_array_depth = 100
10299+
10300+; Limits the length of variable values
10301+hphp.request.max_value_length = 65000
10302+
10303+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10304+; Hardening-Patch's COOKIE variable filters ;
10305+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10306+
10307+; Limits the number of COOKIE variables
10308+hphp.cookie.max_vars = 100
10309+
10310+; Limits the length of variable names (without indices)
10311+hphp.cookie.max_name_length = 64
10312+
10313+; Limits the length of complete variable names (with indices)
10314+hphp.cookie.max_totalname_length = 256
10315+
10316+; Limits the length of array indices
10317+hphp.cookie.max_array_index_length = 64
10318+
10319+; Limits the depth of arrays
10320+hphp.cookie.max_array_depth = 100
10321+
10322+; Limits the length of variable values
10323+hphp.cookie.max_value_length = 10000
10324+
10325+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10326+; Hardening-Patch's GET variable filters ;
10327+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10328+
10329+; Limits the number of COOKIE variables
10330+hphp.get.max_vars = 100
10331+
10332+; Limits the length of variable names (without indices)
10333+hphp.get.max_name_length = 64
10334+
10335+; Limits the length of complete variable names (with indices)
10336+hphp.get.max_totalname_length = 256
10337+
10338+; Limits the length of array indices
10339+hphp.get.max_array_index_length = 64
10340+
10341+; Limits the depth of arrays
10342+hphp.get.max_array_depth = 50
10343+
10344+; Limits the length of variable values
10345+hphp.get.max_value_length = 512
10346+
10347+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10348+; Hardening-Patch's POST variable filters ;
10349+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10350+
10351+; Limits the number of POST variables
10352+hphp.post.max_vars = 200
10353+
10354+; Limits the length of variable names (without indices)
10355+hphp.post.max_name_length = 64
10356+
10357+; Limits the length of complete variable names (with indices)
10358+hphp.post.max_totalname_length = 256
10359+
10360+; Limits the length of array indices
10361+hphp.post.max_array_index_length = 64
10362+
10363+; Limits the depth of arrays
10364+hphp.post.max_array_depth = 100
10365+
10366+; Limits the length of variable values
10367+hphp.post.max_value_length = 65000
10368+
10369+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10370+; Hardening-Patch's fileupload variable filters ;
10371+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10372+
10373+; Limits the number of uploadable files
10374+hphp.upload.max_uploads = 25
10375+
10376+; Filter out the upload of ELF executables
10377+hphp.upload.disallow_elf_files = On
10378+
10379+; External filterscript for upload verification
10380+;hphp.upload.verification_script = /home/hphp/verify_script
10381+
10382+
10383 ; Local Variables:
10384 ; tab-width: 4
10385 ; End:
10386diff -Naur php-4.3.11/README.input_filter hardening-patch-4.3.11-0.3.2/README.input_filter
10387--- php-4.3.11/README.input_filter 1970-01-01 01:00:00.000000000 +0100
10388+++ hardening-patch-4.3.11-0.3.2/README.input_filter 2005-07-09 08:53:02.506357640 +0200
10389@@ -0,0 +1,193 @@
10390+Input Filter Support ported from PHP 5
10391+--------------------------------------
10392+
10393+XSS (Cross Site Scripting) hacks are becoming more and more prevalent,
10394+and can be quite difficult to prevent. Whenever you accept user data
10395+and somehow display this data back to users, you are likely vulnerable
10396+to XSS hacks.
10397+
10398+The Input Filter support in PHP 5 is aimed at providing the framework
10399+through which a company-wide or site-wide security policy can be
10400+enforced. It is implemented as a SAPI hook and is called from the
10401+treat_data and post handler functions. To implement your own security
10402+policy you will need to write a standard PHP extension.
10403+
10404+A simple implementation might look like the following. This stores the
10405+original raw user data and adds a my_get_raw() function while the normal
10406+$_POST, $_GET and $_COOKIE arrays are only populated with stripped
10407+data. In this simple example all I am doing is calling strip_tags() on
10408+the data. If register_globals is turned on, the default globals that
10409+are created will be stripped ($foo) while a $RAW_foo is created with the
10410+original user input.
10411+
10412+ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
10413+ zval *post_array;
10414+ zval *get_array;
10415+ zval *cookie_array;
10416+ZEND_END_MODULE_GLOBALS(my_input_filter)
10417+
10418+#ifdef ZTS
10419+#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
10420+#else
10421+#define IF_G(v) (my_input_filter_globals.v)
10422+#endif
10423+
10424+ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)
10425+
10426+function_entry my_input_filter_functions[] = {
10427+ PHP_FE(my_get_raw, NULL)
10428+ {NULL, NULL, NULL}
10429+};
10430+
10431+zend_module_entry my_input_filter_module_entry = {
10432+ STANDARD_MODULE_HEADER,
10433+ "my_input_filter",
10434+ my_input_filter_functions,
10435+ PHP_MINIT(my_input_filter),
10436+ PHP_MSHUTDOWN(my_input_filter),
10437+ NULL,
10438+ PHP_RSHUTDOWN(my_input_filter),
10439+ PHP_MINFO(my_input_filter),
10440+ "0.1",
10441+ STANDARD_MODULE_PROPERTIES
10442+};
10443+
10444+PHP_MINIT_FUNCTION(my_input_filter)
10445+{
10446+ ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);
10447+
10448+ REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
10449+ REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
10450+ REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
10451+
10452+ sapi_register_input_filter(my_sapi_input_filter);
10453+ return SUCCESS;
10454+}
10455+
10456+PHP_RSHUTDOWN_FUNCTION(my_input_filter)
10457+{
10458+ if(IF_G(get_array)) {
10459+ zval_ptr_dtor(&IF_G(get_array));
10460+ IF_G(get_array) = NULL;
10461+ }
10462+ if(IF_G(post_array)) {
10463+ zval_ptr_dtor(&IF_G(post_array));
10464+ IF_G(post_array) = NULL;
10465+ }
10466+ if(IF_G(cookie_array)) {
10467+ zval_ptr_dtor(&IF_G(cookie_array));
10468+ IF_G(cookie_array) = NULL;
10469+ }
10470+ return SUCCESS;
10471+}
10472+
10473+PHP_MINFO_FUNCTION(my_input_filter)
10474+{
10475+ php_info_print_table_start();
10476+ php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
10477+ php_info_print_table_row( 2, "Revision", "$Revision: 1.1 $");
10478+ php_info_print_table_end();
10479+}
10480+
10481+/* The filter handler. If you return 1 from it, then PHP also registers the
10482+ * (modified) variable. Returning 0 prevents PHP from registering the variable;
10483+ * you can use this if your filter already registers the variable under a
10484+ * different name, or if you just don't want the variable registered at all. */
10485+SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter)
10486+{
10487+ zval new_var;
10488+ zval *array_ptr = NULL;
10489+ char *raw_var;
10490+ int var_len;
10491+
10492+ assert(*val != NULL);
10493+
10494+ switch(arg) {
10495+ case PARSE_GET:
10496+ if(!IF_G(get_array)) {
10497+ ALLOC_ZVAL(array_ptr);
10498+ array_init(array_ptr);
10499+ INIT_PZVAL(array_ptr);
10500+ }
10501+ IF_G(get_array) = array_ptr;
10502+ break;
10503+ case PARSE_POST:
10504+ if(!IF_G(post_array)) {
10505+ ALLOC_ZVAL(array_ptr);
10506+ array_init(array_ptr);
10507+ INIT_PZVAL(array_ptr);
10508+ }
10509+ IF_G(post_array) = array_ptr;
10510+ break;
10511+ case PARSE_COOKIE:
10512+ if(!IF_G(cookie_array)) {
10513+ ALLOC_ZVAL(array_ptr);
10514+ array_init(array_ptr);
10515+ INIT_PZVAL(array_ptr);
10516+ }
10517+ IF_G(cookie_array) = array_ptr;
10518+ break;
10519+ }
10520+ Z_STRLEN(new_var) = val_len;
10521+ Z_STRVAL(new_var) = estrndup(*val, val_len);
10522+ Z_TYPE(new_var) = IS_STRING;
10523+
10524+ var_len = strlen(var);
10525+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
10526+ strcpy(raw_var, "RAW_");
10527+ strlcat(raw_var,var,var_len+5);
10528+
10529+ php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);
10530+
10531+ php_strip_tags(*val, val_len, NULL, NULL, 0);
10532+
10533+ *new_val_len = strlen(*val);
10534+ return 1;
10535+}
10536+
10537+PHP_FUNCTION(my_get_raw)
10538+{
10539+ long arg;
10540+ char *var;
10541+ int var_len;
10542+ zval **tmp;
10543+ zval *array_ptr = NULL;
10544+ HashTable *hash_ptr;
10545+ char *raw_var;
10546+
10547+ if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
10548+ return;
10549+ }
10550+
10551+ switch(arg) {
10552+ case PARSE_GET:
10553+ array_ptr = IF_G(get_array);
10554+ break;
10555+ case PARSE_POST:
10556+ array_ptr = IF_G(post_array);
10557+ break;
10558+ case PARSE_COOKIE:
10559+ array_ptr = IF_G(post_array);
10560+ break;
10561+ }
10562+
10563+ if(!array_ptr) RETURN_FALSE;
10564+
10565+ /*
10566+ * I'm changing the variable name here because when running with register_globals on,
10567+ * the variable will end up in the global symbol table
10568+ */
10569+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
10570+ strcpy(raw_var, "RAW_");
10571+ strlcat(raw_var,var,var_len+5);
10572+ hash_ptr = HASH_OF(array_ptr);
10573+
10574+ if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
10575+ *return_value = **tmp;
10576+ zval_copy_ctor(return_value);
10577+ } else {
10578+ RETVAL_FALSE;
10579+ }
10580+ efree(raw_var);
10581+}
10582+
10583diff -Naur php-4.3.11/sapi/apache/mod_php4.c hardening-patch-4.3.11-0.3.2/sapi/apache/mod_php4.c
10584--- php-4.3.11/sapi/apache/mod_php4.c 2004-07-21 18:25:28.000000000 +0200
10585+++ hardening-patch-4.3.11-0.3.2/sapi/apache/mod_php4.c 2005-07-09 08:53:02.507357488 +0200
10586@@ -446,7 +446,7 @@
10587 sapi_apache_get_fd,
10588 sapi_apache_force_http_10,
10589 sapi_apache_get_target_uid,
10590- sapi_apache_get_target_gid
10591+ sapi_apache_get_target_gid,
10592 };
10593 /* }}} */
10594
10595@@ -892,7 +892,11 @@
10596 {
10597 TSRMLS_FETCH();
10598 if (PG(expose_php)) {
10599+#if HARDENING_PATCH
10600+ ap_add_version_component("PHP/" PHP_VERSION " with Hardening-Patch");
10601+#else
10602 ap_add_version_component("PHP/" PHP_VERSION);
10603+#endif
10604 }
10605 }
10606 #endif
10607diff -Naur php-4.3.11/sapi/apache2filter/sapi_apache2.c hardening-patch-4.3.11-0.3.2/sapi/apache2filter/sapi_apache2.c
10608--- php-4.3.11/sapi/apache2filter/sapi_apache2.c 2005-01-07 07:28:36.000000000 +0100
10609+++ hardening-patch-4.3.11-0.3.2/sapi/apache2filter/sapi_apache2.c 2005-07-09 08:53:02.507357488 +0200
10610@@ -563,7 +563,11 @@
10611 {
10612 TSRMLS_FETCH();
10613 if (PG(expose_php)) {
10614+#if HARDENING_PATCH
10615+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
10616+#else
10617 ap_add_version_component(p, "PHP/" PHP_VERSION);
10618+#endif
10619 }
10620 }
10621
10622diff -Naur php-4.3.11/sapi/apache2handler/sapi_apache2.c hardening-patch-4.3.11-0.3.2/sapi/apache2handler/sapi_apache2.c
10623--- php-4.3.11/sapi/apache2handler/sapi_apache2.c 2005-03-10 12:39:04.000000000 +0100
10624+++ hardening-patch-4.3.11-0.3.2/sapi/apache2handler/sapi_apache2.c 2005-07-09 08:53:02.508357336 +0200
10625@@ -345,7 +345,11 @@
10626 {
10627 TSRMLS_FETCH();
10628 if (PG(expose_php)) {
10629+#if HARDENING_PATCH
10630+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
10631+#else
10632 ap_add_version_component(p, "PHP/" PHP_VERSION);
10633+#endif
10634 }
10635 }
10636
10637diff -Naur php-4.3.11/sapi/cgi/cgi_main.c hardening-patch-4.3.11-0.3.2/sapi/cgi/cgi_main.c
10638--- php-4.3.11/sapi/cgi/cgi_main.c 2005-02-11 03:12:30.000000000 +0100
10639+++ hardening-patch-4.3.11-0.3.2/sapi/cgi/cgi_main.c 2005-07-09 08:53:02.509357184 +0200
10640@@ -1435,11 +1435,19 @@
10641 SG(headers_sent) = 1;
10642 SG(request_info).no_headers = 1;
10643 }
10644+#if HARDENING_PATCH
10645+#if ZEND_DEBUG
10646+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10647+#else
10648+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10649+#endif
10650+#else
10651 #if ZEND_DEBUG
10652 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10653 #else
10654 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10655 #endif
10656+#endif
10657 php_end_ob_buffers(1 TSRMLS_CC);
10658 exit(1);
10659 break;
10660diff -Naur php-4.3.11/sapi/cli/php_cli.c hardening-patch-4.3.11-0.3.2/sapi/cli/php_cli.c
10661--- php-4.3.11/sapi/cli/php_cli.c 2005-03-22 16:09:36.000000000 +0100
10662+++ hardening-patch-4.3.11-0.3.2/sapi/cli/php_cli.c 2005-07-09 08:53:02.510357032 +0200
10663@@ -652,11 +652,19 @@
10664 if (php_request_startup(TSRMLS_C)==FAILURE) {
10665 goto err;
10666 }
10667+#if HARDENING_PATCH
10668+#if ZEND_DEBUG
10669+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10670+#else
10671+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10672+#endif
10673+#else
10674 #if ZEND_DEBUG
10675 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10676 #else
10677 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10678 #endif
10679+#endif
10680 php_end_ob_buffers(1 TSRMLS_CC);
10681 exit_status=1;
10682 goto out;
10683diff -Naur php-4.3.11/TSRM/TSRM.h hardening-patch-4.3.11-0.3.2/TSRM/TSRM.h
10684--- php-4.3.11/TSRM/TSRM.h 2005-02-11 04:34:04.000000000 +0100
10685+++ hardening-patch-4.3.11-0.3.2/TSRM/TSRM.h 2005-07-09 08:53:02.510357032 +0200
10686@@ -33,6 +33,13 @@
10687 # define TSRM_API
10688 #endif
10689
10690+#if HARDENING_PATCH
10691+# if HAVE_REALPATH
10692+# undef realpath
10693+# define realpath php_realpath
10694+# endif
10695+#endif
10696+
10697 /* Only compile multi-threading functions if we're in ZTS mode */
10698 #ifdef ZTS
10699
10700@@ -90,6 +97,7 @@
10701
10702 #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
10703
10704+
10705 #ifdef __cplusplus
10706 extern "C" {
10707 #endif
10708diff -Naur php-4.3.11/TSRM/tsrm_virtual_cwd.c hardening-patch-4.3.11-0.3.2/TSRM/tsrm_virtual_cwd.c
10709--- php-4.3.11/TSRM/tsrm_virtual_cwd.c 2005-02-11 04:34:04.000000000 +0100
10710+++ hardening-patch-4.3.11-0.3.2/TSRM/tsrm_virtual_cwd.c 2005-07-09 08:53:02.511356880 +0200
10711@@ -192,6 +192,165 @@
10712 return p;
10713 }
10714
10715+#if HARDENING_PATCH
10716+CWD_API char *php_realpath(const char *path, char *resolved)
10717+{
10718+ struct stat sb;
10719+ char *p, *q, *s;
10720+ size_t left_len, resolved_len;
10721+ unsigned symlinks;
10722+ int serrno, slen;
10723+ int is_dir = 1;
10724+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
10725+
10726+ serrno = errno;
10727+ symlinks = 0;
10728+ if (path[0] == '/') {
10729+ resolved[0] = '/';
10730+ resolved[1] = '\0';
10731+ if (path[1] == '\0')
10732+ return (resolved);
10733+ resolved_len = 1;
10734+ left_len = strlcpy(left, path + 1, sizeof(left));
10735+ } else {
10736+ if (getcwd(resolved, PATH_MAX) == NULL) {
10737+ strlcpy(resolved, ".", PATH_MAX);
10738+ return (NULL);
10739+ }
10740+ resolved_len = strlen(resolved);
10741+ left_len = strlcpy(left, path, sizeof(left));
10742+ }
10743+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
10744+ errno = ENAMETOOLONG;
10745+ return (NULL);
10746+ }
10747+
10748+ /*
10749+ * Iterate over path components in `left'.
10750+ */
10751+ while (left_len != 0) {
10752+ /*
10753+ * Extract the next path component and adjust `left'
10754+ * and its length.
10755+ */
10756+ p = strchr(left, '/');
10757+ s = p ? p : left + left_len;
10758+ if (s - left >= sizeof(next_token)) {
10759+ errno = ENAMETOOLONG;
10760+ return (NULL);
10761+ }
10762+ memcpy(next_token, left, s - left);
10763+ next_token[s - left] = '\0';
10764+ left_len -= s - left;
10765+ if (p != NULL)
10766+ memmove(left, s + 1, left_len + 1);
10767+ if (resolved[resolved_len - 1] != '/') {
10768+ if (resolved_len + 1 >= PATH_MAX) {
10769+ errno = ENAMETOOLONG;
10770+ return (NULL);
10771+ }
10772+ resolved[resolved_len++] = '/';
10773+ resolved[resolved_len] = '\0';
10774+ }
10775+ if (next_token[0] == '\0')
10776+ continue;
10777+ else if (strcmp(next_token, ".") == 0)
10778+ continue;
10779+ else if (strcmp(next_token, "..") == 0) {
10780+ /*
10781+ * Strip the last path component except when we have
10782+ * single "/"
10783+ */
10784+ if (!is_dir) {
10785+ errno = ENOENT;
10786+ return (NULL);
10787+ }
10788+ if (resolved_len > 1) {
10789+ resolved[resolved_len - 1] = '\0';
10790+ q = strrchr(resolved, '/');
10791+ *q = '\0';
10792+ resolved_len = q - resolved;
10793+ }
10794+ continue;
10795+ }
10796+
10797+ /*
10798+ * Append the next path component and lstat() it. If
10799+ * lstat() fails we still can return successfully if
10800+ * there are no more path components left.
10801+ */
10802+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
10803+ if (resolved_len >= PATH_MAX) {
10804+ errno = ENAMETOOLONG;
10805+ return (NULL);
10806+ }
10807+ if (lstat(resolved, &sb) != 0) {
10808+ if (errno == ENOENT && p == NULL) {
10809+ errno = serrno;
10810+ return (resolved);
10811+ }
10812+ return (NULL);
10813+ }
10814+ if (S_ISLNK(sb.st_mode)) {
10815+ if (symlinks++ > MAXSYMLINKS) {
10816+ errno = ELOOP;
10817+ return (NULL);
10818+ }
10819+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
10820+ if (slen < 0)
10821+ return (NULL);
10822+ symlink[slen] = '\0';
10823+ if (symlink[0] == '/') {
10824+ resolved[1] = 0;
10825+ resolved_len = 1;
10826+ } else if (resolved_len > 1) {
10827+ /* Strip the last path component. */
10828+ resolved[resolved_len - 1] = '\0';
10829+ q = strrchr(resolved, '/');
10830+ *q = '\0';
10831+ resolved_len = q - resolved;
10832+ }
10833+
10834+ /*
10835+ * If there are any path components left, then
10836+ * append them to symlink. The result is placed
10837+ * in `left'.
10838+ */
10839+ if (p != NULL) {
10840+ if (symlink[slen - 1] != '/') {
10841+ if (slen + 1 >= sizeof(symlink)) {
10842+ errno = ENAMETOOLONG;
10843+ return (NULL);
10844+ }
10845+ symlink[slen] = '/';
10846+ symlink[slen + 1] = 0;
10847+ }
10848+ left_len = strlcat(symlink, left, sizeof(left));
10849+ if (left_len >= sizeof(left)) {
10850+ errno = ENAMETOOLONG;
10851+ return (NULL);
10852+ }
10853+ }
10854+ left_len = strlcpy(left, symlink, sizeof(left));
10855+ } else {
10856+ if (S_ISDIR(sb.st_mode)) {
10857+ is_dir = 1;
10858+ } else {
10859+ is_dir = 0;
10860+ }
10861+ }
10862+ }
10863+
10864+ /*
10865+ * Remove trailing slash except when the resolved pathname
10866+ * is a single "/".
10867+ */
10868+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
10869+ resolved[resolved_len - 1] = '\0';
10870+ return (resolved);
10871+}
10872+#endif
10873+
10874 CWD_API void virtual_cwd_startup(void)
10875 {
10876 char cwd[MAXPATHLEN];
10877@@ -314,8 +473,7 @@
10878 path = resolved_path;
10879 path_length = strlen(path);
10880 } else {
10881- /* disable for now
10882- return 1; */
10883+ return 1;
10884 }
10885 }
10886 } else { /* Concat current directory with relative path and then run realpath() on it */
10887@@ -341,9 +499,8 @@
10888 path = resolved_path;
10889 path_length = strlen(path);
10890 } else {
10891- /* disable for now
10892 free(tmp);
10893- return 1; */
10894+ return 1;
10895 }
10896 }
10897 free(tmp);
10898diff -Naur php-4.3.11/TSRM/tsrm_virtual_cwd.h hardening-patch-4.3.11-0.3.2/TSRM/tsrm_virtual_cwd.h
10899--- php-4.3.11/TSRM/tsrm_virtual_cwd.h 2005-02-11 04:34:04.000000000 +0100
10900+++ hardening-patch-4.3.11-0.3.2/TSRM/tsrm_virtual_cwd.h 2005-07-09 08:53:02.511356880 +0200
10901@@ -128,6 +128,22 @@
10902
10903 typedef int (*verify_path_func)(const cwd_state *);
10904
10905+#ifndef HAVE_STRLCPY
10906+CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz);
10907+#undef strlcpy
10908+#define strlcpy php_strlcpy
10909+#endif
10910+
10911+#ifndef HAVE_STRLCAT
10912+CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz);
10913+#undef strlcat
10914+#define strlcat php_strlcat
10915+#endif
10916+
10917+
10918+#if HARDENING_PATCH
10919+CWD_API char *php_realpath(const char *path, char *resolved);
10920+#endif
10921 CWD_API void virtual_cwd_startup(void);
10922 CWD_API void virtual_cwd_shutdown(void);
10923 CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC);
10924diff -Naur php-4.3.11/Zend/zend_alloc.c hardening-patch-4.3.11-0.3.2/Zend/zend_alloc.c
10925--- php-4.3.11/Zend/zend_alloc.c 2004-08-27 18:51:25.000000000 +0200
10926+++ hardening-patch-4.3.11-0.3.2/Zend/zend_alloc.c 2005-07-09 08:53:02.512356728 +0200
10927@@ -56,6 +56,11 @@
10928 # define END_MAGIC_SIZE 0
10929 #endif
10930
10931+#if HARDENING_PATCH_MM_PROTECT
10932+# define CANARY_SIZE sizeof(unsigned int)
10933+#else
10934+# define CANARY_SIZE 0
10935+#endif
10936
10937 # if MEMORY_LIMIT
10938 # if ZEND_DEBUG
10939@@ -95,9 +100,17 @@
10940 if (p==AG(head)) { \
10941 AG(head) = p->pNext; \
10942 } else { \
10943+ if (p != p->pLast->pNext) { \
10944+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
10945+ exit(1); \
10946+ } \
10947 p->pLast->pNext = p->pNext; \
10948 } \
10949 if (p->pNext) { \
10950+ if (p != p->pNext->pLast) { \
10951+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
10952+ exit(1); \
10953+ } \
10954 p->pNext->pLast = p->pLast; \
10955 }
10956
10957@@ -129,6 +142,12 @@
10958 DECLARE_CACHE_VARS();
10959 TSRMLS_FETCH();
10960
10961+#if HARDENING_PATCH_MM_PROTECT
10962+ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) {
10963+ zend_security_log(S_MEMORY, "emalloc() - requested size would result in integer overflow");
10964+ exit(1);
10965+ }
10966+#endif
10967 CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);
10968
10969 if (!ZEND_DISABLE_MEMORY_CACHE && (CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] > 0)) {
10970@@ -146,6 +165,10 @@
10971 AG(cache_stats)[CACHE_INDEX][1]++;
10972 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
10973 #endif
10974+#if HARDENING_PATCH_MM_PROTECT
10975+ p->canary = HG(canary_1);
10976+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
10977+#endif
10978 p->cached = 0;
10979 p->size = size;
10980 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
10981@@ -161,7 +184,7 @@
10982 AG(allocated_memory_peak) = AG(allocated_memory);
10983 }
10984 #endif
10985- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE);
10986+ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE);
10987 }
10988
10989 HANDLE_BLOCK_INTERRUPTIONS();
10990@@ -191,7 +214,10 @@
10991 # endif
10992 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
10993 #endif
10994-
10995+#if HARDENING_PATCH_MM_PROTECT
10996+ p->canary = HG(canary_1);
10997+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
10998+#endif
10999 HANDLE_UNBLOCK_INTERRUPTIONS();
11000 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
11001 }
11002@@ -218,17 +244,33 @@
11003 return emalloc_rel(lval + offset);
11004 }
11005 }
11006-
11007+
11008+#if HARDENING_PATCH
11009+ zend_security_log(S_MEMORY, "Possible integer overflow catched by safe_emalloc()");
11010+#endif
11011 zend_error(E_ERROR, "Possible integer overflow in memory allocation (%ld * %ld + %ld)", nmemb, size, offset);
11012 return 0;
11013 }
11014
11015 ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
11016 {
11017+#if HARDENING_PATCH_MM_PROTECT
11018+ unsigned int *canary_2;
11019+#endif
11020 zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING);
11021 DECLARE_CACHE_VARS();
11022 TSRMLS_FETCH();
11023
11024+#if HARDENING_PATCH_MM_PROTECT
11025+ canary_2 = (unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
11026+ if (p->canary != HG(canary_1) || *canary_2 != HG(canary_2)) {
11027+ zend_security_log(S_MEMORY, "canary mismatch on efree() - heap overflow or double efree detected");
11028+ exit(1);
11029+ }
11030+ /* to catch double efree()s */
11031+ *canary_2 = p->canary = 0;
11032+#endif
11033+
11034 #if defined(ZTS) && TSRM_DEBUG
11035 if (p->thread_id != tsrm_thread_id()) {
11036 tsrm_error(TSRM_ERROR_LEVEL_ERROR, "Memory block allocated at %s:(%d) on thread %x freed at %s:(%d) on thread %x, ignoring",
11037@@ -273,6 +315,9 @@
11038 size_t _size = nmemb * size;
11039
11040 if (nmemb && (_size/nmemb!=size)) {
11041+#if HARDENING_PATCH
11042+ zend_security_log(S_MEMORY, "Possible integer overflow catched by ecalloc()");
11043+#endif
11044 fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size);
11045 #if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID
11046 kill(getpid(), SIGSEGV);
11047@@ -292,6 +337,9 @@
11048
11049 ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
11050 {
11051+#if HARDENING_PATCH_MM_PROTECT
11052+ unsigned int canary_2;
11053+#endif
11054 zend_mem_header *p;
11055 zend_mem_header *orig;
11056 DECLARE_CACHE_VARS();
11057@@ -303,6 +351,14 @@
11058
11059 p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING);
11060
11061+#if HARDENING_PATCH_MM_PROTECT
11062+ canary_2 = *(unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
11063+ if (p->canary != HG(canary_1) || canary_2 != HG(canary_2)) {
11064+ zend_security_log(S_MEMORY, "canary mismatch on erealloc() - heap overflow detected");
11065+ exit(1);
11066+ }
11067+#endif
11068+
11069 #if defined(ZTS) && TSRM_DEBUG
11070 if (p->thread_id != tsrm_thread_id()) {
11071 void *new_p;
11072@@ -326,7 +382,7 @@
11073 }
11074 #endif
11075 REMOVE_POINTER_FROM_LIST(p);
11076- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE);
11077+ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE);
11078 if (!p) {
11079 if (!allow_failure) {
11080 fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size);
11081@@ -348,6 +404,9 @@
11082 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
11083 #endif
11084
11085+#if HARDENING_PATCH_MM_PROTECT
11086+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
11087+#endif
11088 p->size = size;
11089
11090 HANDLE_UNBLOCK_INTERRUPTIONS();
11091@@ -423,6 +482,10 @@
11092 {
11093 AG(head) = NULL;
11094
11095+#if HARDENING_PATCH_MM_PROTECT
11096+ HG(canary_1) = zend_canary();
11097+ HG(canary_2) = zend_canary();
11098+#endif
11099 #if MEMORY_LIMIT
11100 AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */
11101 AG(allocated_memory) = 0;
11102diff -Naur php-4.3.11/Zend/zend_alloc.h hardening-patch-4.3.11-0.3.2/Zend/zend_alloc.h
11103--- php-4.3.11/Zend/zend_alloc.h 2004-08-11 08:10:46.000000000 +0200
11104+++ hardening-patch-4.3.11-0.3.2/Zend/zend_alloc.h 2005-07-09 08:53:02.513356576 +0200
11105@@ -32,6 +32,9 @@
11106 #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL
11107
11108 typedef struct _zend_mem_header {
11109+#if HARDENING_PATCH_MM_PROTECT
11110+ unsigned int canary;
11111+#endif
11112 #if ZEND_DEBUG
11113 long magic;
11114 char *filename;
11115diff -Naur php-4.3.11/Zend/zend_builtin_functions.c hardening-patch-4.3.11-0.3.2/Zend/zend_builtin_functions.c
11116--- php-4.3.11/Zend/zend_builtin_functions.c 2004-12-27 20:28:35.000000000 +0100
11117+++ hardening-patch-4.3.11-0.3.2/Zend/zend_builtin_functions.c 2005-07-09 08:53:02.514356424 +0200
11118@@ -49,6 +49,9 @@
11119 static ZEND_FUNCTION(crash);
11120 #endif
11121 #endif
11122+#if HARDENING_PATCH_MM_PROTECT_DEBUG
11123+static ZEND_FUNCTION(heap_overflow);
11124+#endif
11125 static ZEND_FUNCTION(get_included_files);
11126 static ZEND_FUNCTION(is_subclass_of);
11127 static ZEND_FUNCTION(is_a);
11128@@ -101,6 +104,9 @@
11129 ZEND_FE(crash, NULL)
11130 #endif
11131 #endif
11132+#if HARDENING_PATCH_MM_PROTECT_DEBUG
11133+ ZEND_FE(heap_overflow, NULL)
11134+#endif
11135 ZEND_FE(get_included_files, NULL)
11136 ZEND_FALIAS(get_required_files, get_included_files, NULL)
11137 ZEND_FE(is_subclass_of, NULL)
11138@@ -805,6 +811,19 @@
11139
11140 #endif /* ZEND_DEBUG */
11141
11142+
11143+#if HARDENING_PATCH_MM_PROTECT_DEBUG
11144+ZEND_FUNCTION(heap_overflow)
11145+{
11146+ char *nowhere = emalloc(10);
11147+
11148+ memcpy(nowhere, "something1234567890", sizeof("something1234567890"));
11149+
11150+ efree(nowhere);
11151+}
11152+#endif
11153+
11154+
11155 /* {{{ proto array get_included_files(void)
11156 Returns an array with the file names that were include_once()'d */
11157 ZEND_FUNCTION(get_included_files)
11158diff -Naur php-4.3.11/Zend/zend.c hardening-patch-4.3.11-0.3.2/Zend/zend.c
11159--- php-4.3.11/Zend/zend.c 2005-01-22 21:36:34.000000000 +0100
11160+++ hardening-patch-4.3.11-0.3.2/Zend/zend.c 2005-07-09 08:53:02.514356424 +0200
11161@@ -53,6 +53,12 @@
11162 ZEND_API void (*zend_unblock_interruptions)(void);
11163 ZEND_API void (*zend_ticks_function)(int ticks);
11164 ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
11165+#if HARDENING_PATCH
11166+ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
11167+#endif
11168+#if HARDENING_PATCH_INC_PROTECT
11169+ZEND_API int (*zend_is_valid_include)(zval *z);
11170+#endif
11171
11172 void (*zend_on_timeout)(int seconds TSRMLS_DC);
11173
11174@@ -70,9 +76,80 @@
11175 return SUCCESS;
11176 }
11177
11178+#if HARDENING_PATCH
11179+static ZEND_INI_MH(OnUpdateHPHP_log_syslog)
11180+{
11181+ if (!new_value) {
11182+ EG(hphp_log_syslog) = S_ALL & ~S_SQL | S_MEMORY;
11183+ } else {
11184+ EG(hphp_log_syslog) = atoi(new_value) | S_MEMORY;
11185+ }
11186+ return SUCCESS;
11187+}
11188+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_facility)
11189+{
11190+ if (!new_value) {
11191+ EG(hphp_log_syslog_facility) = LOG_USER;
11192+ } else {
11193+ EG(hphp_log_syslog_facility) = atoi(new_value);
11194+ }
11195+ return SUCCESS;
11196+}
11197+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_priority)
11198+{
11199+ if (!new_value) {
11200+ EG(hphp_log_syslog_priority) = LOG_ALERT;
11201+ } else {
11202+ EG(hphp_log_syslog_priority) = atoi(new_value);
11203+ }
11204+ return SUCCESS;
11205+}
11206+static ZEND_INI_MH(OnUpdateHPHP_log_sapi)
11207+{
11208+ if (!new_value) {
11209+ EG(hphp_log_sapi) = S_ALL & ~S_SQL;
11210+ } else {
11211+ EG(hphp_log_sapi) = atoi(new_value);
11212+ }
11213+ return SUCCESS;
11214+}
11215+static ZEND_INI_MH(OnUpdateHPHP_log_script)
11216+{
11217+ if (!new_value) {
11218+ EG(hphp_log_script) = S_ALL & ~S_MEMORY;
11219+ } else {
11220+ EG(hphp_log_script) = atoi(new_value) & ~S_MEMORY;
11221+ }
11222+ return SUCCESS;
11223+}
11224+static ZEND_INI_MH(OnUpdateHPHP_log_scriptname)
11225+{
11226+ if (!new_value) {
11227+ EG(hphp_log_scriptname) = NULL;
11228+ } else {
11229+ if (EG(hphp_log_scriptname)) {
11230+ pefree(EG(hphp_log_scriptname),1);
11231+ }
11232+ EG(hphp_log_scriptname) = pestrdup(new_value,1);
11233+ }
11234+ return SUCCESS;
11235+}
11236+#endif
11237
11238 ZEND_INI_BEGIN()
11239 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
11240+#if HARDENING_PATCH
11241+ ZEND_INI_ENTRY("hphp.log.syslog", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog)
11242+ ZEND_INI_ENTRY("hphp.log.syslog.facility", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_facility)
11243+ ZEND_INI_ENTRY("hphp.log.syslog.priority", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_priority)
11244+ ZEND_INI_ENTRY("hphp.log.sapi", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_sapi)
11245+ ZEND_INI_ENTRY("hphp.log.script", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_script)
11246+ ZEND_INI_ENTRY("hphp.log.script.name", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_scriptname)
11247+ STD_ZEND_INI_BOOLEAN("hphp.log.use-x-forwarded-for", "0", ZEND_INI_SYSTEM, OnUpdateBool, hphp_log_use_x_forwarded_for, zend_executor_globals, executor_globals)
11248+ STD_ZEND_INI_ENTRY("hphp.executor.max_depth", "0", ZEND_INI_PERDIR, OnUpdateLong, hphp_executor_max_depth, zend_executor_globals, executor_globals)
11249+ STD_ZEND_INI_BOOLEAN("hphp.sql.bailout_on_error", "0", ZEND_INI_PERDIR, OnUpdateBool, hphp_sql_bailout_on_error, hardened_globals_struct, hardened_globals)
11250+ STD_ZEND_INI_BOOLEAN("hphp.multiheader", "0", ZEND_INI_PERDIR, OnUpdateBool, hphp_multiheader, hardened_globals_struct, hardened_globals)
11251+#endif
11252 ZEND_INI_END()
11253
11254
11255@@ -354,6 +431,7 @@
11256 zend_init_rsrc_plist(TSRMLS_C);
11257 EG(lambda_count)=0;
11258 EG(user_error_handler) = NULL;
11259+ EG(in_code_type) = 0;
11260 EG(in_execution) = 0;
11261 EG(current_execute_data) = NULL;
11262 }
11263@@ -420,6 +498,14 @@
11264 extern zend_scanner_globals language_scanner_globals;
11265 #endif
11266
11267+ /* Set up Hardening-Patch utility functions first */
11268+#if HARDENING_PATCH
11269+ zend_security_log = utility_functions->security_log_function;
11270+#endif
11271+#if HARDENING_PATCH_INC_PROTECT
11272+ zend_is_valid_include = utility_functions->is_valid_include;
11273+#endif
11274+
11275 #ifdef ZTS
11276 ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
11277 #else
11278@@ -623,6 +709,7 @@
11279 }
11280 CG(unclean_shutdown) = 1;
11281 CG(in_compilation) = EG(in_execution) = 0;
11282+ EG(in_code_type) = 0;
11283 EG(current_execute_data) = NULL;
11284 longjmp(EG(bailout), FAILURE);
11285 }
11286diff -Naur php-4.3.11/Zend/zend_canary.c hardening-patch-4.3.11-0.3.2/Zend/zend_canary.c
11287--- php-4.3.11/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
11288+++ hardening-patch-4.3.11-0.3.2/Zend/zend_canary.c 2005-07-09 08:53:02.515356272 +0200
11289@@ -0,0 +1,58 @@
11290+/*
11291+ +----------------------------------------------------------------------+
11292+ | Hardening-Patch for PHP |
11293+ +----------------------------------------------------------------------+
11294+ | Copyright (c) 2004-2005 Stefan Esser |
11295+ +----------------------------------------------------------------------+
11296+ | This source file is subject to version 2.02 of the PHP license, |
11297+ | that is bundled with this package in the file LICENSE, and is |
11298+ | available at through the world-wide-web at |
11299+ | http://www.php.net/license/2_02.txt. |
11300+ | If you did not receive a copy of the PHP license and are unable to |
11301+ | obtain it through the world-wide-web, please send a note to |
11302+ | license@php.net so we can mail you a copy immediately. |
11303+ +----------------------------------------------------------------------+
11304+ | Author: Stefan Esser <sesser@hardened-php.net> |
11305+ +----------------------------------------------------------------------+
11306+ */
11307+/* $Id: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */
11308+
11309+#include "zend.h"
11310+
11311+#include <stdio.h>
11312+#include <stdlib.h>
11313+
11314+
11315+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
11316+
11317+/* will be replaced later with more compatible method */
11318+ZEND_API unsigned int zend_canary()
11319+{
11320+ time_t t;
11321+ unsigned int canary;
11322+ int fd;
11323+
11324+ fd = open("/dev/urandom", 0);
11325+ if (fd != -1) {
11326+ int r = read(fd, &canary, sizeof(canary));
11327+ close(fd);
11328+ if (r == sizeof(canary)) {
11329+ return (canary);
11330+ }
11331+ }
11332+ /* not good but we never want to do this */
11333+ time(&t);
11334+ canary = *(unsigned int *)&t + getpid() << 16;
11335+ return (canary);
11336+}
11337+#endif
11338+
11339+
11340+/*
11341+ * Local variables:
11342+ * tab-width: 4
11343+ * c-basic-offset: 4
11344+ * End:
11345+ * vim600: sw=4 ts=4 fdm=marker
11346+ * vim<600: sw=4 ts=4
11347+ */
11348diff -Naur php-4.3.11/Zend/zend_compile.h hardening-patch-4.3.11-0.3.2/Zend/zend_compile.h
11349--- php-4.3.11/Zend/zend_compile.h 2004-09-24 15:15:14.000000000 +0200
11350+++ hardening-patch-4.3.11-0.3.2/Zend/zend_compile.h 2005-07-09 08:53:02.515356272 +0200
11351@@ -546,6 +546,7 @@
11352 #define ZEND_USER_FUNCTION 2
11353 #define ZEND_OVERLOADED_FUNCTION 3
11354 #define ZEND_EVAL_CODE 4
11355+#define ZEND_SANDBOX_CODE 6
11356
11357 #define ZEND_INTERNAL_CLASS 1
11358 #define ZEND_USER_CLASS 2
11359diff -Naur php-4.3.11/Zend/zend_constants.c hardening-patch-4.3.11-0.3.2/Zend/zend_constants.c
11360--- php-4.3.11/Zend/zend_constants.c 2004-07-13 21:29:45.000000000 +0200
11361+++ hardening-patch-4.3.11-0.3.2/Zend/zend_constants.c 2005-07-09 08:53:02.516356120 +0200
11362@@ -111,6 +111,72 @@
11363 REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
11364
11365 REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
11366+#if HARDENING_PATCH
11367+ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
11368+ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
11369+ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_VARS, CONST_PERSISTENT | CONST_CS);
11370+ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
11371+ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
11372+ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
11373+ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
11374+ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
11375+
11376+ /* error levels */
11377+ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
11378+ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
11379+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
11380+ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
11381+ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
11382+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
11383+ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
11384+ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
11385+ /* facility: type of program logging the message */
11386+ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
11387+ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
11388+ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
11389+ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
11390+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
11391+ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
11392+ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
11393+#ifdef LOG_NEWS
11394+ /* No LOG_NEWS on HP-UX */
11395+ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
11396+#endif
11397+#ifdef LOG_UUCP
11398+ /* No LOG_UUCP on HP-UX */
11399+ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
11400+#endif
11401+#ifdef LOG_CRON
11402+ /* apparently some systems don't have this one */
11403+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
11404+#endif
11405+#ifdef LOG_AUTHPRIV
11406+ /* AIX doesn't have LOG_AUTHPRIV */
11407+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
11408+#endif
11409+#if !defined(PHP_WIN32) && !defined(NETWARE)
11410+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
11411+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
11412+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
11413+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
11414+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
11415+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
11416+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
11417+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
11418+#endif
11419+ /* options */
11420+ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
11421+ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
11422+ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
11423+ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
11424+#ifdef LOG_NOWAIT
11425+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
11426+#endif
11427+#ifdef LOG_PERROR
11428+ /* AIX doesn't have LOG_PERROR */
11429+ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
11430+#endif
11431+#endif
11432
11433 /* true/false constants */
11434 {
11435diff -Naur php-4.3.11/Zend/zend_errors.h hardening-patch-4.3.11-0.3.2/Zend/zend_errors.h
11436--- php-4.3.11/Zend/zend_errors.h 2002-12-31 17:22:59.000000000 +0100
11437+++ hardening-patch-4.3.11-0.3.2/Zend/zend_errors.h 2005-07-09 08:53:02.516356120 +0200
11438@@ -36,5 +36,16 @@
11439 #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE)
11440 #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
11441
11442+#if HARDENING_PATCH
11443+#define S_MEMORY (1<<0L)
11444+#define S_VARS (1<<1L)
11445+#define S_FILES (1<<2L)
11446+#define S_INCLUDE (1<<3L)
11447+#define S_SQL (1<<4L)
11448+#define S_EXECUTOR (1<<5L)
11449+#define S_MISC (1<<30L)
11450+#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MISC | S_SQL | S_EXECUTOR)
11451+#endif
11452+
11453 #endif /* ZEND_ERRORS_H */
11454
11455diff -Naur php-4.3.11/Zend/zend_execute_API.c hardening-patch-4.3.11-0.3.2/Zend/zend_execute_API.c
11456--- php-4.3.11/Zend/zend_execute_API.c 2004-11-04 00:15:05.000000000 +0100
11457+++ hardening-patch-4.3.11-0.3.2/Zend/zend_execute_API.c 2005-07-09 08:53:02.517355968 +0200
11458@@ -142,6 +142,7 @@
11459 EG(class_table) = CG(class_table);
11460
11461 EG(in_execution) = 0;
11462+ EG(in_code_type) = 0;
11463
11464 zend_ptr_stack_init(&EG(argument_stack));
11465
11466@@ -431,12 +432,14 @@
11467 zend_execute_data execute_data;
11468
11469 /* Initialize execute_data */
11470+ memset(&execute_data, 0, sizeof(execute_data));
11471 EX(fbc) = NULL;
11472 EX(object).ptr = NULL;
11473 EX(ce) = NULL;
11474 EX(Ts) = NULL;
11475 EX(op_array) = NULL;
11476 EX(opline) = NULL;
11477+ EX(execute_depth) = 0;
11478
11479 *retval_ptr_ptr = NULL;
11480
11481@@ -601,8 +604,7 @@
11482 return SUCCESS;
11483 }
11484
11485-
11486-ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
11487+ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int type TSRMLS_DC)
11488 {
11489 zval pv;
11490 zend_op_array *new_op_array;
11491@@ -635,6 +637,7 @@
11492 zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
11493 zend_op **original_opline_ptr = EG(opline_ptr);
11494
11495+ new_op_array->type = type;
11496 EG(return_value_ptr_ptr) = &local_retval_ptr;
11497 EG(active_op_array) = new_op_array;
11498 EG(no_extensions)=1;
11499@@ -668,6 +671,10 @@
11500 return retval;
11501 }
11502
11503+ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
11504+{
11505+ return (zend_eval_string_ex(str, retval_ptr, string_name, ZEND_EVAL_CODE TSRMLS_CC));
11506+}
11507
11508 void execute_new_code(TSRMLS_D)
11509 {
11510diff -Naur php-4.3.11/Zend/zend_execute.c hardening-patch-4.3.11-0.3.2/Zend/zend_execute.c
11511--- php-4.3.11/Zend/zend_execute.c 2005-02-21 13:38:54.000000000 +0100
11512+++ hardening-patch-4.3.11-0.3.2/Zend/zend_execute.c 2005-07-09 08:53:02.519355664 +0200
11513@@ -1042,6 +1042,7 @@
11514 zend_execute_data execute_data;
11515
11516 /* Initialize execute_data */
11517+ memset(&execute_data, 0, sizeof(execute_data));
11518 EX(fbc) = NULL;
11519 EX(ce) = NULL;
11520 EX(object).ptr = NULL;
11521@@ -1053,9 +1054,21 @@
11522 }
11523 EX(prev_execute_data) = EG(current_execute_data);
11524 EX(original_in_execution)=EG(in_execution);
11525+ EX(original_in_code_type)=EG(in_code_type);
11526
11527 EG(current_execute_data) = &execute_data;
11528
11529+#if HARDENING_PATCH
11530+ EX(execute_depth) = 0;
11531+
11532+ if (op_array->type == ZEND_EVAL_CODE && EG(in_code_type) != ZEND_SANDBOX_CODE) {
11533+ EG(in_code_type) = ZEND_EVAL_CODE;
11534+ } else if (op_array->type == ZEND_SANDBOX_CODE) {
11535+ EG(in_code_type) = ZEND_SANDBOX_CODE;
11536+ op_array->type = ZEND_EVAL_CODE;
11537+ }
11538+#endif
11539+
11540 EG(in_execution) = 1;
11541 if (op_array->start_op) {
11542 EX(opline) = op_array->start_op;
11543@@ -1087,6 +1100,19 @@
11544 }
11545 }
11546
11547+#if HARDENING_PATCH
11548+ if (EX(prev_execute_data) == NULL) {
11549+ EX(execute_depth) = 0;
11550+ } else {
11551+ EX(execute_depth) = EX(prev_execute_data)->execute_depth + 1;
11552+ }
11553+
11554+ if (EG(hphp_executor_max_depth) > 0 && EX(execute_depth) > EG(hphp_executor_max_depth)) {
11555+ zend_security_log(S_EXECUTOR, "Maximum execution depth of %u violated", EG(hphp_executor_max_depth));
11556+ zend_bailout();
11557+ }
11558+#endif
11559+
11560 while (1) {
11561 #ifdef ZEND_WIN32
11562 if (EG(timed_out)) {
11563@@ -1782,6 +1808,7 @@
11564 efree(EX(Ts));
11565 }
11566 EG(in_execution) = EX(original_in_execution);
11567+ EG(in_code_type) = EX(original_in_code_type);
11568 EG(current_execute_data) = EX(prev_execute_data);
11569 return;
11570 }
11571@@ -2161,7 +2188,12 @@
11572 int dummy = 1;
11573 zend_file_handle file_handle = {0};
11574
11575+#if HARDENING_PATCH_INC_PROTECT
11576+ if (zend_is_valid_include(inc_filename)
11577+ && zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
11578+#else
11579 if (zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
11580+#endif
11581 && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
11582
11583 file_handle.filename = inc_filename->value.str.val;
11584@@ -2190,6 +2222,11 @@
11585 break;
11586 case ZEND_INCLUDE:
11587 case ZEND_REQUIRE:
11588+#if HARDENING_PATCH_INC_PROTECT
11589+ if (!zend_is_valid_include(inc_filename)) {
11590+ break;
11591+ }
11592+#endif
11593 new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
11594 break;
11595 case ZEND_EVAL: {
11596diff -Naur php-4.3.11/Zend/zend_execute_globals.h hardening-patch-4.3.11-0.3.2/Zend/zend_execute_globals.h
11597--- php-4.3.11/Zend/zend_execute_globals.h 2002-12-31 17:23:00.000000000 +0100
11598+++ hardening-patch-4.3.11-0.3.2/Zend/zend_execute_globals.h 2005-07-09 08:53:02.519355664 +0200
11599@@ -59,6 +59,8 @@
11600 object_info object;
11601 temp_variable *Ts;
11602 zend_bool original_in_execution;
11603+ zend_uint original_in_code_type;
11604+ zend_uint execute_depth;
11605 zend_op_array *op_array;
11606 struct _zend_execute_data *prev_execute_data;
11607 } zend_execute_data;
11608diff -Naur php-4.3.11/Zend/zend_extensions.h hardening-patch-4.3.11-0.3.2/Zend/zend_extensions.h
11609--- php-4.3.11/Zend/zend_extensions.h 2002-12-31 17:23:02.000000000 +0100
11610+++ hardening-patch-4.3.11-0.3.2/Zend/zend_extensions.h 2005-07-09 08:53:02.520355512 +0200
11611@@ -23,7 +23,9 @@
11612
11613 #include "zend_compile.h"
11614
11615-#define ZEND_EXTENSION_API_NO 20021010
11616+/* Create own API version number for Hardening-Patch */
11617+
11618+#define ZEND_EXTENSION_API_NO 1020050626
11619
11620 typedef struct _zend_extension_version_info {
11621 int zend_extension_api_no;
11622diff -Naur php-4.3.11/Zend/zend_globals.h hardening-patch-4.3.11-0.3.2/Zend/zend_globals.h
11623--- php-4.3.11/Zend/zend_globals.h 2004-11-04 00:15:05.000000000 +0100
11624+++ hardening-patch-4.3.11-0.3.2/Zend/zend_globals.h 2005-07-09 08:53:02.520355512 +0200
11625@@ -163,6 +163,16 @@
11626
11627 int error_reporting;
11628 int orig_error_reporting;
11629+#if HARDENING_PATCH
11630+ int hphp_log_syslog;
11631+ int hphp_log_syslog_facility;
11632+ int hphp_log_syslog_priority;
11633+ int hphp_log_sapi;
11634+ int hphp_log_script;
11635+ char *hphp_log_scriptname;
11636+ zend_bool hphp_log_use_x_forwarded_for;
11637+ long hphp_executor_max_depth;
11638+#endif
11639 int exit_status;
11640
11641 zend_op_array *active_op_array;
11642@@ -176,6 +186,7 @@
11643 int ticks_count;
11644
11645 zend_bool in_execution;
11646+ zend_uint in_code_type;
11647 zend_bool bailout_set;
11648 zend_bool full_tables_cleanup;
11649
11650diff -Naur php-4.3.11/Zend/zend.h hardening-patch-4.3.11-0.3.2/Zend/zend.h
11651--- php-4.3.11/Zend/zend.h 2005-01-25 14:08:41.000000000 +0100
11652+++ hardening-patch-4.3.11-0.3.2/Zend/zend.h 2005-07-09 08:53:02.521355360 +0200
11653@@ -275,9 +275,10 @@
11654 struct _zval_struct {
11655 /* Variable information */
11656 zvalue_value value; /* value */
11657+ zend_uint refcount;
11658+ zend_ushort flags;
11659 zend_uchar type; /* active type */
11660 zend_uchar is_ref;
11661- zend_ushort refcount;
11662 };
11663
11664
11665@@ -338,6 +339,12 @@
11666 void (*ticks_function)(int ticks);
11667 void (*on_timeout)(int seconds TSRMLS_DC);
11668 zend_bool (*open_function)(const char *filename, struct _zend_file_handle *);
11669+#if HARDENING_PATCH
11670+ void (*security_log_function)(int loglevel, char *fmt, ...);
11671+#endif
11672+#if HARDENING_PATCH_INC_PROTECT
11673+ int (*is_valid_include)(zval *z);
11674+#endif
11675 } zend_utility_functions;
11676
11677
11678@@ -469,7 +476,16 @@
11679 extern ZEND_API void (*zend_ticks_function)(int ticks);
11680 extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
11681 extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
11682+#if HARDENING_PATCH
11683+extern ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
11684+#endif
11685+#if HARDENING_PATCH_INC_PROTECT
11686+extern ZEND_API int (*zend_is_valid_include)(zval *z);
11687+#endif
11688
11689+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
11690+ZEND_API unsigned int zend_canary(void);
11691+#endif
11692
11693 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 2, 3);
11694
11695@@ -576,6 +592,11 @@
11696
11697 #define ZEND_MAX_RESERVED_RESOURCES 4
11698
11699+#if HARDENING_PATCH
11700+#include "hardened_globals.h"
11701+#include "php_syslog.h"
11702+#endif
11703+
11704 #endif /* ZEND_H */
11705
11706 /*
11707diff -Naur php-4.3.11/Zend/zend_hash.c hardening-patch-4.3.11-0.3.2/Zend/zend_hash.c
11708--- php-4.3.11/Zend/zend_hash.c 2004-07-12 23:26:46.000000000 +0200
11709+++ hardening-patch-4.3.11-0.3.2/Zend/zend_hash.c 2005-07-09 08:53:02.522355208 +0200
11710@@ -26,6 +26,17 @@
11711 # include <stdlib.h>
11712 #endif
11713
11714+#if HARDENING_PATCH_HASH_PROTECT
11715+ unsigned int zend_hash_canary = 0x1234567;
11716+ zend_bool zend_hash_canary_inited = 0;
11717+#endif
11718+
11719+#define CHECK_HASH_CANARY(hash) \
11720+ if (zend_hash_canary != (hash)->canary) { \
11721+ zend_security_log(S_MEMORY, "Zend HashTable canary was overwritten"); \
11722+ exit(1); \
11723+ }
11724+
11725 #define HANDLE_NUMERIC(key, length, func) { \
11726 register char *tmp=key; \
11727 \
11728@@ -175,6 +186,9 @@
11729 {
11730 uint i = 3;
11731 Bucket **tmp;
11732+#if HARDENING_PATCH_HASH_PROTECT
11733+ TSRMLS_FETCH();
11734+#endif
11735
11736 SET_INCONSISTENT(HT_OK);
11737
11738@@ -184,6 +198,13 @@
11739
11740 ht->nTableSize = 1 << i;
11741 ht->nTableMask = ht->nTableSize - 1;
11742+#if HARDENING_PATCH_HASH_PROTECT
11743+ if (zend_hash_canary_inited==0) {
11744+ zend_hash_canary = zend_canary();
11745+ zend_hash_canary_inited = 1;
11746+ }
11747+ ht->canary = zend_hash_canary;
11748+#endif
11749 ht->pDestructor = pDestructor;
11750 ht->pListHead = NULL;
11751 ht->pListTail = NULL;
11752@@ -259,6 +280,9 @@
11753 }
11754 #endif
11755 if (ht->pDestructor) {
11756+#if HARDENING_PATCH_HASH_PROTECT
11757+ CHECK_HASH_CANARY(ht);
11758+#endif
11759 ht->pDestructor(p->pData);
11760 }
11761 UPDATE_DATA(ht, p, pData, nDataSize);
11762@@ -327,6 +351,9 @@
11763 }
11764 #endif
11765 if (ht->pDestructor) {
11766+#if HARDENING_PATCH_HASH_PROTECT
11767+ CHECK_HASH_CANARY(ht);
11768+#endif
11769 ht->pDestructor(p->pData);
11770 }
11771 UPDATE_DATA(ht, p, pData, nDataSize);
11772@@ -402,6 +429,9 @@
11773 }
11774 #endif
11775 if (ht->pDestructor) {
11776+#if HARDENING_PATCH_HASH_PROTECT
11777+ CHECK_HASH_CANARY(ht);
11778+#endif
11779 ht->pDestructor(p->pData);
11780 }
11781 UPDATE_DATA(ht, p, pData, nDataSize);
11782@@ -450,7 +480,7 @@
11783 IS_CONSISTENT(ht);
11784
11785 if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */
11786- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
11787+ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
11788 if (t) {
11789 HANDLE_BLOCK_INTERRUPTIONS();
11790 ht->arBuckets = t;
11791@@ -460,6 +490,7 @@
11792 HANDLE_UNBLOCK_INTERRUPTIONS();
11793 return SUCCESS;
11794 }
11795+ zend_error(E_ERROR, "zend_hash_do_resize - out of memory");
11796 return FAILURE;
11797 }
11798 return SUCCESS;
11799@@ -524,6 +555,9 @@
11800 ht->pInternalPointer = p->pListNext;
11801 }
11802 if (ht->pDestructor) {
11803+#if HARDENING_PATCH_HASH_PROTECT
11804+ CHECK_HASH_CANARY(ht);
11805+#endif
11806 ht->pDestructor(p->pData);
11807 }
11808 if (!p->pDataPtr) {
11809@@ -553,6 +587,9 @@
11810 q = p;
11811 p = p->pListNext;
11812 if (ht->pDestructor) {
11813+#if HARDENING_PATCH_HASH_PROTECT
11814+ CHECK_HASH_CANARY(ht);
11815+#endif
11816 ht->pDestructor(q->pData);
11817 }
11818 if (!q->pDataPtr && q->pData) {
11819@@ -579,6 +616,9 @@
11820 q = p;
11821 p = p->pListNext;
11822 if (ht->pDestructor) {
11823+#if HARDENING_PATCH_HASH_PROTECT
11824+ CHECK_HASH_CANARY(ht);
11825+#endif
11826 ht->pDestructor(q->pData);
11827 }
11828 if (!q->pDataPtr && q->pData) {
11829@@ -608,6 +648,9 @@
11830 HANDLE_BLOCK_INTERRUPTIONS();
11831
11832 if (ht->pDestructor) {
11833+#if HARDENING_PATCH_HASH_PROTECT
11834+ CHECK_HASH_CANARY(ht);
11835+#endif
11836 ht->pDestructor(p->pData);
11837 }
11838 if (!p->pDataPtr) {
11839diff -Naur php-4.3.11/Zend/zend_hash.h hardening-patch-4.3.11-0.3.2/Zend/zend_hash.h
11840--- php-4.3.11/Zend/zend_hash.h 2002-12-31 17:23:03.000000000 +0100
11841+++ hardening-patch-4.3.11-0.3.2/Zend/zend_hash.h 2005-07-09 08:53:02.522355208 +0200
11842@@ -54,6 +54,9 @@
11843 } Bucket;
11844
11845 typedef struct _hashtable {
11846+#if HARDENING_PATCH_HASH_PROTECT
11847+ unsigned int canary;
11848+#endif
11849 uint nTableSize;
11850 uint nTableMask;
11851 uint nNumOfElements;
11852diff -Naur php-4.3.11/Zend/zend_ini.h hardening-patch-4.3.11-0.3.2/Zend/zend_ini.h
11853--- php-4.3.11/Zend/zend_ini.h 2005-01-09 18:00:16.000000000 +0100
11854+++ hardening-patch-4.3.11-0.3.2/Zend/zend_ini.h 2005-07-09 08:53:02.522355208 +0200
11855@@ -174,6 +174,7 @@
11856 /* Standard message handlers */
11857 BEGIN_EXTERN_C()
11858 ZEND_API ZEND_INI_MH(OnUpdateBool);
11859+#define OnUpdateLong OnUpdateInt
11860 ZEND_API ZEND_INI_MH(OnUpdateInt);
11861 ZEND_API ZEND_INI_MH(OnUpdateReal);
11862 ZEND_API ZEND_INI_MH(OnUpdateString);
11863diff -Naur php-4.3.11/Zend/zend_llist.c hardening-patch-4.3.11-0.3.2/Zend/zend_llist.c
11864--- php-4.3.11/Zend/zend_llist.c 2002-12-31 17:23:04.000000000 +0100
11865+++ hardening-patch-4.3.11-0.3.2/Zend/zend_llist.c 2005-07-09 08:53:02.523355056 +0200
11866@@ -21,9 +21,34 @@
11867 #include "zend.h"
11868 #include "zend_llist.h"
11869 #include "zend_qsort.h"
11870+#include "zend_globals.h"
11871+
11872+#define CHECK_LIST_CANARY(list) \
11873+ if (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t) { \
11874+ zend_security_log(S_MEMORY, "linked list canary was overwritten"); \
11875+ exit(1); \
11876+ }
11877+
11878+#define CHECK_LISTELEMENT_CANARY(elem) \
11879+ if (HG(canary_3) != (elem)->canary) { \
11880+ zend_security_log(S_MEMORY, "linked list element canary was overwritten"); \
11881+ exit(1); \
11882+ }
11883+
11884
11885 ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
11886 {
11887+#if HARDENING_PATCH_LL_PROTECT
11888+ TSRMLS_FETCH();
11889+
11890+ if (!HG(ll_canary_inited)) {
11891+ HG(canary_3) = zend_canary();
11892+ HG(canary_4) = zend_canary();
11893+ HG(ll_canary_inited) = 1;
11894+ }
11895+ l->canary_h = HG(canary_3);
11896+ l->canary_t = HG(canary_4);
11897+#endif
11898 l->head = NULL;
11899 l->tail = NULL;
11900 l->count = 0;
11901@@ -37,6 +62,11 @@
11902 {
11903 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
11904
11905+#if HARDENING_PATCH_LL_PROTECT
11906+ TSRMLS_FETCH();
11907+ CHECK_LIST_CANARY(l)
11908+ tmp->canary = HG(canary_3);
11909+#endif
11910 tmp->prev = l->tail;
11911 tmp->next = NULL;
11912 if (l->tail) {
11913@@ -55,6 +85,11 @@
11914 {
11915 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
11916
11917+#if HARDENING_PATCH_LL_PROTECT
11918+ TSRMLS_FETCH();
11919+ CHECK_LIST_CANARY(l)
11920+ tmp->canary = HG(canary_3);
11921+#endif
11922 tmp->next = l->head;
11923 tmp->prev = NULL;
11924 if (l->head) {
11925@@ -91,10 +126,20 @@
11926 zend_llist_element *current=l->head;
11927 zend_llist_element *next;
11928
11929+#if HARDENING_PATCH_LL_PROTECT
11930+ TSRMLS_FETCH();
11931+ CHECK_LIST_CANARY(l)
11932+#endif
11933 while (current) {
11934+#if HARDENING_PATCH_LL_PROTECT
11935+ CHECK_LISTELEMENT_CANARY(current)
11936+#endif
11937 next = current->next;
11938 if (compare(current->data, element)) {
11939 DEL_LLIST_ELEMENT(current, l);
11940+#if HARDENING_PATCH_LL_PROTECT
11941+ current->canary = 0;
11942+#endif
11943 break;
11944 }
11945 current = next;
11946@@ -106,7 +151,14 @@
11947 {
11948 zend_llist_element *current=l->head, *next;
11949
11950+#if HARDENING_PATCH_LL_PROTECT
11951+ TSRMLS_FETCH();
11952+ CHECK_LIST_CANARY(l)
11953+#endif
11954 while (current) {
11955+#if HARDENING_PATCH_LL_PROTECT
11956+ CHECK_LISTELEMENT_CANARY(current)
11957+#endif
11958 next = current->next;
11959 if (l->dtor) {
11960 l->dtor(current->data);
11961@@ -131,7 +183,14 @@
11962 zend_llist_element *old_tail;
11963 void *data;
11964
11965+#if HARDENING_PATCH_LL_PROTECT
11966+ TSRMLS_FETCH();
11967+ CHECK_LIST_CANARY(l)
11968+#endif
11969 if ((old_tail = l->tail)) {
11970+#if HARDENING_PATCH_LL_PROTECT
11971+ CHECK_LISTELEMENT_CANARY(old_tail)
11972+#endif
11973 if (l->tail->prev) {
11974 l->tail->prev->next = NULL;
11975 }
11976@@ -157,9 +216,16 @@
11977 {
11978 zend_llist_element *ptr;
11979
11980+#if HARDENING_PATCH_LL_PROTECT
11981+ TSRMLS_FETCH();
11982+ CHECK_LIST_CANARY(src)
11983+#endif
11984 zend_llist_init(dst, src->size, src->dtor, src->persistent);
11985 ptr = src->head;
11986 while (ptr) {
11987+#if HARDENING_PATCH_LL_PROTECT
11988+ CHECK_LISTELEMENT_CANARY(ptr)
11989+#endif
11990 zend_llist_add_element(dst, ptr->data);
11991 ptr = ptr->next;
11992 }
11993@@ -170,11 +236,21 @@
11994 {
11995 zend_llist_element *element, *next;
11996
11997+#if HARDENING_PATCH_LL_PROTECT
11998+ TSRMLS_FETCH();
11999+ CHECK_LIST_CANARY(l)
12000+#endif
12001 element=l->head;
12002 while (element) {
12003+#if HARDENING_PATCH_LL_PROTECT
12004+ CHECK_LISTELEMENT_CANARY(element)
12005+#endif
12006 next = element->next;
12007 if (func(element->data)) {
12008 DEL_LLIST_ELEMENT(element, l);
12009+#if HARDENING_PATCH_LL_PROTECT
12010+ element->canary = 0;
12011+#endif
12012 }
12013 element = next;
12014 }
12015@@ -185,7 +261,13 @@
12016 {
12017 zend_llist_element *element;
12018
12019+#if HARDENING_PATCH_LL_PROTECT
12020+ CHECK_LIST_CANARY(l)
12021+#endif
12022 for (element=l->head; element; element=element->next) {
12023+#if HARDENING_PATCH_LL_PROTECT
12024+ CHECK_LISTELEMENT_CANARY(element)
12025+#endif
12026 func(element->data TSRMLS_CC);
12027 }
12028 }
12029@@ -197,6 +279,9 @@
12030 zend_llist_element **elements;
12031 zend_llist_element *element, **ptr;
12032
12033+#if HARDENING_PATCH_LL_PROTECT
12034+ CHECK_LIST_CANARY(l)
12035+#endif
12036 if (l->count <= 0) {
12037 return;
12038 }
12039@@ -206,6 +291,9 @@
12040 ptr = &elements[0];
12041
12042 for (element=l->head; element; element=element->next) {
12043+#if HARDENING_PATCH_LL_PROTECT
12044+ CHECK_LISTELEMENT_CANARY(element)
12045+#endif
12046 *ptr++ = element;
12047 }
12048
12049@@ -228,7 +316,13 @@
12050 {
12051 zend_llist_element *element;
12052
12053+#if HARDENING_PATCH_LL_PROTECT
12054+ CHECK_LIST_CANARY(l)
12055+#endif
12056 for (element=l->head; element; element=element->next) {
12057+#if HARDENING_PATCH_LL_PROTECT
12058+ CHECK_LISTELEMENT_CANARY(element)
12059+#endif
12060 func(element->data, arg TSRMLS_CC);
12061 }
12062 }
12063@@ -239,8 +333,14 @@
12064 zend_llist_element *element;
12065 va_list args;
12066
12067+#if HARDENING_PATCH_LL_PROTECT
12068+ CHECK_LIST_CANARY(l)
12069+#endif
12070 va_start(args, num_args);
12071 for (element=l->head; element; element=element->next) {
12072+#if HARDENING_PATCH_LL_PROTECT
12073+ CHECK_LISTELEMENT_CANARY(element)
12074+#endif
12075 func(element->data, num_args, args TSRMLS_CC);
12076 }
12077 va_end(args);
12078@@ -249,6 +349,10 @@
12079
12080 ZEND_API int zend_llist_count(zend_llist *l)
12081 {
12082+#if HARDENING_PATCH_LL_PROTECT
12083+ TSRMLS_FETCH();
12084+ CHECK_LIST_CANARY(l)
12085+#endif
12086 return l->count;
12087 }
12088
12089@@ -256,8 +360,15 @@
12090 {
12091 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
12092
12093+#if HARDENING_PATCH_LL_PROTECT
12094+ TSRMLS_FETCH();
12095+ CHECK_LIST_CANARY(l)
12096+#endif
12097 *current = l->head;
12098 if (*current) {
12099+#if HARDENING_PATCH_LL_PROTECT
12100+ CHECK_LISTELEMENT_CANARY(*current)
12101+#endif
12102 return (*current)->data;
12103 } else {
12104 return NULL;
12105@@ -269,8 +380,15 @@
12106 {
12107 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
12108
12109+#if HARDENING_PATCH_LL_PROTECT
12110+ TSRMLS_FETCH();
12111+ CHECK_LIST_CANARY(l)
12112+#endif
12113 *current = l->tail;
12114 if (*current) {
12115+#if HARDENING_PATCH_LL_PROTECT
12116+ CHECK_LISTELEMENT_CANARY(*current)
12117+#endif
12118 return (*current)->data;
12119 } else {
12120 return NULL;
12121@@ -282,9 +400,19 @@
12122 {
12123 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
12124
12125+#if HARDENING_PATCH_LL_PROTECT
12126+ TSRMLS_FETCH();
12127+ CHECK_LIST_CANARY(l)
12128+#endif
12129 if (*current) {
12130+#if HARDENING_PATCH_LL_PROTECT
12131+ CHECK_LISTELEMENT_CANARY(*current)
12132+#endif
12133 *current = (*current)->next;
12134 if (*current) {
12135+#if HARDENING_PATCH_LL_PROTECT
12136+ CHECK_LISTELEMENT_CANARY(*current)
12137+#endif
12138 return (*current)->data;
12139 }
12140 }
12141@@ -296,9 +424,19 @@
12142 {
12143 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
12144
12145+#if HARDENING_PATCH_LL_PROTECT
12146+ TSRMLS_FETCH();
12147+ CHECK_LIST_CANARY(l)
12148+#endif
12149 if (*current) {
12150+#if HARDENING_PATCH_LL_PROTECT
12151+ CHECK_LISTELEMENT_CANARY(*current)
12152+#endif
12153 *current = (*current)->prev;
12154 if (*current) {
12155+#if HARDENING_PATCH_LL_PROTECT
12156+ CHECK_LISTELEMENT_CANARY(*current)
12157+#endif
12158 return (*current)->data;
12159 }
12160 }
12161diff -Naur php-4.3.11/Zend/zend_llist.h hardening-patch-4.3.11-0.3.2/Zend/zend_llist.h
12162--- php-4.3.11/Zend/zend_llist.h 2002-12-31 17:23:04.000000000 +0100
12163+++ hardening-patch-4.3.11-0.3.2/Zend/zend_llist.h 2005-07-09 08:53:02.524354904 +0200
12164@@ -24,6 +24,9 @@
12165 #include <stdlib.h>
12166
12167 typedef struct _zend_llist_element {
12168+#if HARDENING_PATCH_LL_PROTECT
12169+ unsigned int canary;
12170+#endif
12171 struct _zend_llist_element *next;
12172 struct _zend_llist_element *prev;
12173 char data[1]; /* Needs to always be last in the struct */
12174@@ -36,6 +39,9 @@
12175 typedef void (*llist_apply_func_t)(void * TSRMLS_DC);
12176
12177 typedef struct _zend_llist {
12178+#if HARDENING_PATCH_LL_PROTECT
12179+ unsigned int canary_h; /* head */
12180+#endif
12181 zend_llist_element *head;
12182 zend_llist_element *tail;
12183 size_t size;
12184@@ -43,6 +49,9 @@
12185 llist_dtor_func_t dtor;
12186 unsigned char persistent;
12187 zend_llist_element *traverse_ptr;
12188+#if HARDENING_PATCH_LL_PROTECT
12189+ unsigned int canary_t; /* tail */
12190+#endif
12191 } zend_llist;
12192
12193 typedef zend_llist_element* zend_llist_position;
12194diff -Naur php-4.3.11/Zend/zend_modules.h hardening-patch-4.3.11-0.3.2/Zend/zend_modules.h
12195--- php-4.3.11/Zend/zend_modules.h 2002-12-31 17:23:04.000000000 +0100
12196+++ hardening-patch-4.3.11-0.3.2/Zend/zend_modules.h 2005-07-09 08:53:02.524354904 +0200
12197@@ -34,7 +34,7 @@
12198 ZEND_API extern unsigned char second_arg_force_ref[];
12199 ZEND_API extern unsigned char third_arg_force_ref[];
12200
12201-#define ZEND_MODULE_API_NO 20020429
12202+#define ZEND_MODULE_API_NO 1020050626
12203 #ifdef ZTS
12204 #define USING_ZTS 1
12205 #else
diff --git a/0.3.2/hardening-patch-4.4.0RC2-0.3.2.patch b/0.3.2/hardening-patch-4.4.0RC2-0.3.2.patch
new file mode 100644
index 0000000..3cae163
--- /dev/null
+++ b/0.3.2/hardening-patch-4.4.0RC2-0.3.2.patch
@@ -0,0 +1,4959 @@
1diff -Naur php-4.4.0RC2/acinclude.m4 hardening-patch-4.4.0RC2-0.3.2/acinclude.m4
2--- php-4.4.0RC2/acinclude.m4 2005-04-30 11:31:09.000000000 +0200
3+++ hardening-patch-4.4.0RC2-0.3.2/acinclude.m4 2005-07-09 08:53:20.597607352 +0200
4@@ -1173,6 +1173,36 @@
5 fi
6 ])
7
8+dnl
9+dnl Check for broken realpath()
10+dnl
11+dnl realpath("/etc/hosts/../passwd",XXX) should not return
12+dnl "/etc/passwd"
13+dnl
14+AC_DEFUN([PHP_AC_BROKEN_REALPATH],[
15+ AC_CACHE_CHECK(whether realpath is broken, ac_cv_broken_realpath,[
16+ AC_TRY_RUN([
17+main() {
18+ char buf[4096+1];
19+ buf[0] = 0;
20+ realpath("/etc/hosts/../passwd", buf);
21+ exit(strcmp(buf, "/etc/passwd")==0);
22+}
23+ ],[
24+ ac_cv_broken_realpath=no
25+ ],[
26+ ac_cv_broken_realpath=yes
27+ ],[
28+ ac_cv_broken_realpath=no
29+ ])
30+ ])
31+ if test "$ac_cv_broken_realpath" = "yes"; then
32+ AC_DEFINE(PHP_BROKEN_REALPATH, 1, [Whether realpath is broken])
33+ else
34+ AC_DEFINE(PHP_BROKEN_REALPATH, 0, [Whether realpath is broken])
35+ fi
36+])
37+
38 dnl PHP_SHARED_MODULE(module-name, object-var, build-dir, cxx)
39 dnl
40 dnl Basically sets up the link-stage for building module-name
41diff -Naur php-4.4.0RC2/configure hardening-patch-4.4.0RC2-0.3.2/configure
42--- php-4.4.0RC2/configure 2005-07-01 12:07:55.000000000 +0200
43+++ hardening-patch-4.4.0RC2-0.3.2/configure 2005-07-09 08:53:20.634601728 +0200
44@@ -394,6 +394,16 @@
45 ac_default_prefix=/usr/local
46 # Any additions from configure.in:
47 ac_help="$ac_help
48+ --disable-hardening-patch-mm-protect Disable the Memory Manager protection."
49+ac_help="$ac_help
50+ --disable-hardening-patch-ll-protect Disable the Linked List protection."
51+ac_help="$ac_help
52+ --disable-hardening-patch-inc-protect Disable include/require protection."
53+ac_help="$ac_help
54+ --disable-hardening-patch-fmt-protect Disable format string protection."
55+ac_help="$ac_help
56+ --disable-hardening-patch-hash-protect Disable Zend HashTable DTOR protection."
57+ac_help="$ac_help
58
59 SAPI modules:
60 "
61@@ -846,6 +856,8 @@
62 ac_help="$ac_help
63 --disable-tokenizer Disable tokenizer support"
64 ac_help="$ac_help
65+ --disable-varfilter Disable Hardening-Patch's variable filter"
66+ac_help="$ac_help
67 --enable-wddx Enable WDDX support."
68 ac_help="$ac_help
69 --disable-xml Disable XML support using bundled expat lib"
70@@ -2682,6 +2694,157 @@
71
72
73
74+# Check whether --enable-hardening-patch-mm-protect or --disable-hardening-patch-mm-protect was given.
75+if test "${enable_hardening_patch_mm_protect+set}" = set; then
76+ enableval="$enable_hardening_patch_mm_protect"
77+
78+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
79+
80+else
81+
82+ DO_HARDENING_PATCH_MM_PROTECT=yes
83+
84+fi
85+
86+
87+# Check whether --enable-hardening-patch-ll-protect or --disable-hardening-patch-ll-protect was given.
88+if test "${enable_hardening_patch_ll_protect+set}" = set; then
89+ enableval="$enable_hardening_patch_ll_protect"
90+
91+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
92+
93+else
94+
95+ DO_HARDENING_PATCH_LL_PROTECT=yes
96+
97+fi
98+
99+
100+# Check whether --enable-hardening-patch-inc-protect or --disable-hardening-patch-inc-protect was given.
101+if test "${enable_hardening_patch_inc_protect+set}" = set; then
102+ enableval="$enable_hardening_patch_inc_protect"
103+
104+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
105+
106+else
107+
108+ DO_HARDENING_PATCH_INC_PROTECT=yes
109+
110+fi
111+
112+
113+# Check whether --enable-hardening-patch-fmt-protect or --disable-hardening-patch-fmt-protect was given.
114+if test "${enable_hardening_patch_fmt_protect+set}" = set; then
115+ enableval="$enable_hardening_patch_fmt_protect"
116+
117+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
118+
119+else
120+
121+ DO_HARDENING_PATCH_FMT_PROTECT=yes
122+
123+fi
124+
125+
126+# Check whether --enable-hardening-patch-hash-protect or --disable-hardening-patch-hash-protect was given.
127+if test "${enable_hardening_patch_hash_protect+set}" = set; then
128+ enableval="$enable_hardening_patch_hash_protect"
129+
130+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
131+
132+else
133+
134+ DO_HARDENING_PATCH_HASH_PROTECT=yes
135+
136+fi
137+
138+
139+echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6
140+echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5
141+echo "$ac_t""$DO_HARDENING_PATCH_MM_PROTECT" 1>&6
142+
143+echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6
144+echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5
145+echo "$ac_t""$DO_HARDENING_PATCH_LL_PROTECT" 1>&6
146+
147+echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6
148+echo "configure:2733: checking whether to protect include/require statements" >&5
149+echo "$ac_t""$DO_HARDENING_PATCH_INC_PROTECT" 1>&6
150+
151+echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6
152+echo "configure:2737: checking whether to protect PHP Format String functions" >&5
153+echo "$ac_t""$DO_HARDENING_PATCH_FMT_PROTECT" 1>&6
154+
155+echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6
156+echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5
157+echo "$ac_t""$DO_HARDENING_PATCH_HASH_PROTECT" 1>&6
158+
159+
160+cat >> confdefs.h <<\EOF
161+#define HARDENING_PATCH 1
162+EOF
163+
164+
165+
166+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
167+ cat >> confdefs.h <<\EOF
168+#define HARDENING_PATCH_MM_PROTECT 1
169+EOF
170+
171+else
172+ cat >> confdefs.h <<\EOF
173+#define HARDENING_PATCH_MM_PROTECT 0
174+EOF
175+
176+fi
177+
178+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
179+ cat >> confdefs.h <<\EOF
180+#define HARDENING_PATCH_LL_PROTECT 1
181+EOF
182+
183+else
184+ cat >> confdefs.h <<\EOF
185+#define HARDENING_PATCH_LL_PROTECT 0
186+EOF
187+
188+fi
189+
190+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
191+ cat >> confdefs.h <<\EOF
192+#define HARDENING_PATCH_INC_PROTECT 1
193+EOF
194+
195+else
196+ cat >> confdefs.h <<\EOF
197+#define HARDENING_PATCH_INC_PROTECT 0
198+EOF
199+
200+fi
201+
202+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
203+ cat >> confdefs.h <<\EOF
204+#define HARDENING_PATCH_FMT_PROTECT 1
205+EOF
206+
207+else
208+ cat >> confdefs.h <<\EOF
209+#define HARDENING_PATCH_FMT_PROTECT 0
210+EOF
211+
212+fi
213+
214+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
215+ cat >> confdefs.h <<\EOF
216+#define HARDENING_PATCH_HASH_PROTECT 1
217+EOF
218+
219+else
220+ cat >> confdefs.h <<\EOF
221+#define HARDENING_PATCH_HASH_PROTECT 0
222+EOF
223+
224+fi
225
226
227
228@@ -15733,6 +15896,62 @@
229 fi
230
231
232+ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6
233+echo "configure:14928: checking whether realpath is broken" >&5
234+if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then
235+ echo $ac_n "(cached) $ac_c" 1>&6
236+else
237+
238+ if test "$cross_compiling" = yes; then
239+
240+ ac_cv_broken_realpath=no
241+
242+else
243+ cat > conftest.$ac_ext <<EOF
244+#line 14939 "configure"
245+#include "confdefs.h"
246+
247+main() {
248+ char buf[4096+1];
249+ buf[0] = 0;
250+ realpath("/etc/hosts/../passwd", buf);
251+ exit(strcmp(buf, "/etc/passwd")==0);
252+}
253+
254+EOF
255+if { (eval echo configure:14958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
256+then
257+
258+ ac_cv_broken_realpath=no
259+
260+else
261+ echo "configure: failed program was:" >&5
262+ cat conftest.$ac_ext >&5
263+ rm -fr conftest*
264+
265+ ac_cv_broken_realpath=yes
266+
267+fi
268+rm -fr conftest*
269+fi
270+
271+
272+fi
273+
274+echo "$ac_t""$ac_cv_broken_realpath" 1>&6
275+ if test "$ac_cv_broken_realpath" = "yes"; then
276+ cat >> confdefs.h <<\EOF
277+#define PHP_BROKEN_REALPATH 1
278+EOF
279+
280+ else
281+ cat >> confdefs.h <<\EOF
282+#define PHP_BROKEN_REALPATH 0
283+EOF
284+
285+ fi
286+
287+
288 echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
289 echo "configure:15738: checking for declared timezone" >&5
290 if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then
291@@ -87305,6 +87524,265 @@
292 fi
293
294
295+echo $ac_n "checking whether to enable Hardening-Patch's variable filter""... $ac_c" 1>&6
296+echo "configure:82041: checking whether to enable Hardening-Patch's variable filter" >&5
297+# Check whether --enable-varfilter or --disable-varfilter was given.
298+if test "${enable_varfilter+set}" = set; then
299+ enableval="$enable_varfilter"
300+ PHP_VARFILTER=$enableval
301+else
302+
303+ PHP_VARFILTER=yes
304+
305+ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then
306+ PHP_VARFILTER=$PHP_ENABLE_ALL
307+ fi
308+
309+fi
310+
311+
312+
313+ext_output="yes, shared"
314+ext_shared=yes
315+case $PHP_VARFILTER in
316+shared,*)
317+ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'`
318+ ;;
319+shared)
320+ PHP_VARFILTER=yes
321+ ;;
322+no)
323+ ext_output=no
324+ ext_shared=no
325+ ;;
326+*)
327+ ext_output=yes
328+ ext_shared=no
329+ ;;
330+esac
331+
332+
333+
334+echo "$ac_t""$ext_output" 1>&6
335+
336+
337+
338+
339+if test "$PHP_VARFILTER" != "no"; then
340+ cat >> confdefs.h <<\EOF
341+#define HAVE_VARFILTER 1
342+EOF
343+
344+
345+ ext_builddir=ext/varfilter
346+ ext_srcdir=$abs_srcdir/ext/varfilter
347+
348+ ac_extra=
349+
350+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then
351+
352+
353+
354+ case ext/varfilter in
355+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
356+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
357+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
358+ esac
359+
360+
361+
362+ b_c_pre=$php_c_pre
363+ b_cxx_pre=$php_cxx_pre
364+ b_c_meta=$php_c_meta
365+ b_cxx_meta=$php_cxx_meta
366+ b_c_post=$php_c_post
367+ b_cxx_post=$php_cxx_post
368+ b_lo=$php_lo
369+
370+
371+ old_IFS=$IFS
372+ for ac_src in varfilter.c; do
373+
374+ IFS=.
375+ set $ac_src
376+ ac_obj=$1
377+ IFS=$old_IFS
378+
379+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
380+
381+ case $ac_src in
382+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
383+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
384+ esac
385+
386+ cat >>Makefile.objects<<EOF
387+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
388+ $ac_comp
389+EOF
390+ done
391+
392+
393+ EXT_STATIC="$EXT_STATIC varfilter"
394+ if test "$ext_shared" != "nocli"; then
395+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
396+ fi
397+ else
398+ if test "$ext_shared" = "shared" || test "$ext_shared" = "yes"; then
399+
400+ case ext/varfilter in
401+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
402+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
403+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
404+ esac
405+
406+
407+
408+ b_c_pre=$shared_c_pre
409+ b_cxx_pre=$shared_cxx_pre
410+ b_c_meta=$shared_c_meta
411+ b_cxx_meta=$shared_cxx_meta
412+ b_c_post=$shared_c_post
413+ b_cxx_post=$shared_cxx_post
414+ b_lo=$shared_lo
415+
416+
417+ old_IFS=$IFS
418+ for ac_src in varfilter.c; do
419+
420+ IFS=.
421+ set $ac_src
422+ ac_obj=$1
423+ IFS=$old_IFS
424+
425+ shared_objects_varfilter="$shared_objects_varfilter $ac_bdir$ac_obj.lo"
426+
427+ case $ac_src in
428+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
429+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
430+ esac
431+
432+ cat >>Makefile.objects<<EOF
433+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
434+ $ac_comp
435+EOF
436+ done
437+
438+
439+ install_modules="install-modules"
440+ PHP_MODULES="$PHP_MODULES \$(phplibdir)/varfilter.la"
441+
442+ PHP_VAR_SUBST="$PHP_VAR_SUBST shared_objects_varfilter"
443+
444+ cat >>Makefile.objects<<EOF
445+\$(phplibdir)/varfilter.la: $ext_builddir/varfilter.la
446+ \$(LIBTOOL) --mode=install cp $ext_builddir/varfilter.la \$(phplibdir)
447+
448+$ext_builddir/varfilter.la: \$(shared_objects_varfilter) \$(VARFILTER_SHARED_DEPENDENCIES)
449+ \$(LIBTOOL) --mode=link \$(CC) \$(COMMON_FLAGS) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(LDFLAGS) -o \$@ -export-dynamic -avoid-version -prefer-pic -module -rpath \$(phplibdir) \$(EXTRA_LDFLAGS) \$(shared_objects_varfilter) \$(VARFILTER_SHARED_LIBADD)
450+
451+EOF
452+
453+ cat >> confdefs.h <<EOF
454+#define COMPILE_DL_VARFILTER 1
455+EOF
456+
457+ fi
458+ fi
459+
460+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" = "cli"; then
461+ if test "$PHP_SAPI" = "cgi"; then
462+
463+
464+ case ext/varfilter in
465+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
466+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
467+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
468+ esac
469+
470+
471+
472+ b_c_pre=$php_c_pre
473+ b_cxx_pre=$php_cxx_pre
474+ b_c_meta=$php_c_meta
475+ b_cxx_meta=$php_cxx_meta
476+ b_c_post=$php_c_post
477+ b_cxx_post=$php_cxx_post
478+ b_lo=$php_lo
479+
480+
481+ old_IFS=$IFS
482+ for ac_src in varfilter.c; do
483+
484+ IFS=.
485+ set $ac_src
486+ ac_obj=$1
487+ IFS=$old_IFS
488+
489+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
490+
491+ case $ac_src in
492+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
493+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
494+ esac
495+
496+ cat >>Makefile.objects<<EOF
497+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
498+ $ac_comp
499+EOF
500+ done
501+
502+
503+ EXT_STATIC="$EXT_STATIC varfilter"
504+ else
505+
506+
507+ case ext/varfilter in
508+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
509+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
510+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
511+ esac
512+
513+
514+
515+ b_c_pre=$php_c_pre
516+ b_cxx_pre=$php_cxx_pre
517+ b_c_meta=$php_c_meta
518+ b_cxx_meta=$php_cxx_meta
519+ b_c_post=$php_c_post
520+ b_cxx_post=$php_cxx_post
521+ b_lo=$php_lo
522+
523+
524+ old_IFS=$IFS
525+ for ac_src in varfilter.c; do
526+
527+ IFS=.
528+ set $ac_src
529+ ac_obj=$1
530+ IFS=$old_IFS
531+
532+ PHP_CLI_OBJS="$PHP_CLI_OBJS $ac_bdir$ac_obj.lo"
533+
534+ case $ac_src in
535+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
536+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
537+ esac
538+
539+ cat >>Makefile.objects<<EOF
540+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
541+ $ac_comp
542+EOF
543+ done
544+
545+
546+ fi
547+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
548+ fi
549+
550+ BUILD_DIR="$BUILD_DIR $ext_builddir"
551+
552+
553+fi
554
555
556 echo $ac_n "checking whether to enable WDDX support""... $ac_c" 1>&6
557@@ -99988,7 +100466,7 @@
558 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
559 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
560 streams.c network.c php_open_temporary_file.c php_logos.c \
561- output.c memory_streams.c user_streams.c; do
562+ output.c memory_streams.c user_streams.c hardening_patch.c; do
563
564 IFS=.
565 set $ac_src
566@@ -100161,7 +100639,7 @@
567 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
568 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
569 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
570- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c; do
571+ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c; do
572
573 IFS=.
574 set $ac_src
575diff -Naur php-4.4.0RC2/configure.in hardening-patch-4.4.0RC2-0.3.2/configure.in
576--- php-4.4.0RC2/configure.in 2005-07-01 11:53:57.000000000 +0200
577+++ hardening-patch-4.4.0RC2-0.3.2/configure.in 2005-07-09 08:53:20.636601424 +0200
578@@ -238,7 +238,7 @@
579 sinclude(Zend/acinclude.m4)
580 sinclude(Zend/Zend.m4)
581 sinclude(TSRM/tsrm.m4)
582-
583+sinclude(main/hardening_patch.m4)
584
585
586 divert(2)
587@@ -612,6 +612,7 @@
588 AC_FUNC_ALLOCA
589 dnl PHP_AC_BROKEN_SPRINTF
590 dnl PHP_AC_BROKEN_SNPRINTF
591+PHP_AC_BROKEN_REALPATH
592 PHP_DECLARED_TIMEZONE
593 PHP_TIME_R_TYPE
594 PHP_READDIR_R_TYPE
595@@ -1241,7 +1242,7 @@
596 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
597 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
598 streams.c network.c php_open_temporary_file.c php_logos.c \
599- output.c memory_streams.c user_streams.c)
600+ output.c memory_streams.c user_streams.c hardening_patch.c)
601 PHP_ADD_SOURCES(/main, internal_functions.c,, sapi)
602 PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli)
603
604@@ -1254,7 +1255,7 @@
605 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
606 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
607 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
608- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c)
609+ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c )
610
611 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
612 PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c)
613diff -Naur php-4.4.0RC2/ext/fbsql/php_fbsql.c hardening-patch-4.4.0RC2-0.3.2/ext/fbsql/php_fbsql.c
614--- php-4.4.0RC2/ext/fbsql/php_fbsql.c 2005-02-09 20:33:32.000000000 +0100
615+++ hardening-patch-4.4.0RC2-0.3.2/ext/fbsql/php_fbsql.c 2005-07-09 08:53:20.637601272 +0200
616@@ -1797,8 +1797,24 @@
617 }
618 else if (fbcmdErrorsFound(md))
619 {
620+#if HARDENING_PATCH
621+ char* query_copy;
622+ int i;
623+#endif
624 FBCErrorMetaData* emd = fbcdcErrorMetaData(c, md);
625 char* emg = fbcemdAllErrorMessages(emd);
626+#if HARDENING_PATCH
627+ query_copy=estrdup(query_copy);
628+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
629+ php_security_log(S_SQL, "fbsql error: %s - query: %s", emg, query_copy);
630+ efree(query_copy);
631+ if (HG(hphp_sql_bailout_on_error)) {
632+ free(emg);
633+ fbcemdRelease(emd);
634+ result = 0;
635+ zend_bailout();
636+ }
637+#endif
638 if (FB_SQL_G(generateWarnings))
639 {
640 if (emg)
641diff -Naur php-4.4.0RC2/ext/mbstring/mbstring.c hardening-patch-4.4.0RC2-0.3.2/ext/mbstring/mbstring.c
642--- php-4.4.0RC2/ext/mbstring/mbstring.c 2005-02-21 09:03:47.000000000 +0100
643+++ hardening-patch-4.4.0RC2-0.3.2/ext/mbstring/mbstring.c 2005-07-09 08:53:20.639600968 +0200
644@@ -1487,6 +1487,7 @@
645 char *strtok_buf = NULL, **val_list;
646 zval *array_ptr = (zval *) arg;
647 int n, num, val_len, *len_list;
648+ unsigned int new_val_len;
649 enum mbfl_no_encoding from_encoding;
650 mbfl_string string, resvar, resval;
651 mbfl_encoding_detector *identd = NULL;
652@@ -1609,8 +1610,14 @@
653 val_len = len_list[n];
654 }
655 n++;
656- /* add variable to symbol table */
657- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
658+ /* we need val to be emalloc()ed */
659+ val = estrndup(val, val_len);
660+ if (sapi_module.input_filter(info->data_type, var, &val, val_len, &new_val_len TSRMLS_CC)) {
661+ /* add variable to symbol table */
662+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
663+ }
664+ efree(val);
665+
666 if (convd != NULL){
667 mbfl_string_clear(&resvar);
668 mbfl_string_clear(&resval);
669diff -Naur php-4.4.0RC2/ext/mysql/php_mysql.c hardening-patch-4.4.0RC2-0.3.2/ext/mysql/php_mysql.c
670--- php-4.4.0RC2/ext/mysql/php_mysql.c 2005-04-08 00:23:01.000000000 +0200
671+++ hardening-patch-4.4.0RC2-0.3.2/ext/mysql/php_mysql.c 2005-07-09 08:53:20.641600664 +0200
672@@ -1218,6 +1218,8 @@
673 {
674 php_mysql_conn *mysql;
675 MYSQL_RES *mysql_result;
676+ char *copy_query;
677+ int i;
678
679 ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, link_id, "MySQL-Link", le_link, le_plink);
680
681@@ -1268,6 +1270,13 @@
682 php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
683 }
684 }
685+ copy_query = estrdup(Z_STRVAL_PP(query));
686+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
687+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
688+ efree(copy_query);
689+ if (HG(hphp_sql_bailout_on_error)) {
690+ zend_bailout();
691+ }
692 RETURN_FALSE;
693 }
694 #else
695@@ -1275,12 +1284,20 @@
696 /* check possible error */
697 if (MySG(trace_mode)){
698 if (mysql_errno(&mysql->conn)){
699- php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, mysql_error(&mysql->conn));
700+ php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
701 }
702 }
703+ copy_query = estrdup(Z_STRVAL_PP(query));
704+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
705+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
706+ efree(copy_query);
707+ if (HG(hphp_sql_bailout_on_error)) {
708+ zend_bailout();
709+ }
710 RETURN_FALSE;
711 }
712 #endif
713+
714 if(use_store == MYSQL_USE_RESULT) {
715 mysql_result=mysql_use_result(&mysql->conn);
716 } else {
717diff -Naur php-4.4.0RC2/ext/pgsql/pgsql.c hardening-patch-4.4.0RC2-0.3.2/ext/pgsql/pgsql.c
718--- php-4.4.0RC2/ext/pgsql/pgsql.c 2005-05-11 01:15:06.000000000 +0200
719+++ hardening-patch-4.4.0RC2-0.3.2/ext/pgsql/pgsql.c 2005-07-09 08:53:20.643600360 +0200
720@@ -1001,10 +1001,28 @@
721 case PGRES_EMPTY_QUERY:
722 case PGRES_BAD_RESPONSE:
723 case PGRES_NONFATAL_ERROR:
724- case PGRES_FATAL_ERROR:
725- PHP_PQ_ERROR("Query failed: %s", pgsql);
726- PQclear(pgsql_result);
727- RETURN_FALSE;
728+ case PGRES_FATAL_ERROR:
729+ {
730+#if HARDENING_PATCH
731+ int i;
732+ char *query_copy;
733+#endif
734+ char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
735+ PQclear(pgsql_result);
736+#if HARDENING_PATCH
737+ query_copy = estrdup(Z_STRVAL_PP(query));
738+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
739+ php_security_log(S_SQL, "PgSQL error: %s - query: %s", msgbuf, query_copy);
740+ efree(query_copy);
741+ if (HG(hphp_sql_bailout_on_error)) {
742+ efree(msgbuf);
743+ zend_bailout();
744+ }
745+#endif
746+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", msgbuf);
747+ efree(msgbuf);
748+ RETURN_FALSE;
749+ }
750 break;
751 case PGRES_COMMAND_OK: /* successful command that did not return rows */
752 default:
753diff -Naur php-4.4.0RC2/ext/standard/array.c hardening-patch-4.4.0RC2-0.3.2/ext/standard/array.c
754--- php-4.4.0RC2/ext/standard/array.c 2005-06-21 14:11:19.000000000 +0200
755+++ hardening-patch-4.4.0RC2-0.3.2/ext/standard/array.c 2005-07-09 08:53:20.645600056 +0200
756@@ -1162,6 +1162,32 @@
757 }
758 }
759 }
760+
761+ if (var_name[0] == 'H') {
762+ if ((strcmp(var_name, "HTTP_GET_VARS")==0)||
763+ (strcmp(var_name, "HTTP_POST_VARS")==0)||
764+ (strcmp(var_name, "HTTP_POST_FILES")==0)||
765+ (strcmp(var_name, "HTTP_ENV_VARS")==0)||
766+ (strcmp(var_name, "HTTP_SERVER_VARS")==0)||
767+ (strcmp(var_name, "HTTP_SESSION_VARS")==0)||
768+ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)||
769+ (strcmp(var_name, "HTTP_RAW_POST_DATA")==0)) {
770+ return 0;
771+ }
772+ } else if (var_name[0] == '_') {
773+ if ((strcmp(var_name, "_COOKIE")==0)||
774+ (strcmp(var_name, "_ENV")==0)||
775+ (strcmp(var_name, "_FILES")==0)||
776+ (strcmp(var_name, "_GET")==0)||
777+ (strcmp(var_name, "_POST")==0)||
778+ (strcmp(var_name, "_REQUEST")==0)||
779+ (strcmp(var_name, "_SESSION")==0)||
780+ (strcmp(var_name, "_SERVER")==0)) {
781+ return 0;
782+ }
783+ } else if (strcmp(var_name, "GLOBALS")==0) {
784+ return 0;
785+ }
786
787 return 1;
788 }
789diff -Naur php-4.4.0RC2/ext/standard/basic_functions.c hardening-patch-4.4.0RC2-0.3.2/ext/standard/basic_functions.c
790--- php-4.4.0RC2/ext/standard/basic_functions.c 2005-05-16 10:55:31.000000000 +0200
791+++ hardening-patch-4.4.0RC2-0.3.2/ext/standard/basic_functions.c 2005-07-09 08:53:20.646599904 +0200
792@@ -687,7 +687,7 @@
793 PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL)
794
795 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
796- PHP_FE(realpath, NULL)
797+ PHP_STATIC_FE("realpath", zif_real_path, NULL)
798 #endif
799
800 #ifdef HAVE_FNMATCH
801@@ -3044,6 +3044,35 @@
802 memcpy(new_key, prefix, prefix_len);
803 memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength);
804
805+ if (new_key[0] == 'H') {
806+ if ((strcmp(new_key, "HTTP_GET_VARS")==0)||
807+ (strcmp(new_key, "HTTP_POST_VARS")==0)||
808+ (strcmp(new_key, "HTTP_POST_FILES")==0)||
809+ (strcmp(new_key, "HTTP_ENV_VARS")==0)||
810+ (strcmp(new_key, "HTTP_SERVER_VARS")==0)||
811+ (strcmp(new_key, "HTTP_SESSION_VARS")==0)||
812+ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)||
813+ (strcmp(new_key, "HTTP_RAW_POST_DATA")==0)) {
814+ efree(new_key);
815+ return 0;
816+ }
817+ } else if (new_key[0] == '_') {
818+ if ((strcmp(new_key, "_COOKIE")==0)||
819+ (strcmp(new_key, "_ENV")==0)||
820+ (strcmp(new_key, "_FILES")==0)||
821+ (strcmp(new_key, "_GET")==0)||
822+ (strcmp(new_key, "_POST")==0)||
823+ (strcmp(new_key, "_REQUEST")==0)||
824+ (strcmp(new_key, "_SESSION")==0)||
825+ (strcmp(new_key, "_SERVER")==0)) {
826+ efree(new_key);
827+ return 0;
828+ }
829+ } else if (strcmp(new_key, "GLOBALS")==0) {
830+ efree(new_key);
831+ return 0;
832+ }
833+
834 zend_hash_del(&EG(symbol_table), new_key, new_key_len);
835 ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0);
836
837diff -Naur php-4.4.0RC2/ext/standard/file.c hardening-patch-4.4.0RC2-0.3.2/ext/standard/file.c
838--- php-4.4.0RC2/ext/standard/file.c 2005-03-27 17:53:59.000000000 +0200
839+++ hardening-patch-4.4.0RC2-0.3.2/ext/standard/file.c 2005-07-09 08:53:20.648599600 +0200
840@@ -2469,7 +2469,7 @@
841 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
842 /* {{{ proto string realpath(string path)
843 Return the resolved path */
844-PHP_FUNCTION(realpath)
845+PHP_FUNCTION(real_path)
846 {
847 zval **path;
848 char resolved_path_buff[MAXPATHLEN];
849diff -Naur php-4.4.0RC2/ext/standard/file.h hardening-patch-4.4.0RC2-0.3.2/ext/standard/file.h
850--- php-4.4.0RC2/ext/standard/file.h 2004-06-21 21:33:47.000000000 +0200
851+++ hardening-patch-4.4.0RC2-0.3.2/ext/standard/file.h 2005-07-09 08:53:20.648599600 +0200
852@@ -64,7 +64,7 @@
853 PHP_FUNCTION(fd_set);
854 PHP_FUNCTION(fd_isset);
855 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
856-PHP_FUNCTION(realpath);
857+PHP_FUNCTION(real_path);
858 #endif
859 #ifdef HAVE_FNMATCH
860 PHP_FUNCTION(fnmatch);
861diff -Naur php-4.4.0RC2/ext/standard/head.c hardening-patch-4.4.0RC2-0.3.2/ext/standard/head.c
862--- php-4.4.0RC2/ext/standard/head.c 2005-01-07 22:14:23.000000000 +0100
863+++ hardening-patch-4.4.0RC2-0.3.2/ext/standard/head.c 2005-07-09 08:53:20.649599448 +0200
864@@ -45,10 +45,31 @@
865 {
866 zend_bool rep = 1;
867 sapi_header_line ctr = {0};
868+#if HARDENING_PATCH
869+ int i;
870+#endif
871
872 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &ctr.line,
873 &ctr.line_len, &rep, &ctr.response_code) == FAILURE)
874 return;
875+
876+#if HARDENING_PATCH
877+ if (!HG(hphp_multiheader)) {
878+ for (i=0; i<ctr.line_len; i++) {
879+ if (ctr.line[i]==0) {
880+ php_security_log(S_MISC, "header(): headerline truncated by an ASCII-NUL char");
881+ ctr.line_len=i;
882+ break;
883+ } else if (ctr.line[i]=='\n') {
884+ if (i>0 && (i<ctr.line_len-1) && (ctr.line[i+1]==' ' || ctr.line[i+1]=='\t')) {
885+ continue;
886+ }
887+ php_security_log(S_MISC, "header(): headerline contains more than one header");
888+ ctr.line_len=i;
889+ }
890+ }
891+ }
892+#endif
893
894 sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr TSRMLS_CC);
895 }
896diff -Naur php-4.4.0RC2/ext/standard/info.c hardening-patch-4.4.0RC2-0.3.2/ext/standard/info.c
897--- php-4.4.0RC2/ext/standard/info.c 2005-06-07 15:37:33.000000000 +0200
898+++ hardening-patch-4.4.0RC2-0.3.2/ext/standard/info.c 2005-07-09 08:53:20.649599448 +0200
899@@ -397,7 +397,7 @@
900
901 if (flag & PHP_INFO_GENERAL) {
902 char *zend_version = get_zend_version();
903- char temp_api[9];
904+ char temp_api[11];
905
906 php_uname = php_get_uname('a');
907
908@@ -419,11 +419,22 @@
909 }
910 }
911
912+#if HARDENING_PATCH
913+ if (!sapi_module.phpinfo_as_text) {
914+ php_printf("<h1 class=\"p\">PHP Version %s with Hardening-Patch %s</h1>\n", PHP_VERSION, HARDENING_PATCH_VERSION);
915+ } else {
916+ char temp_ver[40];
917+
918+ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENING_PATCH_VERSION);
919+ php_info_print_table_row(2, "PHP/Hardening-Patch Version", temp_ver);
920+ }
921+#else
922 if (!sapi_module.phpinfo_as_text) {
923 php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
924 } else {
925 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
926 }
927+#endif
928 php_info_print_box_end();
929 php_info_print_table_start();
930 php_info_print_table_row(2, "System", php_uname );
931diff -Naur php-4.4.0RC2/ext/standard/syslog.c hardening-patch-4.4.0RC2-0.3.2/ext/standard/syslog.c
932--- php-4.4.0RC2/ext/standard/syslog.c 2004-07-30 16:38:29.000000000 +0200
933+++ hardening-patch-4.4.0RC2-0.3.2/ext/standard/syslog.c 2005-07-09 08:53:20.650599296 +0200
934@@ -42,6 +42,8 @@
935 */
936 PHP_MINIT_FUNCTION(syslog)
937 {
938+
939+#if !HARDENING_PATCH
940 /* error levels */
941 REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
942 REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
943@@ -97,7 +99,7 @@
944 /* AIX doesn't have LOG_PERROR */
945 REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
946 #endif
947-
948+#endif
949 return SUCCESS;
950 }
951 /* }}} */
952diff -Naur php-4.4.0RC2/ext/varfilter/config.m4 hardening-patch-4.4.0RC2-0.3.2/ext/varfilter/config.m4
953--- php-4.4.0RC2/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100
954+++ hardening-patch-4.4.0RC2-0.3.2/ext/varfilter/config.m4 2005-07-09 08:53:20.650599296 +0200
955@@ -0,0 +1,11 @@
956+dnl
957+dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $
958+dnl
959+
960+PHP_ARG_ENABLE(varfilter, whether to enable Hardening-Patch's variable filter,
961+[ --disable-varfilter Disable Hardening-Patch's variable filter], yes)
962+
963+if test "$PHP_VARFILTER" != "no"; then
964+ AC_DEFINE(HAVE_VARFILTER, 1, [ ])
965+ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared)
966+fi
967diff -Naur php-4.4.0RC2/ext/varfilter/CREDITS hardening-patch-4.4.0RC2-0.3.2/ext/varfilter/CREDITS
968--- php-4.4.0RC2/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100
969+++ hardening-patch-4.4.0RC2-0.3.2/ext/varfilter/CREDITS 2005-07-09 08:53:20.650599296 +0200
970@@ -0,0 +1,2 @@
971+varfilter
972+Stefan Esser
973\ Kein Zeilenumbruch am Dateiende.
974diff -Naur php-4.4.0RC2/ext/varfilter/php_varfilter.h hardening-patch-4.4.0RC2-0.3.2/ext/varfilter/php_varfilter.h
975--- php-4.4.0RC2/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100
976+++ hardening-patch-4.4.0RC2-0.3.2/ext/varfilter/php_varfilter.h 2005-07-09 08:53:20.651599144 +0200
977@@ -0,0 +1,111 @@
978+/*
979+ +----------------------------------------------------------------------+
980+ | Hardened-PHP Project's varfilter extension |
981+ +----------------------------------------------------------------------+
982+ | Copyright (c) 2004-2005 Stefan Esser |
983+ +----------------------------------------------------------------------+
984+ | This source file is subject to version 2.02 of the PHP license, |
985+ | that is bundled with this package in the file LICENSE, and is |
986+ | available at through the world-wide-web at |
987+ | http://www.php.net/license/2_02.txt. |
988+ | If you did not receive a copy of the PHP license and are unable to |
989+ | obtain it through the world-wide-web, please send a note to |
990+ | license@php.net so we can mail you a copy immediately. |
991+ +----------------------------------------------------------------------+
992+ | Author: Stefan Esser <sesser@hardened-php.net> |
993+ +----------------------------------------------------------------------+
994+
995+ $Id: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $
996+*/
997+
998+#ifndef PHP_VARFILTER_H
999+#define PHP_VARFILTER_H
1000+
1001+extern zend_module_entry varfilter_module_entry;
1002+#define phpext_varfilter_ptr &varfilter_module_entry
1003+
1004+#ifdef PHP_WIN32
1005+#define PHP_VARFILTER_API __declspec(dllexport)
1006+#else
1007+#define PHP_VARFILTER_API
1008+#endif
1009+
1010+#ifdef ZTS
1011+#include "TSRM.h"
1012+#endif
1013+
1014+#include "SAPI.h"
1015+
1016+#include "php_variables.h"
1017+
1018+
1019+PHP_MINIT_FUNCTION(varfilter);
1020+PHP_MSHUTDOWN_FUNCTION(varfilter);
1021+PHP_RINIT_FUNCTION(varfilter);
1022+PHP_RSHUTDOWN_FUNCTION(varfilter);
1023+PHP_MINFO_FUNCTION(varfilter);
1024+
1025+
1026+ZEND_BEGIN_MODULE_GLOBALS(varfilter)
1027+// request variables
1028+ long max_request_variables;
1029+ long cur_request_variables;
1030+ long max_varname_length;
1031+ long max_totalname_length;
1032+ long max_value_length;
1033+ long max_array_depth;
1034+ long max_array_index_length;
1035+// cookie variables
1036+ long max_cookie_vars;
1037+ long cur_cookie_vars;
1038+ long max_cookie_name_length;
1039+ long max_cookie_totalname_length;
1040+ long max_cookie_value_length;
1041+ long max_cookie_array_depth;
1042+ long max_cookie_array_index_length;
1043+// get variables
1044+ long max_get_vars;
1045+ long cur_get_vars;
1046+ long max_get_name_length;
1047+ long max_get_totalname_length;
1048+ long max_get_value_length;
1049+ long max_get_array_depth;
1050+ long max_get_array_index_length;
1051+// post variables
1052+ long max_post_vars;
1053+ long cur_post_vars;
1054+ long max_post_name_length;
1055+ long max_post_totalname_length;
1056+ long max_post_value_length;
1057+ long max_post_array_depth;
1058+ long max_post_array_index_length;
1059+// fileupload
1060+ long max_uploads;
1061+ long cur_uploads;
1062+ zend_bool disallow_elf_files;
1063+ char *verification_script;
1064+
1065+ZEND_END_MODULE_GLOBALS(varfilter)
1066+
1067+
1068+#ifdef ZTS
1069+#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v)
1070+#else
1071+#define VARFILTER_G(v) (varfilter_globals.v)
1072+#endif
1073+
1074+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter);
1075+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter);
1076+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter);
1077+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter);
1078+
1079+#endif /* PHP_VARFILTER_H */
1080+
1081+
1082+/*
1083+ * Local variables:
1084+ * tab-width: 4
1085+ * c-basic-offset: 4
1086+ * indent-tabs-mode: t
1087+ * End:
1088+ */
1089diff -Naur php-4.4.0RC2/ext/varfilter/varfilter.c hardening-patch-4.4.0RC2-0.3.2/ext/varfilter/varfilter.c
1090--- php-4.4.0RC2/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100
1091+++ hardening-patch-4.4.0RC2-0.3.2/ext/varfilter/varfilter.c 2005-07-09 08:58:18.504318648 +0200
1092@@ -0,0 +1,604 @@
1093+/*
1094+ +----------------------------------------------------------------------+
1095+ | Hardened-PHP Project's varfilter extension |
1096+ +----------------------------------------------------------------------+
1097+ | Copyright (c) 2004-2005 Stefan Esser |
1098+ +----------------------------------------------------------------------+
1099+ | This source file is subject to version 2.02 of the PHP license, |
1100+ | that is bundled with this package in the file LICENSE, and is |
1101+ | available at through the world-wide-web at |
1102+ | http://www.php.net/license/2_02.txt. |
1103+ | If you did not receive a copy of the PHP license and are unable to |
1104+ | obtain it through the world-wide-web, please send a note to |
1105+ | license@php.net so we can mail you a copy immediately. |
1106+ +----------------------------------------------------------------------+
1107+ | Author: Stefan Esser <sesser@hardened-php.net> |
1108+ +----------------------------------------------------------------------+
1109+
1110+ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $
1111+*/
1112+
1113+#ifdef HAVE_CONFIG_H
1114+#include "config.h"
1115+#endif
1116+
1117+#include "php.h"
1118+#include "php_ini.h"
1119+#include "ext/standard/info.h"
1120+#include "php_varfilter.h"
1121+#include "hardening_patch.h"
1122+
1123+ZEND_DECLARE_MODULE_GLOBALS(varfilter)
1124+
1125+/* True global resources - no need for thread safety here */
1126+static int le_varfilter;
1127+
1128+/* {{{ varfilter_module_entry
1129+ */
1130+zend_module_entry varfilter_module_entry = {
1131+#if ZEND_MODULE_API_NO >= 20010901
1132+ STANDARD_MODULE_HEADER,
1133+#endif
1134+ "varfilter",
1135+ NULL,
1136+ PHP_MINIT(varfilter),
1137+ PHP_MSHUTDOWN(varfilter),
1138+ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */
1139+ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */
1140+ PHP_MINFO(varfilter),
1141+#if ZEND_MODULE_API_NO >= 20010901
1142+ "0.3.2", /* Replace with version number for your extension */
1143+#endif
1144+ STANDARD_MODULE_PROPERTIES
1145+};
1146+/* }}} */
1147+
1148+#ifdef COMPILE_DL_VARFILTER
1149+ZEND_GET_MODULE(varfilter)
1150+#endif
1151+
1152+/* {{{ PHP_INI
1153+ */
1154+PHP_INI_BEGIN()
1155+ /* for backward compatibility */
1156+ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
1157+ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
1158+ STD_PHP_INI_ENTRY("varfilter.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
1159+ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
1160+ STD_PHP_INI_ENTRY("varfilter.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
1161+ STD_PHP_INI_ENTRY("varfilter.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
1162+
1163+ STD_PHP_INI_ENTRY("hphp.request.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
1164+ STD_PHP_INI_ENTRY("hphp.request.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
1165+ STD_PHP_INI_ENTRY("hphp.request.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
1166+ STD_PHP_INI_ENTRY("hphp.request.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
1167+ STD_PHP_INI_ENTRY("hphp.request.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
1168+ STD_PHP_INI_ENTRY("hphp.request.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
1169+
1170+ STD_PHP_INI_ENTRY("hphp.cookie.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_vars, zend_varfilter_globals, varfilter_globals)
1171+ STD_PHP_INI_ENTRY("hphp.cookie.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_name_length, zend_varfilter_globals, varfilter_globals)
1172+ STD_PHP_INI_ENTRY("hphp.cookie.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_cookie_totalname_length, zend_varfilter_globals, varfilter_globals)
1173+ STD_PHP_INI_ENTRY("hphp.cookie.max_value_length", "10000", PHP_INI_PERDIR, OnUpdateLong, max_cookie_value_length, zend_varfilter_globals, varfilter_globals)
1174+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_depth, zend_varfilter_globals, varfilter_globals)
1175+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_index_length, zend_varfilter_globals, varfilter_globals)
1176+
1177+ STD_PHP_INI_ENTRY("hphp.get.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_get_vars, zend_varfilter_globals, varfilter_globals)
1178+ STD_PHP_INI_ENTRY("hphp.get.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_name_length, zend_varfilter_globals, varfilter_globals)
1179+ STD_PHP_INI_ENTRY("hphp.get.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_get_totalname_length, zend_varfilter_globals, varfilter_globals)
1180+ STD_PHP_INI_ENTRY("hphp.get.max_value_length", "512", PHP_INI_PERDIR, OnUpdateLong, max_get_value_length, zend_varfilter_globals, varfilter_globals)
1181+ STD_PHP_INI_ENTRY("hphp.get.max_array_depth", "50", PHP_INI_PERDIR, OnUpdateLong, max_get_array_depth, zend_varfilter_globals, varfilter_globals)
1182+ STD_PHP_INI_ENTRY("hphp.get.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_array_index_length, zend_varfilter_globals, varfilter_globals)
1183+
1184+ STD_PHP_INI_ENTRY("hphp.post.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_post_vars, zend_varfilter_globals, varfilter_globals)
1185+ STD_PHP_INI_ENTRY("hphp.post.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_name_length, zend_varfilter_globals, varfilter_globals)
1186+ STD_PHP_INI_ENTRY("hphp.post.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_post_totalname_length, zend_varfilter_globals, varfilter_globals)
1187+ STD_PHP_INI_ENTRY("hphp.post.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_post_value_length, zend_varfilter_globals, varfilter_globals)
1188+ STD_PHP_INI_ENTRY("hphp.post.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_post_array_depth, zend_varfilter_globals, varfilter_globals)
1189+ STD_PHP_INI_ENTRY("hphp.post.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_array_index_length, zend_varfilter_globals, varfilter_globals)
1190+
1191+ STD_PHP_INI_ENTRY("hphp.upload.max_uploads", "25", PHP_INI_PERDIR, OnUpdateLong, max_uploads, zend_varfilter_globals, varfilter_globals)
1192+ STD_PHP_INI_ENTRY("hphp.upload.disallow_elf_files", "1", PHP_INI_SYSTEM, OnUpdateBool, disallow_elf_files, zend_varfilter_globals, varfilter_globals)
1193+ STD_PHP_INI_ENTRY("hphp.upload.verification_script", NULL, PHP_INI_SYSTEM, OnUpdateString, verification_script, zend_varfilter_globals, varfilter_globals)
1194+
1195+
1196+PHP_INI_END()
1197+/* }}} */
1198+
1199+/* {{{ php_varfilter_init_globals
1200+ */
1201+static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals)
1202+{
1203+ varfilter_globals->max_request_variables = 200;
1204+ varfilter_globals->max_varname_length = 64;
1205+ varfilter_globals->max_value_length = 10000;
1206+ varfilter_globals->max_array_depth = 100;
1207+ varfilter_globals->max_totalname_length = 256;
1208+ varfilter_globals->max_array_index_length = 64;
1209+
1210+ varfilter_globals->max_cookie_vars = 100;
1211+ varfilter_globals->max_cookie_name_length = 64;
1212+ varfilter_globals->max_cookie_totalname_length = 256;
1213+ varfilter_globals->max_cookie_value_length = 10000;
1214+ varfilter_globals->max_cookie_array_depth = 100;
1215+ varfilter_globals->max_cookie_array_index_length = 64;
1216+
1217+ varfilter_globals->max_get_vars = 100;
1218+ varfilter_globals->max_get_name_length = 64;
1219+ varfilter_globals->max_get_totalname_length = 256;
1220+ varfilter_globals->max_get_value_length = 512;
1221+ varfilter_globals->max_get_array_depth = 50;
1222+ varfilter_globals->max_get_array_index_length = 64;
1223+
1224+ varfilter_globals->max_post_vars = 200;
1225+ varfilter_globals->max_post_name_length = 64;
1226+ varfilter_globals->max_post_totalname_length = 256;
1227+ varfilter_globals->max_post_value_length = 65000;
1228+ varfilter_globals->max_post_array_depth = 100;
1229+ varfilter_globals->max_post_array_index_length = 64;
1230+
1231+ varfilter_globals->max_uploads = 25;
1232+ varfilter_globals->disallow_elf_files = 1;
1233+ varfilter_globals->verification_script = NULL;
1234+}
1235+/* }}} */
1236+
1237+/* {{{ PHP_MINIT_FUNCTION
1238+ */
1239+PHP_MINIT_FUNCTION(varfilter)
1240+{
1241+ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL);
1242+ REGISTER_INI_ENTRIES();
1243+
1244+ sapi_register_input_filter(varfilter_input_filter);
1245+ sapi_register_pre_upload_filter(varfilter_pre_upload_filter);
1246+ sapi_register_upload_content_filter(varfilter_upload_content_filter);
1247+ sapi_register_post_upload_filter(varfilter_post_upload_filter);
1248+
1249+ return SUCCESS;
1250+}
1251+/* }}} */
1252+
1253+/* {{{ PHP_MSHUTDOWN_FUNCTION
1254+ */
1255+PHP_MSHUTDOWN_FUNCTION(varfilter)
1256+{
1257+// zend_hash_apply_with_arguments(&HG(lists.functionlists), (apply_func_args_t) show_stuff, 0);
1258+
1259+ UNREGISTER_INI_ENTRIES();
1260+
1261+ return SUCCESS;
1262+}
1263+/* }}} */
1264+
1265+/* Remove if there's nothing to do at request start */
1266+/* {{{ PHP_RINIT_FUNCTION
1267+ */
1268+PHP_RINIT_FUNCTION(varfilter)
1269+{
1270+ VARFILTER_G(cur_request_variables) = 0;
1271+ VARFILTER_G(cur_get_vars) = 0;
1272+ VARFILTER_G(cur_post_vars) = 0;
1273+ VARFILTER_G(cur_cookie_vars) = 0;
1274+
1275+ VARFILTER_G(cur_uploads) = 0;
1276+
1277+ return SUCCESS;
1278+}
1279+/* }}} */
1280+
1281+/* Remove if there's nothing to do at request end */
1282+/* {{{ PHP_RSHUTDOWN_FUNCTION
1283+ */
1284+PHP_RSHUTDOWN_FUNCTION(varfilter)
1285+{
1286+ return SUCCESS;
1287+}
1288+/* }}} */
1289+
1290+/* {{{ PHP_MINFO_FUNCTION
1291+ */
1292+PHP_MINFO_FUNCTION(varfilter)
1293+{
1294+ php_info_print_table_start();
1295+ php_info_print_table_header(2, "Hardening-Patch's variable filter support", "enabled");
1296+ php_info_print_table_end();
1297+
1298+ DISPLAY_INI_ENTRIES();
1299+}
1300+/* }}} */
1301+
1302+/* {{{ normalize_varname
1303+ */
1304+static void normalize_varname(char *varname)
1305+{
1306+ char *s=varname, *index=NULL, *indexend=NULL, *p;
1307+
1308+ /* overjump leading space */
1309+ while (*s == ' ') {
1310+ s++;
1311+ }
1312+
1313+ /* and remove it */
1314+ if (s != varname) {
1315+ memmove(varname, s, strlen(s)+1);
1316+ }
1317+
1318+ for (p=varname; *p && *p != '['; p++) {
1319+ switch(*p) {
1320+ case ' ':
1321+ case '.':
1322+ *p='_';
1323+ break;
1324+ }
1325+ }
1326+
1327+ /* find index */
1328+ index = strchr(varname, '[');
1329+ if (index) {
1330+ index++;
1331+ s=index;
1332+ } else {
1333+ return;
1334+ }
1335+
1336+ /* done? */
1337+ while (index) {
1338+
1339+ while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
1340+ index++;
1341+ }
1342+ indexend = strchr(index, ']');
1343+ indexend = indexend ? indexend + 1 : index + strlen(index);
1344+
1345+ if (s != index) {
1346+ memmove(s, index, strlen(index)+1);
1347+ s += indexend-index;
1348+ } else {
1349+ s = indexend;
1350+ }
1351+
1352+ if (*s == '[') {
1353+ s++;
1354+ index = s;
1355+ } else {
1356+ index = NULL;
1357+ }
1358+ }
1359+ *s++='\0';
1360+}
1361+/* }}} */
1362+
1363+/* {{{ SAPI_PRE_UPLOAD_FILTER_FUNC
1364+ */
1365+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter)
1366+{
1367+ /* Drop this fileupload if the limit is reached */
1368+ if (VARFILTER_G(max_uploads) && VARFILTER_G(max_uploads) <= VARFILTER_G(cur_uploads)) {
1369+ php_security_log(S_FILES, "configured fileupload limit exceeded - file dropped");
1370+ return FAILURE;
1371+ }
1372+
1373+ return SUCCESS;
1374+}
1375+/* }}} */
1376+
1377+/* {{{ SAPI_UPLOAD_CONTENT_FILTER_FUNC
1378+ */
1379+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter)
1380+{
1381+
1382+ if (VARFILTER_G(disallow_elf_files)) {
1383+
1384+ if (offset == 0 && buffer_len > 10) {
1385+
1386+ if (buffer[0] == 0x7F && buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'F') {
1387+ php_security_log(S_FILES, "uploaded file is an ELF executable - file dropped");
1388+ return FAILURE;
1389+ }
1390+ }
1391+
1392+ }
1393+
1394+ return SUCCESS;
1395+}
1396+/* }}} */
1397+
1398+/* {{{ SAPI_POST_UPLOAD_FILTER_FUNC
1399+ */
1400+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter)
1401+{
1402+ int retval = SUCCESS;
1403+
1404+ if (VARFILTER_G(verification_script)) {
1405+ char cmd[8192];
1406+ FILE *in;
1407+ int first=1;
1408+
1409+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s", VARFILTER_G(verification_script), tmpfilename);
1410+
1411+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
1412+ php_security_log(S_FILES, "unable to execute fileupload verification script - file dropped");
1413+ return FAILURE;
1414+ }
1415+
1416+ retval = FAILURE;
1417+
1418+ /* read and forget the result */
1419+ while (1) {
1420+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
1421+ if (readbytes<=0) {
1422+ break;
1423+ }
1424+ if (first) {
1425+ retval = atoi(cmd) == 1 ? SUCCESS : FAILURE;
1426+ first = 0;
1427+ }
1428+ }
1429+ pclose(in);
1430+ }
1431+
1432+ if (retval != SUCCESS) {
1433+ php_security_log(S_FILES, "fileupload verification script disallows file - file dropped");
1434+ return FAILURE;
1435+ }
1436+
1437+ VARFILTER_G(cur_uploads)++;
1438+ return SUCCESS;
1439+}
1440+/* }}} */
1441+
1442+/* {{{ SAPI_INPUT_FILTER_FUNC
1443+ */
1444+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter)
1445+{
1446+ char *index, *prev_index = NULL, *copy_var;
1447+ unsigned int var_len, total_len, depth = 0, rv;
1448+
1449+ /* Drop this variable if the limit is reached */
1450+ if (VARFILTER_G(max_request_variables) && VARFILTER_G(max_request_variables) <= VARFILTER_G(cur_request_variables)) {
1451+ php_security_log(S_VARS, "configured request variable limit exceeded - dropped %s", var);
1452+ return 0;
1453+ }
1454+ switch (arg) {
1455+ case PARSE_GET:
1456+ if (VARFILTER_G(max_get_vars) && VARFILTER_G(max_get_vars) <= VARFILTER_G(cur_get_vars)) {
1457+ php_security_log(S_VARS, "configured GET variable limit exceeded - dropped %s", var);
1458+ return 0;
1459+ }
1460+ break;
1461+ case PARSE_COOKIE:
1462+ if (VARFILTER_G(max_cookie_vars) && VARFILTER_G(max_cookie_vars) <= VARFILTER_G(cur_cookie_vars)) {
1463+ php_security_log(S_VARS, "configured COOKIE variable limit exceeded - dropped %s", var);
1464+ return 0;
1465+ }
1466+ break;
1467+ case PARSE_POST:
1468+ if (VARFILTER_G(max_post_vars) && VARFILTER_G(max_post_vars) <= VARFILTER_G(cur_post_vars)) {
1469+ php_security_log(S_VARS, "configured POST variable limit exceeded - dropped %s", var);
1470+ return 0;
1471+ }
1472+ break;
1473+ }
1474+
1475+
1476+ /* Drop this variable if it exceeds the value length limit */
1477+ if (VARFILTER_G(max_value_length) && VARFILTER_G(max_value_length) < val_len) {
1478+ php_security_log(S_VARS, "configured request variable value length limit exceeded - dropped %s", var);
1479+ return 0;
1480+ }
1481+ switch (arg) {
1482+ case PARSE_GET:
1483+ if (VARFILTER_G(max_get_value_length) && VARFILTER_G(max_get_value_length) < val_len) {
1484+ php_security_log(S_VARS, "configured GET variable value length limit exceeded - dropped %s", var);
1485+ return 0;
1486+ }
1487+ break;
1488+ case PARSE_COOKIE:
1489+ if (VARFILTER_G(max_cookie_value_length) && VARFILTER_G(max_cookie_value_length) < val_len) {
1490+ php_security_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped %s", var);
1491+ return 0;
1492+ }
1493+ break;
1494+ case PARSE_POST:
1495+ if (VARFILTER_G(max_post_value_length) && VARFILTER_G(max_post_value_length) < val_len) {
1496+ php_security_log(S_VARS, "configured POST variable value length limit exceeded - dropped %s", var);
1497+ return 0;
1498+ }
1499+ break;
1500+ }
1501+
1502+ /* Normalize the variable name */
1503+ normalize_varname(var);
1504+
1505+ /* Find length of variable name */
1506+ index = strchr(var, '[');
1507+ total_len = strlen(var);
1508+ var_len = index ? index-var : total_len;
1509+
1510+ /* Drop this variable if it exceeds the varname/total length limit */
1511+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
1512+ php_security_log(S_VARS, "configured request variable name length limit exceeded - dropped %s", var);
1513+ return 0;
1514+ }
1515+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
1516+ php_security_log(S_VARS, "configured request variable total name length limit exceeded - dropped %s", var);
1517+ return 0;
1518+ }
1519+ switch (arg) {
1520+ case PARSE_GET:
1521+ if (VARFILTER_G(max_get_name_length) && VARFILTER_G(max_get_name_length) < var_len) {
1522+ php_security_log(S_VARS, "configured GET variable name length limit exceeded - dropped %s", var);
1523+ return 0;
1524+ }
1525+ if (VARFILTER_G(max_get_totalname_length) && VARFILTER_G(max_get_totalname_length) < var_len) {
1526+ php_security_log(S_VARS, "configured GET variable total name length limit exceeded - dropped %s", var);
1527+ return 0;
1528+ }
1529+ break;
1530+ case PARSE_COOKIE:
1531+ if (VARFILTER_G(max_cookie_name_length) && VARFILTER_G(max_cookie_name_length) < var_len) {
1532+ php_security_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped %s", var);
1533+ return 0;
1534+ }
1535+ if (VARFILTER_G(max_cookie_totalname_length) && VARFILTER_G(max_cookie_totalname_length) < var_len) {
1536+ php_security_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped %s", var);
1537+ return 0;
1538+ }
1539+ break;
1540+ case PARSE_POST:
1541+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
1542+ php_security_log(S_VARS, "configured POST variable name length limit exceeded - dropped %s", var);
1543+ return 0;
1544+ }
1545+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
1546+ php_security_log(S_VARS, "configured POST variable total name length limit exceeded - dropped %s", var);
1547+ return 0;
1548+ }
1549+ break;
1550+ }
1551+
1552+ /* Find out array depth */
1553+ while (index) {
1554+ unsigned int index_length;
1555+
1556+ depth++;
1557+ index = strchr(index+1, '[');
1558+
1559+ if (prev_index) {
1560+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
1561+
1562+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
1563+ php_security_log(S_VARS, "configured request variable array index length limit exceeded - dropped %s", var);
1564+ return 0;
1565+ }
1566+ switch (arg) {
1567+ case PARSE_GET:
1568+ if (VARFILTER_G(max_get_array_index_length) && VARFILTER_G(max_get_array_index_length) < index_length) {
1569+ php_security_log(S_VARS, "configured GET variable array index length limit exceeded - dropped %s", var);
1570+ return 0;
1571+ }
1572+ break;
1573+ case PARSE_COOKIE:
1574+ if (VARFILTER_G(max_cookie_array_index_length) && VARFILTER_G(max_cookie_array_index_length) < index_length) {
1575+ php_security_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped %s", var);
1576+ return 0;
1577+ }
1578+ break;
1579+ case PARSE_POST:
1580+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
1581+ php_security_log(S_VARS, "configured POST variable array index length limit exceeded - dropped %s", var);
1582+ return 0;
1583+ }
1584+ break;
1585+ }
1586+ prev_index = index;
1587+ }
1588+
1589+ }
1590+
1591+ /* Drop this variable if it exceeds the array depth limit */
1592+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
1593+ php_security_log(S_VARS, "configured request variable array depth limit exceeded - dropped %s", var);
1594+ return 0;
1595+ }
1596+ switch (arg) {
1597+ case PARSE_GET:
1598+ if (VARFILTER_G(max_get_array_depth) && VARFILTER_G(max_get_array_depth) < depth) {
1599+ php_security_log(S_VARS, "configured GET variable array depth limit exceeded - dropped %s", var);
1600+ return 0;
1601+ }
1602+ break;
1603+ case PARSE_COOKIE:
1604+ if (VARFILTER_G(max_cookie_array_depth) && VARFILTER_G(max_cookie_array_depth) < depth) {
1605+ php_security_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped %s", var);
1606+ return 0;
1607+ }
1608+ break;
1609+ case PARSE_POST:
1610+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
1611+ php_security_log(S_VARS, "configured POST variable array depth limit exceeded - dropped %s", var);
1612+ return 0;
1613+ }
1614+ break;
1615+ }
1616+
1617+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
1618+ /* This is to protect several silly scripts that do globalizing themself */
1619+
1620+ switch (var_len) {
1621+ case 18:
1622+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname;
1623+ break;
1624+ case 17:
1625+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname;
1626+ break;
1627+ case 16:
1628+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname;
1629+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname;
1630+ break;
1631+ case 15:
1632+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname;
1633+ break;
1634+ case 14:
1635+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname;
1636+ break;
1637+ case 13:
1638+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname;
1639+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname;
1640+ break;
1641+ case 8:
1642+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname;
1643+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname;
1644+ break;
1645+ case 7:
1646+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname;
1647+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname;
1648+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname;
1649+ break;
1650+ case 6:
1651+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname;
1652+ break;
1653+ case 5:
1654+ if (memcmp(var, "_POST", 5)==0) goto protected_varname;
1655+ break;
1656+ case 4:
1657+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname;
1658+ if (memcmp(var, "_GET", 4)==0) goto protected_varname;
1659+ break;
1660+ }
1661+
1662+ /* Okay let PHP register this variable */
1663+ VARFILTER_G(cur_request_variables)++;
1664+ switch (arg) {
1665+ case PARSE_GET:
1666+ VARFILTER_G(cur_get_vars)++;
1667+ break;
1668+ case PARSE_COOKIE:
1669+ VARFILTER_G(cur_cookie_vars)++;
1670+ break;
1671+ case PARSE_POST:
1672+ VARFILTER_G(cur_post_vars)++;
1673+ break;
1674+ }
1675+
1676+ if (new_val_len) {
1677+ *new_val_len = val_len;
1678+ }
1679+
1680+ return 1;
1681+protected_varname:
1682+ php_security_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
1683+ return 0;
1684+}
1685+/* }}} */
1686+
1687+/*
1688+ * Local variables:
1689+ * tab-width: 4
1690+ * c-basic-offset: 4
1691+ * End:
1692+ * vim600: noet sw=4 ts=4 fdm=marker
1693+ * vim<600: noet sw=4 ts=4
1694+ */
1695+
1696+
1697diff -Naur php-4.4.0RC2/main/fopen_wrappers.c hardening-patch-4.4.0RC2-0.3.2/main/fopen_wrappers.c
1698--- php-4.4.0RC2/main/fopen_wrappers.c 2005-02-03 00:44:07.000000000 +0100
1699+++ hardening-patch-4.4.0RC2-0.3.2/main/fopen_wrappers.c 2005-07-09 08:53:20.652598992 +0200
1700@@ -166,6 +166,21 @@
1701 char *pathbuf;
1702 char *ptr;
1703 char *end;
1704+ char path_copy[MAXPATHLEN];
1705+ int path_len;
1706+
1707+ /* Special case path ends with a trailing slash */
1708+ path_len = strlen(path);
1709+ if (path_len >= MAXPATHLEN) {
1710+ errno = EPERM; /* we deny permission to open it */
1711+ return -1;
1712+ }
1713+ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) {
1714+ memcpy(path_copy, path, path_len+1);
1715+ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--;
1716+ path_copy[path_len] = '\0';
1717+ path = (const char *)&path_copy;
1718+ }
1719
1720 pathbuf = estrdup(PG(open_basedir));
1721
1722diff -Naur php-4.4.0RC2/main/hardened_globals.h hardening-patch-4.4.0RC2-0.3.2/main/hardened_globals.h
1723--- php-4.4.0RC2/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100
1724+++ hardening-patch-4.4.0RC2-0.3.2/main/hardened_globals.h 2005-07-09 08:53:20.653598840 +0200
1725@@ -0,0 +1,56 @@
1726+/*
1727+ +----------------------------------------------------------------------+
1728+ | Hardening-Patch for PHP |
1729+ +----------------------------------------------------------------------+
1730+ | Copyright (c) 2004-2005 Stefan Esser |
1731+ +----------------------------------------------------------------------+
1732+ | This source file is subject to version 2.02 of the PHP license, |
1733+ | that is bundled with this package in the file LICENSE, and is |
1734+ | available at through the world-wide-web at |
1735+ | http://www.php.net/license/2_02.txt. |
1736+ | If you did not receive a copy of the PHP license and are unable to |
1737+ | obtain it through the world-wide-web, please send a note to |
1738+ | license@php.net so we can mail you a copy immediately. |
1739+ +----------------------------------------------------------------------+
1740+ | Author: Stefan Esser <sesser@hardened-php.net> |
1741+ +----------------------------------------------------------------------+
1742+ */
1743+
1744+#ifndef HARDENED_GLOBALS_H
1745+#define HARDENED_GLOBALS_H
1746+
1747+typedef struct _hardened_globals hardened_globals_struct;
1748+
1749+#ifdef ZTS
1750+# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v)
1751+extern int hardened_globals_id;
1752+#else
1753+# define HG(v) (hardened_globals.v)
1754+extern struct _hardened_globals hardened_globals;
1755+#endif
1756+
1757+
1758+struct _hardened_globals {
1759+#if HARDENING_PATCH_MM_PROTECT
1760+ unsigned int canary_1;
1761+ unsigned int canary_2;
1762+#endif
1763+#if HARDENING_PATCH_LL_PROTECT
1764+ unsigned int canary_3;
1765+ unsigned int canary_4;
1766+ unsigned int ll_canary_inited;
1767+#endif
1768+ zend_bool hphp_sql_bailout_on_error;
1769+ zend_bool hphp_multiheader;
1770+ unsigned int dummy;
1771+};
1772+
1773+
1774+#endif /* HARDENED_GLOBALS_H */
1775+
1776+/*
1777+ * Local variables:
1778+ * tab-width: 4
1779+ * c-basic-offset: 4
1780+ * End:
1781+ */
1782diff -Naur php-4.4.0RC2/main/hardening_patch.c hardening-patch-4.4.0RC2-0.3.2/main/hardening_patch.c
1783--- php-4.4.0RC2/main/hardening_patch.c 1970-01-01 01:00:00.000000000 +0100
1784+++ hardening-patch-4.4.0RC2-0.3.2/main/hardening_patch.c 2005-07-09 08:53:20.653598840 +0200
1785@@ -0,0 +1,322 @@
1786+/*
1787+ +----------------------------------------------------------------------+
1788+ | Hardening Patch for PHP |
1789+ +----------------------------------------------------------------------+
1790+ | Copyright (c) 2004-2005 Stefan Esser |
1791+ +----------------------------------------------------------------------+
1792+ | This source file is subject to version 2.02 of the PHP license, |
1793+ | that is bundled with this package in the file LICENSE, and is |
1794+ | available at through the world-wide-web at |
1795+ | http://www.php.net/license/2_02.txt. |
1796+ | If you did not receive a copy of the PHP license and are unable to |
1797+ | obtain it through the world-wide-web, please send a note to |
1798+ | license@php.net so we can mail you a copy immediately. |
1799+ +----------------------------------------------------------------------+
1800+ | Author: Stefan Esser <sesser@hardened-php.net> |
1801+ +----------------------------------------------------------------------+
1802+ */
1803+/* $Id: hardening_patch.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */
1804+
1805+#include "php.h"
1806+
1807+#include <stdio.h>
1808+#include <stdlib.h>
1809+
1810+#if HAVE_UNISTD_H
1811+#include <unistd.h>
1812+#endif
1813+#include "SAPI.h"
1814+#include "php_globals.h"
1815+
1816+#if HARDENING_PATCH
1817+
1818+#ifdef HAVE_SYS_SOCKET_H
1819+#include <sys/socket.h>
1820+#endif
1821+
1822+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
1823+#undef AF_UNIX
1824+#endif
1825+
1826+#if defined(AF_UNIX)
1827+#include <sys/un.h>
1828+#endif
1829+
1830+#define SYSLOG_PATH "/dev/log"
1831+
1832+#include "snprintf.h"
1833+
1834+#include "hardening_patch.h"
1835+
1836+#ifdef ZTS
1837+#include "hardened_globals.h"
1838+int hardened_globals_id;
1839+#else
1840+struct _hardened_globals hardened_globals;
1841+#endif
1842+
1843+static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC)
1844+{
1845+ memset(hardened_globals, 0, sizeof(*hardened_globals));
1846+}
1847+
1848+
1849+PHPAPI void hardened_startup()
1850+{
1851+#ifdef ZTS
1852+ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL);
1853+#else
1854+ hardened_globals_ctor(&hardened_globals TSRMLS_CC);
1855+#endif
1856+}
1857+
1858+char *loglevel2string(int loglevel)
1859+{
1860+ switch (loglevel) {
1861+ case S_FILES:
1862+ return "FILES";
1863+ case S_INCLUDE:
1864+ return "INCLUDE";
1865+ case S_MEMORY:
1866+ return "MEMORY";
1867+ case S_MISC:
1868+ return "MISC";
1869+ case S_SQL:
1870+ return "SQL";
1871+ case S_EXECUTOR:
1872+ return "EXECUTOR";
1873+ case S_VARS:
1874+ return "VARS";
1875+ default:
1876+ return "UNKNOWN";
1877+ }
1878+}
1879+
1880+PHPAPI void php_security_log(int loglevel, char *fmt, ...)
1881+{
1882+#if defined(AF_UNIX)
1883+ int s, r, i=0;
1884+ struct sockaddr_un saun;
1885+ char buf[4096+64];
1886+ char error[4096+100];
1887+ char *ip_address;
1888+ char *fname;
1889+ int lineno;
1890+ va_list ap;
1891+ TSRMLS_FETCH();
1892+
1893+ if (EG(hphp_log_use_x_forwarded_for)) {
1894+ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
1895+ if (ip_address == NULL) {
1896+ ip_address = "X-FORWARDED-FOR not set";
1897+ }
1898+ } else {
1899+ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
1900+ if (ip_address == NULL) {
1901+ ip_address = "REMOTE_ADDR not set";
1902+ }
1903+ }
1904+
1905+
1906+ va_start(ap, fmt);
1907+ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
1908+ va_end(ap);
1909+ while (error[i]) {
1910+ if (error[i] < 32) error[i] = '.';
1911+ i++;
1912+ }
1913+
1914+ if (zend_is_executing(TSRMLS_C)) {
1915+ lineno = zend_get_executed_lineno(TSRMLS_C);
1916+ fname = zend_get_executed_filename(TSRMLS_C);
1917+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s', line %u)", error, ip_address, fname, lineno);
1918+ } else {
1919+ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
1920+ if (fname==NULL) {
1921+ fname = "unknown";
1922+ }
1923+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s')", error, ip_address, fname);
1924+ }
1925+
1926+ /* Syslog-Logging disabled? */
1927+ if ((EG(hphp_log_syslog) & loglevel)==0) {
1928+ goto log_sapi;
1929+ }
1930+
1931+ ap_php_snprintf(error, sizeof(error), "<%u>hphp[%u]: %s\n", EG(hphp_log_syslog_facility)|EG(hphp_log_syslog_priority),getpid(),buf);
1932+
1933+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
1934+ if (s == -1) {
1935+ goto log_sapi;
1936+ }
1937+
1938+ memset(&saun, 0, sizeof(saun));
1939+ saun.sun_family = AF_UNIX;
1940+ strcpy(saun.sun_path, SYSLOG_PATH);
1941+ /*saun.sun_len = sizeof(saun);*/
1942+
1943+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
1944+ if (r) {
1945+ close(s);
1946+ s = socket(AF_UNIX, SOCK_STREAM, 0);
1947+ if (s == -1) {
1948+ goto log_sapi;
1949+ }
1950+
1951+ memset(&saun, 0, sizeof(saun));
1952+ saun.sun_family = AF_UNIX;
1953+ strcpy(saun.sun_path, SYSLOG_PATH);
1954+ /*saun.sun_len = sizeof(saun);*/
1955+
1956+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
1957+ if (r) {
1958+ close(s);
1959+ goto log_sapi;
1960+ }
1961+ }
1962+ send(s, error, strlen(error), 0);
1963+
1964+ close(s);
1965+
1966+log_sapi:
1967+ /* SAPI Logging activated? */
1968+ if ((EG(hphp_log_syslog) & loglevel)!=0) {
1969+ sapi_module.log_message(buf);
1970+ }
1971+
1972+log_script:
1973+ /* script logging activaed? */
1974+ if (((EG(hphp_log_script) & loglevel)!=0) && EG(hphp_log_scriptname)!=NULL) {
1975+ char cmd[8192], *cmdpos, *bufpos;
1976+ FILE *in;
1977+ int space;
1978+
1979+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", EG(hphp_log_scriptname), loglevel2string(loglevel));
1980+ space = sizeof(cmd) - strlen(cmd);
1981+ cmdpos = cmd + strlen(cmd);
1982+ bufpos = buf;
1983+ if (space <= 1) return;
1984+ while (space > 2 && *bufpos) {
1985+ if (*bufpos == '\'') {
1986+ if (space<=5) break;
1987+ *cmdpos++ = '\'';
1988+ *cmdpos++ = '\\';
1989+ *cmdpos++ = '\'';
1990+ *cmdpos++ = '\'';
1991+ bufpos++;
1992+ space-=4;
1993+ } else {
1994+ *cmdpos++ = *bufpos++;
1995+ space--;
1996+ }
1997+ }
1998+ *cmdpos++ = '\'';
1999+ *cmdpos = 0;
2000+
2001+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
2002+ return;
2003+ }
2004+ /* read and forget the result */
2005+ while (1) {
2006+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
2007+ if (readbytes<=0) {
2008+ break;
2009+ }
2010+ }
2011+ pclose(in);
2012+ }
2013+
2014+#endif
2015+}
2016+#endif
2017+
2018+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
2019+
2020+/* will be replaced later with more compatible method */
2021+PHPAPI unsigned int php_canary()
2022+{
2023+ time_t t;
2024+ unsigned int canary;
2025+ int fd;
2026+
2027+ fd = open("/dev/urandom", 0);
2028+ if (fd != -1) {
2029+ int r = read(fd, &canary, sizeof(canary));
2030+ close(fd);
2031+ if (r == sizeof(canary)) {
2032+ return (canary);
2033+ }
2034+ }
2035+ /* not good but we never want to do this */
2036+ time(&t);
2037+ canary = *(unsigned int *)&t + getpid() << 16;
2038+ return (canary);
2039+}
2040+#endif
2041+
2042+#if HARDENING_PATCH_INC_PROTECT
2043+
2044+PHPAPI int php_is_valid_include(zval *z)
2045+{
2046+ char *filename;
2047+ int len, i;
2048+ TSRMLS_FETCH();
2049+
2050+ /* must be of type string */
2051+ if (z->type != IS_STRING || z->value.str.val == NULL) {
2052+ return (0);
2053+ }
2054+
2055+ /* short cut */
2056+ filename = z->value.str.val;
2057+ len = z->value.str.len;
2058+
2059+ /* 1. must be shorter than MAXPATHLEN */
2060+ if (len > MAXPATHLEN) {
2061+ char *fname = estrndup(filename, len);
2062+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
2063+ php_security_log(S_INCLUDE, "Include filename ('%s') longer than MAXPATHLEN chars", fname);
2064+ efree(fname);
2065+ return (0);
2066+ }
2067+
2068+ /* 2. must not be cutted */
2069+ if (len != strlen(filename)) {
2070+ char *fname = estrndup(filename, len);
2071+ for (i=0; fname[i]; i++) if (fname[i] < 32) fname[i]='.';
2072+ php_security_log(S_INCLUDE, "Include filename truncated by a \\0 after '%s'", fname);
2073+ efree(fname);
2074+ return (0);
2075+ }
2076+
2077+ /* 3. must not be a URL */
2078+ if (strstr(filename, "://")) {
2079+ char *fname = estrndup(filename, len);
2080+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
2081+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL", fname);
2082+ efree(fname);
2083+ return (0);
2084+ }
2085+
2086+ /* 4. must not be an uploaded file */
2087+ if (SG(rfc1867_uploaded_files)) {
2088+ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) {
2089+ php_security_log(S_INCLUDE, "Include filename is an uploaded file");
2090+ return (0);
2091+ }
2092+ }
2093+
2094+ /* passed all tests */
2095+ return (1);
2096+}
2097+
2098+#endif
2099+
2100+/*
2101+ * Local variables:
2102+ * tab-width: 4
2103+ * c-basic-offset: 4
2104+ * End:
2105+ * vim600: sw=4 ts=4 fdm=marker
2106+ * vim<600: sw=4 ts=4
2107+ */
2108diff -Naur php-4.4.0RC2/main/hardening_patch.h hardening-patch-4.4.0RC2-0.3.2/main/hardening_patch.h
2109--- php-4.4.0RC2/main/hardening_patch.h 1970-01-01 01:00:00.000000000 +0100
2110+++ hardening-patch-4.4.0RC2-0.3.2/main/hardening_patch.h 2005-07-09 08:58:18.505318496 +0200
2111@@ -0,0 +1,46 @@
2112+/*
2113+ +----------------------------------------------------------------------+
2114+ | Hardening Patch for PHP |
2115+ +----------------------------------------------------------------------+
2116+ | Copyright (c) 2004-2005 Stefan Esser |
2117+ +----------------------------------------------------------------------+
2118+ | This source file is subject to version 2.02 of the PHP license, |
2119+ | that is bundled with this package in the file LICENSE, and is |
2120+ | available at through the world-wide-web at |
2121+ | http://www.php.net/license/2_02.txt. |
2122+ | If you did not receive a copy of the PHP license and are unable to |
2123+ | obtain it through the world-wide-web, please send a note to |
2124+ | license@php.net so we can mail you a copy immediately. |
2125+ +----------------------------------------------------------------------+
2126+ | Author: Stefan Esser <sesser@hardened-php.net> |
2127+ +----------------------------------------------------------------------+
2128+ */
2129+
2130+#ifndef HARDENING_PATCH_H
2131+#define HARDENING_PATCH_H
2132+
2133+#include "zend.h"
2134+
2135+#if HARDENING_PATCH
2136+PHPAPI void php_security_log(int loglevel, char *fmt, ...);
2137+PHPAPI void hardened_startup();
2138+#define HARDENING_PATCH_VERSION "0.3.2"
2139+
2140+#endif
2141+
2142+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
2143+PHPAPI unsigned int php_canary();
2144+#endif
2145+
2146+#if HARDENING_PATCH_INC_PROTECT
2147+PHPAPI int php_is_valid_include(zval *z);
2148+#endif
2149+
2150+#endif /* HARDENING_PATCH_H */
2151+
2152+/*
2153+ * Local variables:
2154+ * tab-width: 4
2155+ * c-basic-offset: 4
2156+ * End:
2157+ */
2158diff -Naur php-4.4.0RC2/main/hardening_patch.m4 hardening-patch-4.4.0RC2-0.3.2/main/hardening_patch.m4
2159--- php-4.4.0RC2/main/hardening_patch.m4 1970-01-01 01:00:00.000000000 +0100
2160+++ hardening-patch-4.4.0RC2-0.3.2/main/hardening_patch.m4 2005-07-09 08:53:20.654598688 +0200
2161@@ -0,0 +1,95 @@
2162+dnl
2163+dnl $Id: hardening_patch.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $
2164+dnl
2165+dnl This file contains Hardening Patch for PHP specific autoconf functions.
2166+dnl
2167+
2168+AC_ARG_ENABLE(hardening-patch-mm-protect,
2169+[ --disable-hardening-patch-mm-protect Disable the Memory Manager protection.],[
2170+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
2171+],[
2172+ DO_HARDENING_PATCH_MM_PROTECT=yes
2173+])
2174+
2175+AC_ARG_ENABLE(hardening-patch-ll-protect,
2176+[ --disable-hardening-patch-ll-protect Disable the Linked List protection.],[
2177+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
2178+],[
2179+ DO_HARDENING_PATCH_LL_PROTECT=yes
2180+])
2181+
2182+AC_ARG_ENABLE(hardening-patch-inc-protect,
2183+[ --disable-hardening-patch-inc-protect Disable include/require protection.],[
2184+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
2185+],[
2186+ DO_HARDENING_PATCH_INC_PROTECT=yes
2187+])
2188+
2189+AC_ARG_ENABLE(hardening-patch-fmt-protect,
2190+[ --disable-hardening-patch-fmt-protect Disable format string protection.],[
2191+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
2192+],[
2193+ DO_HARDENING_PATCH_FMT_PROTECT=yes
2194+])
2195+
2196+AC_ARG_ENABLE(hardening-patch-hash-protect,
2197+[ --disable-hardening-patch-hash-protect Disable HashTable destructor protection.],[
2198+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
2199+],[
2200+ DO_HARDENING_PATCH_HASH_PROTECT=yes
2201+])
2202+
2203+AC_MSG_CHECKING(whether to protect the Zend Memory Manager)
2204+AC_MSG_RESULT($DO_HARDENING_PATCH_MM_PROTECT)
2205+
2206+AC_MSG_CHECKING(whether to protect the Zend Linked Lists)
2207+AC_MSG_RESULT($DO_HARDENING_PATCH_LL_PROTECT)
2208+
2209+AC_MSG_CHECKING(whether to protect include/require statements)
2210+AC_MSG_RESULT($DO_HARDENING_PATCH_INC_PROTECT)
2211+
2212+AC_MSG_CHECKING(whether to protect PHP Format String functions)
2213+AC_MSG_RESULT($DO_HARDENING_PATCH_FMT_PROTECT)
2214+
2215+AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables)
2216+AC_MSG_RESULT($DO_HARDENING_PATCH_HASH_PROTECT)
2217+
2218+
2219+AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2220+
2221+
2222+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
2223+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2224+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 1, [Memory Manager Protection])
2225+else
2226+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 0, [Memory Manager Protection])
2227+fi
2228+
2229+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
2230+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2231+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 1, [Linked List Protection])
2232+else
2233+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 0, [Linked List Protection])
2234+fi
2235+
2236+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
2237+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2238+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 1, [Include/Require Protection])
2239+else
2240+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 0, [Include/Require Protection])
2241+fi
2242+
2243+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
2244+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2245+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 1, [Fmt String Protection])
2246+else
2247+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 0, [Fmt String Protection])
2248+fi
2249+
2250+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
2251+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2252+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 1, [HashTable DTOR Protection])
2253+else
2254+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 0, [HashTable DTOR Protection])
2255+fi
2256+
2257diff -Naur php-4.4.0RC2/main/main.c hardening-patch-4.4.0RC2-0.3.2/main/main.c
2258--- php-4.4.0RC2/main/main.c 2005-06-20 21:59:43.000000000 +0200
2259+++ hardening-patch-4.4.0RC2-0.3.2/main/main.c 2005-07-09 08:53:20.655598536 +0200
2260@@ -100,6 +100,10 @@
2261 PHPAPI int core_globals_id;
2262 #endif
2263
2264+#if HARDENING_PATCH
2265+#include "hardened_globals.h"
2266+#endif
2267+
2268 #define ERROR_BUF_LEN 1024
2269
2270 typedef struct {
2271@@ -150,10 +154,33 @@
2272 */
2273 static PHP_INI_MH(OnChangeMemoryLimit)
2274 {
2275+#if HARDENING_PATCH
2276+ long orig_memory_limit;
2277+
2278+ if (entry->modified) {
2279+ orig_memory_limit = zend_atoi(entry->orig_value, entry->orig_value_length);
2280+ } else {
2281+ orig_memory_limit = 1<<30;
2282+ }
2283+ if (orig_memory_limit < 0 || orig_memory_limit > (1<<30)) {
2284+ orig_memory_limit = 1<<30;
2285+ }
2286+#endif
2287 if (new_value) {
2288 PG(memory_limit) = zend_atoi(new_value, new_value_length);
2289+#if HARDENING_PATCH
2290+ if (PG(memory_limit) > orig_memory_limit) {
2291+ PG(memory_limit) = orig_memory_limit;
2292+ php_security_log(S_MISC, "script tried to increase memory_limit above allowed value");
2293+ return FAILURE;
2294+ }
2295+#endif
2296 } else {
2297+#if HARDENING_PATCH
2298+ PG(memory_limit) = orig_memory_limit;
2299+#else
2300 PG(memory_limit) = 1<<30; /* effectively, no limit */
2301+#endif
2302 }
2303 return zend_set_memory_limit(PG(memory_limit));
2304 }
2305@@ -1096,6 +1123,10 @@
2306 tsrm_ls = ts_resource(0);
2307 #endif
2308
2309+#if HARDENING_PATCH
2310+ hardened_startup();
2311+#endif
2312+
2313 sapi_initialize_empty_request(TSRMLS_C);
2314 sapi_activate(TSRMLS_C);
2315
2316@@ -1108,6 +1139,12 @@
2317 php_output_startup();
2318 php_output_activate(TSRMLS_C);
2319
2320+#if HARDENING_PATCH_INC_PROTECT
2321+ zuf.is_valid_include = php_is_valid_include;
2322+#endif
2323+#if HARDENING_PATCH
2324+ zuf.security_log_function = php_security_log;
2325+#endif
2326 zuf.error_function = php_error_cb;
2327 zuf.printf_function = php_printf;
2328 zuf.write_function = php_body_write_wrapper;
2329@@ -1209,6 +1246,10 @@
2330 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, sizeof(PHP_CONFIG_FILE_PATH)-1, CONST_PERSISTENT | CONST_CS);
2331 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
2332 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
2333+#if HARDENING_PATCH
2334+ REGISTER_MAIN_LONG_CONSTANT("HARDENING_PATCH", 1, CONST_PERSISTENT | CONST_CS);
2335+ REGISTER_MAIN_STRINGL_CONSTANT("HARDENING_PATCH_VERSION", HARDENING_PATCH_VERSION, sizeof(HARDENING_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
2336+#endif
2337 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
2338 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
2339 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);
2340@@ -1316,7 +1357,7 @@
2341 */
2342 static inline void php_register_server_variables(TSRMLS_D)
2343 {
2344- zval *array_ptr=NULL;
2345+ zval *array_ptr=NULL, *vptr;
2346
2347 ALLOC_ZVAL(array_ptr);
2348 array_init(array_ptr);
2349@@ -1326,6 +1367,16 @@
2350 /* Server variables */
2351 if (sapi_module.register_server_variables) {
2352 sapi_module.register_server_variables(array_ptr TSRMLS_CC);
2353+ if (zend_hash_find(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"), (void **)&vptr)==SUCCESS) {
2354+ char *str;
2355+ if (vptr->type != IS_STRING) {
2356+ str = "Array";
2357+ } else {
2358+ str = vptr->value.str.val;
2359+ }
2360+ php_security_log(S_VARS, "Attacker tried to overwrite HTTP_RAW_POST_DATA with '%s' through a HTTP header", str);
2361+ zend_hash_del(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
2362+ }
2363 }
2364
2365 /* PHP Authentication support */
2366diff -Naur php-4.4.0RC2/main/php_config.h.in hardening-patch-4.4.0RC2-0.3.2/main/php_config.h.in
2367--- php-4.4.0RC2/main/php_config.h.in 2005-07-01 12:08:17.000000000 +0200
2368+++ hardening-patch-4.4.0RC2-0.3.2/main/php_config.h.in 2005-07-09 08:53:20.656598384 +0200
2369@@ -860,6 +860,39 @@
2370 /* Enabling BIND8 compatibility for Panther */
2371 #undef BIND_8_COMPAT
2372
2373+/* Hardening-Patch */
2374+#undef HARDENING_PATCH
2375+
2376+/* Memory Manager Protection */
2377+#undef HARDENING_PATCH_MM_PROTECT
2378+
2379+/* Memory Manager Protection */
2380+#undef HARDENING_PATCH_MM_PROTECT
2381+
2382+/* Linked List Protection */
2383+#undef HARDENING_PATCH_LL_PROTECT
2384+
2385+/* Linked List Protection */
2386+#undef HARDENING_PATCH_LL_PROTECT
2387+
2388+/* Include/Require Protection */
2389+#undef HARDENING_PATCH_INC_PROTECT
2390+
2391+/* Include/Require Protection */
2392+#undef HARDENING_PATCH_INC_PROTECT
2393+
2394+/* Fmt String Protection */
2395+#undef HARDENING_PATCH_FMT_PROTECT
2396+
2397+/* Fmt String Protection */
2398+#undef HARDENING_PATCH_FMT_PROTECT
2399+
2400+/* HashTable DTOR Protection */
2401+#undef HARDENING_PATCH_HASH_PROTECT
2402+
2403+/* HashTable DTOR Protection */
2404+#undef HARDENING_PATCH_HASH_PROTECT
2405+
2406 /* Whether you have AOLserver */
2407 #undef HAVE_AOLSERVER
2408
2409@@ -1143,6 +1176,12 @@
2410 /* Define if you have the getaddrinfo function */
2411 #undef HAVE_GETADDRINFO
2412
2413+/* Whether realpath is broken */
2414+#undef PHP_BROKEN_REALPATH
2415+
2416+/* Whether realpath is broken */
2417+#undef PHP_BROKEN_REALPATH
2418+
2419 /* Whether system headers declare timezone */
2420 #undef HAVE_DECLARED_TIMEZONE
2421
2422diff -Naur php-4.4.0RC2/main/php_content_types.c hardening-patch-4.4.0RC2-0.3.2/main/php_content_types.c
2423--- php-4.4.0RC2/main/php_content_types.c 2002-12-31 17:26:14.000000000 +0100
2424+++ hardening-patch-4.4.0RC2-0.3.2/main/php_content_types.c 2005-07-09 08:53:20.657598232 +0200
2425@@ -77,6 +77,7 @@
2426 sapi_register_post_entries(php_post_entries);
2427 sapi_register_default_post_reader(php_default_post_reader);
2428 sapi_register_treat_data(php_default_treat_data);
2429+ sapi_register_input_filter(php_default_input_filter);
2430 return SUCCESS;
2431 }
2432 /* }}} */
2433diff -Naur php-4.4.0RC2/main/php.h hardening-patch-4.4.0RC2-0.3.2/main/php.h
2434--- php-4.4.0RC2/main/php.h 2005-04-17 15:37:29.000000000 +0200
2435+++ hardening-patch-4.4.0RC2-0.3.2/main/php.h 2005-07-09 08:53:20.657598232 +0200
2436@@ -26,7 +26,7 @@
2437 #include <dmalloc.h>
2438 #endif
2439
2440-#define PHP_API_VERSION 20020918
2441+#define PHP_API_VERSION 1020050626
2442 #define PHP_HAVE_STREAMS
2443 #define YYDEBUG 0
2444
2445@@ -35,11 +35,19 @@
2446 #include "zend_qsort.h"
2447 #include "php_compat.h"
2448
2449+
2450 #include "zend_API.h"
2451
2452 #undef sprintf
2453 #define sprintf php_sprintf
2454
2455+#if HARDENING_PATCH
2456+#if HAVE_REALPATH
2457+#undef realpath
2458+#define realpath php_realpath
2459+#endif
2460+#endif
2461+
2462 /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */
2463 #undef PHP_DEBUG
2464 #define PHP_DEBUG ZEND_DEBUG
2465@@ -435,6 +443,10 @@
2466 #endif
2467 #endif /* !XtOffsetOf */
2468
2469+#if HARDENING_PATCH
2470+#include "hardening_patch.h"
2471+#endif
2472+
2473 #endif
2474
2475 /*
2476diff -Naur php-4.4.0RC2/main/php_variables.c hardening-patch-4.4.0RC2-0.3.2/main/php_variables.c
2477--- php-4.4.0RC2/main/php_variables.c 2005-05-17 20:42:35.000000000 +0200
2478+++ hardening-patch-4.4.0RC2-0.3.2/main/php_variables.c 2005-07-09 08:53:20.658598080 +0200
2479@@ -225,17 +225,28 @@
2480 while (var) {
2481 val = strchr(var, '=');
2482 if (val) { /* have a value */
2483- int val_len;
2484+ unsigned int val_len, new_val_len;
2485
2486 *val++ = '\0';
2487 php_url_decode(var, strlen(var));
2488 val_len = php_url_decode(val, strlen(val));
2489- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
2490+ val = estrndup(val, val_len);
2491+ if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) {
2492+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
2493+ }
2494+ efree(val);
2495 }
2496 var = php_strtok_r(NULL, "&", &strtok_buf);
2497 }
2498 }
2499
2500+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter)
2501+{
2502+ /* TODO: check .ini setting here and apply user-defined input filter */
2503+ *new_val_len = val_len;
2504+ return 1;
2505+}
2506+
2507 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
2508 {
2509 char *res = NULL, *var, *val, *separator=NULL;
2510@@ -313,15 +324,26 @@
2511 while (var) {
2512 val = strchr(var, '=');
2513 if (val) { /* have a value */
2514- int val_len;
2515+ unsigned int val_len, new_val_len;
2516
2517 *val++ = '\0';
2518 php_url_decode(var, strlen(var));
2519 val_len = php_url_decode(val, strlen(val));
2520- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
2521+ val = estrndup(val, val_len);
2522+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
2523+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
2524+ }
2525+ efree(val);
2526 } else {
2527+ unsigned int val_len, new_val_len;
2528+
2529 php_url_decode(var, strlen(var));
2530- php_register_variable_safe(var, "", 0, array_ptr TSRMLS_CC);
2531+ val_len = 0;
2532+ val = estrndup("", 0);
2533+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
2534+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
2535+ }
2536+ efree(val);
2537 }
2538 var = php_strtok_r(NULL, separator, &strtok_buf);
2539 }
2540diff -Naur php-4.4.0RC2/main/rfc1867.c hardening-patch-4.4.0RC2-0.3.2/main/rfc1867.c
2541--- php-4.4.0RC2/main/rfc1867.c 2005-04-04 16:59:58.000000000 +0200
2542+++ hardening-patch-4.4.0RC2-0.3.2/main/rfc1867.c 2005-07-09 08:53:20.659597928 +0200
2543@@ -127,6 +127,7 @@
2544 #define UPLOAD_ERROR_C 3 /* Partially uploaded */
2545 #define UPLOAD_ERROR_D 4 /* No file uploaded */
2546 #define UPLOAD_ERROR_E 6 /* Missing /tmp or similar directory */
2547+#define UPLOAD_ERROR_F 7 /* Filter forbids upload */
2548
2549 void php_rfc1867_register_constants(TSRMLS_D)
2550 {
2551@@ -136,6 +137,7 @@
2552 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_PARTIAL", UPLOAD_ERROR_C, CONST_CS | CONST_PERSISTENT);
2553 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE", UPLOAD_ERROR_D, CONST_CS | CONST_PERSISTENT);
2554 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E, CONST_CS | CONST_PERSISTENT);
2555+ REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FILTER", UPLOAD_ERROR_F, CONST_CS | CONST_PERSISTENT);
2556 }
2557
2558 static void normalize_protected_variable(char *varname TSRMLS_DC)
2559@@ -844,6 +846,7 @@
2560 char buff[FILLUNIT];
2561 char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL;
2562 int blen=0, wlen=0;
2563+ unsigned long offset;
2564
2565 zend_llist_clean(&header);
2566
2567@@ -891,21 +894,24 @@
2568 if (!filename && param) {
2569
2570 char *value = multipart_buffer_read_body(mbuff TSRMLS_CC);
2571+ unsigned int new_val_len; /* Dummy variable */
2572
2573 if (!value) {
2574 value = estrdup("");
2575 }
2576
2577+ if (sapi_module.input_filter(PARSE_POST, param, &value, strlen(value), &new_val_len TSRMLS_CC)) {
2578 #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
2579- if (php_mb_encoding_translation(TSRMLS_C)) {
2580- php_mb_gpc_stack_variable(param, value, &val_list, &len_list,
2581- &num_vars, &num_vars_max TSRMLS_CC);
2582- } else {
2583- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2584- }
2585+ if (php_mb_encoding_translation(TSRMLS_C)) {
2586+ php_mb_gpc_stack_variable(param, value, &val_list, &len_list,
2587+ &num_vars, &num_vars_max TSRMLS_CC);
2588+ } else {
2589+ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2590+ }
2591 #else
2592- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2593+ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2594 #endif
2595+ }
2596 if (!strcasecmp(param, "MAX_FILE_SIZE")) {
2597 max_file_size = atol(value);
2598 }
2599@@ -981,6 +987,11 @@
2600 cancel_upload = UPLOAD_ERROR_D;
2601 }
2602
2603+ if (sapi_module.pre_upload_filter && sapi_module.pre_upload_filter(param, filename TSRMLS_CC)==FAILURE) {
2604+ cancel_upload = UPLOAD_ERROR_F;
2605+ }
2606+
2607+ offset = 0;
2608 while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff) TSRMLS_CC)))
2609 {
2610 if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) {
2611@@ -990,6 +1001,11 @@
2612 sapi_module.sapi_error(E_WARNING, "MAX_FILE_SIZE of %ld bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename);
2613 cancel_upload = UPLOAD_ERROR_B;
2614 } else if (blen > 0) {
2615+
2616+ if (sapi_module.upload_content_filter && sapi_module.upload_content_filter(offset, buff, blen, &blen TSRMLS_CC)==FAILURE) {
2617+ cancel_upload = UPLOAD_ERROR_F;
2618+ }
2619+
2620 wlen = write(fd, buff, blen);
2621
2622 if (wlen < blen) {
2623@@ -997,6 +1013,7 @@
2624 cancel_upload = UPLOAD_ERROR_C;
2625 } else {
2626 total_bytes += wlen;
2627+ offset += wlen;
2628 }
2629 }
2630 }
2631@@ -1011,6 +1028,10 @@
2632 }
2633 #endif
2634
2635+ if (!cancel_upload && sapi_module.post_upload_filter && sapi_module.post_upload_filter(temp_filename TSRMLS_CC)==FAILURE) {
2636+ cancel_upload = UPLOAD_ERROR_F;
2637+ }
2638+
2639 if (cancel_upload) {
2640 if (temp_filename) {
2641 if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
2642diff -Naur php-4.4.0RC2/main/SAPI.c hardening-patch-4.4.0RC2-0.3.2/main/SAPI.c
2643--- php-4.4.0RC2/main/SAPI.c 2005-02-22 15:46:24.000000000 +0100
2644+++ hardening-patch-4.4.0RC2-0.3.2/main/SAPI.c 2005-07-09 08:53:20.659597928 +0200
2645@@ -831,6 +831,31 @@
2646 return SUCCESS;
2647 }
2648
2649+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
2650+{
2651+ sapi_module.input_filter = input_filter;
2652+ return SUCCESS;
2653+}
2654+
2655+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC))
2656+{
2657+ sapi_module.pre_upload_filter = pre_upload_filter;
2658+ return SUCCESS;
2659+}
2660+
2661+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC))
2662+{
2663+ sapi_module.upload_content_filter = upload_content_filter;
2664+ return SUCCESS;
2665+}
2666+
2667+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC))
2668+{
2669+ sapi_module.post_upload_filter = post_upload_filter;
2670+ return SUCCESS;
2671+}
2672+
2673+
2674
2675 SAPI_API int sapi_flush(TSRMLS_D)
2676 {
2677diff -Naur php-4.4.0RC2/main/SAPI.h hardening-patch-4.4.0RC2-0.3.2/main/SAPI.h
2678--- php-4.4.0RC2/main/SAPI.h 2003-04-09 22:27:55.000000000 +0200
2679+++ hardening-patch-4.4.0RC2-0.3.2/main/SAPI.h 2005-07-09 08:53:20.660597776 +0200
2680@@ -101,9 +101,10 @@
2681 char *current_user;
2682 int current_user_length;
2683
2684- /* this is necessary for CLI module */
2685- int argc;
2686- char **argv;
2687+ /* this is necessary for CLI module */
2688+ int argc;
2689+ char **argv;
2690+
2691 } sapi_request_info;
2692
2693
2694@@ -177,6 +178,10 @@
2695 SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry);
2696 SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D));
2697 SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC));
2698+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC));
2699+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC));
2700+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC));
2701+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC));
2702
2703 SAPI_API int sapi_flush(TSRMLS_D);
2704 SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
2705@@ -238,8 +243,15 @@
2706 int (*get_target_uid)(uid_t * TSRMLS_DC);
2707 int (*get_target_gid)(gid_t * TSRMLS_DC);
2708
2709+ unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
2710+
2711+ unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC);
2712+ unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC);
2713+ unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC);
2714+
2715 void (*ini_defaults)(HashTable *configuration_hash);
2716 int phpinfo_as_text;
2717+
2718 };
2719
2720
2721@@ -262,16 +274,26 @@
2722
2723 #define SAPI_DEFAULT_MIMETYPE "text/html"
2724 #define SAPI_DEFAULT_CHARSET ""
2725+
2726+#if HARDENING_PATCH
2727+#define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION " with Hardening-Patch"
2728+#else
2729 #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION
2730+#endif
2731
2732 #define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D)
2733 #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC)
2734
2735 #define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC)
2736+#define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
2737+#define SAPI_PRE_UPLOAD_FILTER_FUNC(pre_upload_filter) unsigned int pre_upload_filter(char *varname, char *filename TSRMLS_DC)
2738+#define SAPI_UPLOAD_CONTENT_FILTER_FUNC(upload_content_filter) unsigned int upload_content_filter(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC)
2739+#define SAPI_POST_UPLOAD_FILTER_FUNC(post_upload_filter) unsigned int post_upload_filter(char *tmpfilename TSRMLS_DC)
2740
2741 SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
2742 SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader);
2743 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data);
2744+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter);
2745
2746 #define STANDARD_SAPI_MODULE_PROPERTIES
2747
2748diff -Naur php-4.4.0RC2/main/snprintf.c hardening-patch-4.4.0RC2-0.3.2/main/snprintf.c
2749--- php-4.4.0RC2/main/snprintf.c 2005-04-08 07:44:53.000000000 +0200
2750+++ hardening-patch-4.4.0RC2-0.3.2/main/snprintf.c 2005-07-09 08:53:20.661597624 +0200
2751@@ -1013,7 +1013,11 @@
2752
2753
2754 case 'n':
2755+#if HARDENING_PATCH_FMT_PROTECT
2756+ php_security_log(S_MISC, "'n' specifier within format string");
2757+#else
2758 *(va_arg(ap, int *)) = cc;
2759+#endif
2760 break;
2761
2762 /*
2763diff -Naur php-4.4.0RC2/main/spprintf.c hardening-patch-4.4.0RC2-0.3.2/main/spprintf.c
2764--- php-4.4.0RC2/main/spprintf.c 2005-04-08 07:44:53.000000000 +0200
2765+++ hardening-patch-4.4.0RC2-0.3.2/main/spprintf.c 2005-07-09 08:53:20.661597624 +0200
2766@@ -630,7 +630,11 @@
2767
2768
2769 case 'n':
2770+#if HARDENING_PATCH_FMT_PROTECT
2771+ php_security_log(S_MISC, "'n' specifier within format string");
2772+#else
2773 *(va_arg(ap, int *)) = xbuf->len;
2774+#endif
2775 break;
2776
2777 /*
2778diff -Naur php-4.4.0RC2/php.ini-dist hardening-patch-4.4.0RC2-0.3.2/php.ini-dist
2779--- php-4.4.0RC2/php.ini-dist 2005-04-28 15:14:45.000000000 +0200
2780+++ hardening-patch-4.4.0RC2-0.3.2/php.ini-dist 2005-07-09 08:53:20.662597472 +0200
2781@@ -1112,6 +1112,177 @@
2782 ;exif.decode_jis_motorola = JIS
2783 ;exif.decode_jis_intel = JIS
2784
2785+[hardening-patch]
2786+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2787+; Hardening-Patch's logging ;
2788+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2789+
2790+;
2791+; hphp.log.syslog - Configures level for alerts reported through syslog
2792+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
2793+; hphp.log.script - Configures level for alerts reported through external script
2794+;
2795+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
2796+; Or each number up to get desired Hardening-Patch's reporting level
2797+;
2798+; S_ALL - All alerts
2799+; S_MEMORY - All canary violations and the safe unlink protection use this class
2800+; S_VARS - All variable filters trigger this class
2801+; S_FILES - All violation of uploaded files filter use this class
2802+; S_INCLUDE - The protection against malicious include filenames use this class
2803+; S_SQL - Failed SQL queries in MySQL are logged with this class
2804+; S_EXECUTOR - The execution depth protection uses this logging class
2805+; S_MISC - All other log messages (f.e. format string protection) use this class
2806+;
2807+; Example:
2808+;
2809+; - Report all alerts (except memory alerts) to the SAPI errorlog,
2810+; memory alerts through syslog and SQL+Include alerts fo the script
2811+;
2812+;hphp.log.syslog = S_MEMORY
2813+;hphp.log.sapi = S_ALL & ~S_MEMORY
2814+;hphp.log.script = S_INCLUDE | S_SQL
2815+;
2816+; Syslog logging:
2817+;
2818+; - Facility configuration: one of the following facilities
2819+;
2820+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
2821+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
2822+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
2823+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
2824+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
2825+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
2826+; LOG_PERROR
2827+;
2828+; - Priority configuration: one of the followinf priorities
2829+;
2830+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
2831+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
2832+;
2833+hphp.log.syslog.priority = LOG_ALERT
2834+hphp.log.syslog.facility = LOG_USER
2835+;
2836+; Script logging:
2837+;
2838+;hphp.log.script.name = /home/hphp/log_script
2839+;
2840+; Alert configuration:
2841+;
2842+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
2843+;
2844+;hphp.log.use-x-forwarded-for = On
2845+;
2846+
2847+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2848+; Hardening-Patch's logging ;
2849+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2850+
2851+; Execution depth limit
2852+;hphp.executor.max_depth = 8000
2853+
2854+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2855+; Hardening-Patch's REQUEST variable filters ;
2856+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2857+
2858+; Limits the number of REQUEST variables
2859+hphp.request.max_vars = 200
2860+
2861+; Limits the length of variable names (without indices)
2862+hphp.request.max_varname_length = 64
2863+
2864+; Limits the length of complete variable names (with indices)
2865+hphp.request.max_totalname_length = 256
2866+
2867+; Limits the length of array indices
2868+hphp.request.max_array_index_length = 64
2869+
2870+; Limits the depth of arrays
2871+hphp.request.max_array_depth = 100
2872+
2873+; Limits the length of variable values
2874+hphp.request.max_value_length = 65000
2875+
2876+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2877+; Hardening-Patch's COOKIE variable filters ;
2878+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2879+
2880+; Limits the number of COOKIE variables
2881+hphp.cookie.max_vars = 100
2882+
2883+; Limits the length of variable names (without indices)
2884+hphp.cookie.max_name_length = 64
2885+
2886+; Limits the length of complete variable names (with indices)
2887+hphp.cookie.max_totalname_length = 256
2888+
2889+; Limits the length of array indices
2890+hphp.cookie.max_array_index_length = 64
2891+
2892+; Limits the depth of arrays
2893+hphp.cookie.max_array_depth = 100
2894+
2895+; Limits the length of variable values
2896+hphp.cookie.max_value_length = 10000
2897+
2898+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2899+; Hardening-Patch's GET variable filters ;
2900+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2901+
2902+; Limits the number of COOKIE variables
2903+hphp.get.max_vars = 100
2904+
2905+; Limits the length of variable names (without indices)
2906+hphp.get.max_name_length = 64
2907+
2908+; Limits the length of complete variable names (with indices)
2909+hphp.get.max_totalname_length = 256
2910+
2911+; Limits the length of array indices
2912+hphp.get.max_array_index_length = 64
2913+
2914+; Limits the depth of arrays
2915+hphp.get.max_array_depth = 50
2916+
2917+; Limits the length of variable values
2918+hphp.get.max_value_length = 512
2919+
2920+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2921+; Hardening-Patch's POST variable filters ;
2922+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2923+
2924+; Limits the number of POST variables
2925+hphp.post.max_vars = 200
2926+
2927+; Limits the length of variable names (without indices)
2928+hphp.post.max_name_length = 64
2929+
2930+; Limits the length of complete variable names (with indices)
2931+hphp.post.max_totalname_length = 256
2932+
2933+; Limits the length of array indices
2934+hphp.post.max_array_index_length = 64
2935+
2936+; Limits the depth of arrays
2937+hphp.post.max_array_depth = 100
2938+
2939+; Limits the length of variable values
2940+hphp.post.max_value_length = 65000
2941+
2942+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2943+; Hardening-Patch's fileupload variable filters ;
2944+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2945+
2946+; Limits the number of uploadable files
2947+hphp.upload.max_uploads = 25
2948+
2949+; Filter out the upload of ELF executables
2950+hphp.upload.disallow_elf_files = On
2951+
2952+; External filterscript for upload verification
2953+;hphp.upload.verification_script = /home/hphp/verify_script
2954+
2955+
2956 ; Local Variables:
2957 ; tab-width: 4
2958 ; End:
2959diff -Naur php-4.4.0RC2/php.ini-recommended hardening-patch-4.4.0RC2-0.3.2/php.ini-recommended
2960--- php-4.4.0RC2/php.ini-recommended 2005-04-28 15:14:46.000000000 +0200
2961+++ hardening-patch-4.4.0RC2-0.3.2/php.ini-recommended 2005-07-09 08:53:20.663597320 +0200
2962@@ -1110,6 +1110,177 @@
2963 ;exif.decode_jis_motorola = JIS
2964 ;exif.decode_jis_intel = JIS
2965
2966+[hardening-patch]
2967+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2968+; Hardening-Patch's logging ;
2969+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2970+
2971+;
2972+; hphp.log.syslog - Configures level for alerts reported through syslog
2973+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
2974+; hphp.log.script - Configures level for alerts reported through external script
2975+;
2976+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
2977+; Or each number up to get desired Hardening-Patch's reporting level
2978+;
2979+; S_ALL - All alerts
2980+; S_MEMORY - All canary violations and the safe unlink protection use this class
2981+; S_VARS - All variable filters trigger this class
2982+; S_FILES - All violation of uploaded files filter use this class
2983+; S_INCLUDE - The protection against malicious include filenames use this class
2984+; S_SQL - Failed SQL queries in MySQL are logged with this class
2985+; S_EXECUTOR - The execution depth protection uses this logging class
2986+; S_MISC - All other log messages (f.e. format string protection) use this class
2987+;
2988+; Example:
2989+;
2990+; - Report all alerts (except memory alerts) to the SAPI errorlog,
2991+; memory alerts through syslog and SQL+Include alerts fo the script
2992+;
2993+;hphp.log.syslog = S_MEMORY
2994+;hphp.log.sapi = S_ALL & ~S_MEMORY
2995+;hphp.log.script = S_INCLUDE | S_SQL
2996+;
2997+; Syslog logging:
2998+;
2999+; - Facility configuration: one of the following facilities
3000+;
3001+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
3002+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
3003+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
3004+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
3005+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
3006+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
3007+; LOG_PERROR
3008+;
3009+; - Priority configuration: one of the followinf priorities
3010+;
3011+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
3012+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
3013+;
3014+hphp.log.syslog.priority = LOG_ALERT
3015+hphp.log.syslog.facility = LOG_USER
3016+;
3017+; Script logging:
3018+;
3019+;hphp.log.script.name = /home/hphp/log_script
3020+;
3021+; Alert configuration:
3022+;
3023+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
3024+;
3025+;hphp.log.use-x-forwarded-for = On
3026+;
3027+
3028+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3029+; Hardening-Patch's logging ;
3030+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3031+
3032+; Execution depth limit
3033+;hphp.executor.max_depth = 8000
3034+
3035+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3036+; Hardening-Patch's REQUEST variable filters ;
3037+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3038+
3039+; Limits the number of REQUEST variables
3040+hphp.request.max_vars = 200
3041+
3042+; Limits the length of variable names (without indices)
3043+hphp.request.max_varname_length = 64
3044+
3045+; Limits the length of complete variable names (with indices)
3046+hphp.request.max_totalname_length = 256
3047+
3048+; Limits the length of array indices
3049+hphp.request.max_array_index_length = 64
3050+
3051+; Limits the depth of arrays
3052+hphp.request.max_array_depth = 100
3053+
3054+; Limits the length of variable values
3055+hphp.request.max_value_length = 65000
3056+
3057+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3058+; Hardening-Patch's COOKIE variable filters ;
3059+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3060+
3061+; Limits the number of COOKIE variables
3062+hphp.cookie.max_vars = 100
3063+
3064+; Limits the length of variable names (without indices)
3065+hphp.cookie.max_name_length = 64
3066+
3067+; Limits the length of complete variable names (with indices)
3068+hphp.cookie.max_totalname_length = 256
3069+
3070+; Limits the length of array indices
3071+hphp.cookie.max_array_index_length = 64
3072+
3073+; Limits the depth of arrays
3074+hphp.cookie.max_array_depth = 100
3075+
3076+; Limits the length of variable values
3077+hphp.cookie.max_value_length = 10000
3078+
3079+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3080+; Hardening-Patch's GET variable filters ;
3081+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3082+
3083+; Limits the number of COOKIE variables
3084+hphp.get.max_vars = 100
3085+
3086+; Limits the length of variable names (without indices)
3087+hphp.get.max_name_length = 64
3088+
3089+; Limits the length of complete variable names (with indices)
3090+hphp.get.max_totalname_length = 256
3091+
3092+; Limits the length of array indices
3093+hphp.get.max_array_index_length = 64
3094+
3095+; Limits the depth of arrays
3096+hphp.get.max_array_depth = 50
3097+
3098+; Limits the length of variable values
3099+hphp.get.max_value_length = 512
3100+
3101+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3102+; Hardening-Patch's POST variable filters ;
3103+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3104+
3105+; Limits the number of POST variables
3106+hphp.post.max_vars = 200
3107+
3108+; Limits the length of variable names (without indices)
3109+hphp.post.max_name_length = 64
3110+
3111+; Limits the length of complete variable names (with indices)
3112+hphp.post.max_totalname_length = 256
3113+
3114+; Limits the length of array indices
3115+hphp.post.max_array_index_length = 64
3116+
3117+; Limits the depth of arrays
3118+hphp.post.max_array_depth = 100
3119+
3120+; Limits the length of variable values
3121+hphp.post.max_value_length = 65000
3122+
3123+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3124+; Hardening-Patch's fileupload variable filters ;
3125+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3126+
3127+; Limits the number of uploadable files
3128+hphp.upload.max_uploads = 25
3129+
3130+; Filter out the upload of ELF executables
3131+hphp.upload.disallow_elf_files = On
3132+
3133+; External filterscript for upload verification
3134+;hphp.upload.verification_script = /home/hphp/verify_script
3135+
3136+
3137 ; Local Variables:
3138 ; tab-width: 4
3139 ; End:
3140diff -Naur php-4.4.0RC2/README.input_filter hardening-patch-4.4.0RC2-0.3.2/README.input_filter
3141--- php-4.4.0RC2/README.input_filter 1970-01-01 01:00:00.000000000 +0100
3142+++ hardening-patch-4.4.0RC2-0.3.2/README.input_filter 2005-07-09 08:53:20.664597168 +0200
3143@@ -0,0 +1,193 @@
3144+Input Filter Support ported from PHP 5
3145+--------------------------------------
3146+
3147+XSS (Cross Site Scripting) hacks are becoming more and more prevalent,
3148+and can be quite difficult to prevent. Whenever you accept user data
3149+and somehow display this data back to users, you are likely vulnerable
3150+to XSS hacks.
3151+
3152+The Input Filter support in PHP 5 is aimed at providing the framework
3153+through which a company-wide or site-wide security policy can be
3154+enforced. It is implemented as a SAPI hook and is called from the
3155+treat_data and post handler functions. To implement your own security
3156+policy you will need to write a standard PHP extension.
3157+
3158+A simple implementation might look like the following. This stores the
3159+original raw user data and adds a my_get_raw() function while the normal
3160+$_POST, $_GET and $_COOKIE arrays are only populated with stripped
3161+data. In this simple example all I am doing is calling strip_tags() on
3162+the data. If register_globals is turned on, the default globals that
3163+are created will be stripped ($foo) while a $RAW_foo is created with the
3164+original user input.
3165+
3166+ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
3167+ zval *post_array;
3168+ zval *get_array;
3169+ zval *cookie_array;
3170+ZEND_END_MODULE_GLOBALS(my_input_filter)
3171+
3172+#ifdef ZTS
3173+#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
3174+#else
3175+#define IF_G(v) (my_input_filter_globals.v)
3176+#endif
3177+
3178+ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)
3179+
3180+function_entry my_input_filter_functions[] = {
3181+ PHP_FE(my_get_raw, NULL)
3182+ {NULL, NULL, NULL}
3183+};
3184+
3185+zend_module_entry my_input_filter_module_entry = {
3186+ STANDARD_MODULE_HEADER,
3187+ "my_input_filter",
3188+ my_input_filter_functions,
3189+ PHP_MINIT(my_input_filter),
3190+ PHP_MSHUTDOWN(my_input_filter),
3191+ NULL,
3192+ PHP_RSHUTDOWN(my_input_filter),
3193+ PHP_MINFO(my_input_filter),
3194+ "0.1",
3195+ STANDARD_MODULE_PROPERTIES
3196+};
3197+
3198+PHP_MINIT_FUNCTION(my_input_filter)
3199+{
3200+ ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);
3201+
3202+ REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
3203+ REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
3204+ REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
3205+
3206+ sapi_register_input_filter(my_sapi_input_filter);
3207+ return SUCCESS;
3208+}
3209+
3210+PHP_RSHUTDOWN_FUNCTION(my_input_filter)
3211+{
3212+ if(IF_G(get_array)) {
3213+ zval_ptr_dtor(&IF_G(get_array));
3214+ IF_G(get_array) = NULL;
3215+ }
3216+ if(IF_G(post_array)) {
3217+ zval_ptr_dtor(&IF_G(post_array));
3218+ IF_G(post_array) = NULL;
3219+ }
3220+ if(IF_G(cookie_array)) {
3221+ zval_ptr_dtor(&IF_G(cookie_array));
3222+ IF_G(cookie_array) = NULL;
3223+ }
3224+ return SUCCESS;
3225+}
3226+
3227+PHP_MINFO_FUNCTION(my_input_filter)
3228+{
3229+ php_info_print_table_start();
3230+ php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
3231+ php_info_print_table_row( 2, "Revision", "$Revision: 1.1 $");
3232+ php_info_print_table_end();
3233+}
3234+
3235+/* The filter handler. If you return 1 from it, then PHP also registers the
3236+ * (modified) variable. Returning 0 prevents PHP from registering the variable;
3237+ * you can use this if your filter already registers the variable under a
3238+ * different name, or if you just don't want the variable registered at all. */
3239+SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter)
3240+{
3241+ zval new_var;
3242+ zval *array_ptr = NULL;
3243+ char *raw_var;
3244+ int var_len;
3245+
3246+ assert(*val != NULL);
3247+
3248+ switch(arg) {
3249+ case PARSE_GET:
3250+ if(!IF_G(get_array)) {
3251+ ALLOC_ZVAL(array_ptr);
3252+ array_init(array_ptr);
3253+ INIT_PZVAL(array_ptr);
3254+ }
3255+ IF_G(get_array) = array_ptr;
3256+ break;
3257+ case PARSE_POST:
3258+ if(!IF_G(post_array)) {
3259+ ALLOC_ZVAL(array_ptr);
3260+ array_init(array_ptr);
3261+ INIT_PZVAL(array_ptr);
3262+ }
3263+ IF_G(post_array) = array_ptr;
3264+ break;
3265+ case PARSE_COOKIE:
3266+ if(!IF_G(cookie_array)) {
3267+ ALLOC_ZVAL(array_ptr);
3268+ array_init(array_ptr);
3269+ INIT_PZVAL(array_ptr);
3270+ }
3271+ IF_G(cookie_array) = array_ptr;
3272+ break;
3273+ }
3274+ Z_STRLEN(new_var) = val_len;
3275+ Z_STRVAL(new_var) = estrndup(*val, val_len);
3276+ Z_TYPE(new_var) = IS_STRING;
3277+
3278+ var_len = strlen(var);
3279+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
3280+ strcpy(raw_var, "RAW_");
3281+ strlcat(raw_var,var,var_len+5);
3282+
3283+ php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);
3284+
3285+ php_strip_tags(*val, val_len, NULL, NULL, 0);
3286+
3287+ *new_val_len = strlen(*val);
3288+ return 1;
3289+}
3290+
3291+PHP_FUNCTION(my_get_raw)
3292+{
3293+ long arg;
3294+ char *var;
3295+ int var_len;
3296+ zval **tmp;
3297+ zval *array_ptr = NULL;
3298+ HashTable *hash_ptr;
3299+ char *raw_var;
3300+
3301+ if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
3302+ return;
3303+ }
3304+
3305+ switch(arg) {
3306+ case PARSE_GET:
3307+ array_ptr = IF_G(get_array);
3308+ break;
3309+ case PARSE_POST:
3310+ array_ptr = IF_G(post_array);
3311+ break;
3312+ case PARSE_COOKIE:
3313+ array_ptr = IF_G(post_array);
3314+ break;
3315+ }
3316+
3317+ if(!array_ptr) RETURN_FALSE;
3318+
3319+ /*
3320+ * I'm changing the variable name here because when running with register_globals on,
3321+ * the variable will end up in the global symbol table
3322+ */
3323+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
3324+ strcpy(raw_var, "RAW_");
3325+ strlcat(raw_var,var,var_len+5);
3326+ hash_ptr = HASH_OF(array_ptr);
3327+
3328+ if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
3329+ *return_value = **tmp;
3330+ zval_copy_ctor(return_value);
3331+ } else {
3332+ RETVAL_FALSE;
3333+ }
3334+ efree(raw_var);
3335+}
3336+
3337diff -Naur php-4.4.0RC2/sapi/apache/mod_php4.c hardening-patch-4.4.0RC2-0.3.2/sapi/apache/mod_php4.c
3338--- php-4.4.0RC2/sapi/apache/mod_php4.c 2005-05-19 18:14:46.000000000 +0200
3339+++ hardening-patch-4.4.0RC2-0.3.2/sapi/apache/mod_php4.c 2005-07-09 08:53:20.665597016 +0200
3340@@ -452,7 +452,7 @@
3341 sapi_apache_get_fd,
3342 sapi_apache_force_http_10,
3343 sapi_apache_get_target_uid,
3344- sapi_apache_get_target_gid
3345+ sapi_apache_get_target_gid,
3346 };
3347 /* }}} */
3348
3349@@ -898,7 +898,11 @@
3350 {
3351 TSRMLS_FETCH();
3352 if (PG(expose_php)) {
3353+#if HARDENING_PATCH
3354+ ap_add_version_component("PHP/" PHP_VERSION " with Hardening-Patch");
3355+#else
3356 ap_add_version_component("PHP/" PHP_VERSION);
3357+#endif
3358 }
3359 }
3360 #endif
3361diff -Naur php-4.4.0RC2/sapi/apache2filter/sapi_apache2.c hardening-patch-4.4.0RC2-0.3.2/sapi/apache2filter/sapi_apache2.c
3362--- php-4.4.0RC2/sapi/apache2filter/sapi_apache2.c 2005-04-08 22:35:02.000000000 +0200
3363+++ hardening-patch-4.4.0RC2-0.3.2/sapi/apache2filter/sapi_apache2.c 2005-07-09 08:53:20.665597016 +0200
3364@@ -556,7 +556,11 @@
3365 {
3366 TSRMLS_FETCH();
3367 if (PG(expose_php)) {
3368+#if HARDENING_PATCH
3369+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
3370+#else
3371 ap_add_version_component(p, "PHP/" PHP_VERSION);
3372+#endif
3373 }
3374 }
3375
3376diff -Naur php-4.4.0RC2/sapi/apache2handler/sapi_apache2.c hardening-patch-4.4.0RC2-0.3.2/sapi/apache2handler/sapi_apache2.c
3377--- php-4.4.0RC2/sapi/apache2handler/sapi_apache2.c 2005-04-08 22:35:02.000000000 +0200
3378+++ hardening-patch-4.4.0RC2-0.3.2/sapi/apache2handler/sapi_apache2.c 2005-07-09 08:53:20.666596864 +0200
3379@@ -340,7 +340,11 @@
3380 {
3381 TSRMLS_FETCH();
3382 if (PG(expose_php)) {
3383+#if HARDENING_PATCH
3384+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
3385+#else
3386 ap_add_version_component(p, "PHP/" PHP_VERSION);
3387+#endif
3388 }
3389 }
3390
3391diff -Naur php-4.4.0RC2/sapi/cgi/cgi_main.c hardening-patch-4.4.0RC2-0.3.2/sapi/cgi/cgi_main.c
3392--- php-4.4.0RC2/sapi/cgi/cgi_main.c 2005-04-28 16:24:47.000000000 +0200
3393+++ hardening-patch-4.4.0RC2-0.3.2/sapi/cgi/cgi_main.c 2005-07-09 08:53:20.667596712 +0200
3394@@ -1440,11 +1440,19 @@
3395 SG(headers_sent) = 1;
3396 SG(request_info).no_headers = 1;
3397 }
3398+#if HARDENING_PATCH
3399+#if ZEND_DEBUG
3400+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
3401+#else
3402+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
3403+#endif
3404+#else
3405 #if ZEND_DEBUG
3406 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
3407 #else
3408 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
3409 #endif
3410+#endif
3411 php_end_ob_buffers(1 TSRMLS_CC);
3412 exit(1);
3413 break;
3414diff -Naur php-4.4.0RC2/sapi/cli/php_cli.c hardening-patch-4.4.0RC2-0.3.2/sapi/cli/php_cli.c
3415--- php-4.4.0RC2/sapi/cli/php_cli.c 2005-03-22 16:09:36.000000000 +0100
3416+++ hardening-patch-4.4.0RC2-0.3.2/sapi/cli/php_cli.c 2005-07-09 08:53:20.667596712 +0200
3417@@ -652,11 +652,19 @@
3418 if (php_request_startup(TSRMLS_C)==FAILURE) {
3419 goto err;
3420 }
3421+#if HARDENING_PATCH
3422+#if ZEND_DEBUG
3423+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
3424+#else
3425+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
3426+#endif
3427+#else
3428 #if ZEND_DEBUG
3429 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
3430 #else
3431 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
3432 #endif
3433+#endif
3434 php_end_ob_buffers(1 TSRMLS_CC);
3435 exit_status=1;
3436 goto out;
3437diff -Naur php-4.4.0RC2/TSRM/TSRM.h hardening-patch-4.4.0RC2-0.3.2/TSRM/TSRM.h
3438--- php-4.4.0RC2/TSRM/TSRM.h 2005-02-11 04:34:04.000000000 +0100
3439+++ hardening-patch-4.4.0RC2-0.3.2/TSRM/TSRM.h 2005-07-09 08:53:20.668596560 +0200
3440@@ -33,6 +33,13 @@
3441 # define TSRM_API
3442 #endif
3443
3444+#if HARDENING_PATCH
3445+# if HAVE_REALPATH
3446+# undef realpath
3447+# define realpath php_realpath
3448+# endif
3449+#endif
3450+
3451 /* Only compile multi-threading functions if we're in ZTS mode */
3452 #ifdef ZTS
3453
3454@@ -90,6 +97,7 @@
3455
3456 #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
3457
3458+
3459 #ifdef __cplusplus
3460 extern "C" {
3461 #endif
3462diff -Naur php-4.4.0RC2/TSRM/tsrm_virtual_cwd.c hardening-patch-4.4.0RC2-0.3.2/TSRM/tsrm_virtual_cwd.c
3463--- php-4.4.0RC2/TSRM/tsrm_virtual_cwd.c 2005-02-11 04:34:04.000000000 +0100
3464+++ hardening-patch-4.4.0RC2-0.3.2/TSRM/tsrm_virtual_cwd.c 2005-07-09 08:53:20.669596408 +0200
3465@@ -192,6 +192,165 @@
3466 return p;
3467 }
3468
3469+#if HARDENING_PATCH
3470+CWD_API char *php_realpath(const char *path, char *resolved)
3471+{
3472+ struct stat sb;
3473+ char *p, *q, *s;
3474+ size_t left_len, resolved_len;
3475+ unsigned symlinks;
3476+ int serrno, slen;
3477+ int is_dir = 1;
3478+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
3479+
3480+ serrno = errno;
3481+ symlinks = 0;
3482+ if (path[0] == '/') {
3483+ resolved[0] = '/';
3484+ resolved[1] = '\0';
3485+ if (path[1] == '\0')
3486+ return (resolved);
3487+ resolved_len = 1;
3488+ left_len = strlcpy(left, path + 1, sizeof(left));
3489+ } else {
3490+ if (getcwd(resolved, PATH_MAX) == NULL) {
3491+ strlcpy(resolved, ".", PATH_MAX);
3492+ return (NULL);
3493+ }
3494+ resolved_len = strlen(resolved);
3495+ left_len = strlcpy(left, path, sizeof(left));
3496+ }
3497+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
3498+ errno = ENAMETOOLONG;
3499+ return (NULL);
3500+ }
3501+
3502+ /*
3503+ * Iterate over path components in `left'.
3504+ */
3505+ while (left_len != 0) {
3506+ /*
3507+ * Extract the next path component and adjust `left'
3508+ * and its length.
3509+ */
3510+ p = strchr(left, '/');
3511+ s = p ? p : left + left_len;
3512+ if (s - left >= sizeof(next_token)) {
3513+ errno = ENAMETOOLONG;
3514+ return (NULL);
3515+ }
3516+ memcpy(next_token, left, s - left);
3517+ next_token[s - left] = '\0';
3518+ left_len -= s - left;
3519+ if (p != NULL)
3520+ memmove(left, s + 1, left_len + 1);
3521+ if (resolved[resolved_len - 1] != '/') {
3522+ if (resolved_len + 1 >= PATH_MAX) {
3523+ errno = ENAMETOOLONG;
3524+ return (NULL);
3525+ }
3526+ resolved[resolved_len++] = '/';
3527+ resolved[resolved_len] = '\0';
3528+ }
3529+ if (next_token[0] == '\0')
3530+ continue;
3531+ else if (strcmp(next_token, ".") == 0)
3532+ continue;
3533+ else if (strcmp(next_token, "..") == 0) {
3534+ /*
3535+ * Strip the last path component except when we have
3536+ * single "/"
3537+ */
3538+ if (!is_dir) {
3539+ errno = ENOENT;
3540+ return (NULL);
3541+ }
3542+ if (resolved_len > 1) {
3543+ resolved[resolved_len - 1] = '\0';
3544+ q = strrchr(resolved, '/');
3545+ *q = '\0';
3546+ resolved_len = q - resolved;
3547+ }
3548+ continue;
3549+ }
3550+
3551+ /*
3552+ * Append the next path component and lstat() it. If
3553+ * lstat() fails we still can return successfully if
3554+ * there are no more path components left.
3555+ */
3556+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
3557+ if (resolved_len >= PATH_MAX) {
3558+ errno = ENAMETOOLONG;
3559+ return (NULL);
3560+ }
3561+ if (lstat(resolved, &sb) != 0) {
3562+ if (errno == ENOENT && p == NULL) {
3563+ errno = serrno;
3564+ return (resolved);
3565+ }
3566+ return (NULL);
3567+ }
3568+ if (S_ISLNK(sb.st_mode)) {
3569+ if (symlinks++ > MAXSYMLINKS) {
3570+ errno = ELOOP;
3571+ return (NULL);
3572+ }
3573+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
3574+ if (slen < 0)
3575+ return (NULL);
3576+ symlink[slen] = '\0';
3577+ if (symlink[0] == '/') {
3578+ resolved[1] = 0;
3579+ resolved_len = 1;
3580+ } else if (resolved_len > 1) {
3581+ /* Strip the last path component. */
3582+ resolved[resolved_len - 1] = '\0';
3583+ q = strrchr(resolved, '/');
3584+ *q = '\0';
3585+ resolved_len = q - resolved;
3586+ }
3587+
3588+ /*
3589+ * If there are any path components left, then
3590+ * append them to symlink. The result is placed
3591+ * in `left'.
3592+ */
3593+ if (p != NULL) {
3594+ if (symlink[slen - 1] != '/') {
3595+ if (slen + 1 >= sizeof(symlink)) {
3596+ errno = ENAMETOOLONG;
3597+ return (NULL);
3598+ }
3599+ symlink[slen] = '/';
3600+ symlink[slen + 1] = 0;
3601+ }
3602+ left_len = strlcat(symlink, left, sizeof(left));
3603+ if (left_len >= sizeof(left)) {
3604+ errno = ENAMETOOLONG;
3605+ return (NULL);
3606+ }
3607+ }
3608+ left_len = strlcpy(left, symlink, sizeof(left));
3609+ } else {
3610+ if (S_ISDIR(sb.st_mode)) {
3611+ is_dir = 1;
3612+ } else {
3613+ is_dir = 0;
3614+ }
3615+ }
3616+ }
3617+
3618+ /*
3619+ * Remove trailing slash except when the resolved pathname
3620+ * is a single "/".
3621+ */
3622+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
3623+ resolved[resolved_len - 1] = '\0';
3624+ return (resolved);
3625+}
3626+#endif
3627+
3628 CWD_API void virtual_cwd_startup(void)
3629 {
3630 char cwd[MAXPATHLEN];
3631@@ -314,8 +473,7 @@
3632 path = resolved_path;
3633 path_length = strlen(path);
3634 } else {
3635- /* disable for now
3636- return 1; */
3637+ return 1;
3638 }
3639 }
3640 } else { /* Concat current directory with relative path and then run realpath() on it */
3641@@ -341,9 +499,8 @@
3642 path = resolved_path;
3643 path_length = strlen(path);
3644 } else {
3645- /* disable for now
3646 free(tmp);
3647- return 1; */
3648+ return 1;
3649 }
3650 }
3651 free(tmp);
3652diff -Naur php-4.4.0RC2/TSRM/tsrm_virtual_cwd.h hardening-patch-4.4.0RC2-0.3.2/TSRM/tsrm_virtual_cwd.h
3653--- php-4.4.0RC2/TSRM/tsrm_virtual_cwd.h 2005-02-11 04:34:04.000000000 +0100
3654+++ hardening-patch-4.4.0RC2-0.3.2/TSRM/tsrm_virtual_cwd.h 2005-07-09 08:53:20.669596408 +0200
3655@@ -128,6 +128,22 @@
3656
3657 typedef int (*verify_path_func)(const cwd_state *);
3658
3659+#ifndef HAVE_STRLCPY
3660+CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz);
3661+#undef strlcpy
3662+#define strlcpy php_strlcpy
3663+#endif
3664+
3665+#ifndef HAVE_STRLCAT
3666+CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz);
3667+#undef strlcat
3668+#define strlcat php_strlcat
3669+#endif
3670+
3671+
3672+#if HARDENING_PATCH
3673+CWD_API char *php_realpath(const char *path, char *resolved);
3674+#endif
3675 CWD_API void virtual_cwd_startup(void);
3676 CWD_API void virtual_cwd_shutdown(void);
3677 CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC);
3678diff -Naur php-4.4.0RC2/Zend/zend_alloc.c hardening-patch-4.4.0RC2-0.3.2/Zend/zend_alloc.c
3679--- php-4.4.0RC2/Zend/zend_alloc.c 2005-04-07 22:54:33.000000000 +0200
3680+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_alloc.c 2005-07-09 08:53:20.670596256 +0200
3681@@ -56,6 +56,11 @@
3682 # define END_MAGIC_SIZE 0
3683 #endif
3684
3685+#if HARDENING_PATCH_MM_PROTECT
3686+# define CANARY_SIZE sizeof(unsigned int)
3687+#else
3688+# define CANARY_SIZE 0
3689+#endif
3690
3691 # if MEMORY_LIMIT
3692 # if ZEND_DEBUG
3693@@ -95,9 +100,17 @@
3694 if (p==AG(head)) { \
3695 AG(head) = p->pNext; \
3696 } else { \
3697+ if (p != p->pLast->pNext) { \
3698+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
3699+ exit(1); \
3700+ } \
3701 p->pLast->pNext = p->pNext; \
3702 } \
3703 if (p->pNext) { \
3704+ if (p != p->pNext->pLast) { \
3705+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
3706+ exit(1); \
3707+ } \
3708 p->pNext->pLast = p->pLast; \
3709 }
3710
3711@@ -129,6 +142,12 @@
3712 DECLARE_CACHE_VARS();
3713 TSRMLS_FETCH();
3714
3715+#if HARDENING_PATCH_MM_PROTECT
3716+ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) {
3717+ zend_security_log(S_MEMORY, "emalloc() - requested size would result in integer overflow");
3718+ exit(1);
3719+ }
3720+#endif
3721 CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);
3722
3723 if (!ZEND_DISABLE_MEMORY_CACHE && (CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] > 0)) {
3724@@ -146,6 +165,10 @@
3725 AG(cache_stats)[CACHE_INDEX][1]++;
3726 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
3727 #endif
3728+#if HARDENING_PATCH_MM_PROTECT
3729+ p->canary = HG(canary_1);
3730+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
3731+#endif
3732 p->cached = 0;
3733 p->size = size;
3734 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
3735@@ -161,7 +184,7 @@
3736 AG(allocated_memory_peak) = AG(allocated_memory);
3737 }
3738 #endif
3739- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE);
3740+ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE);
3741 }
3742
3743 HANDLE_BLOCK_INTERRUPTIONS();
3744@@ -191,7 +214,10 @@
3745 # endif
3746 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
3747 #endif
3748-
3749+#if HARDENING_PATCH_MM_PROTECT
3750+ p->canary = HG(canary_1);
3751+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
3752+#endif
3753 HANDLE_UNBLOCK_INTERRUPTIONS();
3754 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
3755 }
3756@@ -218,17 +244,33 @@
3757 return emalloc_rel(lval + offset);
3758 }
3759 }
3760-
3761+
3762+#if HARDENING_PATCH
3763+ zend_security_log(S_MEMORY, "Possible integer overflow catched by safe_emalloc()");
3764+#endif
3765 zend_error(E_ERROR, "Possible integer overflow in memory allocation (%ld * %ld + %ld)", nmemb, size, offset);
3766 return 0;
3767 }
3768
3769 ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
3770 {
3771+#if HARDENING_PATCH_MM_PROTECT
3772+ unsigned int *canary_2;
3773+#endif
3774 zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING);
3775 DECLARE_CACHE_VARS();
3776 TSRMLS_FETCH();
3777
3778+#if HARDENING_PATCH_MM_PROTECT
3779+ canary_2 = (unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
3780+ if (p->canary != HG(canary_1) || *canary_2 != HG(canary_2)) {
3781+ zend_security_log(S_MEMORY, "canary mismatch on efree() - heap overflow or double efree detected");
3782+ exit(1);
3783+ }
3784+ /* to catch double efree()s */
3785+ *canary_2 = p->canary = 0;
3786+#endif
3787+
3788 #if defined(ZTS) && TSRM_DEBUG
3789 if (p->thread_id != tsrm_thread_id()) {
3790 tsrm_error(TSRM_ERROR_LEVEL_ERROR, "Memory block allocated at %s:(%d) on thread %x freed at %s:(%d) on thread %x, ignoring",
3791@@ -273,6 +315,9 @@
3792 size_t _size = nmemb * size;
3793
3794 if (nmemb && (_size/nmemb!=size)) {
3795+#if HARDENING_PATCH
3796+ zend_security_log(S_MEMORY, "Possible integer overflow catched by ecalloc()");
3797+#endif
3798 fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size);
3799 #if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID
3800 kill(getpid(), SIGSEGV);
3801@@ -292,6 +337,9 @@
3802
3803 ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
3804 {
3805+#if HARDENING_PATCH_MM_PROTECT
3806+ unsigned int canary_2;
3807+#endif
3808 zend_mem_header *p;
3809 zend_mem_header *orig;
3810 DECLARE_CACHE_VARS();
3811@@ -303,6 +351,14 @@
3812
3813 p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING);
3814
3815+#if HARDENING_PATCH_MM_PROTECT
3816+ canary_2 = *(unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
3817+ if (p->canary != HG(canary_1) || canary_2 != HG(canary_2)) {
3818+ zend_security_log(S_MEMORY, "canary mismatch on erealloc() - heap overflow detected");
3819+ exit(1);
3820+ }
3821+#endif
3822+
3823 #if defined(ZTS) && TSRM_DEBUG
3824 if (p->thread_id != tsrm_thread_id()) {
3825 void *new_p;
3826@@ -326,7 +382,7 @@
3827 }
3828 #endif
3829 REMOVE_POINTER_FROM_LIST(p);
3830- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE);
3831+ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE);
3832 if (!p) {
3833 if (!allow_failure) {
3834 fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size);
3835@@ -348,6 +404,9 @@
3836 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
3837 #endif
3838
3839+#if HARDENING_PATCH_MM_PROTECT
3840+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
3841+#endif
3842 p->size = size;
3843
3844 HANDLE_UNBLOCK_INTERRUPTIONS();
3845@@ -422,6 +481,10 @@
3846 {
3847 AG(head) = NULL;
3848
3849+#if HARDENING_PATCH_MM_PROTECT
3850+ HG(canary_1) = zend_canary();
3851+ HG(canary_2) = zend_canary();
3852+#endif
3853 #if MEMORY_LIMIT
3854 AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */
3855 AG(allocated_memory) = 0;
3856diff -Naur php-4.4.0RC2/Zend/zend_alloc.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_alloc.h
3857--- php-4.4.0RC2/Zend/zend_alloc.h 2005-06-07 15:37:33.000000000 +0200
3858+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_alloc.h 2005-07-09 08:53:20.671596104 +0200
3859@@ -32,6 +32,9 @@
3860 #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL
3861
3862 typedef struct _zend_mem_header {
3863+#if HARDENING_PATCH_MM_PROTECT
3864+ unsigned int canary;
3865+#endif
3866 #if ZEND_DEBUG
3867 long magic;
3868 char *filename;
3869diff -Naur php-4.4.0RC2/Zend/zend_builtin_functions.c hardening-patch-4.4.0RC2-0.3.2/Zend/zend_builtin_functions.c
3870--- php-4.4.0RC2/Zend/zend_builtin_functions.c 2005-06-23 14:20:47.000000000 +0200
3871+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_builtin_functions.c 2005-07-09 08:53:20.671596104 +0200
3872@@ -49,6 +49,9 @@
3873 static ZEND_FUNCTION(crash);
3874 #endif
3875 #endif
3876+#if HARDENING_PATCH_MM_PROTECT_DEBUG
3877+static ZEND_FUNCTION(heap_overflow);
3878+#endif
3879 static ZEND_FUNCTION(get_included_files);
3880 static ZEND_FUNCTION(is_subclass_of);
3881 static ZEND_FUNCTION(is_a);
3882@@ -101,6 +104,9 @@
3883 ZEND_FE(crash, NULL)
3884 #endif
3885 #endif
3886+#if HARDENING_PATCH_MM_PROTECT_DEBUG
3887+ ZEND_FE(heap_overflow, NULL)
3888+#endif
3889 ZEND_FE(get_included_files, NULL)
3890 ZEND_FALIAS(get_required_files, get_included_files, NULL)
3891 ZEND_FE(is_subclass_of, NULL)
3892@@ -805,6 +811,19 @@
3893
3894 #endif /* ZEND_DEBUG */
3895
3896+
3897+#if HARDENING_PATCH_MM_PROTECT_DEBUG
3898+ZEND_FUNCTION(heap_overflow)
3899+{
3900+ char *nowhere = emalloc(10);
3901+
3902+ memcpy(nowhere, "something1234567890", sizeof("something1234567890"));
3903+
3904+ efree(nowhere);
3905+}
3906+#endif
3907+
3908+
3909 /* {{{ proto array get_included_files(void)
3910 Returns an array with the file names that were include_once()'d */
3911 ZEND_FUNCTION(get_included_files)
3912diff -Naur php-4.4.0RC2/Zend/zend.c hardening-patch-4.4.0RC2-0.3.2/Zend/zend.c
3913--- php-4.4.0RC2/Zend/zend.c 2005-06-09 12:14:25.000000000 +0200
3914+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend.c 2005-07-09 08:53:20.672595952 +0200
3915@@ -53,6 +53,12 @@
3916 ZEND_API void (*zend_unblock_interruptions)(void);
3917 ZEND_API void (*zend_ticks_function)(int ticks);
3918 ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
3919+#if HARDENING_PATCH
3920+ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
3921+#endif
3922+#if HARDENING_PATCH_INC_PROTECT
3923+ZEND_API int (*zend_is_valid_include)(zval *z);
3924+#endif
3925
3926 void (*zend_on_timeout)(int seconds TSRMLS_DC);
3927
3928@@ -70,9 +76,80 @@
3929 return SUCCESS;
3930 }
3931
3932+#if HARDENING_PATCH
3933+static ZEND_INI_MH(OnUpdateHPHP_log_syslog)
3934+{
3935+ if (!new_value) {
3936+ EG(hphp_log_syslog) = S_ALL & ~S_SQL | S_MEMORY;
3937+ } else {
3938+ EG(hphp_log_syslog) = atoi(new_value) | S_MEMORY;
3939+ }
3940+ return SUCCESS;
3941+}
3942+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_facility)
3943+{
3944+ if (!new_value) {
3945+ EG(hphp_log_syslog_facility) = LOG_USER;
3946+ } else {
3947+ EG(hphp_log_syslog_facility) = atoi(new_value);
3948+ }
3949+ return SUCCESS;
3950+}
3951+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_priority)
3952+{
3953+ if (!new_value) {
3954+ EG(hphp_log_syslog_priority) = LOG_ALERT;
3955+ } else {
3956+ EG(hphp_log_syslog_priority) = atoi(new_value);
3957+ }
3958+ return SUCCESS;
3959+}
3960+static ZEND_INI_MH(OnUpdateHPHP_log_sapi)
3961+{
3962+ if (!new_value) {
3963+ EG(hphp_log_sapi) = S_ALL & ~S_SQL;
3964+ } else {
3965+ EG(hphp_log_sapi) = atoi(new_value);
3966+ }
3967+ return SUCCESS;
3968+}
3969+static ZEND_INI_MH(OnUpdateHPHP_log_script)
3970+{
3971+ if (!new_value) {
3972+ EG(hphp_log_script) = S_ALL & ~S_MEMORY;
3973+ } else {
3974+ EG(hphp_log_script) = atoi(new_value) & ~S_MEMORY;
3975+ }
3976+ return SUCCESS;
3977+}
3978+static ZEND_INI_MH(OnUpdateHPHP_log_scriptname)
3979+{
3980+ if (!new_value) {
3981+ EG(hphp_log_scriptname) = NULL;
3982+ } else {
3983+ if (EG(hphp_log_scriptname)) {
3984+ pefree(EG(hphp_log_scriptname),1);
3985+ }
3986+ EG(hphp_log_scriptname) = pestrdup(new_value,1);
3987+ }
3988+ return SUCCESS;
3989+}
3990+#endif
3991
3992 ZEND_INI_BEGIN()
3993 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
3994+#if HARDENING_PATCH
3995+ ZEND_INI_ENTRY("hphp.log.syslog", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog)
3996+ ZEND_INI_ENTRY("hphp.log.syslog.facility", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_facility)
3997+ ZEND_INI_ENTRY("hphp.log.syslog.priority", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_priority)
3998+ ZEND_INI_ENTRY("hphp.log.sapi", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_sapi)
3999+ ZEND_INI_ENTRY("hphp.log.script", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_script)
4000+ ZEND_INI_ENTRY("hphp.log.script.name", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_scriptname)
4001+ STD_ZEND_INI_BOOLEAN("hphp.log.use-x-forwarded-for", "0", ZEND_INI_SYSTEM, OnUpdateBool, hphp_log_use_x_forwarded_for, zend_executor_globals, executor_globals)
4002+ STD_ZEND_INI_ENTRY("hphp.executor.max_depth", "0", ZEND_INI_PERDIR, OnUpdateLong, hphp_executor_max_depth, zend_executor_globals, executor_globals)
4003+ STD_ZEND_INI_BOOLEAN("hphp.sql.bailout_on_error", "0", ZEND_INI_PERDIR, OnUpdateBool, hphp_sql_bailout_on_error, hardened_globals_struct, hardened_globals)
4004+ STD_ZEND_INI_BOOLEAN("hphp.multiheader", "0", ZEND_INI_PERDIR, OnUpdateBool, hphp_multiheader, hardened_globals_struct, hardened_globals)
4005+#endif
4006 ZEND_INI_END()
4007
4008
4009@@ -354,6 +431,7 @@
4010 zend_init_rsrc_plist(TSRMLS_C);
4011 EG(lambda_count)=0;
4012 EG(user_error_handler) = NULL;
4013+ EG(in_code_type) = 0;
4014 EG(in_execution) = 0;
4015 EG(current_execute_data) = NULL;
4016 }
4017@@ -420,6 +498,14 @@
4018 extern zend_scanner_globals language_scanner_globals;
4019 #endif
4020
4021+ /* Set up Hardening-Patch utility functions first */
4022+#if HARDENING_PATCH
4023+ zend_security_log = utility_functions->security_log_function;
4024+#endif
4025+#if HARDENING_PATCH_INC_PROTECT
4026+ zend_is_valid_include = utility_functions->is_valid_include;
4027+#endif
4028+
4029 #ifdef ZTS
4030 ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
4031 #else
4032@@ -623,6 +709,7 @@
4033 }
4034 CG(unclean_shutdown) = 1;
4035 CG(in_compilation) = EG(in_execution) = 0;
4036+ EG(in_code_type) = 0;
4037 EG(current_execute_data) = NULL;
4038 longjmp(EG(bailout), FAILURE);
4039 }
4040diff -Naur php-4.4.0RC2/Zend/zend_canary.c hardening-patch-4.4.0RC2-0.3.2/Zend/zend_canary.c
4041--- php-4.4.0RC2/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
4042+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_canary.c 2005-07-09 08:53:20.673595800 +0200
4043@@ -0,0 +1,58 @@
4044+/*
4045+ +----------------------------------------------------------------------+
4046+ | Hardening-Patch for PHP |
4047+ +----------------------------------------------------------------------+
4048+ | Copyright (c) 2004-2005 Stefan Esser |
4049+ +----------------------------------------------------------------------+
4050+ | This source file is subject to version 2.02 of the PHP license, |
4051+ | that is bundled with this package in the file LICENSE, and is |
4052+ | available at through the world-wide-web at |
4053+ | http://www.php.net/license/2_02.txt. |
4054+ | If you did not receive a copy of the PHP license and are unable to |
4055+ | obtain it through the world-wide-web, please send a note to |
4056+ | license@php.net so we can mail you a copy immediately. |
4057+ +----------------------------------------------------------------------+
4058+ | Author: Stefan Esser <sesser@hardened-php.net> |
4059+ +----------------------------------------------------------------------+
4060+ */
4061+/* $Id: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */
4062+
4063+#include "zend.h"
4064+
4065+#include <stdio.h>
4066+#include <stdlib.h>
4067+
4068+
4069+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
4070+
4071+/* will be replaced later with more compatible method */
4072+ZEND_API unsigned int zend_canary()
4073+{
4074+ time_t t;
4075+ unsigned int canary;
4076+ int fd;
4077+
4078+ fd = open("/dev/urandom", 0);
4079+ if (fd != -1) {
4080+ int r = read(fd, &canary, sizeof(canary));
4081+ close(fd);
4082+ if (r == sizeof(canary)) {
4083+ return (canary);
4084+ }
4085+ }
4086+ /* not good but we never want to do this */
4087+ time(&t);
4088+ canary = *(unsigned int *)&t + getpid() << 16;
4089+ return (canary);
4090+}
4091+#endif
4092+
4093+
4094+/*
4095+ * Local variables:
4096+ * tab-width: 4
4097+ * c-basic-offset: 4
4098+ * End:
4099+ * vim600: sw=4 ts=4 fdm=marker
4100+ * vim<600: sw=4 ts=4
4101+ */
4102diff -Naur php-4.4.0RC2/Zend/zend_compile.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_compile.h
4103--- php-4.4.0RC2/Zend/zend_compile.h 2005-06-06 11:30:09.000000000 +0200
4104+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_compile.h 2005-07-09 08:53:20.673595800 +0200
4105@@ -549,6 +549,7 @@
4106 #define ZEND_USER_FUNCTION 2
4107 #define ZEND_OVERLOADED_FUNCTION 3
4108 #define ZEND_EVAL_CODE 4
4109+#define ZEND_SANDBOX_CODE 6
4110
4111 #define ZEND_INTERNAL_CLASS 1
4112 #define ZEND_USER_CLASS 2
4113diff -Naur php-4.4.0RC2/Zend/zend_constants.c hardening-patch-4.4.0RC2-0.3.2/Zend/zend_constants.c
4114--- php-4.4.0RC2/Zend/zend_constants.c 2004-07-13 21:29:45.000000000 +0200
4115+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_constants.c 2005-07-09 08:53:20.674595648 +0200
4116@@ -111,6 +111,72 @@
4117 REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
4118
4119 REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
4120+#if HARDENING_PATCH
4121+ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
4122+ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
4123+ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_VARS, CONST_PERSISTENT | CONST_CS);
4124+ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
4125+ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
4126+ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
4127+ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
4128+ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
4129+
4130+ /* error levels */
4131+ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
4132+ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
4133+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
4134+ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
4135+ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
4136+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
4137+ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
4138+ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
4139+ /* facility: type of program logging the message */
4140+ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
4141+ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
4142+ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
4143+ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
4144+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
4145+ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
4146+ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
4147+#ifdef LOG_NEWS
4148+ /* No LOG_NEWS on HP-UX */
4149+ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
4150+#endif
4151+#ifdef LOG_UUCP
4152+ /* No LOG_UUCP on HP-UX */
4153+ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
4154+#endif
4155+#ifdef LOG_CRON
4156+ /* apparently some systems don't have this one */
4157+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
4158+#endif
4159+#ifdef LOG_AUTHPRIV
4160+ /* AIX doesn't have LOG_AUTHPRIV */
4161+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
4162+#endif
4163+#if !defined(PHP_WIN32) && !defined(NETWARE)
4164+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
4165+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
4166+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
4167+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
4168+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
4169+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
4170+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
4171+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
4172+#endif
4173+ /* options */
4174+ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
4175+ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
4176+ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
4177+ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
4178+#ifdef LOG_NOWAIT
4179+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
4180+#endif
4181+#ifdef LOG_PERROR
4182+ /* AIX doesn't have LOG_PERROR */
4183+ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
4184+#endif
4185+#endif
4186
4187 /* true/false constants */
4188 {
4189diff -Naur php-4.4.0RC2/Zend/zend_errors.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_errors.h
4190--- php-4.4.0RC2/Zend/zend_errors.h 2002-12-31 17:22:59.000000000 +0100
4191+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_errors.h 2005-07-09 08:53:20.674595648 +0200
4192@@ -36,5 +36,16 @@
4193 #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE)
4194 #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
4195
4196+#if HARDENING_PATCH
4197+#define S_MEMORY (1<<0L)
4198+#define S_VARS (1<<1L)
4199+#define S_FILES (1<<2L)
4200+#define S_INCLUDE (1<<3L)
4201+#define S_SQL (1<<4L)
4202+#define S_EXECUTOR (1<<5L)
4203+#define S_MISC (1<<30L)
4204+#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MISC | S_SQL | S_EXECUTOR)
4205+#endif
4206+
4207 #endif /* ZEND_ERRORS_H */
4208
4209diff -Naur php-4.4.0RC2/Zend/zend_execute_API.c hardening-patch-4.4.0RC2-0.3.2/Zend/zend_execute_API.c
4210--- php-4.4.0RC2/Zend/zend_execute_API.c 2005-05-18 19:58:09.000000000 +0200
4211+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_execute_API.c 2005-07-09 08:53:20.675595496 +0200
4212@@ -142,6 +142,7 @@
4213 EG(class_table) = CG(class_table);
4214
4215 EG(in_execution) = 0;
4216+ EG(in_code_type) = 0;
4217
4218 zend_ptr_stack_init(&EG(argument_stack));
4219
4220@@ -431,12 +432,14 @@
4221 zend_execute_data execute_data;
4222
4223 /* Initialize execute_data */
4224+ memset(&execute_data, 0, sizeof(execute_data));
4225 EX(fbc) = NULL;
4226 EX(object).ptr = NULL;
4227 EX(ce) = NULL;
4228 EX(Ts) = NULL;
4229 EX(op_array) = NULL;
4230 EX(opline) = NULL;
4231+ EX(execute_depth) = 0;
4232
4233 *retval_ptr_ptr = NULL;
4234
4235@@ -606,8 +609,7 @@
4236 return SUCCESS;
4237 }
4238
4239-
4240-ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
4241+ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int type TSRMLS_DC)
4242 {
4243 zval pv;
4244 zend_op_array *new_op_array;
4245@@ -640,6 +642,7 @@
4246 zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
4247 zend_op **original_opline_ptr = EG(opline_ptr);
4248
4249+ new_op_array->type = type;
4250 EG(return_value_ptr_ptr) = &local_retval_ptr;
4251 EG(active_op_array) = new_op_array;
4252 EG(no_extensions)=1;
4253@@ -673,6 +676,10 @@
4254 return retval;
4255 }
4256
4257+ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
4258+{
4259+ return (zend_eval_string_ex(str, retval_ptr, string_name, ZEND_EVAL_CODE TSRMLS_CC));
4260+}
4261
4262 void execute_new_code(TSRMLS_D)
4263 {
4264diff -Naur php-4.4.0RC2/Zend/zend_execute.c hardening-patch-4.4.0RC2-0.3.2/Zend/zend_execute.c
4265--- php-4.4.0RC2/Zend/zend_execute.c 2005-06-27 08:15:48.000000000 +0200
4266+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_execute.c 2005-07-09 08:53:20.676595344 +0200
4267@@ -1042,6 +1042,7 @@
4268 zend_execute_data execute_data;
4269
4270 /* Initialize execute_data */
4271+ memset(&execute_data, 0, sizeof(execute_data));
4272 EX(fbc) = NULL;
4273 EX(ce) = NULL;
4274 EX(object).ptr = NULL;
4275@@ -1053,9 +1054,21 @@
4276 }
4277 EX(prev_execute_data) = EG(current_execute_data);
4278 EX(original_in_execution)=EG(in_execution);
4279+ EX(original_in_code_type)=EG(in_code_type);
4280
4281 EG(current_execute_data) = &execute_data;
4282
4283+#if HARDENING_PATCH
4284+ EX(execute_depth) = 0;
4285+
4286+ if (op_array->type == ZEND_EVAL_CODE && EG(in_code_type) != ZEND_SANDBOX_CODE) {
4287+ EG(in_code_type) = ZEND_EVAL_CODE;
4288+ } else if (op_array->type == ZEND_SANDBOX_CODE) {
4289+ EG(in_code_type) = ZEND_SANDBOX_CODE;
4290+ op_array->type = ZEND_EVAL_CODE;
4291+ }
4292+#endif
4293+
4294 EG(in_execution) = 1;
4295 if (op_array->start_op) {
4296 EX(opline) = op_array->start_op;
4297@@ -1087,6 +1100,19 @@
4298 }
4299 }
4300
4301+#if HARDENING_PATCH
4302+ if (EX(prev_execute_data) == NULL) {
4303+ EX(execute_depth) = 0;
4304+ } else {
4305+ EX(execute_depth) = EX(prev_execute_data)->execute_depth + 1;
4306+ }
4307+
4308+ if (EG(hphp_executor_max_depth) > 0 && EX(execute_depth) > EG(hphp_executor_max_depth)) {
4309+ zend_security_log(S_EXECUTOR, "Maximum execution depth of %u violated", EG(hphp_executor_max_depth));
4310+ zend_bailout();
4311+ }
4312+#endif
4313+
4314 while (1) {
4315 #ifdef ZEND_WIN32
4316 if (EG(timed_out)) {
4317@@ -1816,6 +1842,7 @@
4318 efree(EX(Ts));
4319 }
4320 EG(in_execution) = EX(original_in_execution);
4321+ EG(in_code_type) = EX(original_in_code_type);
4322 EG(current_execute_data) = EX(prev_execute_data);
4323 return;
4324 }
4325@@ -2195,7 +2222,12 @@
4326 int dummy = 1;
4327 zend_file_handle file_handle = {0};
4328
4329+#if HARDENING_PATCH_INC_PROTECT
4330+ if (zend_is_valid_include(inc_filename)
4331+ && zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
4332+#else
4333 if (zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
4334+#endif
4335 && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
4336
4337 file_handle.filename = inc_filename->value.str.val;
4338@@ -2224,6 +2256,11 @@
4339 break;
4340 case ZEND_INCLUDE:
4341 case ZEND_REQUIRE:
4342+#if HARDENING_PATCH_INC_PROTECT
4343+ if (!zend_is_valid_include(inc_filename)) {
4344+ break;
4345+ }
4346+#endif
4347 new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
4348 break;
4349 case ZEND_EVAL: {
4350diff -Naur php-4.4.0RC2/Zend/zend_execute_globals.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_execute_globals.h
4351--- php-4.4.0RC2/Zend/zend_execute_globals.h 2005-06-06 11:30:09.000000000 +0200
4352+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_execute_globals.h 2005-07-09 08:53:20.677595192 +0200
4353@@ -60,6 +60,8 @@
4354 object_info object;
4355 temp_variable *Ts;
4356 zend_bool original_in_execution;
4357+ zend_uint original_in_code_type;
4358+ zend_uint execute_depth;
4359 zend_op_array *op_array;
4360 struct _zend_execute_data *prev_execute_data;
4361 } zend_execute_data;
4362diff -Naur php-4.4.0RC2/Zend/zend_extensions.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_extensions.h
4363--- php-4.4.0RC2/Zend/zend_extensions.h 2005-06-06 11:44:59.000000000 +0200
4364+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_extensions.h 2005-07-09 08:53:20.677595192 +0200
4365@@ -23,7 +23,9 @@
4366
4367 #include "zend_compile.h"
4368
4369-#define ZEND_EXTENSION_API_NO 20050606
4370+/* Create own API version number for Hardening-Patch */
4371+
4372+#define ZEND_EXTENSION_API_NO 1020050705
4373
4374 typedef struct _zend_extension_version_info {
4375 int zend_extension_api_no;
4376diff -Naur php-4.4.0RC2/Zend/zend_globals.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_globals.h
4377--- php-4.4.0RC2/Zend/zend_globals.h 2004-11-04 00:15:05.000000000 +0100
4378+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_globals.h 2005-07-09 08:53:20.678595040 +0200
4379@@ -163,6 +163,16 @@
4380
4381 int error_reporting;
4382 int orig_error_reporting;
4383+#if HARDENING_PATCH
4384+ int hphp_log_syslog;
4385+ int hphp_log_syslog_facility;
4386+ int hphp_log_syslog_priority;
4387+ int hphp_log_sapi;
4388+ int hphp_log_script;
4389+ char *hphp_log_scriptname;
4390+ zend_bool hphp_log_use_x_forwarded_for;
4391+ long hphp_executor_max_depth;
4392+#endif
4393 int exit_status;
4394
4395 zend_op_array *active_op_array;
4396@@ -176,6 +186,7 @@
4397 int ticks_count;
4398
4399 zend_bool in_execution;
4400+ zend_uint in_code_type;
4401 zend_bool bailout_set;
4402 zend_bool full_tables_cleanup;
4403
4404diff -Naur php-4.4.0RC2/Zend/zend.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend.h
4405--- php-4.4.0RC2/Zend/zend.h 2005-01-25 14:08:41.000000000 +0100
4406+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend.h 2005-07-09 08:53:20.678595040 +0200
4407@@ -275,9 +275,10 @@
4408 struct _zval_struct {
4409 /* Variable information */
4410 zvalue_value value; /* value */
4411+ zend_uint refcount;
4412+ zend_ushort flags;
4413 zend_uchar type; /* active type */
4414 zend_uchar is_ref;
4415- zend_ushort refcount;
4416 };
4417
4418
4419@@ -338,6 +339,12 @@
4420 void (*ticks_function)(int ticks);
4421 void (*on_timeout)(int seconds TSRMLS_DC);
4422 zend_bool (*open_function)(const char *filename, struct _zend_file_handle *);
4423+#if HARDENING_PATCH
4424+ void (*security_log_function)(int loglevel, char *fmt, ...);
4425+#endif
4426+#if HARDENING_PATCH_INC_PROTECT
4427+ int (*is_valid_include)(zval *z);
4428+#endif
4429 } zend_utility_functions;
4430
4431
4432@@ -469,7 +476,16 @@
4433 extern ZEND_API void (*zend_ticks_function)(int ticks);
4434 extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
4435 extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
4436+#if HARDENING_PATCH
4437+extern ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
4438+#endif
4439+#if HARDENING_PATCH_INC_PROTECT
4440+extern ZEND_API int (*zend_is_valid_include)(zval *z);
4441+#endif
4442
4443+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
4444+ZEND_API unsigned int zend_canary(void);
4445+#endif
4446
4447 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 2, 3);
4448
4449@@ -576,6 +592,11 @@
4450
4451 #define ZEND_MAX_RESERVED_RESOURCES 4
4452
4453+#if HARDENING_PATCH
4454+#include "hardened_globals.h"
4455+#include "php_syslog.h"
4456+#endif
4457+
4458 #endif /* ZEND_H */
4459
4460 /*
4461diff -Naur php-4.4.0RC2/Zend/zend_hash.c hardening-patch-4.4.0RC2-0.3.2/Zend/zend_hash.c
4462--- php-4.4.0RC2/Zend/zend_hash.c 2005-04-28 09:34:32.000000000 +0200
4463+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_hash.c 2005-07-09 08:53:20.679594888 +0200
4464@@ -26,6 +26,17 @@
4465 # include <stdlib.h>
4466 #endif
4467
4468+#if HARDENING_PATCH_HASH_PROTECT
4469+ unsigned int zend_hash_canary = 0x1234567;
4470+ zend_bool zend_hash_canary_inited = 0;
4471+#endif
4472+
4473+#define CHECK_HASH_CANARY(hash) \
4474+ if (zend_hash_canary != (hash)->canary) { \
4475+ zend_security_log(S_MEMORY, "Zend HashTable canary was overwritten"); \
4476+ exit(1); \
4477+ }
4478+
4479 #define HANDLE_NUMERIC(key, length, func) { \
4480 register char *tmp=key; \
4481 \
4482@@ -175,6 +186,9 @@
4483 {
4484 uint i = 3;
4485 Bucket **tmp;
4486+#if HARDENING_PATCH_HASH_PROTECT
4487+ TSRMLS_FETCH();
4488+#endif
4489
4490 SET_INCONSISTENT(HT_OK);
4491
4492@@ -184,6 +198,13 @@
4493
4494 ht->nTableSize = 1 << i;
4495 ht->nTableMask = ht->nTableSize - 1;
4496+#if HARDENING_PATCH_HASH_PROTECT
4497+ if (zend_hash_canary_inited==0) {
4498+ zend_hash_canary = zend_canary();
4499+ zend_hash_canary_inited = 1;
4500+ }
4501+ ht->canary = zend_hash_canary;
4502+#endif
4503 ht->pDestructor = pDestructor;
4504 ht->pListHead = NULL;
4505 ht->pListTail = NULL;
4506@@ -259,6 +280,9 @@
4507 }
4508 #endif
4509 if (ht->pDestructor) {
4510+#if HARDENING_PATCH_HASH_PROTECT
4511+ CHECK_HASH_CANARY(ht);
4512+#endif
4513 ht->pDestructor(p->pData);
4514 }
4515 UPDATE_DATA(ht, p, pData, nDataSize);
4516@@ -327,6 +351,9 @@
4517 }
4518 #endif
4519 if (ht->pDestructor) {
4520+#if HARDENING_PATCH_HASH_PROTECT
4521+ CHECK_HASH_CANARY(ht);
4522+#endif
4523 ht->pDestructor(p->pData);
4524 }
4525 UPDATE_DATA(ht, p, pData, nDataSize);
4526@@ -402,6 +429,9 @@
4527 }
4528 #endif
4529 if (ht->pDestructor) {
4530+#if HARDENING_PATCH_HASH_PROTECT
4531+ CHECK_HASH_CANARY(ht);
4532+#endif
4533 ht->pDestructor(p->pData);
4534 }
4535 UPDATE_DATA(ht, p, pData, nDataSize);
4536@@ -450,7 +480,7 @@
4537 IS_CONSISTENT(ht);
4538
4539 if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */
4540- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
4541+ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
4542 if (t) {
4543 HANDLE_BLOCK_INTERRUPTIONS();
4544 ht->arBuckets = t;
4545@@ -460,6 +490,7 @@
4546 HANDLE_UNBLOCK_INTERRUPTIONS();
4547 return SUCCESS;
4548 }
4549+ zend_error(E_ERROR, "zend_hash_do_resize - out of memory");
4550 return FAILURE;
4551 }
4552 return SUCCESS;
4553@@ -524,6 +555,9 @@
4554 ht->pInternalPointer = p->pListNext;
4555 }
4556 if (ht->pDestructor) {
4557+#if HARDENING_PATCH_HASH_PROTECT
4558+ CHECK_HASH_CANARY(ht);
4559+#endif
4560 ht->pDestructor(p->pData);
4561 }
4562 if (!p->pDataPtr) {
4563@@ -553,6 +587,9 @@
4564 q = p;
4565 p = p->pListNext;
4566 if (ht->pDestructor) {
4567+#if HARDENING_PATCH_HASH_PROTECT
4568+ CHECK_HASH_CANARY(ht);
4569+#endif
4570 ht->pDestructor(q->pData);
4571 }
4572 if (!q->pDataPtr && q->pData) {
4573@@ -579,6 +616,9 @@
4574 q = p;
4575 p = p->pListNext;
4576 if (ht->pDestructor) {
4577+#if HARDENING_PATCH_HASH_PROTECT
4578+ CHECK_HASH_CANARY(ht);
4579+#endif
4580 ht->pDestructor(q->pData);
4581 }
4582 if (!q->pDataPtr && q->pData) {
4583@@ -608,6 +648,9 @@
4584 HANDLE_BLOCK_INTERRUPTIONS();
4585
4586 if (ht->pDestructor) {
4587+#if HARDENING_PATCH_HASH_PROTECT
4588+ CHECK_HASH_CANARY(ht);
4589+#endif
4590 ht->pDestructor(p->pData);
4591 }
4592 if (!p->pDataPtr) {
4593diff -Naur php-4.4.0RC2/Zend/zend_hash.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_hash.h
4594--- php-4.4.0RC2/Zend/zend_hash.h 2002-12-31 17:23:03.000000000 +0100
4595+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_hash.h 2005-07-09 08:53:20.680594736 +0200
4596@@ -54,6 +54,9 @@
4597 } Bucket;
4598
4599 typedef struct _hashtable {
4600+#if HARDENING_PATCH_HASH_PROTECT
4601+ unsigned int canary;
4602+#endif
4603 uint nTableSize;
4604 uint nTableMask;
4605 uint nNumOfElements;
4606diff -Naur php-4.4.0RC2/Zend/zend_ini.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_ini.h
4607--- php-4.4.0RC2/Zend/zend_ini.h 2005-01-09 18:00:16.000000000 +0100
4608+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_ini.h 2005-07-09 08:53:20.680594736 +0200
4609@@ -174,6 +174,7 @@
4610 /* Standard message handlers */
4611 BEGIN_EXTERN_C()
4612 ZEND_API ZEND_INI_MH(OnUpdateBool);
4613+#define OnUpdateLong OnUpdateInt
4614 ZEND_API ZEND_INI_MH(OnUpdateInt);
4615 ZEND_API ZEND_INI_MH(OnUpdateReal);
4616 ZEND_API ZEND_INI_MH(OnUpdateString);
4617diff -Naur php-4.4.0RC2/Zend/zend_llist.c hardening-patch-4.4.0RC2-0.3.2/Zend/zend_llist.c
4618--- php-4.4.0RC2/Zend/zend_llist.c 2002-12-31 17:23:04.000000000 +0100
4619+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_llist.c 2005-07-09 08:53:20.681594584 +0200
4620@@ -21,9 +21,34 @@
4621 #include "zend.h"
4622 #include "zend_llist.h"
4623 #include "zend_qsort.h"
4624+#include "zend_globals.h"
4625+
4626+#define CHECK_LIST_CANARY(list) \
4627+ if (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t) { \
4628+ zend_security_log(S_MEMORY, "linked list canary was overwritten"); \
4629+ exit(1); \
4630+ }
4631+
4632+#define CHECK_LISTELEMENT_CANARY(elem) \
4633+ if (HG(canary_3) != (elem)->canary) { \
4634+ zend_security_log(S_MEMORY, "linked list element canary was overwritten"); \
4635+ exit(1); \
4636+ }
4637+
4638
4639 ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
4640 {
4641+#if HARDENING_PATCH_LL_PROTECT
4642+ TSRMLS_FETCH();
4643+
4644+ if (!HG(ll_canary_inited)) {
4645+ HG(canary_3) = zend_canary();
4646+ HG(canary_4) = zend_canary();
4647+ HG(ll_canary_inited) = 1;
4648+ }
4649+ l->canary_h = HG(canary_3);
4650+ l->canary_t = HG(canary_4);
4651+#endif
4652 l->head = NULL;
4653 l->tail = NULL;
4654 l->count = 0;
4655@@ -37,6 +62,11 @@
4656 {
4657 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
4658
4659+#if HARDENING_PATCH_LL_PROTECT
4660+ TSRMLS_FETCH();
4661+ CHECK_LIST_CANARY(l)
4662+ tmp->canary = HG(canary_3);
4663+#endif
4664 tmp->prev = l->tail;
4665 tmp->next = NULL;
4666 if (l->tail) {
4667@@ -55,6 +85,11 @@
4668 {
4669 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
4670
4671+#if HARDENING_PATCH_LL_PROTECT
4672+ TSRMLS_FETCH();
4673+ CHECK_LIST_CANARY(l)
4674+ tmp->canary = HG(canary_3);
4675+#endif
4676 tmp->next = l->head;
4677 tmp->prev = NULL;
4678 if (l->head) {
4679@@ -91,10 +126,20 @@
4680 zend_llist_element *current=l->head;
4681 zend_llist_element *next;
4682
4683+#if HARDENING_PATCH_LL_PROTECT
4684+ TSRMLS_FETCH();
4685+ CHECK_LIST_CANARY(l)
4686+#endif
4687 while (current) {
4688+#if HARDENING_PATCH_LL_PROTECT
4689+ CHECK_LISTELEMENT_CANARY(current)
4690+#endif
4691 next = current->next;
4692 if (compare(current->data, element)) {
4693 DEL_LLIST_ELEMENT(current, l);
4694+#if HARDENING_PATCH_LL_PROTECT
4695+ current->canary = 0;
4696+#endif
4697 break;
4698 }
4699 current = next;
4700@@ -106,7 +151,14 @@
4701 {
4702 zend_llist_element *current=l->head, *next;
4703
4704+#if HARDENING_PATCH_LL_PROTECT
4705+ TSRMLS_FETCH();
4706+ CHECK_LIST_CANARY(l)
4707+#endif
4708 while (current) {
4709+#if HARDENING_PATCH_LL_PROTECT
4710+ CHECK_LISTELEMENT_CANARY(current)
4711+#endif
4712 next = current->next;
4713 if (l->dtor) {
4714 l->dtor(current->data);
4715@@ -131,7 +183,14 @@
4716 zend_llist_element *old_tail;
4717 void *data;
4718
4719+#if HARDENING_PATCH_LL_PROTECT
4720+ TSRMLS_FETCH();
4721+ CHECK_LIST_CANARY(l)
4722+#endif
4723 if ((old_tail = l->tail)) {
4724+#if HARDENING_PATCH_LL_PROTECT
4725+ CHECK_LISTELEMENT_CANARY(old_tail)
4726+#endif
4727 if (l->tail->prev) {
4728 l->tail->prev->next = NULL;
4729 }
4730@@ -157,9 +216,16 @@
4731 {
4732 zend_llist_element *ptr;
4733
4734+#if HARDENING_PATCH_LL_PROTECT
4735+ TSRMLS_FETCH();
4736+ CHECK_LIST_CANARY(src)
4737+#endif
4738 zend_llist_init(dst, src->size, src->dtor, src->persistent);
4739 ptr = src->head;
4740 while (ptr) {
4741+#if HARDENING_PATCH_LL_PROTECT
4742+ CHECK_LISTELEMENT_CANARY(ptr)
4743+#endif
4744 zend_llist_add_element(dst, ptr->data);
4745 ptr = ptr->next;
4746 }
4747@@ -170,11 +236,21 @@
4748 {
4749 zend_llist_element *element, *next;
4750
4751+#if HARDENING_PATCH_LL_PROTECT
4752+ TSRMLS_FETCH();
4753+ CHECK_LIST_CANARY(l)
4754+#endif
4755 element=l->head;
4756 while (element) {
4757+#if HARDENING_PATCH_LL_PROTECT
4758+ CHECK_LISTELEMENT_CANARY(element)
4759+#endif
4760 next = element->next;
4761 if (func(element->data)) {
4762 DEL_LLIST_ELEMENT(element, l);
4763+#if HARDENING_PATCH_LL_PROTECT
4764+ element->canary = 0;
4765+#endif
4766 }
4767 element = next;
4768 }
4769@@ -185,7 +261,13 @@
4770 {
4771 zend_llist_element *element;
4772
4773+#if HARDENING_PATCH_LL_PROTECT
4774+ CHECK_LIST_CANARY(l)
4775+#endif
4776 for (element=l->head; element; element=element->next) {
4777+#if HARDENING_PATCH_LL_PROTECT
4778+ CHECK_LISTELEMENT_CANARY(element)
4779+#endif
4780 func(element->data TSRMLS_CC);
4781 }
4782 }
4783@@ -197,6 +279,9 @@
4784 zend_llist_element **elements;
4785 zend_llist_element *element, **ptr;
4786
4787+#if HARDENING_PATCH_LL_PROTECT
4788+ CHECK_LIST_CANARY(l)
4789+#endif
4790 if (l->count <= 0) {
4791 return;
4792 }
4793@@ -206,6 +291,9 @@
4794 ptr = &elements[0];
4795
4796 for (element=l->head; element; element=element->next) {
4797+#if HARDENING_PATCH_LL_PROTECT
4798+ CHECK_LISTELEMENT_CANARY(element)
4799+#endif
4800 *ptr++ = element;
4801 }
4802
4803@@ -228,7 +316,13 @@
4804 {
4805 zend_llist_element *element;
4806
4807+#if HARDENING_PATCH_LL_PROTECT
4808+ CHECK_LIST_CANARY(l)
4809+#endif
4810 for (element=l->head; element; element=element->next) {
4811+#if HARDENING_PATCH_LL_PROTECT
4812+ CHECK_LISTELEMENT_CANARY(element)
4813+#endif
4814 func(element->data, arg TSRMLS_CC);
4815 }
4816 }
4817@@ -239,8 +333,14 @@
4818 zend_llist_element *element;
4819 va_list args;
4820
4821+#if HARDENING_PATCH_LL_PROTECT
4822+ CHECK_LIST_CANARY(l)
4823+#endif
4824 va_start(args, num_args);
4825 for (element=l->head; element; element=element->next) {
4826+#if HARDENING_PATCH_LL_PROTECT
4827+ CHECK_LISTELEMENT_CANARY(element)
4828+#endif
4829 func(element->data, num_args, args TSRMLS_CC);
4830 }
4831 va_end(args);
4832@@ -249,6 +349,10 @@
4833
4834 ZEND_API int zend_llist_count(zend_llist *l)
4835 {
4836+#if HARDENING_PATCH_LL_PROTECT
4837+ TSRMLS_FETCH();
4838+ CHECK_LIST_CANARY(l)
4839+#endif
4840 return l->count;
4841 }
4842
4843@@ -256,8 +360,15 @@
4844 {
4845 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
4846
4847+#if HARDENING_PATCH_LL_PROTECT
4848+ TSRMLS_FETCH();
4849+ CHECK_LIST_CANARY(l)
4850+#endif
4851 *current = l->head;
4852 if (*current) {
4853+#if HARDENING_PATCH_LL_PROTECT
4854+ CHECK_LISTELEMENT_CANARY(*current)
4855+#endif
4856 return (*current)->data;
4857 } else {
4858 return NULL;
4859@@ -269,8 +380,15 @@
4860 {
4861 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
4862
4863+#if HARDENING_PATCH_LL_PROTECT
4864+ TSRMLS_FETCH();
4865+ CHECK_LIST_CANARY(l)
4866+#endif
4867 *current = l->tail;
4868 if (*current) {
4869+#if HARDENING_PATCH_LL_PROTECT
4870+ CHECK_LISTELEMENT_CANARY(*current)
4871+#endif
4872 return (*current)->data;
4873 } else {
4874 return NULL;
4875@@ -282,9 +400,19 @@
4876 {
4877 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
4878
4879+#if HARDENING_PATCH_LL_PROTECT
4880+ TSRMLS_FETCH();
4881+ CHECK_LIST_CANARY(l)
4882+#endif
4883 if (*current) {
4884+#if HARDENING_PATCH_LL_PROTECT
4885+ CHECK_LISTELEMENT_CANARY(*current)
4886+#endif
4887 *current = (*current)->next;
4888 if (*current) {
4889+#if HARDENING_PATCH_LL_PROTECT
4890+ CHECK_LISTELEMENT_CANARY(*current)
4891+#endif
4892 return (*current)->data;
4893 }
4894 }
4895@@ -296,9 +424,19 @@
4896 {
4897 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
4898
4899+#if HARDENING_PATCH_LL_PROTECT
4900+ TSRMLS_FETCH();
4901+ CHECK_LIST_CANARY(l)
4902+#endif
4903 if (*current) {
4904+#if HARDENING_PATCH_LL_PROTECT
4905+ CHECK_LISTELEMENT_CANARY(*current)
4906+#endif
4907 *current = (*current)->prev;
4908 if (*current) {
4909+#if HARDENING_PATCH_LL_PROTECT
4910+ CHECK_LISTELEMENT_CANARY(*current)
4911+#endif
4912 return (*current)->data;
4913 }
4914 }
4915diff -Naur php-4.4.0RC2/Zend/zend_llist.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_llist.h
4916--- php-4.4.0RC2/Zend/zend_llist.h 2002-12-31 17:23:04.000000000 +0100
4917+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_llist.h 2005-07-09 08:53:20.681594584 +0200
4918@@ -24,6 +24,9 @@
4919 #include <stdlib.h>
4920
4921 typedef struct _zend_llist_element {
4922+#if HARDENING_PATCH_LL_PROTECT
4923+ unsigned int canary;
4924+#endif
4925 struct _zend_llist_element *next;
4926 struct _zend_llist_element *prev;
4927 char data[1]; /* Needs to always be last in the struct */
4928@@ -36,6 +39,9 @@
4929 typedef void (*llist_apply_func_t)(void * TSRMLS_DC);
4930
4931 typedef struct _zend_llist {
4932+#if HARDENING_PATCH_LL_PROTECT
4933+ unsigned int canary_h; /* head */
4934+#endif
4935 zend_llist_element *head;
4936 zend_llist_element *tail;
4937 size_t size;
4938@@ -43,6 +49,9 @@
4939 llist_dtor_func_t dtor;
4940 unsigned char persistent;
4941 zend_llist_element *traverse_ptr;
4942+#if HARDENING_PATCH_LL_PROTECT
4943+ unsigned int canary_t; /* tail */
4944+#endif
4945 } zend_llist;
4946
4947 typedef zend_llist_element* zend_llist_position;
4948diff -Naur php-4.4.0RC2/Zend/zend_modules.h hardening-patch-4.4.0RC2-0.3.2/Zend/zend_modules.h
4949--- php-4.4.0RC2/Zend/zend_modules.h 2002-12-31 17:23:04.000000000 +0100
4950+++ hardening-patch-4.4.0RC2-0.3.2/Zend/zend_modules.h 2005-07-09 08:53:20.682594432 +0200
4951@@ -34,7 +34,7 @@
4952 ZEND_API extern unsigned char second_arg_force_ref[];
4953 ZEND_API extern unsigned char third_arg_force_ref[];
4954
4955-#define ZEND_MODULE_API_NO 20020429
4956+#define ZEND_MODULE_API_NO 1020050626
4957 #ifdef ZTS
4958 #define USING_ZTS 1
4959 #else
diff --git a/0.3.2/hardening-patch-5.0.4-0.3.2.patch b/0.3.2/hardening-patch-5.0.4-0.3.2.patch
new file mode 100644
index 0000000..9880282
--- /dev/null
+++ b/0.3.2/hardening-patch-5.0.4-0.3.2.patch
@@ -0,0 +1,11892 @@
1diff -Naur php-5.0.4/acinclude.m4 hardening-patch-5.0.4-0.3.2/acinclude.m4
2--- php-5.0.4/acinclude.m4 2005-01-25 14:02:45.000000000 +0100
3+++ hardening-patch-5.0.4-0.3.2/acinclude.m4 2005-06-26 20:59:20.000000000 +0200
4@@ -1169,6 +1169,36 @@
5 fi
6 ])
7
8+dnl
9+dnl Check for broken realpath()
10+dnl
11+dnl realpath("/etc/hosts/../passwd",XXX) should not return
12+dnl "/etc/passwd"
13+dnl
14+AC_DEFUN([PHP_AC_BROKEN_REALPATH],[
15+ AC_CACHE_CHECK(whether realpath is broken, ac_cv_broken_realpath,[
16+ AC_TRY_RUN([
17+main() {
18+ char buf[4096+1];
19+ buf[0] = 0;
20+ realpath("/etc/hosts/../passwd", buf);
21+ exit(strcmp(buf, "/etc/passwd")==0);
22+}
23+ ],[
24+ ac_cv_broken_realpath=no
25+ ],[
26+ ac_cv_broken_realpath=yes
27+ ],[
28+ ac_cv_broken_realpath=no
29+ ])
30+ ])
31+ if test "$ac_cv_broken_realpath" = "yes"; then
32+ AC_DEFINE(PHP_BROKEN_REALPATH, 1, [Whether realpath is broken])
33+ else
34+ AC_DEFINE(PHP_BROKEN_REALPATH, 0, [Whether realpath is broken])
35+ fi
36+])
37+
38 dnl PHP_SHARED_MODULE(module-name, object-var, build-dir, cxx)
39 dnl
40 dnl Basically sets up the link-stage for building module-name
41diff -Naur php-5.0.4/configure hardening-patch-5.0.4-0.3.2/configure
42--- php-5.0.4/configure 2005-04-03 11:42:50.000000000 +0200
43+++ hardening-patch-5.0.4-0.3.2/configure 2005-06-28 15:47:07.000000000 +0200
44@@ -401,6 +401,16 @@
45 ac_default_prefix=/usr/local
46 # Any additions from configure.in:
47 ac_help="$ac_help
48+ --disable-hardening-patch-mm-protect Disable the Memory Manager protection."
49+ac_help="$ac_help
50+ --disable-hardening-patch-ll-protect Disable the Linked List protection."
51+ac_help="$ac_help
52+ --disable-hardening-patch-inc-protect Disable include/require protection."
53+ac_help="$ac_help
54+ --disable-hardening-patch-fmt-protect Disable format string protection."
55+ac_help="$ac_help
56+ --disable-hardening-patch-hash-protect Disable Zend HashTable DTOR protection."
57+ac_help="$ac_help
58
59 SAPI modules:
60 "
61@@ -857,6 +867,8 @@
62 ac_help="$ac_help
63 --disable-tokenizer Disable tokenizer support"
64 ac_help="$ac_help
65+ --disable-varfilter Disable Hardening-Patch's variable filter"
66+ac_help="$ac_help
67 --enable-wddx Enable WDDX support."
68 ac_help="$ac_help
69 --disable-xml Disable XML support."
70@@ -2749,6 +2761,157 @@
71
72
73
74+# Check whether --enable-hardening-patch-mm-protect or --disable-hardening-patch-mm-protect was given.
75+if test "${enable_hardening_patch_mm_protect+set}" = set; then
76+ enableval="$enable_hardening_patch_mm_protect"
77+
78+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
79+
80+else
81+
82+ DO_HARDENING_PATCH_MM_PROTECT=yes
83+
84+fi
85+
86+
87+# Check whether --enable-hardening-patch-ll-protect or --disable-hardening-patch-ll-protect was given.
88+if test "${enable_hardening_patch_ll_protect+set}" = set; then
89+ enableval="$enable_hardening_patch_ll_protect"
90+
91+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
92+
93+else
94+
95+ DO_HARDENING_PATCH_LL_PROTECT=yes
96+
97+fi
98+
99+
100+# Check whether --enable-hardening-patch-inc-protect or --disable-hardening-patch-inc-protect was given.
101+if test "${enable_hardening_patch_inc_protect+set}" = set; then
102+ enableval="$enable_hardening_patch_inc_protect"
103+
104+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
105+
106+else
107+
108+ DO_HARDENING_PATCH_INC_PROTECT=yes
109+
110+fi
111+
112+
113+# Check whether --enable-hardening-patch-fmt-protect or --disable-hardening-patch-fmt-protect was given.
114+if test "${enable_hardening_patch_fmt_protect+set}" = set; then
115+ enableval="$enable_hardening_patch_fmt_protect"
116+
117+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
118+
119+else
120+
121+ DO_HARDENING_PATCH_FMT_PROTECT=yes
122+
123+fi
124+
125+
126+# Check whether --enable-hardening-patch-hash-protect or --disable-hardening-patch-hash-protect was given.
127+if test "${enable_hardening_patch_hash_protect+set}" = set; then
128+ enableval="$enable_hardening_patch_hash_protect"
129+
130+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
131+
132+else
133+
134+ DO_HARDENING_PATCH_HASH_PROTECT=yes
135+
136+fi
137+
138+
139+echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6
140+echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5
141+echo "$ac_t""$DO_HARDENING_PATCH_MM_PROTECT" 1>&6
142+
143+echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6
144+echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5
145+echo "$ac_t""$DO_HARDENING_PATCH_LL_PROTECT" 1>&6
146+
147+echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6
148+echo "configure:2733: checking whether to protect include/require statements" >&5
149+echo "$ac_t""$DO_HARDENING_PATCH_INC_PROTECT" 1>&6
150+
151+echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6
152+echo "configure:2737: checking whether to protect PHP Format String functions" >&5
153+echo "$ac_t""$DO_HARDENING_PATCH_FMT_PROTECT" 1>&6
154+
155+echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6
156+echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5
157+echo "$ac_t""$DO_HARDENING_PATCH_HASH_PROTECT" 1>&6
158+
159+
160+cat >> confdefs.h <<\EOF
161+#define HARDENING_PATCH 1
162+EOF
163+
164+
165+
166+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
167+ cat >> confdefs.h <<\EOF
168+#define HARDENING_PATCH_MM_PROTECT 1
169+EOF
170+
171+else
172+ cat >> confdefs.h <<\EOF
173+#define HARDENING_PATCH_MM_PROTECT 0
174+EOF
175+
176+fi
177+
178+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
179+ cat >> confdefs.h <<\EOF
180+#define HARDENING_PATCH_LL_PROTECT 1
181+EOF
182+
183+else
184+ cat >> confdefs.h <<\EOF
185+#define HARDENING_PATCH_LL_PROTECT 0
186+EOF
187+
188+fi
189+
190+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
191+ cat >> confdefs.h <<\EOF
192+#define HARDENING_PATCH_INC_PROTECT 1
193+EOF
194+
195+else
196+ cat >> confdefs.h <<\EOF
197+#define HARDENING_PATCH_INC_PROTECT 0
198+EOF
199+
200+fi
201+
202+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
203+ cat >> confdefs.h <<\EOF
204+#define HARDENING_PATCH_FMT_PROTECT 1
205+EOF
206+
207+else
208+ cat >> confdefs.h <<\EOF
209+#define HARDENING_PATCH_FMT_PROTECT 0
210+EOF
211+
212+fi
213+
214+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
215+ cat >> confdefs.h <<\EOF
216+#define HARDENING_PATCH_HASH_PROTECT 1
217+EOF
218+
219+else
220+ cat >> confdefs.h <<\EOF
221+#define HARDENING_PATCH_HASH_PROTECT 0
222+EOF
223+
224+fi
225
226
227
228@@ -17390,6 +17553,62 @@
229 fi
230
231
232+ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6
233+echo "configure:14928: checking whether realpath is broken" >&5
234+if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then
235+ echo $ac_n "(cached) $ac_c" 1>&6
236+else
237+
238+ if test "$cross_compiling" = yes; then
239+
240+ ac_cv_broken_realpath=no
241+
242+else
243+ cat > conftest.$ac_ext <<EOF
244+#line 14939 "configure"
245+#include "confdefs.h"
246+
247+main() {
248+ char buf[4096+1];
249+ buf[0] = 0;
250+ realpath("/etc/hosts/../passwd", buf);
251+ exit(strcmp(buf, "/etc/passwd")==0);
252+}
253+
254+EOF
255+if { (eval echo configure:14958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
256+then
257+
258+ ac_cv_broken_realpath=no
259+
260+else
261+ echo "configure: failed program was:" >&5
262+ cat conftest.$ac_ext >&5
263+ rm -fr conftest*
264+
265+ ac_cv_broken_realpath=yes
266+
267+fi
268+rm -fr conftest*
269+fi
270+
271+
272+fi
273+
274+echo "$ac_t""$ac_cv_broken_realpath" 1>&6
275+ if test "$ac_cv_broken_realpath" = "yes"; then
276+ cat >> confdefs.h <<\EOF
277+#define PHP_BROKEN_REALPATH 1
278+EOF
279+
280+ else
281+ cat >> confdefs.h <<\EOF
282+#define PHP_BROKEN_REALPATH 0
283+EOF
284+
285+ fi
286+
287+
288 echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
289 echo "configure:17395: checking for declared timezone" >&5
290 if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then
291@@ -86878,6 +87097,265 @@
292 fi
293
294
295+echo $ac_n "checking whether to enable Hardening-Patch's variable filter""... $ac_c" 1>&6
296+echo "configure:82041: checking whether to enable Hardening-Patch's variable filter" >&5
297+# Check whether --enable-varfilter or --disable-varfilter was given.
298+if test "${enable_varfilter+set}" = set; then
299+ enableval="$enable_varfilter"
300+ PHP_VARFILTER=$enableval
301+else
302+
303+ PHP_VARFILTER=yes
304+
305+ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then
306+ PHP_VARFILTER=$PHP_ENABLE_ALL
307+ fi
308+
309+fi
310+
311+
312+
313+ext_output="yes, shared"
314+ext_shared=yes
315+case $PHP_VARFILTER in
316+shared,*)
317+ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'`
318+ ;;
319+shared)
320+ PHP_VARFILTER=yes
321+ ;;
322+no)
323+ ext_output=no
324+ ext_shared=no
325+ ;;
326+*)
327+ ext_output=yes
328+ ext_shared=no
329+ ;;
330+esac
331+
332+
333+
334+echo "$ac_t""$ext_output" 1>&6
335+
336+
337+
338+
339+if test "$PHP_VARFILTER" != "no"; then
340+ cat >> confdefs.h <<\EOF
341+#define HAVE_VARFILTER 1
342+EOF
343+
344+
345+ ext_builddir=ext/varfilter
346+ ext_srcdir=$abs_srcdir/ext/varfilter
347+
348+ ac_extra=
349+
350+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then
351+
352+
353+
354+ case ext/varfilter in
355+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
356+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
357+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
358+ esac
359+
360+
361+
362+ b_c_pre=$php_c_pre
363+ b_cxx_pre=$php_cxx_pre
364+ b_c_meta=$php_c_meta
365+ b_cxx_meta=$php_cxx_meta
366+ b_c_post=$php_c_post
367+ b_cxx_post=$php_cxx_post
368+ b_lo=$php_lo
369+
370+
371+ old_IFS=$IFS
372+ for ac_src in varfilter.c; do
373+
374+ IFS=.
375+ set $ac_src
376+ ac_obj=$1
377+ IFS=$old_IFS
378+
379+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
380+
381+ case $ac_src in
382+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
383+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
384+ esac
385+
386+ cat >>Makefile.objects<<EOF
387+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
388+ $ac_comp
389+EOF
390+ done
391+
392+
393+ EXT_STATIC="$EXT_STATIC varfilter"
394+ if test "$ext_shared" != "nocli"; then
395+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
396+ fi
397+ else
398+ if test "$ext_shared" = "shared" || test "$ext_shared" = "yes"; then
399+
400+ case ext/varfilter in
401+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
402+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
403+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
404+ esac
405+
406+
407+
408+ b_c_pre=$shared_c_pre
409+ b_cxx_pre=$shared_cxx_pre
410+ b_c_meta=$shared_c_meta
411+ b_cxx_meta=$shared_cxx_meta
412+ b_c_post=$shared_c_post
413+ b_cxx_post=$shared_cxx_post
414+ b_lo=$shared_lo
415+
416+
417+ old_IFS=$IFS
418+ for ac_src in varfilter.c; do
419+
420+ IFS=.
421+ set $ac_src
422+ ac_obj=$1
423+ IFS=$old_IFS
424+
425+ shared_objects_varfilter="$shared_objects_varfilter $ac_bdir$ac_obj.lo"
426+
427+ case $ac_src in
428+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
429+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
430+ esac
431+
432+ cat >>Makefile.objects<<EOF
433+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
434+ $ac_comp
435+EOF
436+ done
437+
438+
439+ install_modules="install-modules"
440+ PHP_MODULES="$PHP_MODULES \$(phplibdir)/varfilter.la"
441+
442+ PHP_VAR_SUBST="$PHP_VAR_SUBST shared_objects_varfilter"
443+
444+ cat >>Makefile.objects<<EOF
445+\$(phplibdir)/varfilter.la: $ext_builddir/varfilter.la
446+ \$(LIBTOOL) --mode=install cp $ext_builddir/varfilter.la \$(phplibdir)
447+
448+$ext_builddir/varfilter.la: \$(shared_objects_varfilter) \$(VARFILTER_SHARED_DEPENDENCIES)
449+ \$(LIBTOOL) --mode=link \$(CC) \$(COMMON_FLAGS) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(LDFLAGS) -o \$@ -export-dynamic -avoid-version -prefer-pic -module -rpath \$(phplibdir) \$(EXTRA_LDFLAGS) \$(shared_objects_varfilter) \$(VARFILTER_SHARED_LIBADD)
450+
451+EOF
452+
453+ cat >> confdefs.h <<EOF
454+#define COMPILE_DL_VARFILTER 1
455+EOF
456+
457+ fi
458+ fi
459+
460+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" = "cli"; then
461+ if test "$PHP_SAPI" = "cgi"; then
462+
463+
464+ case ext/varfilter in
465+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
466+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
467+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
468+ esac
469+
470+
471+
472+ b_c_pre=$php_c_pre
473+ b_cxx_pre=$php_cxx_pre
474+ b_c_meta=$php_c_meta
475+ b_cxx_meta=$php_cxx_meta
476+ b_c_post=$php_c_post
477+ b_cxx_post=$php_cxx_post
478+ b_lo=$php_lo
479+
480+
481+ old_IFS=$IFS
482+ for ac_src in varfilter.c; do
483+
484+ IFS=.
485+ set $ac_src
486+ ac_obj=$1
487+ IFS=$old_IFS
488+
489+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
490+
491+ case $ac_src in
492+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
493+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
494+ esac
495+
496+ cat >>Makefile.objects<<EOF
497+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
498+ $ac_comp
499+EOF
500+ done
501+
502+
503+ EXT_STATIC="$EXT_STATIC varfilter"
504+ else
505+
506+
507+ case ext/varfilter in
508+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
509+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
510+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
511+ esac
512+
513+
514+
515+ b_c_pre=$php_c_pre
516+ b_cxx_pre=$php_cxx_pre
517+ b_c_meta=$php_c_meta
518+ b_cxx_meta=$php_cxx_meta
519+ b_c_post=$php_c_post
520+ b_cxx_post=$php_cxx_post
521+ b_lo=$php_lo
522+
523+
524+ old_IFS=$IFS
525+ for ac_src in varfilter.c; do
526+
527+ IFS=.
528+ set $ac_src
529+ ac_obj=$1
530+ IFS=$old_IFS
531+
532+ PHP_CLI_OBJS="$PHP_CLI_OBJS $ac_bdir$ac_obj.lo"
533+
534+ case $ac_src in
535+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
536+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
537+ esac
538+
539+ cat >>Makefile.objects<<EOF
540+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
541+ $ac_comp
542+EOF
543+ done
544+
545+
546+ fi
547+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
548+ fi
549+
550+ BUILD_DIR="$BUILD_DIR $ext_builddir"
551+
552+
553+fi
554
555
556 echo $ac_n "checking whether to enable WDDX support""... $ac_c" 1>&6
557@@ -97351,7 +97829,7 @@
558 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
559 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
560 network.c php_open_temporary_file.c php_logos.c \
561- output.c ; do
562+ output.c hardening_patch.c ; do
563
564 IFS=.
565 set $ac_src
566@@ -97579,7 +98057,7 @@
567 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
568 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
569 zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
570- zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c; do
571+ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_canary.c; do
572
573 IFS=.
574 set $ac_src
575diff -Naur php-5.0.4/configure.in hardening-patch-5.0.4-0.3.2/configure.in
576--- php-5.0.4/configure.in 2005-03-30 23:43:12.000000000 +0200
577+++ hardening-patch-5.0.4-0.3.2/configure.in 2005-06-26 22:28:34.000000000 +0200
578@@ -235,7 +235,7 @@
579 sinclude(Zend/acinclude.m4)
580 sinclude(Zend/Zend.m4)
581 sinclude(TSRM/tsrm.m4)
582-
583+sinclude(main/hardening_patch.m4)
584
585
586 divert(2)
587@@ -620,6 +620,7 @@
588 AC_FUNC_ALLOCA
589 dnl PHP_AC_BROKEN_SPRINTF
590 dnl PHP_AC_BROKEN_SNPRINTF
591+PHP_AC_BROKEN_REALPATH
592 PHP_DECLARED_TIMEZONE
593 PHP_TIME_R_TYPE
594 PHP_READDIR_R_TYPE
595@@ -1262,7 +1263,7 @@
596 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
597 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
598 network.c php_open_temporary_file.c php_logos.c \
599- output.c )
600+ output.c hardening_patch.c )
601
602 PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \
603 plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c)
604@@ -1280,7 +1281,7 @@
605 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
606 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
607 zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
608- zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c)
609+ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_canary.c )
610
611 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
612 PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c \
613diff -Naur php-5.0.4/ext/fbsql/php_fbsql.c hardening-patch-5.0.4-0.3.2/ext/fbsql/php_fbsql.c
614--- php-5.0.4/ext/fbsql/php_fbsql.c 2005-02-09 20:32:45.000000000 +0100
615+++ hardening-patch-5.0.4-0.3.2/ext/fbsql/php_fbsql.c 2005-07-03 20:50:08.000000000 +0200
616@@ -1852,8 +1852,24 @@
617 }
618 else if (fbcmdErrorsFound(md))
619 {
620+#if HARDENING_PATCH
621+ char* query_copy;
622+ int i;
623+#endif
624 FBCErrorMetaData* emd = fbcdcErrorMetaData(c, md);
625 char* emg = fbcemdAllErrorMessages(emd);
626+#if HARDENING_PATCH
627+ query_copy=estrdup(query_copy);
628+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
629+ php_security_log(S_SQL, "fbsql error: %s - query: %s", emg, query_copy);
630+ efree(query_copy);
631+ if (HG(hphp_sql_bailout_on_error)) {
632+ free(emg);
633+ fbcemdRelease(emd);
634+ result = 0;
635+ zend_bailout();
636+ }
637+#endif
638 if (FB_SQL_G(generateWarnings))
639 {
640 if (emg)
641diff -Naur php-5.0.4/ext/mysql/php_mysql.c hardening-patch-5.0.4-0.3.2/ext/mysql/php_mysql.c
642--- php-5.0.4/ext/mysql/php_mysql.c 2005-02-22 15:59:30.000000000 +0100
643+++ hardening-patch-5.0.4-0.3.2/ext/mysql/php_mysql.c 2005-07-03 11:04:29.000000000 +0200
644@@ -1221,6 +1221,8 @@
645 {
646 php_mysql_conn *mysql;
647 MYSQL_RES *mysql_result;
648+ char *copy_query;
649+ int i;
650
651 ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, link_id, "MySQL-Link", le_link, le_plink);
652
653@@ -1271,6 +1273,13 @@
654 php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
655 }
656 }
657+ copy_query = estrdup(Z_STRVAL_PP(query));
658+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
659+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
660+ efree(copy_query);
661+ if (HG(hphp_sql_bailout_on_error)) {
662+ zend_bailout();
663+ }
664 RETURN_FALSE;
665 }
666 #else
667@@ -1281,6 +1290,13 @@
668 php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
669 }
670 }
671+ copy_query = estrdup(Z_STRVAL_PP(query));
672+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
673+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
674+ efree(copy_query);
675+ if (HG(hphp_sql_bailout_on_error)) {
676+ zend_bailout();
677+ }
678 RETURN_FALSE;
679 }
680 #endif
681diff -Naur php-5.0.4/ext/mysqli/mysqli_nonapi.c hardening-patch-5.0.4-0.3.2/ext/mysqli/mysqli_nonapi.c
682--- php-5.0.4/ext/mysqli/mysqli_nonapi.c 2005-02-25 00:59:49.000000000 +0100
683+++ hardening-patch-5.0.4-0.3.2/ext/mysqli/mysqli_nonapi.c 2005-07-09 08:40:55.890819992 +0200
684@@ -228,6 +228,17 @@
685 if (mysql_real_query(mysql->mysql, query, query_len)) {
686 char s_error[MYSQL_ERRMSG_SIZE], s_sqlstate[SQLSTATE_LENGTH+1];
687 unsigned int s_errno;
688+#if HARDENING_PATCH
689+ char *query_copy = estrdup(query);
690+ int i;
691+
692+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
693+ php_security_log(S_SQL, "MySQLi error: %s - query: %s", mysql->mysql->net.last_errno, query_copy);
694+ efree(query_copy);
695+ if (HG(hphp_sql_bailout_on_error)) {
696+ zend_bailout();
697+ }
698+#endif
699 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
700
701 /* we have to save error information, cause
702@@ -268,6 +279,17 @@
703 MYSQLI_DISABLE_MQ;
704
705 if (mysql_real_query(mysql->mysql, query, query_len)) {
706+#if HARDENING_PATCH
707+ char *query_copy = estrdup(query);
708+ int i;
709+
710+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
711+ php_security_log(S_SQL, "MySQLi error: %s - query: %s", mysql->mysql->net.last_errno, query_copy);
712+ efree(query_copy);
713+ if (HG(hphp_sql_bailout_on_error)) {
714+ zend_bailout();
715+ }
716+#endif
717 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
718 RETURN_FALSE;
719 }
720diff -Naur php-5.0.4/ext/pgsql/pgsql.c hardening-patch-5.0.4-0.3.2/ext/pgsql/pgsql.c
721--- php-5.0.4/ext/pgsql/pgsql.c 2004-05-12 18:49:47.000000000 +0200
722+++ hardening-patch-5.0.4-0.3.2/ext/pgsql/pgsql.c 2005-07-03 21:16:44.000000000 +0200
723@@ -1076,10 +1076,28 @@
724 case PGRES_EMPTY_QUERY:
725 case PGRES_BAD_RESPONSE:
726 case PGRES_NONFATAL_ERROR:
727- case PGRES_FATAL_ERROR:
728- PHP_PQ_ERROR("Query failed: %s", pgsql);
729- PQclear(pgsql_result);
730- RETURN_FALSE;
731+ case PGRES_FATAL_ERROR:
732+ {
733+#if HARDENING_PATCH
734+ int i;
735+ char *query_copy;
736+#endif
737+ char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
738+ PQclear(pgsql_result);
739+#if HARDENING_PATCH
740+ query_copy = estrdup(Z_STRVAL_PP(query));
741+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
742+ php_security_log(S_SQL, "PgSQL error: %s - query: %s", msgbuf, query_copy);
743+ efree(query_copy);
744+ if (HG(hphp_sql_bailout_on_error)) {
745+ efree(msgbuf);
746+ zend_bailout();
747+ }
748+#endif
749+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", msgbuf);
750+ efree(msgbuf);
751+ RETURN_FALSE;
752+ }
753 break;
754 case PGRES_COMMAND_OK: /* successful command that did not return rows */
755 default:
756diff -Naur php-5.0.4/ext/sqlite/sqlite.c hardening-patch-5.0.4-0.3.2/ext/sqlite/sqlite.c
757--- php-5.0.4/ext/sqlite/sqlite.c 2004-09-26 03:41:40.000000000 +0200
758+++ hardening-patch-5.0.4-0.3.2/ext/sqlite/sqlite.c 2005-07-03 20:52:00.000000000 +0200
759@@ -1473,6 +1473,19 @@
760 db->last_err_code = ret;
761
762 if (ret != SQLITE_OK) {
763+#if HARDENING_PATCH
764+ char *query_copy;
765+ int i;
766+
767+ query_copy = estrdup(sql);
768+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
769+ php_security_log(S_SQL, "SQLite error: %s - query: %s", errtext, query_copy);
770+ efree(query_copy);
771+ if (HG(hphp_sql_bailout_on_error)) {
772+ sqlite_freemem(errtext);
773+ zend_bailout();
774+ }
775+#endif
776 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
777 sqlite_freemem(errtext);
778 goto terminate;
779diff -Naur php-5.0.4/ext/standard/array.c hardening-patch-5.0.4-0.3.2/ext/standard/array.c
780--- php-5.0.4/ext/standard/array.c 2005-03-12 11:12:49.000000000 +0100
781+++ hardening-patch-5.0.4-0.3.2/ext/standard/array.c 2005-06-27 00:46:39.000000000 +0200
782@@ -1255,6 +1255,32 @@
783 }
784 }
785 }
786+
787+ if (var_name[0] == 'H') {
788+ if ((strcmp(var_name, "HTTP_GET_VARS")==0)||
789+ (strcmp(var_name, "HTTP_POST_VARS")==0)||
790+ (strcmp(var_name, "HTTP_POST_FILES")==0)||
791+ (strcmp(var_name, "HTTP_ENV_VARS")==0)||
792+ (strcmp(var_name, "HTTP_SERVER_VARS")==0)||
793+ (strcmp(var_name, "HTTP_SESSION_VARS")==0)||
794+ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)||
795+ (strcmp(var_name, "HTTP_RAW_POST_DATA")==0)) {
796+ return 0;
797+ }
798+ } else if (var_name[0] == '_') {
799+ if ((strcmp(var_name, "_COOKIE")==0)||
800+ (strcmp(var_name, "_ENV")==0)||
801+ (strcmp(var_name, "_FILES")==0)||
802+ (strcmp(var_name, "_GET")==0)||
803+ (strcmp(var_name, "_POST")==0)||
804+ (strcmp(var_name, "_REQUEST")==0)||
805+ (strcmp(var_name, "_SESSION")==0)||
806+ (strcmp(var_name, "_SERVER")==0)) {
807+ return 0;
808+ }
809+ } else if (strcmp(var_name, "GLOBALS")==0) {
810+ return 0;
811+ }
812
813 return 1;
814 }
815diff -Naur php-5.0.4/ext/standard/basic_functions.c hardening-patch-5.0.4-0.3.2/ext/standard/basic_functions.c
816--- php-5.0.4/ext/standard/basic_functions.c 2005-03-10 13:10:57.000000000 +0100
817+++ hardening-patch-5.0.4-0.3.2/ext/standard/basic_functions.c 2005-06-27 00:47:11.000000000 +0200
818@@ -617,7 +617,7 @@
819 PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL)
820
821 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
822- PHP_FE(realpath, NULL)
823+ PHP_STATIC_FE("realpath", zif_real_path, NULL)
824 #endif
825
826 #ifdef HAVE_FNMATCH
827@@ -3124,6 +3124,35 @@
828 memcpy(new_key, prefix, prefix_len);
829 memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength);
830
831+ if (new_key[0] == 'H') {
832+ if ((strcmp(new_key, "HTTP_GET_VARS")==0)||
833+ (strcmp(new_key, "HTTP_POST_VARS")==0)||
834+ (strcmp(new_key, "HTTP_POST_FILES")==0)||
835+ (strcmp(new_key, "HTTP_ENV_VARS")==0)||
836+ (strcmp(new_key, "HTTP_SERVER_VARS")==0)||
837+ (strcmp(new_key, "HTTP_SESSION_VARS")==0)||
838+ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)||
839+ (strcmp(new_key, "HTTP_RAW_POST_DATA")==0)) {
840+ efree(new_key);
841+ return 0;
842+ }
843+ } else if (new_key[0] == '_') {
844+ if ((strcmp(new_key, "_COOKIE")==0)||
845+ (strcmp(new_key, "_ENV")==0)||
846+ (strcmp(new_key, "_FILES")==0)||
847+ (strcmp(new_key, "_GET")==0)||
848+ (strcmp(new_key, "_POST")==0)||
849+ (strcmp(new_key, "_REQUEST")==0)||
850+ (strcmp(new_key, "_SESSION")==0)||
851+ (strcmp(new_key, "_SERVER")==0)) {
852+ efree(new_key);
853+ return 0;
854+ }
855+ } else if (strcmp(new_key, "GLOBALS")==0) {
856+ efree(new_key);
857+ return 0;
858+ }
859+
860 zend_hash_del(&EG(symbol_table), new_key, new_key_len);
861 ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0);
862
863diff -Naur php-5.0.4/ext/standard/file.c hardening-patch-5.0.4-0.3.2/ext/standard/file.c
864--- php-5.0.4/ext/standard/file.c 2005-03-27 17:53:30.000000000 +0200
865+++ hardening-patch-5.0.4-0.3.2/ext/standard/file.c 2005-06-26 20:59:20.000000000 +0200
866@@ -2044,7 +2044,7 @@
867 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
868 /* {{{ proto string realpath(string path)
869 Return the resolved path */
870-PHP_FUNCTION(realpath)
871+PHP_FUNCTION(real_path)
872 {
873 zval **path;
874 char resolved_path_buff[MAXPATHLEN];
875diff -Naur php-5.0.4/ext/standard/file.h hardening-patch-5.0.4-0.3.2/ext/standard/file.h
876--- php-5.0.4/ext/standard/file.h 2004-06-21 23:08:05.000000000 +0200
877+++ hardening-patch-5.0.4-0.3.2/ext/standard/file.h 2005-06-26 20:59:20.000000000 +0200
878@@ -60,7 +60,7 @@
879 PHP_FUNCTION(fd_set);
880 PHP_FUNCTION(fd_isset);
881 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
882-PHP_FUNCTION(realpath);
883+PHP_FUNCTION(real_path);
884 PHP_FUNCTION(fnmatch);
885 #endif
886 PHP_NAMED_FUNCTION(php_if_ftruncate);
887diff -Naur php-5.0.4/ext/standard/ftp_fopen_wrapper.c hardening-patch-5.0.4-0.3.2/ext/standard/ftp_fopen_wrapper.c
888--- php-5.0.4/ext/standard/ftp_fopen_wrapper.c 2005-03-21 09:42:34.000000000 +0100
889+++ hardening-patch-5.0.4-0.3.2/ext/standard/ftp_fopen_wrapper.c 2005-06-27 10:41:04.000000000 +0200
890@@ -113,7 +113,7 @@
891 {
892 php_stream *stream = NULL, *reuseid = NULL;
893 php_url *resource = NULL;
894- int result, use_ssl, use_ssl_on_data = 0;
895+ int result, use_ssl, use_ssl_on_data = 0, tmp_len;
896 char *scratch;
897 char tmp_line[512];
898
899@@ -206,10 +206,25 @@
900 #endif
901 }
902
903+#define PHP_FTP_CNTRL_CHK(val, val_len, err_msg) { \
904+ unsigned char *s = val, *e = s + val_len; \
905+ while (s < e) { \
906+ if (iscntrl(*s)) { \
907+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, err_msg, val); \
908+ goto connect_errexit; \
909+ } \
910+ s++; \
911+ } \
912+}
913+
914 /* send the user name */
915 php_stream_write_string(stream, "USER ");
916 if (resource->user != NULL) {
917- php_raw_url_decode(resource->user, strlen(resource->user));
918+ unsigned char *s, *e;
919+ tmp_len = php_raw_url_decode(resource->user, strlen(resource->user));
920+
921+ PHP_FTP_CNTRL_CHK(resource->user, tmp_len, "Invalid login %s")
922+
923 php_stream_write_string(stream, resource->user);
924 } else {
925 php_stream_write_string(stream, "anonymous");
926@@ -225,7 +240,10 @@
927
928 php_stream_write_string(stream, "PASS ");
929 if (resource->pass != NULL) {
930- php_raw_url_decode(resource->pass, strlen(resource->pass));
931+ tmp_len = php_raw_url_decode(resource->pass, strlen(resource->pass));
932+
933+ PHP_FTP_CNTRL_CHK(resource->pass, tmp_len, "Invalid password %s")
934+
935 php_stream_write_string(stream, resource->pass);
936 } else {
937 /* if the user has configured who they are,
938diff -Naur php-5.0.4/ext/standard/head.c hardening-patch-5.0.4-0.3.2/ext/standard/head.c
939--- php-5.0.4/ext/standard/head.c 2005-01-07 22:16:00.000000000 +0100
940+++ hardening-patch-5.0.4-0.3.2/ext/standard/head.c 2005-07-05 18:33:34.000000000 +0200
941@@ -45,10 +45,31 @@
942 {
943 zend_bool rep = 1;
944 sapi_header_line ctr = {0};
945+#if HARDENING_PATCH
946+ int i;
947+#endif
948
949 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &ctr.line,
950 &ctr.line_len, &rep, &ctr.response_code) == FAILURE)
951 return;
952+
953+#if HARDENING_PATCH
954+ if (!HG(hphp_multiheader)) {
955+ for (i=0; i<ctr.line_len; i++) {
956+ if (ctr.line[i]==0) {
957+ php_security_log(S_MISC, "header(): headerline truncated by an ASCII-NUL char");
958+ ctr.line_len=i;
959+ break;
960+ } else if (ctr.line[i]=='\n') {
961+ if (i>0 && (i<ctr.line_len-1) && (ctr.line[i+1]==' ' || ctr.line[i+1]=='\t')) {
962+ continue;
963+ }
964+ php_security_log(S_MISC, "header(): headerline contains more than one header");
965+ ctr.line_len=i;
966+ }
967+ }
968+ }
969+#endif
970
971 sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr TSRMLS_CC);
972 }
973diff -Naur php-5.0.4/ext/standard/info.c hardening-patch-5.0.4-0.3.2/ext/standard/info.c
974--- php-5.0.4/ext/standard/info.c 2004-05-02 15:23:30.000000000 +0200
975+++ hardening-patch-5.0.4-0.3.2/ext/standard/info.c 2005-06-26 22:09:23.000000000 +0200
976@@ -394,7 +394,7 @@
977
978 if (flag & PHP_INFO_GENERAL) {
979 char *zend_version = get_zend_version();
980- char temp_api[10];
981+ char temp_api[11];
982 char *logo_guid;
983
984 php_uname = php_get_uname('a');
985@@ -415,11 +415,22 @@
986 PUTS("\" alt=\"PHP Logo\" /></a>");
987 }
988
989+#if HARDENING_PATCH
990+ if (!sapi_module.phpinfo_as_text) {
991+ php_printf("<h1 class=\"p\">PHP Version %s with Hardening-Patch %s</h1>\n", PHP_VERSION, HARDENING_PATCH_VERSION);
992+ } else {
993+ char temp_ver[40];
994+
995+ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENING_PATCH_VERSION);
996+ php_info_print_table_row(2, "PHP/Hardening-Patch Version", temp_ver);
997+ }
998+#else
999 if (!sapi_module.phpinfo_as_text) {
1000 php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
1001 } else {
1002 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1003- }
1004+ }
1005+#endif
1006 php_info_print_box_end();
1007 php_info_print_table_start();
1008 php_info_print_table_row(2, "System", php_uname );
1009diff -Naur php-5.0.4/ext/standard/syslog.c hardening-patch-5.0.4-0.3.2/ext/standard/syslog.c
1010--- php-5.0.4/ext/standard/syslog.c 2004-07-30 16:39:18.000000000 +0200
1011+++ hardening-patch-5.0.4-0.3.2/ext/standard/syslog.c 2005-07-06 13:19:50.000000000 +0200
1012@@ -42,6 +42,7 @@
1013 */
1014 PHP_MINIT_FUNCTION(syslog)
1015 {
1016+#if !HARDENING_PATCH
1017 /* error levels */
1018 REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
1019 REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
1020@@ -97,7 +98,7 @@
1021 /* AIX doesn't have LOG_PERROR */
1022 REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
1023 #endif
1024-
1025+#endif
1026 return SUCCESS;
1027 }
1028 /* }}} */
1029diff -Naur php-5.0.4/ext/varfilter/config.m4 hardening-patch-5.0.4-0.3.2/ext/varfilter/config.m4
1030--- php-5.0.4/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100
1031+++ hardening-patch-5.0.4-0.3.2/ext/varfilter/config.m4 2005-07-06 13:12:40.000000000 +0200
1032@@ -0,0 +1,11 @@
1033+dnl
1034+dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $
1035+dnl
1036+
1037+PHP_ARG_ENABLE(varfilter, whether to enable Hardening-Patch's variable filter,
1038+[ --disable-varfilter Disable Hardening-Patch's variable filter], yes)
1039+
1040+if test "$PHP_VARFILTER" != "no"; then
1041+ AC_DEFINE(HAVE_VARFILTER, 1, [ ])
1042+ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared)
1043+fi
1044diff -Naur php-5.0.4/ext/varfilter/CREDITS hardening-patch-5.0.4-0.3.2/ext/varfilter/CREDITS
1045--- php-5.0.4/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100
1046+++ hardening-patch-5.0.4-0.3.2/ext/varfilter/CREDITS 2005-07-06 13:12:40.000000000 +0200
1047@@ -0,0 +1,2 @@
1048+varfilter
1049+Stefan Esser
1050\ Kein Zeilenumbruch am Dateiende.
1051diff -Naur php-5.0.4/ext/varfilter/php_varfilter.h hardening-patch-5.0.4-0.3.2/ext/varfilter/php_varfilter.h
1052--- php-5.0.4/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100
1053+++ hardening-patch-5.0.4-0.3.2/ext/varfilter/php_varfilter.h 2005-07-06 13:12:40.000000000 +0200
1054@@ -0,0 +1,111 @@
1055+/*
1056+ +----------------------------------------------------------------------+
1057+ | Hardened-PHP Project's varfilter extension |
1058+ +----------------------------------------------------------------------+
1059+ | Copyright (c) 2004-2005 Stefan Esser |
1060+ +----------------------------------------------------------------------+
1061+ | This source file is subject to version 2.02 of the PHP license, |
1062+ | that is bundled with this package in the file LICENSE, and is |
1063+ | available at through the world-wide-web at |
1064+ | http://www.php.net/license/2_02.txt. |
1065+ | If you did not receive a copy of the PHP license and are unable to |
1066+ | obtain it through the world-wide-web, please send a note to |
1067+ | license@php.net so we can mail you a copy immediately. |
1068+ +----------------------------------------------------------------------+
1069+ | Author: Stefan Esser <sesser@hardened-php.net> |
1070+ +----------------------------------------------------------------------+
1071+
1072+ $Id: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $
1073+*/
1074+
1075+#ifndef PHP_VARFILTER_H
1076+#define PHP_VARFILTER_H
1077+
1078+extern zend_module_entry varfilter_module_entry;
1079+#define phpext_varfilter_ptr &varfilter_module_entry
1080+
1081+#ifdef PHP_WIN32
1082+#define PHP_VARFILTER_API __declspec(dllexport)
1083+#else
1084+#define PHP_VARFILTER_API
1085+#endif
1086+
1087+#ifdef ZTS
1088+#include "TSRM.h"
1089+#endif
1090+
1091+#include "SAPI.h"
1092+
1093+#include "php_variables.h"
1094+
1095+
1096+PHP_MINIT_FUNCTION(varfilter);
1097+PHP_MSHUTDOWN_FUNCTION(varfilter);
1098+PHP_RINIT_FUNCTION(varfilter);
1099+PHP_RSHUTDOWN_FUNCTION(varfilter);
1100+PHP_MINFO_FUNCTION(varfilter);
1101+
1102+
1103+ZEND_BEGIN_MODULE_GLOBALS(varfilter)
1104+// request variables
1105+ long max_request_variables;
1106+ long cur_request_variables;
1107+ long max_varname_length;
1108+ long max_totalname_length;
1109+ long max_value_length;
1110+ long max_array_depth;
1111+ long max_array_index_length;
1112+// cookie variables
1113+ long max_cookie_vars;
1114+ long cur_cookie_vars;
1115+ long max_cookie_name_length;
1116+ long max_cookie_totalname_length;
1117+ long max_cookie_value_length;
1118+ long max_cookie_array_depth;
1119+ long max_cookie_array_index_length;
1120+// get variables
1121+ long max_get_vars;
1122+ long cur_get_vars;
1123+ long max_get_name_length;
1124+ long max_get_totalname_length;
1125+ long max_get_value_length;
1126+ long max_get_array_depth;
1127+ long max_get_array_index_length;
1128+// post variables
1129+ long max_post_vars;
1130+ long cur_post_vars;
1131+ long max_post_name_length;
1132+ long max_post_totalname_length;
1133+ long max_post_value_length;
1134+ long max_post_array_depth;
1135+ long max_post_array_index_length;
1136+// fileupload
1137+ long max_uploads;
1138+ long cur_uploads;
1139+ zend_bool disallow_elf_files;
1140+ char *verification_script;
1141+
1142+ZEND_END_MODULE_GLOBALS(varfilter)
1143+
1144+
1145+#ifdef ZTS
1146+#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v)
1147+#else
1148+#define VARFILTER_G(v) (varfilter_globals.v)
1149+#endif
1150+
1151+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter);
1152+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter);
1153+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter);
1154+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter);
1155+
1156+#endif /* PHP_VARFILTER_H */
1157+
1158+
1159+/*
1160+ * Local variables:
1161+ * tab-width: 4
1162+ * c-basic-offset: 4
1163+ * indent-tabs-mode: t
1164+ * End:
1165+ */
1166diff -Naur php-5.0.4/ext/varfilter/varfilter.c hardening-patch-5.0.4-0.3.2/ext/varfilter/varfilter.c
1167--- php-5.0.4/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100
1168+++ hardening-patch-5.0.4-0.3.2/ext/varfilter/varfilter.c 2005-07-09 08:46:50.126967912 +0200
1169@@ -0,0 +1,604 @@
1170+/*
1171+ +----------------------------------------------------------------------+
1172+ | Hardened-PHP Project's varfilter extension |
1173+ +----------------------------------------------------------------------+
1174+ | Copyright (c) 2004-2005 Stefan Esser |
1175+ +----------------------------------------------------------------------+
1176+ | This source file is subject to version 2.02 of the PHP license, |
1177+ | that is bundled with this package in the file LICENSE, and is |
1178+ | available at through the world-wide-web at |
1179+ | http://www.php.net/license/2_02.txt. |
1180+ | If you did not receive a copy of the PHP license and are unable to |
1181+ | obtain it through the world-wide-web, please send a note to |
1182+ | license@php.net so we can mail you a copy immediately. |
1183+ +----------------------------------------------------------------------+
1184+ | Author: Stefan Esser <sesser@hardened-php.net> |
1185+ +----------------------------------------------------------------------+
1186+
1187+ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $
1188+*/
1189+
1190+#ifdef HAVE_CONFIG_H
1191+#include "config.h"
1192+#endif
1193+
1194+#include "php.h"
1195+#include "php_ini.h"
1196+#include "ext/standard/info.h"
1197+#include "php_varfilter.h"
1198+#include "hardening_patch.h"
1199+
1200+ZEND_DECLARE_MODULE_GLOBALS(varfilter)
1201+
1202+/* True global resources - no need for thread safety here */
1203+static int le_varfilter;
1204+
1205+/* {{{ varfilter_module_entry
1206+ */
1207+zend_module_entry varfilter_module_entry = {
1208+#if ZEND_MODULE_API_NO >= 20010901
1209+ STANDARD_MODULE_HEADER,
1210+#endif
1211+ "varfilter",
1212+ NULL,
1213+ PHP_MINIT(varfilter),
1214+ PHP_MSHUTDOWN(varfilter),
1215+ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */
1216+ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */
1217+ PHP_MINFO(varfilter),
1218+#if ZEND_MODULE_API_NO >= 20010901
1219+ "0.3.2", /* Replace with version number for your extension */
1220+#endif
1221+ STANDARD_MODULE_PROPERTIES
1222+};
1223+/* }}} */
1224+
1225+#ifdef COMPILE_DL_VARFILTER
1226+ZEND_GET_MODULE(varfilter)
1227+#endif
1228+
1229+/* {{{ PHP_INI
1230+ */
1231+PHP_INI_BEGIN()
1232+ /* for backward compatibility */
1233+ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
1234+ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
1235+ STD_PHP_INI_ENTRY("varfilter.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
1236+ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
1237+ STD_PHP_INI_ENTRY("varfilter.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
1238+ STD_PHP_INI_ENTRY("varfilter.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
1239+
1240+ STD_PHP_INI_ENTRY("hphp.request.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
1241+ STD_PHP_INI_ENTRY("hphp.request.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
1242+ STD_PHP_INI_ENTRY("hphp.request.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
1243+ STD_PHP_INI_ENTRY("hphp.request.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
1244+ STD_PHP_INI_ENTRY("hphp.request.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
1245+ STD_PHP_INI_ENTRY("hphp.request.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
1246+
1247+ STD_PHP_INI_ENTRY("hphp.cookie.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_vars, zend_varfilter_globals, varfilter_globals)
1248+ STD_PHP_INI_ENTRY("hphp.cookie.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_name_length, zend_varfilter_globals, varfilter_globals)
1249+ STD_PHP_INI_ENTRY("hphp.cookie.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_cookie_totalname_length, zend_varfilter_globals, varfilter_globals)
1250+ STD_PHP_INI_ENTRY("hphp.cookie.max_value_length", "10000", PHP_INI_PERDIR, OnUpdateLong, max_cookie_value_length, zend_varfilter_globals, varfilter_globals)
1251+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_depth, zend_varfilter_globals, varfilter_globals)
1252+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_index_length, zend_varfilter_globals, varfilter_globals)
1253+
1254+ STD_PHP_INI_ENTRY("hphp.get.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_get_vars, zend_varfilter_globals, varfilter_globals)
1255+ STD_PHP_INI_ENTRY("hphp.get.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_name_length, zend_varfilter_globals, varfilter_globals)
1256+ STD_PHP_INI_ENTRY("hphp.get.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_get_totalname_length, zend_varfilter_globals, varfilter_globals)
1257+ STD_PHP_INI_ENTRY("hphp.get.max_value_length", "512", PHP_INI_PERDIR, OnUpdateLong, max_get_value_length, zend_varfilter_globals, varfilter_globals)
1258+ STD_PHP_INI_ENTRY("hphp.get.max_array_depth", "50", PHP_INI_PERDIR, OnUpdateLong, max_get_array_depth, zend_varfilter_globals, varfilter_globals)
1259+ STD_PHP_INI_ENTRY("hphp.get.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_array_index_length, zend_varfilter_globals, varfilter_globals)
1260+
1261+ STD_PHP_INI_ENTRY("hphp.post.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_post_vars, zend_varfilter_globals, varfilter_globals)
1262+ STD_PHP_INI_ENTRY("hphp.post.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_name_length, zend_varfilter_globals, varfilter_globals)
1263+ STD_PHP_INI_ENTRY("hphp.post.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_post_totalname_length, zend_varfilter_globals, varfilter_globals)
1264+ STD_PHP_INI_ENTRY("hphp.post.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_post_value_length, zend_varfilter_globals, varfilter_globals)
1265+ STD_PHP_INI_ENTRY("hphp.post.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_post_array_depth, zend_varfilter_globals, varfilter_globals)
1266+ STD_PHP_INI_ENTRY("hphp.post.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_array_index_length, zend_varfilter_globals, varfilter_globals)
1267+
1268+ STD_PHP_INI_ENTRY("hphp.upload.max_uploads", "25", PHP_INI_PERDIR, OnUpdateLong, max_uploads, zend_varfilter_globals, varfilter_globals)
1269+ STD_PHP_INI_ENTRY("hphp.upload.disallow_elf_files", "1", PHP_INI_SYSTEM, OnUpdateBool, disallow_elf_files, zend_varfilter_globals, varfilter_globals)
1270+ STD_PHP_INI_ENTRY("hphp.upload.verification_script", NULL, PHP_INI_SYSTEM, OnUpdateString, verification_script, zend_varfilter_globals, varfilter_globals)
1271+
1272+
1273+PHP_INI_END()
1274+/* }}} */
1275+
1276+/* {{{ php_varfilter_init_globals
1277+ */
1278+static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals)
1279+{
1280+ varfilter_globals->max_request_variables = 200;
1281+ varfilter_globals->max_varname_length = 64;
1282+ varfilter_globals->max_value_length = 10000;
1283+ varfilter_globals->max_array_depth = 100;
1284+ varfilter_globals->max_totalname_length = 256;
1285+ varfilter_globals->max_array_index_length = 64;
1286+
1287+ varfilter_globals->max_cookie_vars = 100;
1288+ varfilter_globals->max_cookie_name_length = 64;
1289+ varfilter_globals->max_cookie_totalname_length = 256;
1290+ varfilter_globals->max_cookie_value_length = 10000;
1291+ varfilter_globals->max_cookie_array_depth = 100;
1292+ varfilter_globals->max_cookie_array_index_length = 64;
1293+
1294+ varfilter_globals->max_get_vars = 100;
1295+ varfilter_globals->max_get_name_length = 64;
1296+ varfilter_globals->max_get_totalname_length = 256;
1297+ varfilter_globals->max_get_value_length = 512;
1298+ varfilter_globals->max_get_array_depth = 50;
1299+ varfilter_globals->max_get_array_index_length = 64;
1300+
1301+ varfilter_globals->max_post_vars = 200;
1302+ varfilter_globals->max_post_name_length = 64;
1303+ varfilter_globals->max_post_totalname_length = 256;
1304+ varfilter_globals->max_post_value_length = 65000;
1305+ varfilter_globals->max_post_array_depth = 100;
1306+ varfilter_globals->max_post_array_index_length = 64;
1307+
1308+ varfilter_globals->max_uploads = 25;
1309+ varfilter_globals->disallow_elf_files = 1;
1310+ varfilter_globals->verification_script = NULL;
1311+}
1312+/* }}} */
1313+
1314+/* {{{ PHP_MINIT_FUNCTION
1315+ */
1316+PHP_MINIT_FUNCTION(varfilter)
1317+{
1318+ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL);
1319+ REGISTER_INI_ENTRIES();
1320+
1321+ sapi_register_input_filter(varfilter_input_filter);
1322+ sapi_register_pre_upload_filter(varfilter_pre_upload_filter);
1323+ sapi_register_upload_content_filter(varfilter_upload_content_filter);
1324+ sapi_register_post_upload_filter(varfilter_post_upload_filter);
1325+
1326+ return SUCCESS;
1327+}
1328+/* }}} */
1329+
1330+/* {{{ PHP_MSHUTDOWN_FUNCTION
1331+ */
1332+PHP_MSHUTDOWN_FUNCTION(varfilter)
1333+{
1334+// zend_hash_apply_with_arguments(&HG(lists.functionlists), (apply_func_args_t) show_stuff, 0);
1335+
1336+ UNREGISTER_INI_ENTRIES();
1337+
1338+ return SUCCESS;
1339+}
1340+/* }}} */
1341+
1342+/* Remove if there's nothing to do at request start */
1343+/* {{{ PHP_RINIT_FUNCTION
1344+ */
1345+PHP_RINIT_FUNCTION(varfilter)
1346+{
1347+ VARFILTER_G(cur_request_variables) = 0;
1348+ VARFILTER_G(cur_get_vars) = 0;
1349+ VARFILTER_G(cur_post_vars) = 0;
1350+ VARFILTER_G(cur_cookie_vars) = 0;
1351+
1352+ VARFILTER_G(cur_uploads) = 0;
1353+
1354+ return SUCCESS;
1355+}
1356+/* }}} */
1357+
1358+/* Remove if there's nothing to do at request end */
1359+/* {{{ PHP_RSHUTDOWN_FUNCTION
1360+ */
1361+PHP_RSHUTDOWN_FUNCTION(varfilter)
1362+{
1363+ return SUCCESS;
1364+}
1365+/* }}} */
1366+
1367+/* {{{ PHP_MINFO_FUNCTION
1368+ */
1369+PHP_MINFO_FUNCTION(varfilter)
1370+{
1371+ php_info_print_table_start();
1372+ php_info_print_table_header(2, "Hardening-Patch's variable filter support", "enabled");
1373+ php_info_print_table_end();
1374+
1375+ DISPLAY_INI_ENTRIES();
1376+}
1377+/* }}} */
1378+
1379+/* {{{ normalize_varname
1380+ */
1381+static void normalize_varname(char *varname)
1382+{
1383+ char *s=varname, *index=NULL, *indexend=NULL, *p;
1384+
1385+ /* overjump leading space */
1386+ while (*s == ' ') {
1387+ s++;
1388+ }
1389+
1390+ /* and remove it */
1391+ if (s != varname) {
1392+ memmove(varname, s, strlen(s)+1);
1393+ }
1394+
1395+ for (p=varname; *p && *p != '['; p++) {
1396+ switch(*p) {
1397+ case ' ':
1398+ case '.':
1399+ *p='_';
1400+ break;
1401+ }
1402+ }
1403+
1404+ /* find index */
1405+ index = strchr(varname, '[');
1406+ if (index) {
1407+ index++;
1408+ s=index;
1409+ } else {
1410+ return;
1411+ }
1412+
1413+ /* done? */
1414+ while (index) {
1415+
1416+ while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
1417+ index++;
1418+ }
1419+ indexend = strchr(index, ']');
1420+ indexend = indexend ? indexend + 1 : index + strlen(index);
1421+
1422+ if (s != index) {
1423+ memmove(s, index, strlen(index)+1);
1424+ s += indexend-index;
1425+ } else {
1426+ s = indexend;
1427+ }
1428+
1429+ if (*s == '[') {
1430+ s++;
1431+ index = s;
1432+ } else {
1433+ index = NULL;
1434+ }
1435+ }
1436+ *s++='\0';
1437+}
1438+/* }}} */
1439+
1440+/* {{{ SAPI_PRE_UPLOAD_FILTER_FUNC
1441+ */
1442+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter)
1443+{
1444+ /* Drop this fileupload if the limit is reached */
1445+ if (VARFILTER_G(max_uploads) && VARFILTER_G(max_uploads) <= VARFILTER_G(cur_uploads)) {
1446+ php_security_log(S_FILES, "configured fileupload limit exceeded - file dropped");
1447+ return FAILURE;
1448+ }
1449+
1450+ return SUCCESS;
1451+}
1452+/* }}} */
1453+
1454+/* {{{ SAPI_UPLOAD_CONTENT_FILTER_FUNC
1455+ */
1456+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter)
1457+{
1458+
1459+ if (VARFILTER_G(disallow_elf_files)) {
1460+
1461+ if (offset == 0 && buffer_len > 10) {
1462+
1463+ if (buffer[0] == 0x7F && buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'F') {
1464+ php_security_log(S_FILES, "uploaded file is an ELF executable - file dropped");
1465+ return FAILURE;
1466+ }
1467+ }
1468+
1469+ }
1470+
1471+ return SUCCESS;
1472+}
1473+/* }}} */
1474+
1475+/* {{{ SAPI_POST_UPLOAD_FILTER_FUNC
1476+ */
1477+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter)
1478+{
1479+ int retval = SUCCESS;
1480+
1481+ if (VARFILTER_G(verification_script)) {
1482+ char cmd[8192];
1483+ FILE *in;
1484+ int first=1;
1485+
1486+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s", VARFILTER_G(verification_script), tmpfilename);
1487+
1488+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
1489+ php_security_log(S_FILES, "unable to execute fileupload verification script - file dropped");
1490+ return FAILURE;
1491+ }
1492+
1493+ retval = FAILURE;
1494+
1495+ /* read and forget the result */
1496+ while (1) {
1497+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
1498+ if (readbytes<=0) {
1499+ break;
1500+ }
1501+ if (first) {
1502+ retval = atoi(cmd) == 1 ? SUCCESS : FAILURE;
1503+ first = 0;
1504+ }
1505+ }
1506+ pclose(in);
1507+ }
1508+
1509+ if (retval != SUCCESS) {
1510+ php_security_log(S_FILES, "fileupload verification script disallows file - file dropped");
1511+ return FAILURE;
1512+ }
1513+
1514+ VARFILTER_G(cur_uploads)++;
1515+ return SUCCESS;
1516+}
1517+/* }}} */
1518+
1519+/* {{{ SAPI_INPUT_FILTER_FUNC
1520+ */
1521+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter)
1522+{
1523+ char *index, *prev_index = NULL, *copy_var;
1524+ unsigned int var_len, total_len, depth = 0, rv;
1525+
1526+ /* Drop this variable if the limit is reached */
1527+ if (VARFILTER_G(max_request_variables) && VARFILTER_G(max_request_variables) <= VARFILTER_G(cur_request_variables)) {
1528+ php_security_log(S_VARS, "configured request variable limit exceeded - dropped %s", var);
1529+ return 0;
1530+ }
1531+ switch (arg) {
1532+ case PARSE_GET:
1533+ if (VARFILTER_G(max_get_vars) && VARFILTER_G(max_get_vars) <= VARFILTER_G(cur_get_vars)) {
1534+ php_security_log(S_VARS, "configured GET variable limit exceeded - dropped %s", var);
1535+ return 0;
1536+ }
1537+ break;
1538+ case PARSE_COOKIE:
1539+ if (VARFILTER_G(max_cookie_vars) && VARFILTER_G(max_cookie_vars) <= VARFILTER_G(cur_cookie_vars)) {
1540+ php_security_log(S_VARS, "configured COOKIE variable limit exceeded - dropped %s", var);
1541+ return 0;
1542+ }
1543+ break;
1544+ case PARSE_POST:
1545+ if (VARFILTER_G(max_post_vars) && VARFILTER_G(max_post_vars) <= VARFILTER_G(cur_post_vars)) {
1546+ php_security_log(S_VARS, "configured POST variable limit exceeded - dropped %s", var);
1547+ return 0;
1548+ }
1549+ break;
1550+ }
1551+
1552+
1553+ /* Drop this variable if it exceeds the value length limit */
1554+ if (VARFILTER_G(max_value_length) && VARFILTER_G(max_value_length) < val_len) {
1555+ php_security_log(S_VARS, "configured request variable value length limit exceeded - dropped %s", var);
1556+ return 0;
1557+ }
1558+ switch (arg) {
1559+ case PARSE_GET:
1560+ if (VARFILTER_G(max_get_value_length) && VARFILTER_G(max_get_value_length) < val_len) {
1561+ php_security_log(S_VARS, "configured GET variable value length limit exceeded - dropped %s", var);
1562+ return 0;
1563+ }
1564+ break;
1565+ case PARSE_COOKIE:
1566+ if (VARFILTER_G(max_cookie_value_length) && VARFILTER_G(max_cookie_value_length) < val_len) {
1567+ php_security_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped %s", var);
1568+ return 0;
1569+ }
1570+ break;
1571+ case PARSE_POST:
1572+ if (VARFILTER_G(max_post_value_length) && VARFILTER_G(max_post_value_length) < val_len) {
1573+ php_security_log(S_VARS, "configured POST variable value length limit exceeded - dropped %s", var);
1574+ return 0;
1575+ }
1576+ break;
1577+ }
1578+
1579+ /* Normalize the variable name */
1580+ normalize_varname(var);
1581+
1582+ /* Find length of variable name */
1583+ index = strchr(var, '[');
1584+ total_len = strlen(var);
1585+ var_len = index ? index-var : total_len;
1586+
1587+ /* Drop this variable if it exceeds the varname/total length limit */
1588+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
1589+ php_security_log(S_VARS, "configured request variable name length limit exceeded - dropped %s", var);
1590+ return 0;
1591+ }
1592+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
1593+ php_security_log(S_VARS, "configured request variable total name length limit exceeded - dropped %s", var);
1594+ return 0;
1595+ }
1596+ switch (arg) {
1597+ case PARSE_GET:
1598+ if (VARFILTER_G(max_get_name_length) && VARFILTER_G(max_get_name_length) < var_len) {
1599+ php_security_log(S_VARS, "configured GET variable name length limit exceeded - dropped %s", var);
1600+ return 0;
1601+ }
1602+ if (VARFILTER_G(max_get_totalname_length) && VARFILTER_G(max_get_totalname_length) < var_len) {
1603+ php_security_log(S_VARS, "configured GET variable total name length limit exceeded - dropped %s", var);
1604+ return 0;
1605+ }
1606+ break;
1607+ case PARSE_COOKIE:
1608+ if (VARFILTER_G(max_cookie_name_length) && VARFILTER_G(max_cookie_name_length) < var_len) {
1609+ php_security_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped %s", var);
1610+ return 0;
1611+ }
1612+ if (VARFILTER_G(max_cookie_totalname_length) && VARFILTER_G(max_cookie_totalname_length) < var_len) {
1613+ php_security_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped %s", var);
1614+ return 0;
1615+ }
1616+ break;
1617+ case PARSE_POST:
1618+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
1619+ php_security_log(S_VARS, "configured POST variable name length limit exceeded - dropped %s", var);
1620+ return 0;
1621+ }
1622+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
1623+ php_security_log(S_VARS, "configured POST variable total name length limit exceeded - dropped %s", var);
1624+ return 0;
1625+ }
1626+ break;
1627+ }
1628+
1629+ /* Find out array depth */
1630+ while (index) {
1631+ unsigned int index_length;
1632+
1633+ depth++;
1634+ index = strchr(index+1, '[');
1635+
1636+ if (prev_index) {
1637+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
1638+
1639+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
1640+ php_security_log(S_VARS, "configured request variable array index length limit exceeded - dropped %s", var);
1641+ return 0;
1642+ }
1643+ switch (arg) {
1644+ case PARSE_GET:
1645+ if (VARFILTER_G(max_get_array_index_length) && VARFILTER_G(max_get_array_index_length) < index_length) {
1646+ php_security_log(S_VARS, "configured GET variable array index length limit exceeded - dropped %s", var);
1647+ return 0;
1648+ }
1649+ break;
1650+ case PARSE_COOKIE:
1651+ if (VARFILTER_G(max_cookie_array_index_length) && VARFILTER_G(max_cookie_array_index_length) < index_length) {
1652+ php_security_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped %s", var);
1653+ return 0;
1654+ }
1655+ break;
1656+ case PARSE_POST:
1657+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
1658+ php_security_log(S_VARS, "configured POST variable array index length limit exceeded - dropped %s", var);
1659+ return 0;
1660+ }
1661+ break;
1662+ }
1663+ prev_index = index;
1664+ }
1665+
1666+ }
1667+
1668+ /* Drop this variable if it exceeds the array depth limit */
1669+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
1670+ php_security_log(S_VARS, "configured request variable array depth limit exceeded - dropped %s", var);
1671+ return 0;
1672+ }
1673+ switch (arg) {
1674+ case PARSE_GET:
1675+ if (VARFILTER_G(max_get_array_depth) && VARFILTER_G(max_get_array_depth) < depth) {
1676+ php_security_log(S_VARS, "configured GET variable array depth limit exceeded - dropped %s", var);
1677+ return 0;
1678+ }
1679+ break;
1680+ case PARSE_COOKIE:
1681+ if (VARFILTER_G(max_cookie_array_depth) && VARFILTER_G(max_cookie_array_depth) < depth) {
1682+ php_security_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped %s", var);
1683+ return 0;
1684+ }
1685+ break;
1686+ case PARSE_POST:
1687+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
1688+ php_security_log(S_VARS, "configured POST variable array depth limit exceeded - dropped %s", var);
1689+ return 0;
1690+ }
1691+ break;
1692+ }
1693+
1694+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
1695+ /* This is to protect several silly scripts that do globalizing themself */
1696+
1697+ switch (var_len) {
1698+ case 18:
1699+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname;
1700+ break;
1701+ case 17:
1702+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname;
1703+ break;
1704+ case 16:
1705+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname;
1706+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname;
1707+ break;
1708+ case 15:
1709+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname;
1710+ break;
1711+ case 14:
1712+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname;
1713+ break;
1714+ case 13:
1715+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname;
1716+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname;
1717+ break;
1718+ case 8:
1719+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname;
1720+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname;
1721+ break;
1722+ case 7:
1723+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname;
1724+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname;
1725+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname;
1726+ break;
1727+ case 6:
1728+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname;
1729+ break;
1730+ case 5:
1731+ if (memcmp(var, "_POST", 5)==0) goto protected_varname;
1732+ break;
1733+ case 4:
1734+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname;
1735+ if (memcmp(var, "_GET", 4)==0) goto protected_varname;
1736+ break;
1737+ }
1738+
1739+ /* Okay let PHP register this variable */
1740+ VARFILTER_G(cur_request_variables)++;
1741+ switch (arg) {
1742+ case PARSE_GET:
1743+ VARFILTER_G(cur_get_vars)++;
1744+ break;
1745+ case PARSE_COOKIE:
1746+ VARFILTER_G(cur_cookie_vars)++;
1747+ break;
1748+ case PARSE_POST:
1749+ VARFILTER_G(cur_post_vars)++;
1750+ break;
1751+ }
1752+
1753+ if (new_val_len) {
1754+ *new_val_len = val_len;
1755+ }
1756+
1757+ return 1;
1758+protected_varname:
1759+ php_security_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
1760+ return 0;
1761+}
1762+/* }}} */
1763+
1764+/*
1765+ * Local variables:
1766+ * tab-width: 4
1767+ * c-basic-offset: 4
1768+ * End:
1769+ * vim600: noet sw=4 ts=4 fdm=marker
1770+ * vim<600: noet sw=4 ts=4
1771+ */
1772+
1773+
1774diff -Naur php-5.0.4/main/fopen_wrappers.c hardening-patch-5.0.4-0.3.2/main/fopen_wrappers.c
1775--- php-5.0.4/main/fopen_wrappers.c 2005-03-11 07:55:22.000000000 +0100
1776+++ hardening-patch-5.0.4-0.3.2/main/fopen_wrappers.c 2005-06-26 20:59:20.000000000 +0200
1777@@ -163,6 +163,21 @@
1778 char *pathbuf;
1779 char *ptr;
1780 char *end;
1781+ char path_copy[MAXPATHLEN];
1782+ int path_len;
1783+
1784+ /* Special case path ends with a trailing slash */
1785+ path_len = strlen(path);
1786+ if (path_len >= MAXPATHLEN) {
1787+ errno = EPERM; /* we deny permission to open it */
1788+ return -1;
1789+ }
1790+ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) {
1791+ memcpy(path_copy, path, path_len+1);
1792+ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--;
1793+ path_copy[path_len] = '\0';
1794+ path = (const char *)&path_copy;
1795+ }
1796
1797 pathbuf = estrdup(PG(open_basedir));
1798
1799diff -Naur php-5.0.4/main/hardened_globals.h hardening-patch-5.0.4-0.3.2/main/hardened_globals.h
1800--- php-5.0.4/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100
1801+++ hardening-patch-5.0.4-0.3.2/main/hardened_globals.h 2005-07-05 18:31:23.000000000 +0200
1802@@ -0,0 +1,56 @@
1803+/*
1804+ +----------------------------------------------------------------------+
1805+ | Hardening-Patch for PHP |
1806+ +----------------------------------------------------------------------+
1807+ | Copyright (c) 2004-2005 Stefan Esser |
1808+ +----------------------------------------------------------------------+
1809+ | This source file is subject to version 2.02 of the PHP license, |
1810+ | that is bundled with this package in the file LICENSE, and is |
1811+ | available at through the world-wide-web at |
1812+ | http://www.php.net/license/2_02.txt. |
1813+ | If you did not receive a copy of the PHP license and are unable to |
1814+ | obtain it through the world-wide-web, please send a note to |
1815+ | license@php.net so we can mail you a copy immediately. |
1816+ +----------------------------------------------------------------------+
1817+ | Author: Stefan Esser <sesser@hardened-php.net> |
1818+ +----------------------------------------------------------------------+
1819+ */
1820+
1821+#ifndef HARDENED_GLOBALS_H
1822+#define HARDENED_GLOBALS_H
1823+
1824+typedef struct _hardened_globals hardened_globals_struct;
1825+
1826+#ifdef ZTS
1827+# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v)
1828+extern int hardened_globals_id;
1829+#else
1830+# define HG(v) (hardened_globals.v)
1831+extern struct _hardened_globals hardened_globals;
1832+#endif
1833+
1834+
1835+struct _hardened_globals {
1836+#if HARDENING_PATCH_MM_PROTECT
1837+ unsigned int canary_1;
1838+ unsigned int canary_2;
1839+#endif
1840+#if HARDENING_PATCH_LL_PROTECT
1841+ unsigned int canary_3;
1842+ unsigned int canary_4;
1843+ unsigned int ll_canary_inited;
1844+#endif
1845+ zend_bool hphp_sql_bailout_on_error;
1846+ zend_bool hphp_multiheader;
1847+ unsigned int dummy;
1848+};
1849+
1850+
1851+#endif /* HARDENED_GLOBALS_H */
1852+
1853+/*
1854+ * Local variables:
1855+ * tab-width: 4
1856+ * c-basic-offset: 4
1857+ * End:
1858+ */
1859diff -Naur php-5.0.4/main/hardening_patch.c hardening-patch-5.0.4-0.3.2/main/hardening_patch.c
1860--- php-5.0.4/main/hardening_patch.c 1970-01-01 01:00:00.000000000 +0100
1861+++ hardening-patch-5.0.4-0.3.2/main/hardening_patch.c 2005-07-03 10:39:30.000000000 +0200
1862@@ -0,0 +1,322 @@
1863+/*
1864+ +----------------------------------------------------------------------+
1865+ | Hardening Patch for PHP |
1866+ +----------------------------------------------------------------------+
1867+ | Copyright (c) 2004-2005 Stefan Esser |
1868+ +----------------------------------------------------------------------+
1869+ | This source file is subject to version 2.02 of the PHP license, |
1870+ | that is bundled with this package in the file LICENSE, and is |
1871+ | available at through the world-wide-web at |
1872+ | http://www.php.net/license/2_02.txt. |
1873+ | If you did not receive a copy of the PHP license and are unable to |
1874+ | obtain it through the world-wide-web, please send a note to |
1875+ | license@php.net so we can mail you a copy immediately. |
1876+ +----------------------------------------------------------------------+
1877+ | Author: Stefan Esser <sesser@hardened-php.net> |
1878+ +----------------------------------------------------------------------+
1879+ */
1880+/* $Id: hardening_patch.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */
1881+
1882+#include "php.h"
1883+
1884+#include <stdio.h>
1885+#include <stdlib.h>
1886+
1887+#if HAVE_UNISTD_H
1888+#include <unistd.h>
1889+#endif
1890+#include "SAPI.h"
1891+#include "php_globals.h"
1892+
1893+#if HARDENING_PATCH
1894+
1895+#ifdef HAVE_SYS_SOCKET_H
1896+#include <sys/socket.h>
1897+#endif
1898+
1899+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
1900+#undef AF_UNIX
1901+#endif
1902+
1903+#if defined(AF_UNIX)
1904+#include <sys/un.h>
1905+#endif
1906+
1907+#define SYSLOG_PATH "/dev/log"
1908+
1909+#include "snprintf.h"
1910+
1911+#include "hardening_patch.h"
1912+
1913+#ifdef ZTS
1914+#include "hardened_globals.h"
1915+int hardened_globals_id;
1916+#else
1917+struct _hardened_globals hardened_globals;
1918+#endif
1919+
1920+static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC)
1921+{
1922+ memset(hardened_globals, 0, sizeof(*hardened_globals));
1923+}
1924+
1925+
1926+PHPAPI void hardened_startup()
1927+{
1928+#ifdef ZTS
1929+ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL);
1930+#else
1931+ hardened_globals_ctor(&hardened_globals TSRMLS_CC);
1932+#endif
1933+}
1934+
1935+char *loglevel2string(int loglevel)
1936+{
1937+ switch (loglevel) {
1938+ case S_FILES:
1939+ return "FILES";
1940+ case S_INCLUDE:
1941+ return "INCLUDE";
1942+ case S_MEMORY:
1943+ return "MEMORY";
1944+ case S_MISC:
1945+ return "MISC";
1946+ case S_SQL:
1947+ return "SQL";
1948+ case S_EXECUTOR:
1949+ return "EXECUTOR";
1950+ case S_VARS:
1951+ return "VARS";
1952+ default:
1953+ return "UNKNOWN";
1954+ }
1955+}
1956+
1957+PHPAPI void php_security_log(int loglevel, char *fmt, ...)
1958+{
1959+#if defined(AF_UNIX)
1960+ int s, r, i=0;
1961+ struct sockaddr_un saun;
1962+ char buf[4096+64];
1963+ char error[4096+100];
1964+ char *ip_address;
1965+ char *fname;
1966+ int lineno;
1967+ va_list ap;
1968+ TSRMLS_FETCH();
1969+
1970+ if (EG(hphp_log_use_x_forwarded_for)) {
1971+ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
1972+ if (ip_address == NULL) {
1973+ ip_address = "X-FORWARDED-FOR not set";
1974+ }
1975+ } else {
1976+ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
1977+ if (ip_address == NULL) {
1978+ ip_address = "REMOTE_ADDR not set";
1979+ }
1980+ }
1981+
1982+
1983+ va_start(ap, fmt);
1984+ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
1985+ va_end(ap);
1986+ while (error[i]) {
1987+ if (error[i] < 32) error[i] = '.';
1988+ i++;
1989+ }
1990+
1991+ if (zend_is_executing(TSRMLS_C)) {
1992+ lineno = zend_get_executed_lineno(TSRMLS_C);
1993+ fname = zend_get_executed_filename(TSRMLS_C);
1994+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s', line %u)", error, ip_address, fname, lineno);
1995+ } else {
1996+ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
1997+ if (fname==NULL) {
1998+ fname = "unknown";
1999+ }
2000+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s')", error, ip_address, fname);
2001+ }
2002+
2003+ /* Syslog-Logging disabled? */
2004+ if ((EG(hphp_log_syslog) & loglevel)==0) {
2005+ goto log_sapi;
2006+ }
2007+
2008+ ap_php_snprintf(error, sizeof(error), "<%u>hphp[%u]: %s\n", EG(hphp_log_syslog_facility)|EG(hphp_log_syslog_priority),getpid(),buf);
2009+
2010+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
2011+ if (s == -1) {
2012+ goto log_sapi;
2013+ }
2014+
2015+ memset(&saun, 0, sizeof(saun));
2016+ saun.sun_family = AF_UNIX;
2017+ strcpy(saun.sun_path, SYSLOG_PATH);
2018+ /*saun.sun_len = sizeof(saun);*/
2019+
2020+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
2021+ if (r) {
2022+ close(s);
2023+ s = socket(AF_UNIX, SOCK_STREAM, 0);
2024+ if (s == -1) {
2025+ goto log_sapi;
2026+ }
2027+
2028+ memset(&saun, 0, sizeof(saun));
2029+ saun.sun_family = AF_UNIX;
2030+ strcpy(saun.sun_path, SYSLOG_PATH);
2031+ /*saun.sun_len = sizeof(saun);*/
2032+
2033+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
2034+ if (r) {
2035+ close(s);
2036+ goto log_sapi;
2037+ }
2038+ }
2039+ send(s, error, strlen(error), 0);
2040+
2041+ close(s);
2042+
2043+log_sapi:
2044+ /* SAPI Logging activated? */
2045+ if ((EG(hphp_log_syslog) & loglevel)!=0) {
2046+ sapi_module.log_message(buf);
2047+ }
2048+
2049+log_script:
2050+ /* script logging activaed? */
2051+ if (((EG(hphp_log_script) & loglevel)!=0) && EG(hphp_log_scriptname)!=NULL) {
2052+ char cmd[8192], *cmdpos, *bufpos;
2053+ FILE *in;
2054+ int space;
2055+
2056+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", EG(hphp_log_scriptname), loglevel2string(loglevel));
2057+ space = sizeof(cmd) - strlen(cmd);
2058+ cmdpos = cmd + strlen(cmd);
2059+ bufpos = buf;
2060+ if (space <= 1) return;
2061+ while (space > 2 && *bufpos) {
2062+ if (*bufpos == '\'') {
2063+ if (space<=5) break;
2064+ *cmdpos++ = '\'';
2065+ *cmdpos++ = '\\';
2066+ *cmdpos++ = '\'';
2067+ *cmdpos++ = '\'';
2068+ bufpos++;
2069+ space-=4;
2070+ } else {
2071+ *cmdpos++ = *bufpos++;
2072+ space--;
2073+ }
2074+ }
2075+ *cmdpos++ = '\'';
2076+ *cmdpos = 0;
2077+
2078+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
2079+ return;
2080+ }
2081+ /* read and forget the result */
2082+ while (1) {
2083+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
2084+ if (readbytes<=0) {
2085+ break;
2086+ }
2087+ }
2088+ pclose(in);
2089+ }
2090+
2091+#endif
2092+}
2093+#endif
2094+
2095+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
2096+
2097+/* will be replaced later with more compatible method */
2098+PHPAPI unsigned int php_canary()
2099+{
2100+ time_t t;
2101+ unsigned int canary;
2102+ int fd;
2103+
2104+ fd = open("/dev/urandom", 0);
2105+ if (fd != -1) {
2106+ int r = read(fd, &canary, sizeof(canary));
2107+ close(fd);
2108+ if (r == sizeof(canary)) {
2109+ return (canary);
2110+ }
2111+ }
2112+ /* not good but we never want to do this */
2113+ time(&t);
2114+ canary = *(unsigned int *)&t + getpid() << 16;
2115+ return (canary);
2116+}
2117+#endif
2118+
2119+#if HARDENING_PATCH_INC_PROTECT
2120+
2121+PHPAPI int php_is_valid_include(zval *z)
2122+{
2123+ char *filename;
2124+ int len, i;
2125+ TSRMLS_FETCH();
2126+
2127+ /* must be of type string */
2128+ if (z->type != IS_STRING || z->value.str.val == NULL) {
2129+ return (0);
2130+ }
2131+
2132+ /* short cut */
2133+ filename = z->value.str.val;
2134+ len = z->value.str.len;
2135+
2136+ /* 1. must be shorter than MAXPATHLEN */
2137+ if (len > MAXPATHLEN) {
2138+ char *fname = estrndup(filename, len);
2139+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
2140+ php_security_log(S_INCLUDE, "Include filename ('%s') longer than MAXPATHLEN chars", fname);
2141+ efree(fname);
2142+ return (0);
2143+ }
2144+
2145+ /* 2. must not be cutted */
2146+ if (len != strlen(filename)) {
2147+ char *fname = estrndup(filename, len);
2148+ for (i=0; fname[i]; i++) if (fname[i] < 32) fname[i]='.';
2149+ php_security_log(S_INCLUDE, "Include filename truncated by a \\0 after '%s'", fname);
2150+ efree(fname);
2151+ return (0);
2152+ }
2153+
2154+ /* 3. must not be a URL */
2155+ if (strstr(filename, "://")) {
2156+ char *fname = estrndup(filename, len);
2157+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
2158+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL", fname);
2159+ efree(fname);
2160+ return (0);
2161+ }
2162+
2163+ /* 4. must not be an uploaded file */
2164+ if (SG(rfc1867_uploaded_files)) {
2165+ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) {
2166+ php_security_log(S_INCLUDE, "Include filename is an uploaded file");
2167+ return (0);
2168+ }
2169+ }
2170+
2171+ /* passed all tests */
2172+ return (1);
2173+}
2174+
2175+#endif
2176+
2177+/*
2178+ * Local variables:
2179+ * tab-width: 4
2180+ * c-basic-offset: 4
2181+ * End:
2182+ * vim600: sw=4 ts=4 fdm=marker
2183+ * vim<600: sw=4 ts=4
2184+ */
2185diff -Naur php-5.0.4/main/hardening_patch.h hardening-patch-5.0.4-0.3.2/main/hardening_patch.h
2186--- php-5.0.4/main/hardening_patch.h 1970-01-01 01:00:00.000000000 +0100
2187+++ hardening-patch-5.0.4-0.3.2/main/hardening_patch.h 2005-07-09 08:47:01.529234504 +0200
2188@@ -0,0 +1,46 @@
2189+/*
2190+ +----------------------------------------------------------------------+
2191+ | Hardening Patch for PHP |
2192+ +----------------------------------------------------------------------+
2193+ | Copyright (c) 2004-2005 Stefan Esser |
2194+ +----------------------------------------------------------------------+
2195+ | This source file is subject to version 2.02 of the PHP license, |
2196+ | that is bundled with this package in the file LICENSE, and is |
2197+ | available at through the world-wide-web at |
2198+ | http://www.php.net/license/2_02.txt. |
2199+ | If you did not receive a copy of the PHP license and are unable to |
2200+ | obtain it through the world-wide-web, please send a note to |
2201+ | license@php.net so we can mail you a copy immediately. |
2202+ +----------------------------------------------------------------------+
2203+ | Author: Stefan Esser <sesser@hardened-php.net> |
2204+ +----------------------------------------------------------------------+
2205+ */
2206+
2207+#ifndef HARDENING_PATCH_H
2208+#define HARDENING_PATCH_H
2209+
2210+#include "zend.h"
2211+
2212+#if HARDENING_PATCH
2213+PHPAPI void php_security_log(int loglevel, char *fmt, ...);
2214+PHPAPI void hardened_startup();
2215+#define HARDENING_PATCH_VERSION "0.3.2"
2216+
2217+#endif
2218+
2219+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
2220+PHPAPI unsigned int php_canary();
2221+#endif
2222+
2223+#if HARDENING_PATCH_INC_PROTECT
2224+PHPAPI int php_is_valid_include(zval *z);
2225+#endif
2226+
2227+#endif /* HARDENING_PATCH_H */
2228+
2229+/*
2230+ * Local variables:
2231+ * tab-width: 4
2232+ * c-basic-offset: 4
2233+ * End:
2234+ */
2235diff -Naur php-5.0.4/main/hardening_patch.m4 hardening-patch-5.0.4-0.3.2/main/hardening_patch.m4
2236--- php-5.0.4/main/hardening_patch.m4 1970-01-01 01:00:00.000000000 +0100
2237+++ hardening-patch-5.0.4-0.3.2/main/hardening_patch.m4 2005-06-26 21:42:36.000000000 +0200
2238@@ -0,0 +1,95 @@
2239+dnl
2240+dnl $Id: hardening_patch.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $
2241+dnl
2242+dnl This file contains Hardening Patch for PHP specific autoconf functions.
2243+dnl
2244+
2245+AC_ARG_ENABLE(hardening-patch-mm-protect,
2246+[ --disable-hardening-patch-mm-protect Disable the Memory Manager protection.],[
2247+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
2248+],[
2249+ DO_HARDENING_PATCH_MM_PROTECT=yes
2250+])
2251+
2252+AC_ARG_ENABLE(hardening-patch-ll-protect,
2253+[ --disable-hardening-patch-ll-protect Disable the Linked List protection.],[
2254+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
2255+],[
2256+ DO_HARDENING_PATCH_LL_PROTECT=yes
2257+])
2258+
2259+AC_ARG_ENABLE(hardening-patch-inc-protect,
2260+[ --disable-hardening-patch-inc-protect Disable include/require protection.],[
2261+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
2262+],[
2263+ DO_HARDENING_PATCH_INC_PROTECT=yes
2264+])
2265+
2266+AC_ARG_ENABLE(hardening-patch-fmt-protect,
2267+[ --disable-hardening-patch-fmt-protect Disable format string protection.],[
2268+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
2269+],[
2270+ DO_HARDENING_PATCH_FMT_PROTECT=yes
2271+])
2272+
2273+AC_ARG_ENABLE(hardening-patch-hash-protect,
2274+[ --disable-hardening-patch-hash-protect Disable HashTable destructor protection.],[
2275+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
2276+],[
2277+ DO_HARDENING_PATCH_HASH_PROTECT=yes
2278+])
2279+
2280+AC_MSG_CHECKING(whether to protect the Zend Memory Manager)
2281+AC_MSG_RESULT($DO_HARDENING_PATCH_MM_PROTECT)
2282+
2283+AC_MSG_CHECKING(whether to protect the Zend Linked Lists)
2284+AC_MSG_RESULT($DO_HARDENING_PATCH_LL_PROTECT)
2285+
2286+AC_MSG_CHECKING(whether to protect include/require statements)
2287+AC_MSG_RESULT($DO_HARDENING_PATCH_INC_PROTECT)
2288+
2289+AC_MSG_CHECKING(whether to protect PHP Format String functions)
2290+AC_MSG_RESULT($DO_HARDENING_PATCH_FMT_PROTECT)
2291+
2292+AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables)
2293+AC_MSG_RESULT($DO_HARDENING_PATCH_HASH_PROTECT)
2294+
2295+
2296+AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2297+
2298+
2299+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
2300+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2301+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 1, [Memory Manager Protection])
2302+else
2303+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 0, [Memory Manager Protection])
2304+fi
2305+
2306+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
2307+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2308+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 1, [Linked List Protection])
2309+else
2310+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 0, [Linked List Protection])
2311+fi
2312+
2313+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
2314+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2315+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 1, [Include/Require Protection])
2316+else
2317+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 0, [Include/Require Protection])
2318+fi
2319+
2320+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
2321+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2322+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 1, [Fmt String Protection])
2323+else
2324+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 0, [Fmt String Protection])
2325+fi
2326+
2327+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
2328+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2329+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 1, [HashTable DTOR Protection])
2330+else
2331+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 0, [HashTable DTOR Protection])
2332+fi
2333+
2334diff -Naur php-5.0.4/main/main.c hardening-patch-5.0.4-0.3.2/main/main.c
2335--- php-5.0.4/main/main.c 2005-03-24 02:11:35.000000000 +0100
2336+++ hardening-patch-5.0.4-0.3.2/main/main.c 2005-06-26 23:26:26.000000000 +0200
2337@@ -92,6 +92,10 @@
2338
2339 #include "SAPI.h"
2340 #include "rfc1867.h"
2341+#if HARDENING_PATCH
2342+#include "hardened_globals.h"
2343+#endif
2344+
2345 /* }}} */
2346
2347 #ifndef ZTS
2348@@ -116,10 +120,33 @@
2349 */
2350 static PHP_INI_MH(OnChangeMemoryLimit)
2351 {
2352+#if HARDENING_PATCH
2353+ long orig_memory_limit;
2354+
2355+ if (entry->modified) {
2356+ orig_memory_limit = zend_atoi(entry->orig_value, entry->orig_value_length);
2357+ } else {
2358+ orig_memory_limit = 1<<30;
2359+ }
2360+ if (orig_memory_limit < 0 || orig_memory_limit > (1<<30)) {
2361+ orig_memory_limit = 1<<30;
2362+ }
2363+#endif
2364 if (new_value) {
2365 PG(memory_limit) = zend_atoi(new_value, new_value_length);
2366+#if HARDENING_PATCH
2367+ if (PG(memory_limit) > orig_memory_limit) {
2368+ PG(memory_limit) = orig_memory_limit;
2369+ php_security_log(S_MISC, "script tried to increase memory_limit above allowed value");
2370+ return FAILURE;
2371+ }
2372+#endif
2373 } else {
2374+#if HARDENING_PATCH
2375+ PG(memory_limit) = orig_memory_limit;
2376+#else
2377 PG(memory_limit) = 1<<30; /* effectively, no limit */
2378+#endif
2379 }
2380 return zend_set_memory_limit(PG(memory_limit));
2381 }
2382@@ -1313,6 +1340,10 @@
2383 tsrm_ls = ts_resource(0);
2384 #endif
2385
2386+#if HARDENING_PATCH
2387+ hardened_startup();
2388+#endif
2389+
2390 module_shutdown = 0;
2391 module_startup = 1;
2392 sapi_initialize_empty_request(TSRMLS_C);
2393@@ -1326,6 +1357,12 @@
2394
2395 php_output_startup();
2396
2397+#if HARDENING_PATCH_INC_PROTECT
2398+ zuf.is_valid_include = php_is_valid_include;
2399+#endif
2400+#if HARDENING_PATCH
2401+ zuf.security_log_function = php_security_log;
2402+#endif
2403 zuf.error_function = php_error_cb;
2404 zuf.printf_function = php_printf;
2405 zuf.write_function = php_body_write_wrapper;
2406@@ -1429,6 +1466,10 @@
2407 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, sizeof(PHP_CONFIG_FILE_PATH)-1, CONST_PERSISTENT | CONST_CS);
2408 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
2409 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
2410+#if HARDENING_PATCH
2411+ REGISTER_MAIN_LONG_CONSTANT("HARDENING_PATCH", 1, CONST_PERSISTENT | CONST_CS);
2412+ REGISTER_MAIN_STRINGL_CONSTANT("HARDENING_PATCH_VERSION", HARDENING_PATCH_VERSION, sizeof(HARDENING_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
2413+#endif
2414 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
2415 php_output_register_constants(TSRMLS_C);
2416 php_rfc1867_register_constants(TSRMLS_C);
2417diff -Naur php-5.0.4/main/php_config.h.in hardening-patch-5.0.4-0.3.2/main/php_config.h.in
2418--- php-5.0.4/main/php_config.h.in 2005-04-03 11:42:53.000000000 +0200
2419+++ hardening-patch-5.0.4-0.3.2/main/php_config.h.in 2005-06-26 22:25:22.000000000 +0200
2420@@ -746,6 +746,39 @@
2421 /* hardcode for each of the cross compiler host */
2422 #undef PHP_UNAME
2423
2424+/* Hardening-Patch for PHP */
2425+#undef HARDENING_PATCH
2426+
2427+/* Memory Manager Protection */
2428+#undef HARDENING_PATCH_MM_PROTECT
2429+
2430+/* Memory Manager Protection */
2431+#undef HARDENING_PATCH_MM_PROTECT
2432+
2433+/* Linked List Protection */
2434+#undef HARDENING_PATCH_LL_PROTECT
2435+
2436+/* Linked List Protection */
2437+#undef HARDENING_PATCH_LL_PROTECT
2438+
2439+/* Include/Require Protection */
2440+#undef HARDENING_PATCH_INC_PROTECT
2441+
2442+/* Include/Require Protection */
2443+#undef HARDENING_PATCH_INC_PROTECT
2444+
2445+/* Fmt String Protection */
2446+#undef HARDENING_PATCH_FMT_PROTECT
2447+
2448+/* Fmt String Protection */
2449+#undef HARDENING_PATCH_FMT_PROTECT
2450+
2451+/* HashTable DTOR Protection */
2452+#undef HARDENING_PATCH_HASH_PROTECT
2453+
2454+/* HashTable DTOR Protection */
2455+#undef HARDENING_PATCH_HASH_PROTECT
2456+
2457 /* Whether you have AOLserver */
2458 #undef HAVE_AOLSERVER
2459
2460@@ -1077,6 +1110,12 @@
2461 /* Define if you have the getaddrinfo function */
2462 #undef HAVE_GETADDRINFO
2463
2464+/* Whether realpath is broken */
2465+#undef PHP_BROKEN_REALPATH
2466+
2467+/* Whether realpath is broken */
2468+#undef PHP_BROKEN_REALPATH
2469+
2470 /* Whether system headers declare timezone */
2471 #undef HAVE_DECLARED_TIMEZONE
2472
2473diff -Naur php-5.0.4/main/php.h hardening-patch-5.0.4-0.3.2/main/php.h
2474--- php-5.0.4/main/php.h 2005-03-14 10:41:39.000000000 +0100
2475+++ hardening-patch-5.0.4-0.3.2/main/php.h 2005-06-28 14:49:57.000000000 +0200
2476@@ -26,7 +26,7 @@
2477 #include <dmalloc.h>
2478 #endif
2479
2480-#define PHP_API_VERSION 20031224
2481+#define PHP_API_VERSION 1020050627
2482 #define PHP_HAVE_STREAMS
2483 #define YYDEBUG 0
2484
2485@@ -35,11 +35,19 @@
2486 #include "zend_qsort.h"
2487 #include "php_compat.h"
2488
2489+
2490 #include "zend_API.h"
2491
2492 #undef sprintf
2493 #define sprintf php_sprintf
2494
2495+#if HARDENING_PATCH
2496+#if HAVE_REALPATH
2497+#undef realpath
2498+#define realpath php_realpath
2499+#endif
2500+#endif
2501+
2502 /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */
2503 #undef PHP_DEBUG
2504 #define PHP_DEBUG ZEND_DEBUG
2505@@ -341,6 +349,7 @@
2506 #define PHP_FUNCTION ZEND_FUNCTION
2507 #define PHP_METHOD ZEND_METHOD
2508
2509+#define PHP_STATIC_FE ZEND_STATIC_FE
2510 #define PHP_NAMED_FE ZEND_NAMED_FE
2511 #define PHP_FE ZEND_FE
2512 #define PHP_FALIAS ZEND_FALIAS
2513@@ -446,6 +455,10 @@
2514 #endif
2515 #endif /* !XtOffsetOf */
2516
2517+#if HARDENING_PATCH
2518+#include "hardening_patch.h"
2519+#endif
2520+
2521 #endif
2522
2523 /*
2524diff -Naur php-5.0.4/main/php_variables.c hardening-patch-5.0.4-0.3.2/main/php_variables.c
2525--- php-5.0.4/main/php_variables.c 2005-02-17 05:46:10.000000000 +0100
2526+++ hardening-patch-5.0.4-0.3.2/main/php_variables.c 2005-06-27 01:01:54.000000000 +0200
2527@@ -493,7 +493,7 @@
2528 */
2529 static inline void php_register_server_variables(TSRMLS_D)
2530 {
2531- zval *array_ptr=NULL;
2532+ zval *array_ptr=NULL, *vptr;
2533 /* turn off magic_quotes while importing server variables */
2534 int magic_quotes_gpc = PG(magic_quotes_gpc);
2535
2536@@ -506,6 +506,16 @@
2537 /* Server variables */
2538 if (sapi_module.register_server_variables) {
2539 sapi_module.register_server_variables(array_ptr TSRMLS_CC);
2540+ if (zend_hash_find(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"), (void **)&vptr)==SUCCESS) {
2541+ char *str;
2542+ if (vptr->type != IS_STRING) {
2543+ str = "Array";
2544+ } else {
2545+ str = vptr->value.str.val;
2546+ }
2547+ php_security_log(S_VARS, "Attacker tried to overwrite HTTP_RAW_POST_DATA with '%s' through a HTTP header", str);
2548+ zend_hash_del(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
2549+ }
2550 }
2551
2552 /* PHP Authentication support */
2553diff -Naur php-5.0.4/main/rfc1867.c hardening-patch-5.0.4-0.3.2/main/rfc1867.c
2554--- php-5.0.4/main/rfc1867.c 2005-02-15 01:26:35.000000000 +0100
2555+++ hardening-patch-5.0.4-0.3.2/main/rfc1867.c 2005-06-26 23:13:12.000000000 +0200
2556@@ -131,6 +131,7 @@
2557 #define UPLOAD_ERROR_C 3 /* Partially uploaded */
2558 #define UPLOAD_ERROR_D 4 /* No file uploaded */
2559 #define UPLOAD_ERROR_E 6 /* Missing /tmp or similar directory */
2560+#define UPLOAD_ERROR_F 7 /* Filter forbids upload */
2561
2562 void php_rfc1867_register_constants(TSRMLS_D)
2563 {
2564@@ -140,6 +141,7 @@
2565 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_PARTIAL", UPLOAD_ERROR_C, CONST_CS | CONST_PERSISTENT);
2566 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE", UPLOAD_ERROR_D, CONST_CS | CONST_PERSISTENT);
2567 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E, CONST_CS | CONST_PERSISTENT);
2568+ REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FILTER", UPLOAD_ERROR_F, CONST_CS | CONST_PERSISTENT);
2569 }
2570
2571 static void normalize_protected_variable(char *varname TSRMLS_DC)
2572@@ -849,6 +851,7 @@
2573 char buff[FILLUNIT];
2574 char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL;
2575 int blen=0, wlen=0;
2576+ unsigned long offset;
2577
2578 zend_llist_clean(&header);
2579
2580@@ -988,6 +991,11 @@
2581 cancel_upload = UPLOAD_ERROR_D;
2582 }
2583
2584+ if (sapi_module.pre_upload_filter && sapi_module.pre_upload_filter(param, filename TSRMLS_CC)==FAILURE) {
2585+ cancel_upload = UPLOAD_ERROR_F;
2586+ }
2587+
2588+ offset = 0;
2589 while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff) TSRMLS_CC)))
2590 {
2591 if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) {
2592@@ -1001,6 +1009,11 @@
2593 #endif
2594 cancel_upload = UPLOAD_ERROR_B;
2595 } else if (blen > 0) {
2596+
2597+ if (sapi_module.upload_content_filter && sapi_module.upload_content_filter(offset, buff, blen, &blen TSRMLS_CC)==FAILURE) {
2598+ cancel_upload = UPLOAD_ERROR_F;
2599+ }
2600+
2601 wlen = fwrite(buff, 1, blen, fp);
2602
2603 if (wlen < blen) {
2604@@ -1024,6 +1037,10 @@
2605 }
2606 #endif
2607
2608+ if (!cancel_upload && sapi_module.post_upload_filter && sapi_module.post_upload_filter(temp_filename TSRMLS_CC)==FAILURE) {
2609+ cancel_upload = UPLOAD_ERROR_F;
2610+ }
2611+
2612 if (cancel_upload) {
2613 if (temp_filename) {
2614 if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
2615diff -Naur php-5.0.4/main/SAPI.c hardening-patch-5.0.4-0.3.2/main/SAPI.c
2616--- php-5.0.4/main/SAPI.c 2005-02-22 15:46:15.000000000 +0100
2617+++ hardening-patch-5.0.4-0.3.2/main/SAPI.c 2005-06-26 23:18:17.000000000 +0200
2618@@ -821,6 +821,30 @@
2619 zend_hash_del(&known_post_content_types, post_entry->content_type, post_entry->content_type_len+1);
2620 }
2621
2622+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
2623+{
2624+ sapi_module.input_filter = input_filter;
2625+ return SUCCESS;
2626+}
2627+
2628+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC))
2629+{
2630+ sapi_module.pre_upload_filter = pre_upload_filter;
2631+ return SUCCESS;
2632+}
2633+
2634+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC))
2635+{
2636+ sapi_module.upload_content_filter = upload_content_filter;
2637+ return SUCCESS;
2638+}
2639+
2640+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC))
2641+{
2642+ sapi_module.post_upload_filter = post_upload_filter;
2643+ return SUCCESS;
2644+}
2645+
2646
2647 SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D))
2648 {
2649@@ -835,11 +859,6 @@
2650 return SUCCESS;
2651 }
2652
2653-SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
2654-{
2655- sapi_module.input_filter = input_filter;
2656- return SUCCESS;
2657-}
2658
2659 SAPI_API int sapi_flush(TSRMLS_D)
2660 {
2661diff -Naur php-5.0.4/main/SAPI.h hardening-patch-5.0.4-0.3.2/main/SAPI.h
2662--- php-5.0.4/main/SAPI.h 2004-01-08 18:33:04.000000000 +0100
2663+++ hardening-patch-5.0.4-0.3.2/main/SAPI.h 2005-06-26 23:16:27.000000000 +0200
2664@@ -103,9 +103,10 @@
2665 char *current_user;
2666 int current_user_length;
2667
2668- /* this is necessary for CLI module */
2669- int argc;
2670- char **argv;
2671+ /* this is necessary for CLI module */
2672+ int argc;
2673+ char **argv;
2674+
2675 } sapi_request_info;
2676
2677
2678@@ -183,6 +184,10 @@
2679 SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC));
2680 SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC));
2681
2682+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC));
2683+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC));
2684+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC));
2685+
2686 SAPI_API int sapi_flush(TSRMLS_D);
2687 SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
2688 SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC);
2689@@ -245,6 +250,10 @@
2690 int (*get_target_gid)(gid_t * TSRMLS_DC);
2691
2692 unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
2693+
2694+ unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC);
2695+ unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC);
2696+ unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC);
2697
2698 void (*ini_defaults)(HashTable *configuration_hash);
2699 int phpinfo_as_text;
2700@@ -270,7 +279,11 @@
2701
2702 #define SAPI_DEFAULT_MIMETYPE "text/html"
2703 #define SAPI_DEFAULT_CHARSET ""
2704+#if HARDENING_PATCH
2705+#define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION " with Hardening-Patch"
2706+#else
2707 #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION
2708+#endif
2709
2710 #define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D)
2711 #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC)
2712@@ -278,6 +291,10 @@
2713 #define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC)
2714 #define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
2715
2716+#define SAPI_PRE_UPLOAD_FILTER_FUNC(pre_upload_filter) unsigned int pre_upload_filter(char *varname, char *filename TSRMLS_DC)
2717+#define SAPI_UPLOAD_CONTENT_FILTER_FUNC(upload_content_filter) unsigned int upload_content_filter(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC)
2718+#define SAPI_POST_UPLOAD_FILTER_FUNC(post_upload_filter) unsigned int post_upload_filter(char *tmpfilename TSRMLS_DC)
2719+
2720 BEGIN_EXTERN_C()
2721 SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
2722 SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader);
2723diff -Naur php-5.0.4/main/snprintf.c hardening-patch-5.0.4-0.3.2/main/snprintf.c
2724--- php-5.0.4/main/snprintf.c 2004-11-16 00:14:40.000000000 +0100
2725+++ hardening-patch-5.0.4-0.3.2/main/snprintf.c 2005-06-26 22:07:19.000000000 +0200
2726@@ -1013,7 +1013,11 @@
2727
2728
2729 case 'n':
2730+#if HARDENING_PATCH_FMT_PROTECT
2731+ php_security_log(S_MISC, "'n' specifier within format string");
2732+#else
2733 *(va_arg(ap, int *)) = cc;
2734+#endif
2735 break;
2736
2737 /*
2738diff -Naur php-5.0.4/main/spprintf.c hardening-patch-5.0.4-0.3.2/main/spprintf.c
2739--- php-5.0.4/main/spprintf.c 2004-04-16 01:04:49.000000000 +0200
2740+++ hardening-patch-5.0.4-0.3.2/main/spprintf.c 2005-06-26 22:03:49.000000000 +0200
2741@@ -630,7 +630,11 @@
2742
2743
2744 case 'n':
2745+#if HARDENING_PATCH_FMT_PROTECT
2746+ php_security_log(S_MISC, "'n' specifier within format string");
2747+#else
2748 *(va_arg(ap, int *)) = xbuf->len;
2749+#endif
2750 break;
2751
2752 /*
2753diff -Naur php-5.0.4/pear/go-pear-list.php hardening-patch-5.0.4-0.3.2/pear/go-pear-list.php
2754--- php-5.0.4/pear/go-pear-list.php 2005-03-18 02:59:00.000000000 +0100
2755+++ hardening-patch-5.0.4-0.3.2/pear/go-pear-list.php 2005-07-02 00:15:21.000000000 +0200
2756@@ -8,7 +8,7 @@
2757 $packages = array(
2758 // required packages for the installer
2759 "PEAR" => "1.3.5",
2760-"XML_RPC" => "1.2.2",
2761+"XML_RPC" => "1.3.1",
2762 "Console_Getopt" => "1.2",
2763 "Archive_Tar" => "1.3.1",
2764
2765diff -Naur php-5.0.4/pear/packages/XML_RPC-1.2.2.tar hardening-patch-5.0.4-0.3.2/pear/packages/XML_RPC-1.2.2.tar
2766--- php-5.0.4/pear/packages/XML_RPC-1.2.2.tar 2005-03-28 19:05:50.000000000 +0200
2767+++ hardening-patch-5.0.4-0.3.2/pear/packages/XML_RPC-1.2.2.tar 1970-01-01 01:00:00.000000000 +0100
2768@@ -1,3393 +0,0 @@
2769-package2.xml
2770-<package packagerversion="1.4.0a1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
2771- <name>XML_RPC</name>
2772- <channel>pear.php.net</channel>
2773- <summary>PHP implementation of the XML-RPC protocol</summary>
2774- <description>A PEAR-ified version of Useful Inc&apos;s XML-RPC for PHP.
2775-
2776-It has support for HTTP/HTTPS transport, proxies and authentication.</description>
2777- <lead>
2778- <name>Stig Bakken</name>
2779- <user>ssb</user>
2780- <email>stig@php.net</email>
2781- <active>no</active>
2782- </lead>
2783- <lead>
2784- <name>Daniel Convissor</name>
2785- <user>danielc</user>
2786- <email>danielc@php.net</email>
2787- <active>yes</active>
2788- </lead>
2789- <date>2005-03-07</date>
2790- <time>12:54:49</time>
2791- <version>
2792- <release>1.2.2</release>
2793- <api>1.2.0</api>
2794- </version>
2795- <stability>
2796- <release>stable</release>
2797- <api>stable</api>
2798- </stability>
2799- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2800- <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.</notes>
2801- <contents>
2802- <dir name="/">
2803- <file md5sum="9aca4434f486b517a75c7f2878fb1e9c" name="tests/protoport.php" role="test">
2804- <tasks:replace from="@package_version@" to="version" type="package-info" />
2805- </file>
2806- <file md5sum="49639b76a2296777a1dfa076ae41024a" name="tests/test_Dump.php" role="test">
2807- <tasks:replace from="@package_version@" to="version" type="package-info" />
2808- </file>
2809- <file baseinstalldir="XML/RPC" md5sum="2fb141b1f8927ef27ab0c222f2117d77" name="Dump.php" role="php">
2810- <tasks:replace from="@package_version@" to="version" type="package-info" />
2811- </file>
2812- <file baseinstalldir="XML" md5sum="fbfa3c674175786cc95893cc5192d910" name="RPC.php" role="php">
2813- <tasks:replace from="@package_version@" to="version" type="package-info" />
2814- </file>
2815- <file baseinstalldir="XML/RPC" md5sum="6fc2498def65f09d4ae535fa5f987f62" name="Server.php" role="php">
2816- <tasks:replace from="@package_version@" to="version" type="package-info" />
2817- </file>
2818- </dir>
2819- </contents>
2820- <compatible>
2821- <name>PEAR</name>
2822- <channel>pear.php.net</channel>
2823- <min>1.4.0a1</min>
2824- <max>1.4.0a4</max>
2825- </compatible>
2826- <dependencies>
2827- <required>
2828- <php>
2829- <min>4.2.0</min>
2830- <max>6.0.0</max>
2831- </php>
2832- <pearinstaller>
2833- <min>1.4.0a1</min>
2834- </pearinstaller>
2835- </required>
2836- </dependencies>
2837- <phprelease />
2838- <changelog>
2839- <release>
2840- <version>
2841- <release>1.2.1</release>
2842- <api>1.2.0</api>
2843- </version>
2844- <stability>
2845- <release>stable</release>
2846- <api>stable</api>
2847- </stability>
2848- <date>2005-03-01</date>
2849- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2850- <notes>* Add isset() check before examining the dispatch map. Bug 3658.</notes>
2851- </release>
2852- <release>
2853- <version>
2854- <release>1.2.0</release>
2855- <api>1.2.0</api>
2856- </version>
2857- <stability>
2858- <release>stable</release>
2859- <api>stable</api>
2860- </stability>
2861- <date>2005-02-27</date>
2862- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2863- <notes>* Provide the &quot;stable&quot; release.
2864-* Add package2.xml for compatibility with PEAR 1.4.0.
2865-* For changes since 1.1.0, see the changelogs for the various RC releases.</notes>
2866- </release>
2867- <release>
2868- <version>
2869- <release>1.2.0RC7</release>
2870- <api>1.2.0RC7</api>
2871- </version>
2872- <stability>
2873- <release>beta</release>
2874- <api>beta</api>
2875- </stability>
2876- <date>2005-02-22</date>
2877- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2878- <notes>* Add the setSendEncoding() method and $send_encoding
2879- property to XML_RPC_Message. Request 3537.
2880-* Allow class methods to be mapped using either syntax:
2881- &apos;function&apos; =&gt; &apos;hello::sayHello&apos;,
2882- or
2883- &apos;function&apos; =&gt; array(&apos;hello&apos;, &apos;sayhello&apos;),
2884- Bug 3363.
2885-* Use 8192 instead of 32768 for bytes in fread()
2886- in parseResponseFile(). Bug 3340.</notes>
2887- </release>
2888- <release>
2889- <version>
2890- <release>1.2.0RC6</release>
2891- <api>1.2.0RC6</api>
2892- </version>
2893- <stability>
2894- <release>beta</release>
2895- <api>beta</api>
2896- </stability>
2897- <date>2005-01-25</date>
2898- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2899- <notes>* Don&apos;t put the protocol in the Host field of the POST data. (danielc)</notes>
2900- </release>
2901- <release>
2902- <version>
2903- <release>1.2.0RC5</release>
2904- <api>1.2.0RC5</api>
2905- </version>
2906- <stability>
2907- <release>beta</release>
2908- <api>beta</api>
2909- </stability>
2910- <date>2005-01-24</date>
2911- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2912- <notes>* If $port is 443 but a protocol isn&apos;t specified in $server, assume ssl:// is the protocol.</notes>
2913- </release>
2914- <release>
2915- <version>
2916- <release>1.2.0RC4</release>
2917- <api>1.2.0RC4</api>
2918- </version>
2919- <stability>
2920- <release>beta</release>
2921- <api>beta</api>
2922- </stability>
2923- <date>2005-01-24</date>
2924- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2925- <notes>* When a connection attempt fails, have the method return 0. (danielc)
2926-* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
2927-* Add tests for setting the client properties. (danielc)
2928-* Remove $GLOBALS[&apos;XML_RPC_twoslash&apos;] since it&apos;s not used. (danielc)
2929-* Bundle the tests with the package. (danielc)</notes>
2930- </release>
2931- <release>
2932- <version>
2933- <release>1.2.0RC3</release>
2934- <api>1.2.0RC3</api>
2935- </version>
2936- <stability>
2937- <release>beta</release>
2938- <api>beta</api>
2939- </stability>
2940- <date>2005-01-19</date>
2941- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2942- <notes>* ssl uses port 443, not 445.</notes>
2943- </release>
2944- <release>
2945- <version>
2946- <release>1.2.0RC2</release>
2947- <api>1.2.0RC2</api>
2948- </version>
2949- <stability>
2950- <release>beta</release>
2951- <api>beta</api>
2952- </stability>
2953- <date>2005-01-11</date>
2954- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2955- <notes>* Handle ssl:// in the $server string. (danielc)
2956-* Also default to port 445 for ssl:// requests as well. (danielc)
2957-* Enhance debugging in the server. (danielc)</notes>
2958- </release>
2959- <release>
2960- <version>
2961- <release>1.2.0RC1</release>
2962- <api>1.2.0RC1</api>
2963- </version>
2964- <stability>
2965- <release>beta</release>
2966- <api>beta</api>
2967- </stability>
2968- <date>2004-12-30</date>
2969- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2970- <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
2971-* Allow array function callbacks (Matt Kane)
2972-* Some minor speed-ups (Matt Kane)
2973-* Add Dump.php to the package (Christian Weiske)
2974-* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
2975-* Silence fsockopen() errors. Bug 1714. (danielc)
2976-* Encode empty arrays as an array. Bug 1493. (danielc)
2977-* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
2978-* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
2979-* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()&apos;ing error messages. (danielc)
2980-* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
2981-* Allow raiseError() to be called statically. (danielc)
2982-* Stop double escaping of character entities. Bug 987. (danielc)
2983- NOTICE: the following have been removed:
2984- * XML_RPC_dh()
2985- * $GLOBALS[&apos;XML_RPC_entities&apos;]
2986- * XML_RPC_entity_decode()
2987- * XML_RPC_lookup_entity()
2988-* Determine the XML&apos;s encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)</notes>
2989- </release>
2990- <release>
2991- <version>
2992- <release>1.1.0</release>
2993- <api>1.1.0</api>
2994- </version>
2995- <stability>
2996- <release>stable</release>
2997- <api>stable</api>
2998- </stability>
2999- <date>2004-03-15</date>
3000- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3001- <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
3002-* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
3003-* Remove &quot;require_once &apos;PEAR.php&apos;&quot;, include only when needed to raise an error
3004-* Replace echo and error_log() with raiseError() (mroch)
3005-* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
3006-* be tolerant of junk after methodResponse (Luca Mariano, mroch)
3007-* Silent notice even in the error log (pierre)
3008-* fix include of shared xml extension on win32 (pierre)</notes>
3009- </release>
3010- <release>
3011- <version>
3012- <release>1.0.4</release>
3013- <api>1.0.4</api>
3014- </version>
3015- <stability>
3016- <release>stable</release>
3017- <api>stable</api>
3018- </stability>
3019- <date>2002-10-02</date>
3020- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3021- <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)</notes>
3022- </release>
3023- <release>
3024- <version>
3025- <release>1.0.3</release>
3026- <api>1.0.3</api>
3027- </version>
3028- <stability>
3029- <release>stable</release>
3030- <api>stable</api>
3031- </stability>
3032- <date>2002-05-19</date>
3033- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3034- <notes>* fix bug when parsing responses with boolean types</notes>
3035- </release>
3036- <release>
3037- <version>
3038- <release>1.0.2</release>
3039- <api>1.0.2</api>
3040- </version>
3041- <stability>
3042- <release>stable</release>
3043- <api>stable</api>
3044- </stability>
3045- <date>2002-04-16</date>
3046- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3047- <notes>* E_ALL fixes
3048-* fix HTTP response header parsing</notes>
3049- </release>
3050- <release>
3051- <version>
3052- <release>1.0.1</release>
3053- <api>1.0.1</api>
3054- </version>
3055- <stability>
3056- <release>stable</release>
3057- <api>stable</api>
3058- </stability>
3059- <date>2001-09-25</date>
3060- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3061- <notes>This is a PEAR-ified version of Useful Inc&apos;s 1.0.1 release.
3062-Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.</notes>
3063- </release>
3064- </changelog>
3065-</package>
3066-
3067-/**
3068- * Tests that properties of XML_RPC_Client get properly set
3069- *
3070- * Any individual tests that fail will have their name, expected result
3071- * and actual result printed out. So seeing no output when executing
3072- * this file is a good thing.
3073- *
3074- * Can be run via CLI or a web server.
3075- *
3076- * PHP versions 4 and 5
3077- *
3078- * LICENSE: This source file is subject to version 3.0 of the PHP license
3079- * that is available through the world-wide-web at the following URI:
3080- * http://www.php.net/license/3_0.txt. If you did not receive a copy of
3081- * the PHP License and are unable to obtain it through the web, please
3082- * send a note to license@php.net so we can mail you a copy immediately.
3083- *
3084- * @category Web Services
3085- * @package XML_RPC
3086- * @author Daniel Convissor <danielc@php.net>
3087- * @copyright 2005 The PHP Group
3088- * @license http://www.php.net/license/3_0.txt PHP License
3089- * @version CVS: $Id: protoport.php,v 1.4 2005/01/24 17:48:47 danielc Exp $
3090- * @link http://pear.php.net/package/XML_RPC
3091- * @since File available since Release 1.2
3092- */
3093-
3094-/*
3095- * If the package version number is found in the left hand
3096- * portion of the if() expression below, that means this file has
3097- * come from the PEAR installer. Therefore, let's test the
3098- * installed version of XML_RPC which should be in the include path.
3099- *
3100- * If the version has not been substituted in the if() expression,
3101- * this file has likely come from a CVS checkout or a .tar file.
3102- * Therefore, we'll assume the tests should use the version of
3103- * XML_RPC that has come from there as well.
3104- */
3105-if ('1.2.2' != '@'.'package_version'.'@') {
3106- /**
3107- * Get the needed class from the PEAR installation
3108- */
3109- require_once 'XML/RPC.php';
3110-} else {
3111- /**
3112- * Get the needed class from the parent directory
3113- */
3114- require_once '../RPC.php';
3115-}
3116-
3117-/**
3118- * Compare the test result to the expected result
3119- *
3120- * If the test fails, echo out the results.
3121- *
3122- * @param array $expect the array of object properties you expect
3123- * from the test
3124- * @param object $actual the object results from the test
3125- * @param string $test_name the name of the test
3126- *
3127- * @return void
3128- */
3129-function compare($expect, $actual, $test_name) {
3130- $actual = get_object_vars($actual);
3131- if (count(array_diff($actual, $expect))) {
3132- echo "$test_name failed.\nExpect: ";
3133- print_r($expect);
3134- echo "Actual: ";
3135- print_r($actual);
3136- echo "\n";
3137- }
3138-}
3139-
3140-if (php_sapi_name() != 'cli') {
3141- echo "<pre>\n";
3142-}
3143-
3144-
3145-$x = array(
3146- 'path' => 'thepath',
3147- 'server' => 'theserver',
3148- 'protocol' => 'http://',
3149- 'port' => 80,
3150- 'proxy' => '',
3151- 'proxy_protocol' => 'http://',
3152- 'proxy_port' => 8080,
3153- 'proxy_user' => '',
3154- 'proxy_pass' => '',
3155- 'errno' => 0,
3156- 'errstring' => '',
3157- 'debug' => 0,
3158- 'username' => '',
3159- 'password' => '',
3160-);
3161-$c = new XML_RPC_Client('thepath', 'theserver');
3162-compare($x, $c, 'defaults');
3163-
3164-$x = array(
3165- 'path' => 'thepath',
3166- 'server' => 'theserver',
3167- 'protocol' => 'http://',
3168- 'port' => 80,
3169- 'proxy' => '',
3170- 'proxy_protocol' => 'http://',
3171- 'proxy_port' => 8080,
3172- 'proxy_user' => '',
3173- 'proxy_pass' => '',
3174- 'errno' => 0,
3175- 'errstring' => '',
3176- 'debug' => 0,
3177- 'username' => '',
3178- 'password' => '',
3179-);
3180-$c = new XML_RPC_Client('thepath', 'http://theserver');
3181-compare($x, $c, 'defaults with http');
3182-
3183-$x = array(
3184- 'path' => 'thepath',
3185- 'server' => 'theserver',
3186- 'protocol' => 'ssl://',
3187- 'port' => 443,
3188- 'proxy' => '',
3189- 'proxy_protocol' => 'http://',
3190- 'proxy_port' => 8080,
3191- 'proxy_user' => '',
3192- 'proxy_pass' => '',
3193- 'errno' => 0,
3194- 'errstring' => '',
3195- 'debug' => 0,
3196- 'username' => '',
3197- 'password' => '',
3198-);
3199-$c = new XML_RPC_Client('thepath', 'https://theserver');
3200-compare($x, $c, 'defaults with https');
3201-
3202-$x = array(
3203- 'path' => 'thepath',
3204- 'server' => 'theserver',
3205- 'protocol' => 'ssl://',
3206- 'port' => 443,
3207- 'proxy' => '',
3208- 'proxy_protocol' => 'http://',
3209- 'proxy_port' => 8080,
3210- 'proxy_user' => '',
3211- 'proxy_pass' => '',
3212- 'errno' => 0,
3213- 'errstring' => '',
3214- 'debug' => 0,
3215- 'username' => '',
3216- 'password' => '',
3217-);
3218-$c = new XML_RPC_Client('thepath', 'ssl://theserver');
3219-compare($x, $c, 'defaults with ssl');
3220-
3221-
3222-$x = array(
3223- 'path' => 'thepath',
3224- 'server' => 'theserver',
3225- 'protocol' => 'http://',
3226- 'port' => 65,
3227- 'proxy' => '',
3228- 'proxy_protocol' => 'http://',
3229- 'proxy_port' => 8080,
3230- 'proxy_user' => '',
3231- 'proxy_pass' => '',
3232- 'errno' => 0,
3233- 'errstring' => '',
3234- 'debug' => 0,
3235- 'username' => '',
3236- 'password' => '',
3237-);
3238-$c = new XML_RPC_Client('thepath', 'theserver', 65);
3239-compare($x, $c, 'port 65');
3240-
3241-$x = array(
3242- 'path' => 'thepath',
3243- 'server' => 'theserver',
3244- 'protocol' => 'http://',
3245- 'port' => 65,
3246- 'proxy' => '',
3247- 'proxy_protocol' => 'http://',
3248- 'proxy_port' => 8080,
3249- 'proxy_user' => '',
3250- 'proxy_pass' => '',
3251- 'errno' => 0,
3252- 'errstring' => '',
3253- 'debug' => 0,
3254- 'username' => '',
3255- 'password' => '',
3256-);
3257-$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
3258-compare($x, $c, 'port 65 with http');
3259-
3260-$x = array(
3261- 'path' => 'thepath',
3262- 'server' => 'theserver',
3263- 'protocol' => 'ssl://',
3264- 'port' => 65,
3265- 'proxy' => '',
3266- 'proxy_protocol' => 'http://',
3267- 'proxy_port' => 8080,
3268- 'proxy_user' => '',
3269- 'proxy_pass' => '',
3270- 'errno' => 0,
3271- 'errstring' => '',
3272- 'debug' => 0,
3273- 'username' => '',
3274- 'password' => '',
3275-);
3276-$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
3277-compare($x, $c, 'port 65 with https');
3278-
3279-$x = array(
3280- 'path' => 'thepath',
3281- 'server' => 'theserver',
3282- 'protocol' => 'ssl://',
3283- 'port' => 65,
3284- 'proxy' => '',
3285- 'proxy_protocol' => 'http://',
3286- 'proxy_port' => 8080,
3287- 'proxy_user' => '',
3288- 'proxy_pass' => '',
3289- 'errno' => 0,
3290- 'errstring' => '',
3291- 'debug' => 0,
3292- 'username' => '',
3293- 'password' => '',
3294-);
3295-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
3296-compare($x, $c, 'port 65 with ssl');
3297-
3298-
3299-$x = array(
3300- 'path' => 'thepath',
3301- 'server' => 'theserver',
3302- 'protocol' => 'http://',
3303- 'port' => 80,
3304- 'proxy' => 'theproxy',
3305- 'proxy_protocol' => 'http://',
3306- 'proxy_port' => 8080,
3307- 'proxy_user' => '',
3308- 'proxy_pass' => '',
3309- 'errno' => 0,
3310- 'errstring' => '',
3311- 'debug' => 0,
3312- 'username' => '',
3313- 'password' => '',
3314-);
3315-$c = new XML_RPC_Client('thepath', 'theserver', 0,
3316- 'theproxy');
3317-compare($x, $c, 'defaults proxy');
3318-
3319-$x = array(
3320- 'path' => 'thepath',
3321- 'server' => 'theserver',
3322- 'protocol' => 'http://',
3323- 'port' => 80,
3324- 'proxy' => 'theproxy',
3325- 'proxy_protocol' => 'http://',
3326- 'proxy_port' => 8080,
3327- 'proxy_user' => '',
3328- 'proxy_pass' => '',
3329- 'errno' => 0,
3330- 'errstring' => '',
3331- 'debug' => 0,
3332- 'username' => '',
3333- 'password' => '',
3334-);
3335-$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
3336- 'http://theproxy');
3337-compare($x, $c, 'defaults with http proxy');
3338-
3339-$x = array(
3340- 'path' => 'thepath',
3341- 'server' => 'theserver',
3342- 'protocol' => 'ssl://',
3343- 'port' => 443,
3344- 'proxy' => 'theproxy',
3345- 'proxy_protocol' => 'ssl://',
3346- 'proxy_port' => 443,
3347- 'proxy_user' => '',
3348- 'proxy_pass' => '',
3349- 'errno' => 0,
3350- 'errstring' => '',
3351- 'debug' => 0,
3352- 'username' => '',
3353- 'password' => '',
3354-);
3355-$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
3356- 'https://theproxy');
3357-compare($x, $c, 'defaults with https proxy');
3358-
3359-$x = array(
3360- 'path' => 'thepath',
3361- 'server' => 'theserver',
3362- 'protocol' => 'ssl://',
3363- 'port' => 443,
3364- 'proxy' => 'theproxy',
3365- 'proxy_protocol' => 'ssl://',
3366- 'proxy_port' => 443,
3367- 'proxy_user' => '',
3368- 'proxy_pass' => '',
3369- 'errno' => 0,
3370- 'errstring' => '',
3371- 'debug' => 0,
3372- 'username' => '',
3373- 'password' => '',
3374-);
3375-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
3376- 'ssl://theproxy');
3377-compare($x, $c, 'defaults with ssl proxy');
3378-
3379-
3380-$x = array(
3381- 'path' => 'thepath',
3382- 'server' => 'theserver',
3383- 'protocol' => 'http://',
3384- 'port' => 65,
3385- 'proxy' => 'theproxy',
3386- 'proxy_protocol' => 'http://',
3387- 'proxy_port' => 6565,
3388- 'proxy_user' => '',
3389- 'proxy_pass' => '',
3390- 'errno' => 0,
3391- 'errstring' => '',
3392- 'debug' => 0,
3393- 'username' => '',
3394- 'password' => '',
3395-);
3396-$c = new XML_RPC_Client('thepath', 'theserver', 65,
3397- 'theproxy', 6565);
3398-compare($x, $c, 'port 65 proxy 6565');
3399-
3400-$x = array(
3401- 'path' => 'thepath',
3402- 'server' => 'theserver',
3403- 'protocol' => 'http://',
3404- 'port' => 65,
3405- 'proxy' => 'theproxy',
3406- 'proxy_protocol' => 'http://',
3407- 'proxy_port' => 6565,
3408- 'proxy_user' => '',
3409- 'proxy_pass' => '',
3410- 'errno' => 0,
3411- 'errstring' => '',
3412- 'debug' => 0,
3413- 'username' => '',
3414- 'password' => '',
3415-);
3416-$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
3417- 'http://theproxy', 6565);
3418-compare($x, $c, 'port 65 with http proxy 6565');
3419-
3420-$x = array(
3421- 'path' => 'thepath',
3422- 'server' => 'theserver',
3423- 'protocol' => 'ssl://',
3424- 'port' => 65,
3425- 'proxy' => 'theproxy',
3426- 'proxy_protocol' => 'ssl://',
3427- 'proxy_port' => 6565,
3428- 'proxy_user' => '',
3429- 'proxy_pass' => '',
3430- 'errno' => 0,
3431- 'errstring' => '',
3432- 'debug' => 0,
3433- 'username' => '',
3434- 'password' => '',
3435-);
3436-$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
3437- 'https://theproxy', 6565);
3438-compare($x, $c, 'port 65 with https proxy 6565');
3439-
3440-$x = array(
3441- 'path' => 'thepath',
3442- 'server' => 'theserver',
3443- 'protocol' => 'ssl://',
3444- 'port' => 65,
3445- 'proxy' => 'theproxy',
3446- 'proxy_protocol' => 'ssl://',
3447- 'proxy_port' => 6565,
3448- 'proxy_user' => '',
3449- 'proxy_pass' => '',
3450- 'errno' => 0,
3451- 'errstring' => '',
3452- 'debug' => 0,
3453- 'username' => '',
3454- 'password' => '',
3455-);
3456-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
3457- 'ssl://theproxy', 6565);
3458-compare($x, $c, 'port 65 with ssl proxy 6565');
3459-
3460-
3461-$x = array(
3462- 'path' => 'thepath',
3463- 'server' => 'theserver',
3464- 'protocol' => 'ssl://',
3465- 'port' => 443,
3466- 'proxy' => 'theproxy',
3467- 'proxy_protocol' => 'ssl://',
3468- 'proxy_port' => 443,
3469- 'proxy_user' => '',
3470- 'proxy_pass' => '',
3471- 'errno' => 0,
3472- 'errstring' => '',
3473- 'debug' => 0,
3474- 'username' => '',
3475- 'password' => '',
3476-);
3477-$c = new XML_RPC_Client('thepath', 'theserver', 443,
3478- 'theproxy', 443);
3479-compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
3480-
3481-$x = array(
3482- 'path' => 'thepath',
3483- 'server' => 'theserver',
3484- 'protocol' => 'http://',
3485- 'port' => 80,
3486- 'proxy' => 'theproxy',
3487- 'proxy_protocol' => 'ssl://',
3488- 'proxy_port' => 6565,
3489- 'proxy_user' => '',
3490- 'proxy_pass' => '',
3491- 'errno' => 0,
3492- 'errstring' => '',
3493- 'debug' => 0,
3494- 'username' => '',
3495- 'password' => '',
3496-);
3497-$c = new XML_RPC_Client('thepath', 'theserver', 0,
3498- 'ssl://theproxy', 6565);
3499-compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
3500-
3501-
3502-/*
3503- * If the package version number is found in the left hand
3504- * portion of the if() expression below, that means this file has
3505- * come from the PEAR installer. Therefore, let's test the
3506- * installed version of XML_RPC which should be in the include path.
3507- *
3508- * If the version has not been substituted in the if() expression,
3509- * this file has likely come from a CVS checkout or a .tar file.
3510- * Therefore, we'll assume the tests should use the version of
3511- * XML_RPC that has come from there as well.
3512- */
3513-if ('1.2.2' != '@'.'package_version'.'@') {
3514- /**
3515- * Get the needed class from the PEAR installation
3516- */
3517- require_once 'XML/RPC/Dump.php';
3518-} else {
3519- /**
3520- * Get the needed class from the parent directory
3521- */
3522- require_once '../Dump.php';
3523-}
3524-
3525-$val = new XML_RPC_Value(array(
3526- 'title' =>new XML_RPC_Value('das ist der Titel', 'string'),
3527- 'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
3528- 'endDate' =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
3529- 'error' =>'string',
3530- 'arkey' => new XML_RPC_Value( array(
3531- new XML_RPC_Value('simple string'),
3532- new XML_RPC_Value(12345, 'int')
3533- ), 'array')
3534- )
3535- ,'struct');
3536-
3537-XML_RPC_Dump($val);
3538-
3539-echo '==============' . "\r\n";
3540-$val2 = new XML_RPC_Value(44353, 'int');
3541-XML_RPC_Dump($val2);
3542-
3543-echo '==============' . "\r\n";
3544-$val3 = new XML_RPC_Value('this should be a string', 'string');
3545-XML_RPC_Dump($val3);
3546-
3547-echo '==============' . "\r\n";
3548-$val4 = new XML_RPC_Value(true, 'boolean');
3549-XML_RPC_Dump($val4);
3550-
3551-
3552-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3553-
3554-/**
3555- * Function and class to dump XML_RPC_Value objects in a nice way
3556- *
3557- * Should be helpful as a normal var_dump(..) displays all internals which
3558- * doesn't really give you an overview due to too much information.
3559- *
3560- * @category Web Services
3561- * @package XML_RPC
3562- * @author Christian Weiske <cweiske@php.net>
3563- * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $
3564- * @link http://pear.php.net/package/XML_RPC
3565- */
3566-
3567-
3568-/**
3569- * Pull in the XML_RPC class
3570- */
3571-require_once 'XML/RPC.php';
3572-
3573-
3574-/**
3575- * Generates the dump of the XML_RPC_Value and echoes it
3576- *
3577- * @param object $value the XML_RPC_Value object to dump
3578- *
3579- * @return void
3580- */
3581-function XML_RPC_Dump($value)
3582-{
3583- $dumper = new XML_RPC_Dump();
3584- echo $dumper->generateDump($value);
3585-}
3586-
3587-
3588-/**
3589- * Class which generates a dump of a XML_RPC_Value object
3590- *
3591- * @category Web Services
3592- * @package XML_RPC
3593- * @author Christian Weiske <cweiske@php.net>
3594- * @version Release: 1.2.2
3595- * @link http://pear.php.net/package/XML_RPC
3596- */
3597-class XML_RPC_Dump
3598-{
3599- /**
3600- * The indentation array cache
3601- * @var array
3602- */
3603- var $arIndent = array();
3604-
3605- /**
3606- * The spaces used for indenting the XML
3607- * @var string
3608- */
3609- var $strBaseIndent = ' ';
3610-
3611- /**
3612- * Returns the dump in XML format without printing it out
3613- *
3614- * @param object $value the XML_RPC_Value object to dump
3615- * @param int $nLevel the level of indentation
3616- *
3617- * @return string the dump
3618- */
3619- function generateDump($value, $nLevel = 0)
3620- {
3621- if (!is_object($value) && get_class($value) != 'xml_rpc_value') {
3622- require_once 'PEAR.php';
3623- PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n",
3624- 0, PEAR_ERROR_PRINT);
3625- if (is_object($value)) {
3626- $strType = get_class($value);
3627- } else {
3628- $strType = gettype($value);
3629- }
3630- return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: '
3631- . $strType . "\r\n";
3632- }
3633-
3634- switch ($value->kindOf()) {
3635- case 'struct':
3636- $ret = $this->genStruct($value, $nLevel);
3637- break;
3638- case 'array':
3639- $ret = $this->genArray($value, $nLevel);
3640- break;
3641- case 'scalar':
3642- $ret = $this->genScalar($value->scalarval(), $nLevel);
3643- break;
3644- default:
3645- require_once 'PEAR.php';
3646- PEAR::raiseError('Illegal type "' . $value->kindOf()
3647- . '" in XML_RPC_Value' . "\r\n", 0,
3648- PEAR_ERROR_PRINT);
3649- }
3650-
3651- return $ret;
3652- }
3653-
3654- /**
3655- * Returns the scalar value dump
3656- *
3657- * @param object $value the scalar XML_RPC_Value object to dump
3658- * @param int $nLevel the level of indentation
3659- *
3660- * @return string Dumped version of the scalar value
3661- */
3662- function genScalar($value, $nLevel)
3663- {
3664- if (gettype($value) == 'object') {
3665- $strClass = ' ' . get_class($value);
3666- } else {
3667- $strClass = '';
3668- }
3669- return $this->getIndent($nLevel) . gettype($value) . $strClass
3670- . ' ' . $value . "\r\n";
3671- }
3672-
3673- /**
3674- * Returns the dump of a struct
3675- *
3676- * @param object $value the struct XML_RPC_Value object to dump
3677- * @param int $nLevel the level of indentation
3678- *
3679- * @return string Dumped version of the scalar value
3680- */
3681- function genStruct($value, $nLevel)
3682- {
3683- $value->structreset();
3684- $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n";
3685- while (list($key, $keyval) = $value->structeach()) {
3686- $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n";
3687- $strOutput .= $this->generateDump($keyval, $nLevel + 2);
3688- }
3689- return $strOutput;
3690- }
3691-
3692- /**
3693- * Returns the dump of an array
3694- *
3695- * @param object $value the array XML_RPC_Value object to dump
3696- * @param int $nLevel the level of indentation
3697- *
3698- * @return string Dumped version of the scalar value
3699- */
3700- function genArray($value, $nLevel)
3701- {
3702- $nSize = $value->arraysize();
3703- $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n";
3704- for($nA = 0; $nA < $nSize; $nA++) {
3705- $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n";
3706- $strOutput .= $this->generateDump($value->arraymem($nA),
3707- $nLevel + 2);
3708- }
3709- return $strOutput;
3710- }
3711-
3712- /**
3713- * Returns the indent for a specific level and caches it for faster use
3714- *
3715- * @param int $nLevel the level
3716- *
3717- * @return string the indented string
3718- */
3719- function getIndent($nLevel)
3720- {
3721- if (!isset($this->arIndent[$nLevel])) {
3722- $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel);
3723- }
3724- return $this->arIndent[$nLevel];
3725- }
3726-}
3727-
3728-/*
3729- * Local variables:
3730- * tab-width: 4
3731- * c-basic-offset: 4
3732- * c-hanging-comment-ender-p: nil
3733- * End:
3734- */
3735-
3736-?>
3737-
3738-
3739-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3740-
3741-/**
3742- * PHP implementation of the XML-RPC protocol
3743- *
3744- * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
3745- * It has support for HTTP transport, proxies and authentication.
3746- *
3747- * PHP versions 4 and 5
3748- *
3749- * LICENSE: License is granted to use or modify this software
3750- * ("XML-RPC for PHP") for commercial or non-commercial use provided the
3751- * copyright of the author is preserved in any distributed or derivative work.
3752- *
3753- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
3754- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3755- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3756- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3757- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3758- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3759- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3760- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3761- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3762- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3763- *
3764- * @category Web Services
3765- * @package XML_RPC
3766- * @author Edd Dumbill <edd@usefulinc.com>
3767- * @author Stig Bakken <stig@php.net>
3768- * @author Martin Jansen <mj@php.net>
3769- * @author Daniel Convissor <danielc@php.net>
3770- * @copyright 1999-2001 Edd Dumbill
3771- * @version CVS: $Id: RPC.php,v 1.60 2005/03/07 17:45:08 danielc Exp $
3772- * @link http://pear.php.net/package/XML_RPC
3773- */
3774-
3775-
3776-if (!function_exists('xml_parser_create')) {
3777- // Win 32 fix. From: "Leo West" <lwest@imaginet.fr>
3778- if ($WINDIR) {
3779- dl('php_xml.dll');
3780- } else {
3781- dl('xml.so');
3782- }
3783-}
3784-
3785-/**#@+
3786- * Error constants
3787- */
3788-define('XML_RPC_ERROR_INVALID_TYPE', 101);
3789-define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
3790-define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
3791-define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
3792-/**#@-*/
3793-
3794-
3795-/**
3796- * Data types
3797- * @global string $GLOBALS['XML_RPC_I4']
3798- */
3799-$GLOBALS['XML_RPC_I4'] = 'i4';
3800-
3801-/**
3802- * Data types
3803- * @global string $GLOBALS['XML_RPC_Int']
3804- */
3805-$GLOBALS['XML_RPC_Int'] = 'int';
3806-
3807-/**
3808- * Data types
3809- * @global string $GLOBALS['XML_RPC_Boolean']
3810- */
3811-$GLOBALS['XML_RPC_Boolean'] = 'boolean';
3812-
3813-/**
3814- * Data types
3815- * @global string $GLOBALS['XML_RPC_Double']
3816- */
3817-$GLOBALS['XML_RPC_Double'] = 'double';
3818-
3819-/**
3820- * Data types
3821- * @global string $GLOBALS['XML_RPC_String']
3822- */
3823-$GLOBALS['XML_RPC_String'] = 'string';
3824-
3825-/**
3826- * Data types
3827- * @global string $GLOBALS['XML_RPC_DateTime']
3828- */
3829-$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601';
3830-
3831-/**
3832- * Data types
3833- * @global string $GLOBALS['XML_RPC_Base64']
3834- */
3835-$GLOBALS['XML_RPC_Base64'] = 'base64';
3836-
3837-/**
3838- * Data types
3839- * @global string $GLOBALS['XML_RPC_Array']
3840- */
3841-$GLOBALS['XML_RPC_Array'] = 'array';
3842-
3843-/**
3844- * Data types
3845- * @global string $GLOBALS['XML_RPC_Struct']
3846- */
3847-$GLOBALS['XML_RPC_Struct'] = 'struct';
3848-
3849-
3850-/**
3851- * Data type meta-types
3852- * @global array $GLOBALS['XML_RPC_Types']
3853- */
3854-$GLOBALS['XML_RPC_Types'] = array(
3855- $GLOBALS['XML_RPC_I4'] => 1,
3856- $GLOBALS['XML_RPC_Int'] => 1,
3857- $GLOBALS['XML_RPC_Boolean'] => 1,
3858- $GLOBALS['XML_RPC_String'] => 1,
3859- $GLOBALS['XML_RPC_Double'] => 1,
3860- $GLOBALS['XML_RPC_DateTime'] => 1,
3861- $GLOBALS['XML_RPC_Base64'] => 1,
3862- $GLOBALS['XML_RPC_Array'] => 2,
3863- $GLOBALS['XML_RPC_Struct'] => 3,
3864-);
3865-
3866-
3867-/**
3868- * Error message numbers
3869- * @global array $GLOBALS['XML_RPC_err']
3870- */
3871-$GLOBALS['XML_RPC_err'] = array(
3872- 'unknown_method' => 1,
3873- 'invalid_return' => 2,
3874- 'incorrect_params' => 3,
3875- 'introspect_unknown' => 4,
3876- 'http_error' => 5,
3877-);
3878-
3879-/**
3880- * Error message strings
3881- * @global array $GLOBALS['XML_RPC_str']
3882- */
3883-$GLOBALS['XML_RPC_str'] = array(
3884- 'unknown_method' => 'Unknown method',
3885- 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload',
3886- 'incorrect_params' => 'Incorrect parameters passed to method',
3887- 'introspect_unknown' => 'Can\'t introspect: method unknown',
3888- 'http_error' => 'Didn\'t receive 200 OK from remote server.',
3889-);
3890-
3891-
3892-/**
3893- * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII)
3894- * @global string $GLOBALS['XML_RPC_defencoding']
3895- */
3896-$GLOBALS['XML_RPC_defencoding'] = 'UTF-8';
3897-
3898-/**
3899- * User error codes start at 800
3900- * @global int $GLOBALS['XML_RPC_erruser']
3901- */
3902-$GLOBALS['XML_RPC_erruser'] = 800;
3903-
3904-/**
3905- * XML parse error codes start at 100
3906- * @global int $GLOBALS['XML_RPC_errxml']
3907- */
3908-$GLOBALS['XML_RPC_errxml'] = 100;
3909-
3910-
3911-/**
3912- * Compose backslashes for escaping regexp
3913- * @global string $GLOBALS['XML_RPC_backslash']
3914- */
3915-$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92);
3916-
3917-
3918-/**
3919- * Stores state during parsing
3920- *
3921- * quick explanation of components:
3922- * + st = builds up a string for evaluation
3923- * + ac = accumulates values
3924- * + qt = decides if quotes are needed for evaluation
3925- * + cm = denotes struct or array (comma needed)
3926- * + isf = indicates a fault
3927- * + lv = indicates "looking for a value": implements the logic
3928- * to allow values with no types to be strings
3929- * + params = stores parameters in method calls
3930- * + method = stores method name
3931- *
3932- * @global array $GLOBALS['XML_RPC_xh']
3933- */
3934-$GLOBALS['XML_RPC_xh'] = array();
3935-
3936-
3937-/**
3938- * Start element handler for the XML parser
3939- *
3940- * @return void
3941- */
3942-function XML_RPC_se($parser, $name, $attrs)
3943-{
3944- global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String;
3945-
3946- switch ($name) {
3947- case 'STRUCT':
3948- case 'ARRAY':
3949- $XML_RPC_xh[$parser]['st'] .= 'array(';
3950- $XML_RPC_xh[$parser]['cm']++;
3951- // this last line turns quoting off
3952- // this means if we get an empty array we'll
3953- // simply get a bit of whitespace in the eval
3954- $XML_RPC_xh[$parser]['qt'] = 0;
3955- break;
3956-
3957- case 'NAME':
3958- $XML_RPC_xh[$parser]['st'] .= "'";
3959- $XML_RPC_xh[$parser]['ac'] = '';
3960- break;
3961-
3962- case 'FAULT':
3963- $XML_RPC_xh[$parser]['isf'] = 1;
3964- break;
3965-
3966- case 'PARAM':
3967- $XML_RPC_xh[$parser]['st'] = '';
3968- break;
3969-
3970- case 'VALUE':
3971- $XML_RPC_xh[$parser]['st'] .= 'new XML_RPC_Value(';
3972- $XML_RPC_xh[$parser]['lv'] = 1;
3973- $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String;
3974- $XML_RPC_xh[$parser]['ac'] = '';
3975- $XML_RPC_xh[$parser]['qt'] = 0;
3976- // look for a value: if this is still 1 by the
3977- // time we reach the first data segment then the type is string
3978- // by implication and we need to add in a quote
3979- break;
3980-
3981- case 'I4':
3982- case 'INT':
3983- case 'STRING':
3984- case 'BOOLEAN':
3985- case 'DOUBLE':
3986- case 'DATETIME.ISO8601':
3987- case 'BASE64':
3988- $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator
3989-
3990- if ($name == 'DATETIME.ISO8601' || $name == 'STRING') {
3991- $XML_RPC_xh[$parser]['qt'] = 1;
3992-
3993- if ($name == 'DATETIME.ISO8601') {
3994- $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime;
3995- }
3996-
3997- } elseif ($name == 'BASE64') {
3998- $XML_RPC_xh[$parser]['qt'] = 2;
3999- } else {
4000- // No quoting is required here -- but
4001- // at the end of the element we must check
4002- // for data format errors.
4003- $XML_RPC_xh[$parser]['qt'] = 0;
4004- }
4005- break;
4006-
4007- case 'MEMBER':
4008- $XML_RPC_xh[$parser]['ac'] = '';
4009- }
4010-
4011- if ($name != 'VALUE') {
4012- $XML_RPC_xh[$parser]['lv'] = 0;
4013- }
4014-}
4015-
4016-/**
4017- * End element handler for the XML parser
4018- *
4019- * @return void
4020- */
4021-function XML_RPC_ee($parser, $name)
4022-{
4023- global $XML_RPC_xh, $XML_RPC_Types, $XML_RPC_String;
4024-
4025- switch ($name) {
4026- case 'STRUCT':
4027- case 'ARRAY':
4028- if ($XML_RPC_xh[$parser]['cm']
4029- && substr($XML_RPC_xh[$parser]['st'], -1) == ',')
4030- {
4031- $XML_RPC_xh[$parser]['st'] = substr($XML_RPC_xh[$parser]['st'], 0, -1);
4032- }
4033-
4034- $XML_RPC_xh[$parser]['st'] .= ')';
4035- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4036- $XML_RPC_xh[$parser]['cm']--;
4037- break;
4038-
4039- case 'NAME':
4040- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . "' => ";
4041- break;
4042-
4043- case 'BOOLEAN':
4044- // special case here: we translate boolean 1 or 0 into PHP
4045- // constants true or false
4046- if ($XML_RPC_xh[$parser]['ac'] == '1') {
4047- $XML_RPC_xh[$parser]['ac'] = 'true';
4048- } else {
4049- $XML_RPC_xh[$parser]['ac'] = 'false';
4050- }
4051-
4052- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4053- // Drop through intentionally.
4054-
4055- case 'I4':
4056- case 'INT':
4057- case 'STRING':
4058- case 'DOUBLE':
4059- case 'DATETIME.ISO8601':
4060- case 'BASE64':
4061- if ($XML_RPC_xh[$parser]['qt'] == 1) {
4062- // we use double quotes rather than single so backslashification works OK
4063- $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
4064- } elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
4065- $XML_RPC_xh[$parser]['st'] .= "base64_decode('"
4066- . $XML_RPC_xh[$parser]['ac'] . "')";
4067- } elseif ($name == 'BOOLEAN') {
4068- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
4069- } else {
4070- // we have an I4, INT or a DOUBLE
4071- // we must check that only 0123456789-.<space> are characters here
4072- if (!ereg("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) {
4073- XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE',
4074- XML_RPC_ERROR_NON_NUMERIC_FOUND);
4075- $XML_RPC_xh[$parser]['st'] .= 'XML_RPC_ERROR_NON_NUMERIC_FOUND';
4076- } else {
4077- // it's ok, add it on
4078- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
4079- }
4080- }
4081-
4082- $XML_RPC_xh[$parser]['ac'] = '';
4083- $XML_RPC_xh[$parser]['qt'] = 0;
4084- $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value
4085- break;
4086-
4087- case 'VALUE':
4088- // deal with a string value
4089- if (strlen($XML_RPC_xh[$parser]['ac']) > 0 &&
4090- $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) {
4091-
4092- $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
4093- }
4094-
4095- // This if () detects if no scalar was inside <VALUE></VALUE>
4096- // and pads an empty "".
4097- if ($XML_RPC_xh[$parser]['st'][strlen($XML_RPC_xh[$parser]['st'])-1] == '(') {
4098- $XML_RPC_xh[$parser]['st'] .= '""';
4099- }
4100- $XML_RPC_xh[$parser]['st'] .= ", '" . $XML_RPC_xh[$parser]['vt'] . "')";
4101- if ($XML_RPC_xh[$parser]['cm']) {
4102- $XML_RPC_xh[$parser]['st'] .= ',';
4103- }
4104- break;
4105-
4106- case 'MEMBER':
4107- $XML_RPC_xh[$parser]['ac'] = '';
4108- $XML_RPC_xh[$parser]['qt'] = 0;
4109- break;
4110-
4111- case 'DATA':
4112- $XML_RPC_xh[$parser]['ac'] = '';
4113- $XML_RPC_xh[$parser]['qt'] = 0;
4114- break;
4115-
4116- case 'PARAM':
4117- $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['st'];
4118- break;
4119-
4120- case 'METHODNAME':
4121- $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", '',
4122- $XML_RPC_xh[$parser]['ac']);
4123- break;
4124-
4125- case 'BOOLEAN':
4126- // special case here: we translate boolean 1 or 0 into PHP
4127- // constants true or false
4128- if ($XML_RPC_xh[$parser]['ac'] == '1') {
4129- $XML_RPC_xh[$parser]['ac'] = 'true';
4130- } else {
4131- $XML_RPC_xh[$parser]['ac'] = 'false';
4132- }
4133-
4134- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4135- }
4136-
4137- // if it's a valid type name, set the type
4138- if (isset($XML_RPC_Types[strtolower($name)])) {
4139- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4140- }
4141-}
4142-
4143-/**
4144- * Character data handler for the XML parser
4145- *
4146- * @return void
4147- */
4148-function XML_RPC_cd($parser, $data)
4149-{
4150- global $XML_RPC_xh, $XML_RPC_backslash;
4151-
4152- if ($XML_RPC_xh[$parser]['lv'] != 3) {
4153- // "lookforvalue==3" means that we've found an entire value
4154- // and should discard any further character data
4155-
4156- if ($XML_RPC_xh[$parser]['lv'] == 1) {
4157- // if we've found text and we're just in a <value> then
4158- // turn quoting on, as this will be a string
4159- $XML_RPC_xh[$parser]['qt'] = 1;
4160- // and say we've found a value
4161- $XML_RPC_xh[$parser]['lv'] = 2;
4162- }
4163-
4164- // replace characters that eval would
4165- // do special things with
4166- if (!isset($XML_RPC_xh[$parser]['ac'])) {
4167- $XML_RPC_xh[$parser]['ac'] = '';
4168- }
4169- $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$',
4170- str_replace('"', '\"', str_replace(chr(92),
4171- $XML_RPC_backslash, $data)));
4172- }
4173-}
4174-
4175-/**
4176- * Base class
4177- *
4178- * This class provides common functions for all of the XML_RPC classes.
4179- *
4180- * @category Web Services
4181- * @package XML_RPC
4182- * @author Edd Dumbill <edd@usefulinc.com>
4183- * @author Stig Bakken <stig@php.net>
4184- * @author Martin Jansen <mj@php.net>
4185- * @copyright 1999-2001 Edd Dumbill
4186- * @version Release: 1.2.2
4187- * @link http://pear.php.net/package/XML_RPC
4188- */
4189-class XML_RPC_Base {
4190-
4191- /**
4192- * PEAR Error handling
4193- *
4194- * @return object PEAR_Error object
4195- */
4196- function raiseError($msg, $code)
4197- {
4198- include_once 'PEAR.php';
4199- if (is_object(@$this)) {
4200- return PEAR::raiseError(get_class($this) . ': ' . $msg, $code);
4201- } else {
4202- return PEAR::raiseError('XML_RPC: ' . $msg, $code);
4203- }
4204- }
4205-
4206- /**
4207- * Tell whether something is a PEAR_Error object
4208- *
4209- * @param mixed $value the item to check
4210- *
4211- * @return bool whether $value is a PEAR_Error object or not
4212- *
4213- * @access public
4214- */
4215- function isError($value)
4216- {
4217- return is_a($value, 'PEAR_Error');
4218- }
4219-}
4220-
4221-/**
4222- *
4223- *
4224- * @category Web Services
4225- * @package XML_RPC
4226- * @author Edd Dumbill <edd@usefulinc.com>
4227- * @author Stig Bakken <stig@php.net>
4228- * @author Martin Jansen <mj@php.net>
4229- * @author Daniel Convissor <danielc@php.net>
4230- * @copyright 1999-2001 Edd Dumbill
4231- * @version Release: 1.2.2
4232- * @link http://pear.php.net/package/XML_RPC
4233- */
4234-class XML_RPC_Client extends XML_RPC_Base {
4235-
4236- /**
4237- * The path and name of the RPC server script you want the request to go to
4238- * @var string
4239- */
4240- var $path = '';
4241-
4242- /**
4243- * The name of the remote server to connect to
4244- * @var string
4245- */
4246- var $server = '';
4247-
4248- /**
4249- * The protocol to use in contacting the remote server
4250- * @var string
4251- */
4252- var $protocol = 'http://';
4253-
4254- /**
4255- * The port for connecting to the remote server
4256- *
4257- * The default is 80 for http:// connections
4258- * and 443 for https:// and ssl:// connections.
4259- *
4260- * @var integer
4261- */
4262- var $port = 80;
4263-
4264- /**
4265- * A user name for accessing the RPC server
4266- * @var string
4267- * @see XML_RPC_Client::setCredentials()
4268- */
4269- var $username = '';
4270-
4271- /**
4272- * A password for accessing the RPC server
4273- * @var string
4274- * @see XML_RPC_Client::setCredentials()
4275- */
4276- var $password = '';
4277-
4278- /**
4279- * The name of the proxy server to use, if any
4280- * @var string
4281- */
4282- var $proxy = '';
4283-
4284- /**
4285- * The protocol to use in contacting the proxy server, if any
4286- * @var string
4287- */
4288- var $proxy_protocol = 'http://';
4289-
4290- /**
4291- * The port for connecting to the proxy server
4292- *
4293- * The default is 8080 for http:// connections
4294- * and 443 for https:// and ssl:// connections.
4295- *
4296- * @var integer
4297- */
4298- var $proxy_port = 8080;
4299-
4300- /**
4301- * A user name for accessing the proxy server
4302- * @var string
4303- */
4304- var $proxy_user = '';
4305-
4306- /**
4307- * A password for accessing the proxy server
4308- * @var string
4309- */
4310- var $proxy_pass = '';
4311-
4312- /**
4313- * The error number, if any
4314- * @var integer
4315- */
4316- var $errno = 0;
4317-
4318- /**
4319- * The error message, if any
4320- * @var string
4321- */
4322- var $errstring = '';
4323-
4324- /**
4325- * The current debug mode (1 = on, 0 = off)
4326- * @var integer
4327- */
4328- var $debug = 0;
4329-
4330-
4331- /**
4332- * Sets the object's properties
4333- *
4334- * @param string $path the path and name of the RPC server script
4335- * you want the request to go to
4336- * @param string $server the URL of the remote server to connect to.
4337- * If this parameter doesn't specify a
4338- * protocol and $port is 443, ssl:// is
4339- * assumed.
4340- * @param integer $port a port for connecting to the remote server.
4341- * Defaults to 80 for http:// connections and
4342- * 443 for https:// and ssl:// connections.
4343- * @param string $proxy the URL of the proxy server to use, if any.
4344- * If this parameter doesn't specify a
4345- * protocol and $port is 443, ssl:// is
4346- * assumed.
4347- * @param integer $proxy_port a port for connecting to the remote server.
4348- * Defaults to 8080 for http:// connections and
4349- * 443 for https:// and ssl:// connections.
4350- * @param string $proxy_user a user name for accessing the proxy server
4351- * @param string $proxy_pass a password for accessing the proxy server
4352- *
4353- * @return void
4354- */
4355- function XML_RPC_Client($path, $server, $port = 0,
4356- $proxy = '', $proxy_port = 0,
4357- $proxy_user = '', $proxy_pass = '')
4358- {
4359- $this->path = $path;
4360- $this->proxy_user = $proxy_user;
4361- $this->proxy_pass = $proxy_pass;
4362-
4363- preg_match('@^(http://|https://|ssl://)?(.*)$@', $server, $match);
4364- if ($match[1] == '') {
4365- if ($port == 443) {
4366- $this->server = $match[2];
4367- $this->protocol = 'ssl://';
4368- $this->port = 443;
4369- } else {
4370- $this->server = $match[2];
4371- if ($port) {
4372- $this->port = $port;
4373- }
4374- }
4375- } elseif ($match[1] == 'http://') {
4376- $this->server = $match[2];
4377- if ($port) {
4378- $this->port = $port;
4379- }
4380- } else {
4381- $this->server = $match[2];
4382- $this->protocol = 'ssl://';
4383- if ($port) {
4384- $this->port = $port;
4385- } else {
4386- $this->port = 443;
4387- }
4388- }
4389-
4390- if ($proxy) {
4391- preg_match('@^(http://|https://|ssl://)?(.*)$@', $proxy, $match);
4392- if ($match[1] == '') {
4393- if ($proxy_port == 443) {
4394- $this->proxy = $match[2];
4395- $this->proxy_protocol = 'ssl://';
4396- $this->proxy_port = 443;
4397- } else {
4398- $this->proxy = $match[2];
4399- if ($proxy_port) {
4400- $this->proxy_port = $proxy_port;
4401- }
4402- }
4403- } elseif ($match[1] == 'http://') {
4404- $this->proxy = $match[2];
4405- if ($proxy_port) {
4406- $this->proxy_port = $proxy_port;
4407- }
4408- } else {
4409- $this->proxy = $match[2];
4410- $this->proxy_protocol = 'ssl://';
4411- if ($proxy_port) {
4412- $this->proxy_port = $proxy_port;
4413- } else {
4414- $this->proxy_port = 443;
4415- }
4416- }
4417- }
4418- }
4419-
4420- /**
4421- * Change the current debug mode
4422- *
4423- * @param int $in where 1 = on, 0 = off
4424- *
4425- * @return void
4426- */
4427- function setDebug($in)
4428- {
4429- if ($in) {
4430- $this->debug = 1;
4431- } else {
4432- $this->debug = 0;
4433- }
4434- }
4435-
4436- /**
4437- * Set username and password properties for connecting to the RPC server
4438- *
4439- * @param string $u the user name
4440- * @param string $p the password
4441- *
4442- * @return void
4443- *
4444- * @see XML_RPC_Client::$username, XML_RPC_Client::$password
4445- */
4446- function setCredentials($u, $p)
4447- {
4448- $this->username = $u;
4449- $this->password = $p;
4450- }
4451-
4452- /**
4453- * Transmit the RPC request via HTTP 1.0 protocol
4454- *
4455- * @param object $msg the XML_RPC_Message object
4456- * @param int $timeout how many seconds to wait for the request
4457- *
4458- * @return object an XML_RPC_Response object. 0 is returned if any
4459- * problems happen.
4460- *
4461- * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(),
4462- * XML_RPC_Client::setCredentials()
4463- */
4464- function send($msg, $timeout = 0)
4465- {
4466- $msg->debug = $this->debug;
4467- return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
4468- $timeout, $this->username,
4469- $this->password);
4470- }
4471-
4472- /**
4473- * Transmit the RPC request via HTTP 1.0 protocol
4474- *
4475- * Requests should be sent using XML_RPC_Client send() rather than
4476- * calling this method directly.
4477- *
4478- * @param object $msg the XML_RPC_Message object
4479- * @param string $server the server to send the request to
4480- * @param int $port the server port send the request to
4481- * @param int $timeout how many seconds to wait for the request
4482- * before giving up
4483- * @param string $username a user name for accessing the RPC server
4484- * @param string $password a password for accessing the RPC server
4485- *
4486- * @return object an XML_RPC_Response object. 0 is returned if any
4487- * problems happen.
4488- *
4489- * @see XML_RPC_Client::send()
4490- */
4491- function sendPayloadHTTP10($msg, $server, $port, $timeout = 0,
4492- $username = '', $password = '')
4493- {
4494- /*
4495- * If we're using a proxy open a socket to the proxy server
4496- * instead to the xml-rpc server
4497- */
4498- if ($this->proxy) {
4499- if ($this->proxy_protocol == 'http://') {
4500- $protocol = '';
4501- } else {
4502- $protocol = $this->proxy_protocol;
4503- }
4504- if ($timeout > 0) {
4505- $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
4506- $this->errno, $this->errstr, $timeout);
4507- } else {
4508- $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
4509- $this->errno, $this->errstr);
4510- }
4511- } else {
4512- if ($this->protocol == 'http://') {
4513- $protocol = '';
4514- } else {
4515- $protocol = $this->protocol;
4516- }
4517- if ($timeout > 0) {
4518- $fp = @fsockopen($protocol . $server, $port,
4519- $this->errno, $this->errstr, $timeout);
4520- } else {
4521- $fp = @fsockopen($protocol . $server, $port,
4522- $this->errno, $this->errstr);
4523- }
4524- }
4525-
4526- /*
4527- * Just raising the error without returning it is strange,
4528- * but keep it here for backwards compatibility.
4529- */
4530- if (!$fp && $this->proxy) {
4531- $this->raiseError('Connection to proxy server '
4532- . $this->proxy . ':' . $this->proxy_port
4533- . ' failed. ' . $this->errstr,
4534- XML_RPC_ERROR_CONNECTION_FAILED);
4535- return 0;
4536- } elseif (!$fp) {
4537- $this->raiseError('Connection to RPC server '
4538- . $server . ':' . $port
4539- . ' failed. ' . $this->errstr,
4540- XML_RPC_ERROR_CONNECTION_FAILED);
4541- return 0;
4542- }
4543-
4544- // Only create the payload if it was not created previously
4545- if (empty($msg->payload)) {
4546- $msg->createPayload();
4547- }
4548-
4549- // thanks to Grant Rauscher <grant7@firstworld.net> for this
4550- $credentials = '';
4551- if ($username != '') {
4552- $credentials = 'Authorization: Basic ' .
4553- base64_encode($username . ':' . $password) . "\r\n";
4554- }
4555-
4556- if ($this->proxy) {
4557- $op = 'POST ' . $this->protocol . $server;
4558- if ($this->proxy_port) {
4559- $op .= ':' . $this->port;
4560- }
4561- } else {
4562- $op = 'POST ';
4563- }
4564-
4565- $op .= $this->path. " HTTP/1.0\r\n" .
4566- "User-Agent: PEAR XML_RPC\r\n" .
4567- 'Host: ' . $server . "\r\n";
4568- if ($this->proxy && $this->proxy_user != '') {
4569- $op .= 'Proxy-Authorization: Basic ' .
4570- base64_encode($this->proxy_user . ':' . $this->proxy_pass) .
4571- "\r\n";
4572- }
4573- $op .= $credentials .
4574- "Content-Type: text/xml\r\n" .
4575- 'Content-Length: ' . strlen($msg->payload) . "\r\n\r\n" .
4576- $msg->payload;
4577-
4578- if (!fputs($fp, $op, strlen($op))) {
4579- $this->errstr = 'Write error';
4580- return 0;
4581- }
4582- $resp = $msg->parseResponseFile($fp);
4583- fclose($fp);
4584- return $resp;
4585- }
4586-}
4587-
4588-/**
4589- *
4590- *
4591- * @category Web Services
4592- * @package XML_RPC
4593- * @author Edd Dumbill <edd@usefulinc.com>
4594- * @author Stig Bakken <stig@php.net>
4595- * @author Martin Jansen <mj@php.net>
4596- * @copyright 1999-2001 Edd Dumbill
4597- * @version Release: 1.2.2
4598- * @link http://pear.php.net/package/XML_RPC
4599- */
4600-class XML_RPC_Response extends XML_RPC_Base
4601-{
4602- var $xv;
4603- var $fn;
4604- var $fs;
4605- var $hdrs;
4606-
4607- /**
4608- * @return void
4609- */
4610- function XML_RPC_Response($val, $fcode = 0, $fstr = '')
4611- {
4612- if ($fcode != 0) {
4613- $this->fn = $fcode;
4614- $this->fs = htmlspecialchars($fstr);
4615- } else {
4616- $this->xv = $val;
4617- }
4618- }
4619-
4620- /**
4621- * @return int the error code
4622- */
4623- function faultCode()
4624- {
4625- if (isset($this->fn)) {
4626- return $this->fn;
4627- } else {
4628- return 0;
4629- }
4630- }
4631-
4632- /**
4633- * @return string the error string
4634- */
4635- function faultString()
4636- {
4637- return $this->fs;
4638- }
4639-
4640- /**
4641- * @return mixed the value
4642- */
4643- function value()
4644- {
4645- return $this->xv;
4646- }
4647-
4648- /**
4649- * @return string the error message in XML format
4650- */
4651- function serialize()
4652- {
4653- $rs = "<methodResponse>\n";
4654- if ($this->fn) {
4655- $rs .= "<fault>
4656- <value>
4657- <struct>
4658- <member>
4659- <name>faultCode</name>
4660- <value><int>" . $this->fn . "</int></value>
4661- </member>
4662- <member>
4663- <name>faultString</name>
4664- <value><string>" . $this->fs . "</string></value>
4665- </member>
4666- </struct>
4667- </value>
4668-</fault>";
4669- } else {
4670- $rs .= "<params>\n<param>\n" . $this->xv->serialize() .
4671- "</param>\n</params>";
4672- }
4673- $rs .= "\n</methodResponse>";
4674- return $rs;
4675- }
4676-}
4677-
4678-/**
4679- *
4680- *
4681- * @category Web Services
4682- * @package XML_RPC
4683- * @author Edd Dumbill <edd@usefulinc.com>
4684- * @author Stig Bakken <stig@php.net>
4685- * @author Martin Jansen <mj@php.net>
4686- * @author Daniel Convissor <danielc@php.net>
4687- * @copyright 1999-2001 Edd Dumbill
4688- * @version Release: 1.2.2
4689- * @link http://pear.php.net/package/XML_RPC
4690- */
4691-class XML_RPC_Message extends XML_RPC_Base
4692-{
4693- /**
4694- * The current debug mode (1 = on, 0 = off)
4695- * @var integer
4696- */
4697- var $debug = 0;
4698-
4699- /**
4700- * The encoding to be used for outgoing messages
4701- *
4702- * Defaults to the value of <var>$GLOBALS['XML_RPC_defencoding']</var>
4703- *
4704- * @var string
4705- * @see XML_RPC_Message::setSendEncoding(),
4706- * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header()
4707- */
4708- var $send_encoding = '';
4709-
4710- /**
4711- * The method presently being evaluated
4712- * @var string
4713- */
4714- var $methodname = '';
4715-
4716- /**
4717- * @var array
4718- */
4719- var $params = array();
4720-
4721- /**
4722- * The XML message being generated
4723- * @var string
4724- */
4725- var $payload = '';
4726-
4727- /**
4728- * @return void
4729- */
4730- function XML_RPC_Message($meth, $pars = 0)
4731- {
4732- $this->methodname = $meth;
4733- if (is_array($pars) && sizeof($pars) > 0) {
4734- for ($i = 0; $i < sizeof($pars); $i++) {
4735- $this->addParam($pars[$i]);
4736- }
4737- }
4738- }
4739-
4740- /**
4741- * Produces the XML declaration including the encoding attribute
4742- *
4743- * The encoding is determined by this class' <var>$send_encoding</var>
4744- * property. If the <var>$send_encoding</var> property is not set, use
4745- * <var>$GLOBALS['XML_RPC_defencoding']</var>.
4746- *
4747- * @return string the XML declaration and <methodCall> element
4748- *
4749- * @see XML_RPC_Message::setSendEncoding(),
4750- * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding']
4751- */
4752- function xml_header()
4753- {
4754- global $XML_RPC_defencoding;
4755- if (!$this->send_encoding) {
4756- $this->send_encoding = $XML_RPC_defencoding;
4757- }
4758- return '<?xml version="1.0" encoding="' . $this->send_encoding . '"?>'
4759- . "\n<methodCall>\n";
4760- }
4761-
4762- /**
4763- * @return string the closing </methodCall> tag
4764- */
4765- function xml_footer()
4766- {
4767- return "</methodCall>\n";
4768- }
4769-
4770- /**
4771- * @return void
4772- *
4773- * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer()
4774- */
4775- function createPayload()
4776- {
4777- $this->payload = $this->xml_header();
4778- $this->payload .= '<methodName>' . $this->methodname . "</methodName>\n";
4779- $this->payload .= "<params>\n";
4780- for ($i = 0; $i < sizeof($this->params); $i++) {
4781- $p = $this->params[$i];
4782- $this->payload .= "<param>\n" . $p->serialize() . "</param>\n";
4783- }
4784- $this->payload .= "</params>\n";
4785- $this->payload .= $this->xml_footer();
4786- $this->payload = ereg_replace("[\r\n]+", "\r\n", $this->payload);
4787- }
4788-
4789- /**
4790- * @return string the name of the method
4791- */
4792- function method($meth = '')
4793- {
4794- if ($meth != '') {
4795- $this->methodname = $meth;
4796- }
4797- return $this->methodname;
4798- }
4799-
4800- /**
4801- * @return string the payload
4802- */
4803- function serialize()
4804- {
4805- $this->createPayload();
4806- return $this->payload;
4807- }
4808-
4809- /**
4810- * @return void
4811- */
4812- function addParam($par)
4813- {
4814- $this->params[] = $par;
4815- }
4816-
4817- /**
4818- * @return void
4819- */
4820- function getParam($i)
4821- {
4822- return $this->params[$i];
4823- }
4824-
4825- /**
4826- * @return int the number of parameters
4827- */
4828- function getNumParams()
4829- {
4830- return sizeof($this->params);
4831- }
4832-
4833- /**
4834- * Sets the XML declaration's encoding attribute
4835- *
4836- * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII)
4837- *
4838- * @return void
4839- *
4840- * @see XML_RPC_Message::$send_encoding, XML_RPC_Message::xml_header()
4841- * @since Method available since Release 1.2.0
4842- */
4843- function setSendEncoding($type)
4844- {
4845- $this->send_encoding = $type;
4846- }
4847-
4848- /**
4849- * Determine the XML's encoding via the encoding attribute
4850- * in the XML declaration
4851- *
4852- * If the encoding parameter is not set or is not ISO-8859-1, UTF-8
4853- * or US-ASCII, $XML_RPC_defencoding will be returned.
4854- *
4855- * @param string $data the XML that will be parsed
4856- *
4857- * @return string the encoding to be used
4858- *
4859- * @link http://php.net/xml_parser_create
4860- * @since Method available since Release 1.2.0
4861- */
4862- function getEncoding($data)
4863- {
4864- global $XML_RPC_defencoding;
4865-
4866- if (preg_match('/<\?xml[^>]*\s*encoding\s*=\s*[\'"]([^"\']*)[\'"]/i',
4867- $data, $match))
4868- {
4869- $match[1] = trim(strtoupper($match[1]));
4870- switch ($match[1]) {
4871- case 'ISO-8859-1':
4872- case 'UTF-8':
4873- case 'US-ASCII':
4874- return $match[1];
4875- break;
4876-
4877- default:
4878- return $XML_RPC_defencoding;
4879- }
4880- } else {
4881- return $XML_RPC_defencoding;
4882- }
4883- }
4884-
4885- /**
4886- * @return object a new XML_RPC_Response object
4887- */
4888- function parseResponseFile($fp)
4889- {
4890- $ipd = '';
4891- while ($data = @fread($fp, 8192)) {
4892- $ipd .= $data;
4893- }
4894- return $this->parseResponse($ipd);
4895- }
4896-
4897- /**
4898- * @return object a new XML_RPC_Response object
4899- */
4900- function parseResponse($data = '')
4901- {
4902- global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding;
4903-
4904- $encoding = $this->getEncoding($data);
4905- $parser = xml_parser_create($encoding);
4906-
4907- $XML_RPC_xh[$parser] = array();
4908-
4909- $XML_RPC_xh[$parser]['st'] = '';
4910- $XML_RPC_xh[$parser]['cm'] = 0;
4911- $XML_RPC_xh[$parser]['isf'] = 0;
4912- $XML_RPC_xh[$parser]['ac'] = '';
4913- $XML_RPC_xh[$parser]['qt'] = '';
4914-
4915- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
4916- xml_set_element_handler($parser, 'XML_RPC_se', 'XML_RPC_ee');
4917- xml_set_character_data_handler($parser, 'XML_RPC_cd');
4918-
4919- $hdrfnd = 0;
4920- if ($this->debug) {
4921- print "<PRE>---GOT---\n";
4922- print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
4923- print "\n---END---\n</PRE>";
4924- }
4925-
4926- // see if we got an HTTP 200 OK, else bomb
4927- // but only do this if we're using the HTTP protocol.
4928- if (ereg('^HTTP', $data) &&
4929- !ereg('^HTTP/[0-9\.]+ 200 ', $data)) {
4930- $errstr = substr($data, 0, strpos($data, "\n") - 1);
4931- error_log('HTTP error, got response: ' . $errstr);
4932- $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'],
4933- $XML_RPC_str['http_error'] . ' (' .
4934- $errstr . ')');
4935- xml_parser_free($parser);
4936- return $r;
4937- }
4938- // gotta get rid of headers here
4939-
4940-
4941- if ((!$hdrfnd) && ($brpos = strpos($data,"\r\n\r\n"))) {
4942- $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
4943- $data = substr($data, $brpos + 4);
4944- $hdrfnd = 1;
4945- }
4946-
4947- /*
4948- * be tolerant of junk after methodResponse
4949- * (e.g. javascript automatically inserted by free hosts)
4950- * thanks to Luca Mariano <luca.mariano@email.it>
4951- */
4952- $data = substr($data, 0, strpos($data, "</methodResponse>") + 17);
4953-
4954- if (!xml_parse($parser, $data, sizeof($data))) {
4955- // thanks to Peter Kocks <peter.kocks@baygate.com>
4956- if ((xml_get_current_line_number($parser)) == 1) {
4957- $errstr = 'XML error at line 1, check URL';
4958- } else {
4959- $errstr = sprintf('XML error: %s at line %d',
4960- xml_error_string(xml_get_error_code($parser)),
4961- xml_get_current_line_number($parser));
4962- }
4963- error_log($errstr);
4964- $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
4965- $XML_RPC_str['invalid_return']);
4966- xml_parser_free($parser);
4967- return $r;
4968- }
4969- xml_parser_free($parser);
4970- if ($this->debug) {
4971- print '<PRE>---EVALING---[' .
4972- strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
4973- htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---</PRE>";
4974- }
4975- if (strlen($XML_RPC_xh[$parser]['st']) == 0) {
4976- // then something odd has happened
4977- // and it's time to generate a client side error
4978- // indicating something odd went on
4979- $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
4980- $XML_RPC_str['invalid_return']);
4981- } else {
4982- eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;');
4983- if ($XML_RPC_xh[$parser]['isf']) {
4984- $f = $v->structmem('faultCode');
4985- $fs = $v->structmem('faultString');
4986- $r = new XML_RPC_Response($v, $f->scalarval(),
4987- $fs->scalarval());
4988- } else {
4989- $r = new XML_RPC_Response($v);
4990- }
4991- }
4992- $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
4993- return $r;
4994- }
4995-}
4996-
4997-/**
4998- *
4999- *
5000- * @category Web Services
5001- * @package XML_RPC
5002- * @author Edd Dumbill <edd@usefulinc.com>
5003- * @author Stig Bakken <stig@php.net>
5004- * @author Martin Jansen <mj@php.net>
5005- * @copyright 1999-2001 Edd Dumbill
5006- * @version Release: 1.2.2
5007- * @link http://pear.php.net/package/XML_RPC
5008- */
5009-class XML_RPC_Value extends XML_RPC_Base
5010-{
5011- var $me = array();
5012- var $mytype = 0;
5013-
5014- /**
5015- * @return void
5016- */
5017- function XML_RPC_Value($val = -1, $type = '')
5018- {
5019- global $XML_RPC_Types;
5020- $this->me = array();
5021- $this->mytype = 0;
5022- if ($val != -1 || $type != '') {
5023- if ($type == '') {
5024- $type = 'string';
5025- }
5026- if (!array_key_exists($type, $XML_RPC_Types)) {
5027- // XXX
5028- // need some way to report this error
5029- } elseif ($XML_RPC_Types[$type] == 1) {
5030- $this->addScalar($val, $type);
5031- } elseif ($XML_RPC_Types[$type] == 2) {
5032- $this->addArray($val);
5033- } elseif ($XML_RPC_Types[$type] == 3) {
5034- $this->addStruct($val);
5035- }
5036- }
5037- }
5038-
5039- /**
5040- * @return int returns 1 if successful or 0 if there are problems
5041- */
5042- function addScalar($val, $type = 'string')
5043- {
5044- global $XML_RPC_Types, $XML_RPC_Boolean;
5045-
5046- if ($this->mytype == 1) {
5047- $this->raiseError('Scalar can have only one value',
5048- XML_RPC_ERROR_INVALID_TYPE);
5049- return 0;
5050- }
5051- $typeof = $XML_RPC_Types[$type];
5052- if ($typeof != 1) {
5053- $this->raiseError("Not a scalar type (${typeof})",
5054- XML_RPC_ERROR_INVALID_TYPE);
5055- return 0;
5056- }
5057-
5058- if ($type == $XML_RPC_Boolean) {
5059- if (strcasecmp($val, 'true') == 0
5060- || $val == 1
5061- || ($val == true && strcasecmp($val, 'false')))
5062- {
5063- $val = 1;
5064- } else {
5065- $val = 0;
5066- }
5067- }
5068-
5069- if ($this->mytype == 2) {
5070- // we're adding to an array here
5071- $ar = $this->me['array'];
5072- $ar[] = new XML_RPC_Value($val, $type);
5073- $this->me['array'] = $ar;
5074- } else {
5075- // a scalar, so set the value and remember we're scalar
5076- $this->me[$type] = $val;
5077- $this->mytype = $typeof;
5078- }
5079- return 1;
5080- }
5081-
5082- /**
5083- * @return int returns 1 if successful or 0 if there are problems
5084- */
5085- function addArray($vals)
5086- {
5087- global $XML_RPC_Types;
5088- if ($this->mytype != 0) {
5089- $this->raiseError(
5090- 'Already initialized as a [' . $this->kindOf() . ']',
5091- XML_RPC_ERROR_ALREADY_INITIALIZED);
5092- return 0;
5093- }
5094- $this->mytype = $XML_RPC_Types['array'];
5095- $this->me['array'] = $vals;
5096- return 1;
5097- }
5098-
5099- /**
5100- * @return int returns 1 if successful or 0 if there are problems
5101- */
5102- function addStruct($vals)
5103- {
5104- global $XML_RPC_Types;
5105- if ($this->mytype != 0) {
5106- $this->raiseError(
5107- 'Already initialized as a [' . $this->kindOf() . ']',
5108- XML_RPC_ERROR_ALREADY_INITIALIZED);
5109- return 0;
5110- }
5111- $this->mytype = $XML_RPC_Types['struct'];
5112- $this->me['struct'] = $vals;
5113- return 1;
5114- }
5115-
5116- /**
5117- * @return void
5118- */
5119- function dump($ar)
5120- {
5121- reset($ar);
5122- while (list($key, $val) = each($ar)) {
5123- echo "$key => $val<br>";
5124- if ($key == 'array') {
5125- while (list($key2, $val2) = each($val)) {
5126- echo "-- $key2 => $val2<br>";
5127- }
5128- }
5129- }
5130- }
5131-
5132- /**
5133- * @return string the data type of the current value
5134- */
5135- function kindOf()
5136- {
5137- switch ($this->mytype) {
5138- case 3:
5139- return 'struct';
5140-
5141- case 2:
5142- return 'array';
5143-
5144- case 1:
5145- return 'scalar';
5146-
5147- default:
5148- return 'undef';
5149- }
5150- }
5151-
5152- /**
5153- * @return string the data in XML format
5154- */
5155- function serializedata($typ, $val)
5156- {
5157- $rs = '';
5158- global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
5159- if (!array_key_exists($typ, $XML_RPC_Types)) {
5160- // XXX
5161- // need some way to report this error
5162- return;
5163- }
5164- switch ($XML_RPC_Types[$typ]) {
5165- case 3:
5166- // struct
5167- $rs .= "<struct>\n";
5168- reset($val);
5169- while (list($key2, $val2) = each($val)) {
5170- $rs .= "<member><name>${key2}</name>\n";
5171- $rs .= $this->serializeval($val2);
5172- $rs .= "</member>\n";
5173- }
5174- $rs .= '</struct>';
5175- break;
5176-
5177- case 2:
5178- // array
5179- $rs .= "<array>\n<data>\n";
5180- for ($i = 0; $i < sizeof($val); $i++) {
5181- $rs .= $this->serializeval($val[$i]);
5182- }
5183- $rs .= "</data>\n</array>";
5184- break;
5185-
5186- case 1:
5187- switch ($typ) {
5188- case $XML_RPC_Base64:
5189- $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
5190- break;
5191- case $XML_RPC_Boolean:
5192- $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
5193- break;
5194- case $XML_RPC_String:
5195- $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
5196- break;
5197- default:
5198- $rs .= "<${typ}>${val}</${typ}>";
5199- }
5200- }
5201- return $rs;
5202- }
5203-
5204- /**
5205- * @return string the data in XML format
5206- */
5207- function serialize()
5208- {
5209- return $this->serializeval($this);
5210- }
5211-
5212- /**
5213- * @return string the data in XML format
5214- */
5215- function serializeval($o)
5216- {
5217- $rs = '';
5218- $ar = $o->me;
5219- reset($ar);
5220- list($typ, $val) = each($ar);
5221- $rs .= '<value>';
5222- $rs .= $this->serializedata($typ, $val);
5223- $rs .= "</value>\n";
5224- return $rs;
5225- }
5226-
5227- /**
5228- * @return mixed the contents of the element requested
5229- */
5230- function structmem($m)
5231- {
5232- return $this->me['struct'][$m];
5233- }
5234-
5235- /**
5236- * @return void
5237- */
5238- function structreset()
5239- {
5240- reset($this->me['struct']);
5241- }
5242-
5243- /**
5244- * @return the key/value pair of the struct's current element
5245- */
5246- function structeach()
5247- {
5248- return each($this->me['struct']);
5249- }
5250-
5251- /**
5252- * @return mixed the current value
5253- */
5254- function getval() {
5255- // UNSTABLE
5256- global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
5257-
5258- reset($this->me);
5259- list($a, $b) = each($this->me);
5260-
5261- // contributed by I Sofer, 2001-03-24
5262- // add support for nested arrays to scalarval
5263- // i've created a new method here, so as to
5264- // preserve back compatibility
5265-
5266- if (is_array($b)) {
5267- foreach ($b as $id => $cont) {
5268- $b[$id] = $cont->scalarval();
5269- }
5270- }
5271-
5272- // add support for structures directly encoding php objects
5273- if (is_object($b)) {
5274- $t = get_object_vars($b);
5275- foreach ($t as $id => $cont) {
5276- $t[$id] = $cont->scalarval();
5277- }
5278- foreach ($t as $id => $cont) {
5279- eval('$b->'.$id.' = $cont;');
5280- }
5281- }
5282-
5283- // end contrib
5284- return $b;
5285- }
5286-
5287- /**
5288- * @return mixed
5289- */
5290- function scalarval()
5291- {
5292- global $XML_RPC_Boolean, $XML_RPC_Base64;
5293- reset($this->me);
5294- list($a, $b) = each($this->me);
5295- return $b;
5296- }
5297-
5298- /**
5299- * @return string
5300- */
5301- function scalartyp()
5302- {
5303- global $XML_RPC_I4, $XML_RPC_Int;
5304- reset($this->me);
5305- list($a, $b) = each($this->me);
5306- if ($a == $XML_RPC_I4) {
5307- $a = $XML_RPC_Int;
5308- }
5309- return $a;
5310- }
5311-
5312- /**
5313- * @return mixed the struct's current element
5314- */
5315- function arraymem($m)
5316- {
5317- return $this->me['array'][$m];
5318- }
5319-
5320- /**
5321- * @return int the number of elements in the array
5322- */
5323- function arraysize()
5324- {
5325- reset($this->me);
5326- list($a, $b) = each($this->me);
5327- return sizeof($b);
5328- }
5329-}
5330-
5331-/**
5332- * Return an ISO8601 encoded string
5333- *
5334- * While timezones ought to be supported, the XML-RPC spec says:
5335- *
5336- * "Don't assume a timezone. It should be specified by the server in its
5337- * documentation what assumptions it makes about timezones."
5338- *
5339- * This routine always assumes localtime unless $utc is set to 1, in which
5340- * case UTC is assumed and an adjustment for locale is made when encoding.
5341- *
5342- * @return string the formatted date
5343- */
5344-function XML_RPC_iso8601_encode($timet, $utc = 0) {
5345- if (!$utc) {
5346- $t = strftime('%Y%m%dT%H:%M:%S', $timet);
5347- } else {
5348- if (function_exists('gmstrftime')) {
5349- // gmstrftime doesn't exist in some versions
5350- // of PHP
5351- $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet);
5352- } else {
5353- $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z'));
5354- }
5355- }
5356- return $t;
5357-}
5358-
5359-/**
5360- * Convert a datetime string into a Unix timestamp
5361- *
5362- * While timezones ought to be supported, the XML-RPC spec says:
5363- *
5364- * "Don't assume a timezone. It should be specified by the server in its
5365- * documentation what assumptions it makes about timezones."
5366- *
5367- * This routine always assumes localtime unless $utc is set to 1, in which
5368- * case UTC is assumed and an adjustment for locale is made when encoding.
5369- *
5370- * @return int the unix timestamp of the date submitted
5371- */
5372-function XML_RPC_iso8601_decode($idate, $utc = 0) {
5373- $t = 0;
5374- if (ereg('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) {
5375- if ($utc) {
5376- $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
5377- } else {
5378- $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
5379- }
5380- }
5381- return $t;
5382-}
5383-
5384-/**
5385- * Takes a message in PHP XML_RPC object format and translates it into
5386- * native PHP types
5387- *
5388- * @return mixed
5389- *
5390- * @author Dan Libby <dan@libby.com>
5391- */
5392-function XML_RPC_decode($XML_RPC_val)
5393-{
5394- $kind = $XML_RPC_val->kindOf();
5395-
5396- if ($kind == 'scalar') {
5397- return $XML_RPC_val->scalarval();
5398-
5399- } elseif ($kind == 'array') {
5400- $size = $XML_RPC_val->arraysize();
5401- $arr = array();
5402- for ($i = 0; $i < $size; $i++) {
5403- $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i));
5404- }
5405- return $arr;
5406-
5407- } elseif ($kind == 'struct') {
5408- $XML_RPC_val->structreset();
5409- $arr = array();
5410- while (list($key, $value) = $XML_RPC_val->structeach()) {
5411- $arr[$key] = XML_RPC_decode($value);
5412- }
5413- return $arr;
5414- }
5415-}
5416-
5417-/**
5418- * Takes native php types and encodes them into XML_RPC PHP object format
5419- *
5420- * Feature creep -- could support more types via optional type argument.
5421- *
5422- * @return string
5423- *
5424- * @author Dan Libby <dan@libby.com>
5425- */
5426-function XML_RPC_encode($php_val) {
5427- global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double, $XML_RPC_String,
5428- $XML_RPC_Array, $XML_RPC_Struct;
5429-
5430- $type = gettype($php_val);
5431- $XML_RPC_val = new XML_RPC_Value;
5432-
5433- switch ($type) {
5434- case 'array':
5435- if (empty($php_val)) {
5436- $XML_RPC_val->addArray($php_val);
5437- break;
5438- }
5439- $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1));
5440- if (empty($tmp)) {
5441- $arr = array();
5442- foreach ($php_val as $k => $v) {
5443- $arr[$k] = XML_RPC_encode($v);
5444- }
5445- $XML_RPC_val->addArray($arr);
5446- break;
5447- }
5448- // fall though if it's not an enumerated array
5449-
5450- case 'object':
5451- $arr = array();
5452- foreach ($php_val as $k => $v) {
5453- $arr[$k] = XML_RPC_encode($v);
5454- }
5455- $XML_RPC_val->addStruct($arr);
5456- break;
5457-
5458- case 'integer':
5459- $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
5460- break;
5461-
5462- case 'double':
5463- $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
5464- break;
5465-
5466- case 'string':
5467- case 'NULL':
5468- $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
5469- break;
5470-
5471- case 'boolean':
5472- // Add support for encoding/decoding of booleans, since they
5473- // are supported in PHP
5474- // by <G_Giunta_2001-02-29>
5475- $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
5476- break;
5477-
5478- case 'unknown type':
5479- default:
5480- $XML_RPC_val = false;
5481- }
5482- return $XML_RPC_val;
5483-}
5484-
5485-/*
5486- * Local variables:
5487- * tab-width: 4
5488- * c-basic-offset: 4
5489- * c-hanging-comment-ender-p: nil
5490- * End:
5491- */
5492-
5493-?>
5494-XML_RPC-1.2.2/Server.php
5495-
5496-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5497-
5498-/**
5499- * PHP implementation of the XML-RPC protocol
5500- *
5501- * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
5502- * It has support for HTTP transport, proxies and authentication.
5503- *
5504- * PHP versions 4 and 5
5505- *
5506- * LICENSE: License is granted to use or modify this software
5507- * ("XML-RPC for PHP") for commercial or non-commercial use provided the
5508- * copyright of the author is preserved in any distributed or derivative work.
5509- *
5510- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
5511- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5512- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5513- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5514- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5515- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5516- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5517- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5518- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5519- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5520- *
5521- * @category Web Services
5522- * @package XML_RPC
5523- * @author Edd Dumbill <edd@usefulinc.com>
5524- * @author Stig Bakken <stig@php.net>
5525- * @author Martin Jansen <mj@php.net>
5526- * @copyright 1999-2001 Edd Dumbill
5527- * @version CVS: $Id: Server.php,v 1.17 2005/03/01 17:09:49 danielc Exp $
5528- * @link http://pear.php.net/package/XML_RPC
5529- */
5530-
5531-
5532-/**
5533- * Pull in the XML_RPC class
5534- */
5535-require_once 'XML/RPC.php';
5536-
5537-
5538-/**
5539- * listMethods: either a string, or nothing
5540- * @global array $GLOBALS['XML_RPC_Server_listMethods_sig']
5541- */
5542-$GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
5543- array($GLOBALS['XML_RPC_Array'],
5544- $GLOBALS['XML_RPC_String']
5545- ),
5546- array($GLOBALS['XML_RPC_Array'])
5547-);
5548-
5549-/**
5550- * @global string $GLOBALS['XML_RPC_Server_listMethods_doc']
5551- */
5552-$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the'
5553- . ' methods that the XML-RPC server knows how to dispatch';
5554-
5555-/**
5556- * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig']
5557- */
5558-$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
5559- array($GLOBALS['XML_RPC_Array'],
5560- $GLOBALS['XML_RPC_String']
5561- )
5562-);
5563-
5564-/**
5565- * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc']
5566- */
5567-$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
5568- . ' signatures (an array of arrays) for the method name passed. If'
5569- . ' no signatures are known, returns a none-array (test for type !='
5570- . ' array to detect missing signature)';
5571-
5572-/**
5573- * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig']
5574- */
5575-$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
5576- array($GLOBALS['XML_RPC_String'],
5577- $GLOBALS['XML_RPC_String']
5578- )
5579-);
5580-
5581-/**
5582- * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc']
5583- */
5584-$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined'
5585- . ' for the method passed, otherwise returns an empty string';
5586-
5587-/**
5588- * @global array $GLOBALS['XML_RPC_Server_dmap']
5589- */
5590-$GLOBALS['XML_RPC_Server_dmap'] = array(
5591- 'system.listMethods' => array(
5592- 'function' => 'XML_RPC_Server_listMethods',
5593- 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'],
5594- 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc']
5595- ),
5596- 'system.methodHelp' => array(
5597- 'function' => 'XML_RPC_Server_methodHelp',
5598- 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'],
5599- 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc']
5600- ),
5601- 'system.methodSignature' => array(
5602- 'function' => 'XML_RPC_Server_methodSignature',
5603- 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'],
5604- 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc']
5605- )
5606-);
5607-
5608-/**
5609- * @global string $GLOBALS['XML_RPC_Server_debuginfo']
5610- */
5611-$GLOBALS['XML_RPC_Server_debuginfo'] = '';
5612-
5613-
5614-/**
5615- * Lists all the methods that the XML-RPC server knows how to dispatch
5616- *
5617- * @return object a new XML_RPC_Response object
5618- */
5619-function XML_RPC_Server_listMethods($server, $m)
5620-{
5621- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
5622-
5623- $v = new XML_RPC_Value();
5624- $dmap = $server->dmap;
5625- $outAr = array();
5626- for (reset($dmap); list($key, $val) = each($dmap); ) {
5627- $outAr[] = new XML_RPC_Value($key, 'string');
5628- }
5629- $dmap = $XML_RPC_Server_dmap;
5630- for (reset($dmap); list($key, $val) = each($dmap); ) {
5631- $outAr[] = new XML_RPC_Value($key, 'string');
5632- }
5633- $v->addArray($outAr);
5634- return new XML_RPC_Response($v);
5635-}
5636-
5637-/**
5638- * Returns an array of known signatures (an array of arrays)
5639- * for the given method
5640- *
5641- * If no signatures are known, returns a none-array
5642- * (test for type != array to detect missing signature)
5643- *
5644- * @return object a new XML_RPC_Response object
5645- */
5646-function XML_RPC_Server_methodSignature($server, $m)
5647-{
5648- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
5649-
5650- $methName = $m->getParam(0);
5651- $methName = $methName->scalarval();
5652- if (strpos($methName, 'system.') === 0) {
5653- $dmap = $XML_RPC_Server_dmap;
5654- $sysCall = 1;
5655- } else {
5656- $dmap = $server->dmap;
5657- $sysCall = 0;
5658- }
5659- // print "<!-- ${methName} -->\n";
5660- if (isset($dmap[$methName])) {
5661- if ($dmap[$methName]['signature']) {
5662- $sigs = array();
5663- $thesigs = $dmap[$methName]['signature'];
5664- for ($i = 0; $i < sizeof($thesigs); $i++) {
5665- $cursig = array();
5666- $inSig = $thesigs[$i];
5667- for ($j = 0; $j < sizeof($inSig); $j++) {
5668- $cursig[] = new XML_RPC_Value($inSig[$j], 'string');
5669- }
5670- $sigs[] = new XML_RPC_Value($cursig, 'array');
5671- }
5672- $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array'));
5673- } else {
5674- $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string'));
5675- }
5676- } else {
5677- $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
5678- $XML_RPC_str['introspect_unknown']);
5679- }
5680- return $r;
5681-}
5682-
5683-/**
5684- * Returns help text if defined for the method passed, otherwise returns
5685- * an empty string
5686- *
5687- * @return object a new XML_RPC_Response object
5688- */
5689-function XML_RPC_Server_methodHelp($server, $m)
5690-{
5691- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
5692-
5693- $methName = $m->getParam(0);
5694- $methName = $methName->scalarval();
5695- if (strpos($methName, 'system.') === 0) {
5696- $dmap = $XML_RPC_Server_dmap;
5697- $sysCall = 1;
5698- } else {
5699- $dmap = $server->dmap;
5700- $sysCall = 0;
5701- }
5702- // print "<!-- ${methName} -->\n";
5703- if (isset($dmap[$methName])) {
5704- if ($dmap[$methName]['docstring']) {
5705- $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']),
5706- 'string');
5707- } else {
5708- $r = new XML_RPC_Response(new XML_RPC_Value('', 'string'));
5709- }
5710- } else {
5711- $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
5712- $XML_RPC_str['introspect_unknown']);
5713- }
5714- return $r;
5715-}
5716-
5717-/**
5718- * @return void
5719- */
5720-function XML_RPC_Server_debugmsg($m)
5721-{
5722- global $XML_RPC_Server_debuginfo;
5723- $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n";
5724-}
5725-
5726-
5727-/**
5728- *
5729- *
5730- * @category Web Services
5731- * @package XML_RPC
5732- * @author Edd Dumbill <edd@usefulinc.com>
5733- * @author Stig Bakken <stig@php.net>
5734- * @author Martin Jansen <mj@php.net>
5735- * @copyright 1999-2001 Edd Dumbill
5736- * @version Release: 1.2.2
5737- * @link http://pear.php.net/package/XML_RPC
5738- */
5739-class XML_RPC_Server
5740-{
5741- var $dmap = array();
5742- var $encoding = '';
5743- var $debug = 0;
5744-
5745- /**
5746- * @return void
5747- */
5748- function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0)
5749- {
5750- global $HTTP_RAW_POST_DATA;
5751-
5752- if ($debug) {
5753- $this->debug = 1;
5754- } else {
5755- $this->debug = 0;
5756- }
5757-
5758- // dispMap is a despatch array of methods
5759- // mapped to function names and signatures
5760- // if a method
5761- // doesn't appear in the map then an unknown
5762- // method error is generated
5763- $this->dmap = $dispMap;
5764- if ($serviceNow) {
5765- $this->service();
5766- }
5767- }
5768-
5769- /**
5770- * @return string the debug information if debug debug mode is on
5771- */
5772- function serializeDebug()
5773- {
5774- global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA;
5775-
5776- if ($this->debug) {
5777- XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n"
5778- . $HTTP_RAW_POST_DATA
5779- . "\n" . '^^^ END POST DATA ^^^');
5780- }
5781-
5782- if ($XML_RPC_Server_debuginfo != '') {
5783- return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n"
5784- . preg_replace('/-(?=-)/', '- ', $XML_RPC_Server_debuginfo)
5785- . "-->\n";
5786- } else {
5787- return '';
5788- }
5789- }
5790-
5791- /**
5792- * Print out the result
5793- *
5794- * The encoding and content-type are determined by
5795- * XML_RPC_Message::getEncoding()
5796- *
5797- * @return void
5798- *
5799- * @see XML_RPC_Message::getEncoding()
5800- */
5801- function service()
5802- {
5803- $r = $this->parseRequest();
5804- $payload = '<?xml version="1.0" encoding="'
5805- . $this->encoding . '"?>' . "\n"
5806- . $this->serializeDebug()
5807- . $r->serialize();
5808- header('Content-Length: ' . strlen($payload));
5809- header('Content-Type: text/xml; charset=' . $this->encoding);
5810- print $payload;
5811- }
5812-
5813- /**
5814- * @return array
5815- */
5816- function verifySignature($in, $sig)
5817- {
5818- for ($i = 0; $i < sizeof($sig); $i++) {
5819- // check each possible signature in turn
5820- $cursig = $sig[$i];
5821- if (sizeof($cursig) == $in->getNumParams() + 1) {
5822- $itsOK = 1;
5823- for ($n = 0; $n < $in->getNumParams(); $n++) {
5824- $p = $in->getParam($n);
5825- // print "<!-- $p -->\n";
5826- if ($p->kindOf() == 'scalar') {
5827- $pt = $p->scalartyp();
5828- } else {
5829- $pt = $p->kindOf();
5830- }
5831- // $n+1 as first type of sig is return type
5832- if ($pt != $cursig[$n+1]) {
5833- $itsOK = 0;
5834- $pno = $n+1;
5835- $wanted = $cursig[$n+1];
5836- $got = $pt;
5837- break;
5838- }
5839- }
5840- if ($itsOK) {
5841- return array(1);
5842- }
5843- }
5844- }
5845- return array(0, "Wanted ${wanted}, got ${got} at param ${pno})");
5846- }
5847-
5848- /**
5849- * @return object a new XML_RPC_Response object
5850- */
5851- function parseRequest($data = '')
5852- {
5853- global $XML_RPC_xh, $HTTP_RAW_POST_DATA,
5854- $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml,
5855- $XML_RPC_defencoding, $XML_RPC_Server_dmap;
5856-
5857- if ($data == '') {
5858- $data = $HTTP_RAW_POST_DATA;
5859- }
5860-
5861- $this->encoding = XML_RPC_Message::getEncoding($data);
5862- $parser = xml_parser_create($this->encoding);
5863-
5864- $XML_RPC_xh[$parser] = array();
5865- $XML_RPC_xh[$parser]['st'] = '';
5866- $XML_RPC_xh[$parser]['cm'] = 0;
5867- $XML_RPC_xh[$parser]['isf'] = 0;
5868- $XML_RPC_xh[$parser]['params'] = array();
5869- $XML_RPC_xh[$parser]['method'] = '';
5870-
5871- $plist = '';
5872-
5873- // decompose incoming XML into request structure
5874-
5875- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
5876- xml_set_element_handler($parser, 'XML_RPC_se', 'XML_RPC_ee');
5877- xml_set_character_data_handler($parser, 'XML_RPC_cd');
5878- if (!xml_parse($parser, $data, 1)) {
5879- // return XML error as a faultCode
5880- $r = new XML_RPC_Response(0,
5881- $XML_RPC_errxml+xml_get_error_code($parser),
5882- sprintf('XML error: %s at line %d',
5883- xml_error_string(xml_get_error_code($parser)),
5884- xml_get_current_line_number($parser)));
5885- xml_parser_free($parser);
5886- } else {
5887- xml_parser_free($parser);
5888- $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']);
5889- // now add parameters in
5890- for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) {
5891- // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n";
5892- $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n";
5893- eval('$m->addParam(' . $XML_RPC_xh[$parser]['params'][$i] . ');');
5894- }
5895- XML_RPC_Server_debugmsg($plist);
5896-
5897- // now to deal with the method
5898- $methName = $XML_RPC_xh[$parser]['method'];
5899- if (strpos($methName, 'system.') === 0) {
5900- $dmap = $XML_RPC_Server_dmap;
5901- $sysCall = 1;
5902- } else {
5903- $dmap = $this->dmap;
5904- $sysCall = 0;
5905- }
5906-
5907- if (isset($dmap[$methName]['function'])
5908- && is_string($dmap[$methName]['function'])
5909- && strpos($dmap[$methName]['function'], '::') !== false)
5910- {
5911- $dmap[$methName]['function'] =
5912- explode('::', $dmap[$methName]['function']);
5913- }
5914-
5915- if (isset($dmap[$methName]['function'])
5916- && is_callable($dmap[$methName]['function']))
5917- {
5918- // dispatch if exists
5919- if (isset($dmap[$methName]['signature'])) {
5920- $sr = $this->verifySignature($m,
5921- $dmap[$methName]['signature'] );
5922- }
5923- if ( (!isset($dmap[$methName]['signature'])) || $sr[0]) {
5924- // if no signature or correct signature
5925- if ($sysCall) {
5926- $r = call_user_func($dmap[$methName]['function'], $this, $m);
5927- } else {
5928- $r = call_user_func($dmap[$methName]['function'], $m);
5929- }
5930- } else {
5931- $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
5932- $XML_RPC_str['incorrect_params']
5933- . ': ' . $sr[1]);
5934- }
5935- } else {
5936- // else prepare error response
5937- $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'],
5938- $XML_RPC_str['unknown_method']);
5939- }
5940- }
5941- return $r;
5942- }
5943-
5944- /**
5945- * Echos back the input packet as a string value
5946- *
5947- * @return void
5948- *
5949- * Useful for debugging.
5950- */
5951- function echoInput() {
5952- global $HTTP_RAW_POST_DATA;
5953-
5954- $r = new XML_RPC_Response(0);
5955- $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string');
5956- print $r->serialize();
5957- }
5958-}
5959-
5960-/*
5961- * Local variables:
5962- * tab-width: 4
5963- * c-basic-offset: 4
5964- * c-hanging-comment-ender-p: nil
5965- * End:
5966- */
5967-
5968-?>
5969-
5970-<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
5971-<package version="1.0" packagerversion="1.4.0a1">
5972- <name>XML_RPC</name>
5973- <summary>PHP implementation of the XML-RPC protocol</summary>
5974- <description>A PEAR-ified version of Useful Inc's XML-RPC for PHP.
5975-
5976-It has support for HTTP/HTTPS transport, proxies and authentication.
5977- </description>
5978- <maintainers>
5979- <maintainer>
5980- <user>ssb</user>
5981- <name>Stig Bakken</name>
5982- <email>stig@php.net</email>
5983- <role>lead</role>
5984- </maintainer>
5985- <maintainer>
5986- <user>danielc</user>
5987- <name>Daniel Convissor</name>
5988- <email>danielc@php.net</email>
5989- <role>lead</role>
5990- </maintainer>
5991- </maintainers>
5992- <release>
5993- <version>1.2.2</version>
5994- <date>2005-03-07</date>
5995- <license>PHP License</license>
5996- <state>stable</state>
5997- <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.
5998- </notes>
5999- <filelist>
6000- <file role="php" baseinstalldir="XML" name="RPC.php">
6001- <replace from="@package_version@" to="version" type="package-info"/>
6002- </file>
6003- <file role="php" baseinstalldir="XML/RPC" name="Server.php">
6004- <replace from="@package_version@" to="version" type="package-info"/>
6005- </file>
6006- <file role="php" baseinstalldir="XML/RPC" name="Dump.php">
6007- <replace from="@package_version@" to="version" type="package-info"/>
6008- </file>
6009- <file role="test" name="tests/protoport.php">
6010- <replace from="@package_version@" to="version" type="package-info"/>
6011- </file>
6012- <file role="test" name="tests/test_Dump.php">
6013- <replace from="@package_version@" to="version" type="package-info"/>
6014- </file>
6015- </filelist>
6016- </release>
6017- <changelog>
6018- <release>
6019- <version>1.2.1</version>
6020- <date>2005-03-01</date>
6021- <state>stable</state>
6022- <notes>* Add isset() check before examining the dispatch map. Bug 3658.
6023- </notes>
6024- </release>
6025- <release>
6026- <version>1.2.0</version>
6027- <date>2005-02-27</date>
6028- <state>stable</state>
6029- <notes>* Provide the &quot;stable&quot; release.
6030-* Add package2.xml for compatibility with PEAR 1.4.0.
6031-* For changes since 1.1.0, see the changelogs for the various RC releases.
6032- </notes>
6033- </release>
6034- <release>
6035- <version>1.2.0RC7</version>
6036- <date>2005-02-22</date>
6037- <state>beta</state>
6038- <notes>* Add the setSendEncoding() method and $send_encoding
6039- property to XML_RPC_Message. Request 3537.
6040-* Allow class methods to be mapped using either syntax:
6041- 'function' =&gt; 'hello::sayHello',
6042- or
6043- 'function' =&gt; array('hello', 'sayhello'),
6044- Bug 3363.
6045-* Use 8192 instead of 32768 for bytes in fread()
6046- in parseResponseFile(). Bug 3340.
6047- </notes>
6048- </release>
6049- <release>
6050- <version>1.2.0RC6</version>
6051- <date>2005-01-25</date>
6052- <state>beta</state>
6053- <notes>* Don't put the protocol in the Host field of the POST data. (danielc)
6054- </notes>
6055- </release>
6056- <release>
6057- <version>1.2.0RC5</version>
6058- <date>2005-01-24</date>
6059- <state>beta</state>
6060- <notes>* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
6061- </notes>
6062- </release>
6063- <release>
6064- <version>1.2.0RC4</version>
6065- <date>2005-01-24</date>
6066- <state>beta</state>
6067- <notes>* When a connection attempt fails, have the method return 0. (danielc)
6068-* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
6069-* Add tests for setting the client properties. (danielc)
6070-* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc)
6071-* Bundle the tests with the package. (danielc)
6072- </notes>
6073- </release>
6074- <release>
6075- <version>1.2.0RC3</version>
6076- <date>2005-01-19</date>
6077- <state>beta</state>
6078- <notes>* ssl uses port 443, not 445.
6079- </notes>
6080- </release>
6081- <release>
6082- <version>1.2.0RC2</version>
6083- <date>2005-01-11</date>
6084- <state>beta</state>
6085- <notes>* Handle ssl:// in the $server string. (danielc)
6086-* Also default to port 445 for ssl:// requests as well. (danielc)
6087-* Enhance debugging in the server. (danielc)
6088- </notes>
6089- </release>
6090- <release>
6091- <version>1.2.0RC1</version>
6092- <date>2004-12-30</date>
6093- <state>beta</state>
6094- <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
6095-* Allow array function callbacks (Matt Kane)
6096-* Some minor speed-ups (Matt Kane)
6097-* Add Dump.php to the package (Christian Weiske)
6098-* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
6099-* Silence fsockopen() errors. Bug 1714. (danielc)
6100-* Encode empty arrays as an array. Bug 1493. (danielc)
6101-* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
6102-* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
6103-* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc)
6104-* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
6105-* Allow raiseError() to be called statically. (danielc)
6106-* Stop double escaping of character entities. Bug 987. (danielc)
6107- NOTICE: the following have been removed:
6108- * XML_RPC_dh()
6109- * $GLOBALS['XML_RPC_entities']
6110- * XML_RPC_entity_decode()
6111- * XML_RPC_lookup_entity()
6112-* Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)
6113- </notes>
6114- </release>
6115- <release>
6116- <version>1.1.0</version>
6117- <date>2004-03-15</date>
6118- <state>stable</state>
6119- <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
6120-* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
6121-* Remove &quot;require_once 'PEAR.php'&quot;, include only when needed to raise an error
6122-* Replace echo and error_log() with raiseError() (mroch)
6123-* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
6124-* be tolerant of junk after methodResponse (Luca Mariano, mroch)
6125-* Silent notice even in the error log (pierre)
6126-* fix include of shared xml extension on win32 (pierre)
6127- </notes>
6128- </release>
6129- <release>
6130- <version>1.0.4</version>
6131- <date>2002-10-02</date>
6132- <state>stable</state>
6133- <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)
6134- </notes>
6135- </release>
6136- <release>
6137- <version>1.0.3</version>
6138- <date>2002-05-19</date>
6139- <state>stable</state>
6140- <notes>* fix bug when parsing responses with boolean types
6141- </notes>
6142- </release>
6143- <release>
6144- <version>1.0.2</version>
6145- <date>2002-04-16</date>
6146- <state>stable</state>
6147- <notes>* E_ALL fixes
6148-* fix HTTP response header parsing
6149- </notes>
6150- </release>
6151- <release>
6152- <version>1.0.1</version>
6153- <date>2001-09-25</date>
6154- <state>stable</state>
6155- <notes>This is a PEAR-ified version of Useful Inc's 1.0.1 release.
6156-Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.
6157- </notes>
6158- </release>
6159- </changelog>
6160-</package>
6161-
6162\ Kein Zeilenumbruch am Dateiende.
6163diff -Naur php-5.0.4/pear/packages/XML_RPC-1.3.1.tar hardening-patch-5.0.4-0.3.2/pear/packages/XML_RPC-1.3.1.tar
6164--- php-5.0.4/pear/packages/XML_RPC-1.3.1.tar 1970-01-01 01:00:00.000000000 +0100
6165+++ hardening-patch-5.0.4-0.3.2/pear/packages/XML_RPC-1.3.1.tar 2005-06-29 16:04:30.000000000 +0200
6166@@ -0,0 +1,3733 @@
6167+package2.xml
6168+<package packagerversion="1.4.0a12" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
6169+ <name>XML_RPC</name>
6170+ <channel>pear.php.net</channel>
6171+ <summary>PHP implementation of the XML-RPC protocol</summary>
6172+ <description>A PEAR-ified version of Useful Inc&apos;s XML-RPC for PHP.
6173+
6174+It has support for HTTP/HTTPS transport, proxies and authentication.</description>
6175+ <lead>
6176+ <name>Stig Bakken</name>
6177+ <user>ssb</user>
6178+ <email>stig@php.net</email>
6179+ <active>no</active>
6180+ </lead>
6181+ <lead>
6182+ <name>Daniel Convissor</name>
6183+ <user>danielc</user>
6184+ <email>danielc@php.net</email>
6185+ <active>yes</active>
6186+ </lead>
6187+ <date>2005-06-29</date>
6188+ <time>15:09:18</time>
6189+ <version>
6190+ <release>1.3.1</release>
6191+ <api>1.3.0</api>
6192+ </version>
6193+ <stability>
6194+ <release>stable</release>
6195+ <api>stable</api>
6196+ </stability>
6197+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6198+ <notes>* Security fix. Update highly recommended!</notes>
6199+ <contents>
6200+ <dir name="/">
6201+ <file md5sum="9b06c053e8e534f8d731eb90de2d0681" name="tests/protoport.php" role="test">
6202+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6203+ </file>
6204+ <file md5sum="74d1c90ae551d28bd40030fcc0b0f38d" name="tests/test_Dump.php" role="test">
6205+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6206+ </file>
6207+ <file baseinstalldir="XML/RPC" md5sum="5e2dfc5771116965655e07b4665563ce" name="Dump.php" role="php">
6208+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6209+ </file>
6210+ <file baseinstalldir="XML" md5sum="1e79cf06ae3ada5a6603c003ac0521e3" name="RPC.php" role="php">
6211+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6212+ </file>
6213+ <file baseinstalldir="XML/RPC" md5sum="6a750e3517d25ca01e685e8afe3976d6" name="Server.php" role="php">
6214+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6215+ </file>
6216+ </dir>
6217+ </contents>
6218+ <compatible>
6219+ <name>PEAR</name>
6220+ <channel>pear.php.net</channel>
6221+ <min>1.4.0a1</min>
6222+ <max>1.4.0a12</max>
6223+ </compatible>
6224+ <dependencies>
6225+ <required>
6226+ <php>
6227+ <min>4.2.0</min>
6228+ <max>6.0.0</max>
6229+ </php>
6230+ <pearinstaller>
6231+ <min>1.4.0a1</min>
6232+ </pearinstaller>
6233+ </required>
6234+ </dependencies>
6235+ <phprelease />
6236+ <changelog>
6237+ <release>
6238+ <version>
6239+ <release>1.3.0RC3</release>
6240+ <api>1.3.0</api>
6241+ </version>
6242+ <stability>
6243+ <release>beta</release>
6244+ <api>stable</api>
6245+ </stability>
6246+ <date>2005-05-10</date>
6247+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6248+ <notes>* When verifying requests against function signatures, if the number of parameters don&apos;t match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
6249+* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
6250+* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
6251+* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
6252+* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
6253+* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().</notes>
6254+ </release>
6255+ <release>
6256+ <version>
6257+ <release>1.3.0RC2</release>
6258+ <api>1.3.0</api>
6259+ </version>
6260+ <stability>
6261+ <release>beta</release>
6262+ <api>beta</api>
6263+ </stability>
6264+ <date>2005-05-05</date>
6265+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6266+ <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
6267+* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
6268+* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
6269+* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.</notes>
6270+ </release>
6271+ <release>
6272+ <version>
6273+ <release>1.3.0RC1</release>
6274+ <api>1.3.0</api>
6275+ </version>
6276+ <stability>
6277+ <release>beta</release>
6278+ <api>beta</api>
6279+ </stability>
6280+ <date>2005-04-07</date>
6281+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6282+ <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
6283+* Add Fault Code 6: &quot;The requested method didn&apos;t return an XML_RPC_Response object.&quot; Request 4032.
6284+* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
6285+* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
6286+* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
6287+* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.</notes>
6288+ </release>
6289+ <release>
6290+ <version>
6291+ <release>1.2.2</release>
6292+ <api>1.2.0</api>
6293+ </version>
6294+ <stability>
6295+ <release>stable</release>
6296+ <api>stable</api>
6297+ </stability>
6298+ <date>2005-03-07</date>
6299+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6300+ <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.</notes>
6301+ </release>
6302+ <release>
6303+ <version>
6304+ <release>1.2.1</release>
6305+ <api>1.2.0</api>
6306+ </version>
6307+ <stability>
6308+ <release>stable</release>
6309+ <api>stable</api>
6310+ </stability>
6311+ <date>2005-03-01</date>
6312+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6313+ <notes>* Add isset() check before examining the dispatch map. Bug 3658.</notes>
6314+ </release>
6315+ <release>
6316+ <version>
6317+ <release>1.2.0</release>
6318+ <api>1.2.0</api>
6319+ </version>
6320+ <stability>
6321+ <release>stable</release>
6322+ <api>stable</api>
6323+ </stability>
6324+ <date>2005-02-27</date>
6325+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6326+ <notes>* Provide the &quot;stable&quot; release.
6327+* Add package2.xml for compatibility with PEAR 1.4.0.
6328+* For changes since 1.1.0, see the changelogs for the various RC releases.</notes>
6329+ </release>
6330+ <release>
6331+ <version>
6332+ <release>1.2.0RC7</release>
6333+ <api>1.2.0RC7</api>
6334+ </version>
6335+ <stability>
6336+ <release>beta</release>
6337+ <api>beta</api>
6338+ </stability>
6339+ <date>2005-02-22</date>
6340+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6341+ <notes>* Add the setSendEncoding() method and $send_encoding
6342+ property to XML_RPC_Message. Request 3537.
6343+* Allow class methods to be mapped using either syntax:
6344+ &apos;function&apos; =&gt; &apos;hello::sayHello&apos;,
6345+ or
6346+ &apos;function&apos; =&gt; array(&apos;hello&apos;, &apos;sayhello&apos;),
6347+ Bug 3363.
6348+* Use 8192 instead of 32768 for bytes in fread()
6349+ in parseResponseFile(). Bug 3340.</notes>
6350+ </release>
6351+ <release>
6352+ <version>
6353+ <release>1.2.0RC6</release>
6354+ <api>1.2.0RC6</api>
6355+ </version>
6356+ <stability>
6357+ <release>beta</release>
6358+ <api>beta</api>
6359+ </stability>
6360+ <date>2005-01-25</date>
6361+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6362+ <notes>* Don&apos;t put the protocol in the Host field of the POST data. (danielc)</notes>
6363+ </release>
6364+ <release>
6365+ <version>
6366+ <release>1.2.0RC5</release>
6367+ <api>1.2.0RC5</api>
6368+ </version>
6369+ <stability>
6370+ <release>beta</release>
6371+ <api>beta</api>
6372+ </stability>
6373+ <date>2005-01-24</date>
6374+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6375+ <notes>* If $port is 443 but a protocol isn&apos;t specified in $server, assume ssl:// is the protocol.</notes>
6376+ </release>
6377+ <release>
6378+ <version>
6379+ <release>1.2.0RC4</release>
6380+ <api>1.2.0RC4</api>
6381+ </version>
6382+ <stability>
6383+ <release>beta</release>
6384+ <api>beta</api>
6385+ </stability>
6386+ <date>2005-01-24</date>
6387+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6388+ <notes>* When a connection attempt fails, have the method return 0. (danielc)
6389+* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
6390+* Add tests for setting the client properties. (danielc)
6391+* Remove $GLOBALS[&apos;XML_RPC_twoslash&apos;] since it&apos;s not used. (danielc)
6392+* Bundle the tests with the package. (danielc)</notes>
6393+ </release>
6394+ <release>
6395+ <version>
6396+ <release>1.2.0RC3</release>
6397+ <api>1.2.0RC3</api>
6398+ </version>
6399+ <stability>
6400+ <release>beta</release>
6401+ <api>beta</api>
6402+ </stability>
6403+ <date>2005-01-19</date>
6404+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6405+ <notes>* ssl uses port 443, not 445.</notes>
6406+ </release>
6407+ <release>
6408+ <version>
6409+ <release>1.2.0RC2</release>
6410+ <api>1.2.0RC2</api>
6411+ </version>
6412+ <stability>
6413+ <release>beta</release>
6414+ <api>beta</api>
6415+ </stability>
6416+ <date>2005-01-11</date>
6417+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6418+ <notes>* Handle ssl:// in the $server string. (danielc)
6419+* Also default to port 445 for ssl:// requests as well. (danielc)
6420+* Enhance debugging in the server. (danielc)</notes>
6421+ </release>
6422+ <release>
6423+ <version>
6424+ <release>1.2.0RC1</release>
6425+ <api>1.2.0RC1</api>
6426+ </version>
6427+ <stability>
6428+ <release>beta</release>
6429+ <api>beta</api>
6430+ </stability>
6431+ <date>2004-12-30</date>
6432+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6433+ <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
6434+* Allow array function callbacks (Matt Kane)
6435+* Some minor speed-ups (Matt Kane)
6436+* Add Dump.php to the package (Christian Weiske)
6437+* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
6438+* Silence fsockopen() errors. Bug 1714. (danielc)
6439+* Encode empty arrays as an array. Bug 1493. (danielc)
6440+* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
6441+* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
6442+* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()&apos;ing error messages. (danielc)
6443+* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
6444+* Allow raiseError() to be called statically. (danielc)
6445+* Stop double escaping of character entities. Bug 987. (danielc)
6446+ NOTICE: the following have been removed:
6447+ * XML_RPC_dh()
6448+ * $GLOBALS[&apos;XML_RPC_entities&apos;]
6449+ * XML_RPC_entity_decode()
6450+ * XML_RPC_lookup_entity()
6451+* Determine the XML&apos;s encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)</notes>
6452+ </release>
6453+ <release>
6454+ <version>
6455+ <release>1.1.0</release>
6456+ <api>1.1.0</api>
6457+ </version>
6458+ <stability>
6459+ <release>stable</release>
6460+ <api>stable</api>
6461+ </stability>
6462+ <date>2004-03-15</date>
6463+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6464+ <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
6465+* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
6466+* Remove &quot;require_once &apos;PEAR.php&apos;&quot;, include only when needed to raise an error
6467+* Replace echo and error_log() with raiseError() (mroch)
6468+* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
6469+* be tolerant of junk after methodResponse (Luca Mariano, mroch)
6470+* Silent notice even in the error log (pierre)
6471+* fix include of shared xml extension on win32 (pierre)</notes>
6472+ </release>
6473+ <release>
6474+ <version>
6475+ <release>1.0.4</release>
6476+ <api>1.0.4</api>
6477+ </version>
6478+ <stability>
6479+ <release>stable</release>
6480+ <api>stable</api>
6481+ </stability>
6482+ <date>2002-10-02</date>
6483+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6484+ <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)</notes>
6485+ </release>
6486+ <release>
6487+ <version>
6488+ <release>1.0.3</release>
6489+ <api>1.0.3</api>
6490+ </version>
6491+ <stability>
6492+ <release>stable</release>
6493+ <api>stable</api>
6494+ </stability>
6495+ <date>2002-05-19</date>
6496+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6497+ <notes>* fix bug when parsing responses with boolean types</notes>
6498+ </release>
6499+ <release>
6500+ <version>
6501+ <release>1.0.2</release>
6502+ <api>1.0.2</api>
6503+ </version>
6504+ <stability>
6505+ <release>stable</release>
6506+ <api>stable</api>
6507+ </stability>
6508+ <date>2002-04-16</date>
6509+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6510+ <notes>* E_ALL fixes
6511+* fix HTTP response header parsing</notes>
6512+ </release>
6513+ <release>
6514+ <version>
6515+ <release>1.0.1</release>
6516+ <api>1.0.1</api>
6517+ </version>
6518+ <stability>
6519+ <release>stable</release>
6520+ <api>stable</api>
6521+ </stability>
6522+ <date>2001-09-25</date>
6523+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6524+ <notes>This is a PEAR-ified version of Useful Inc&apos;s 1.0.1 release.
6525+Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.</notes>
6526+ </release>
6527+ </changelog>
6528+</package>
6529+
6530+
6531+/**
6532+ * Tests that properties of XML_RPC_Client get properly set
6533+ *
6534+ * Any individual tests that fail will have their name, expected result
6535+ * and actual result printed out. So seeing no output when executing
6536+ * this file is a good thing.
6537+ *
6538+ * Can be run via CLI or a web server.
6539+ *
6540+ * PHP versions 4 and 5
6541+ *
6542+ * LICENSE: This source file is subject to version 3.0 of the PHP license
6543+ * that is available through the world-wide-web at the following URI:
6544+ * http://www.php.net/license/3_0.txt. If you did not receive a copy of
6545+ * the PHP License and are unable to obtain it through the web, please
6546+ * send a note to license@php.net so we can mail you a copy immediately.
6547+ *
6548+ * @category Web Services
6549+ * @package XML_RPC
6550+ * @author Daniel Convissor <danielc@php.net>
6551+ * @copyright 2005 The PHP Group
6552+ * @license http://www.php.net/license/3_0.txt PHP License
6553+ * @version CVS: $Id: protoport.php,v 1.4 2005/01/24 17:48:47 danielc Exp $
6554+ * @link http://pear.php.net/package/XML_RPC
6555+ * @since File available since Release 1.2
6556+ */
6557+
6558+/*
6559+ * If the package version number is found in the left hand
6560+ * portion of the if() expression below, that means this file has
6561+ * come from the PEAR installer. Therefore, let's test the
6562+ * installed version of XML_RPC which should be in the include path.
6563+ *
6564+ * If the version has not been substituted in the if() expression,
6565+ * this file has likely come from a CVS checkout or a .tar file.
6566+ * Therefore, we'll assume the tests should use the version of
6567+ * XML_RPC that has come from there as well.
6568+ */
6569+if ('1.3.1' != '@'.'package_version'.'@') {
6570+ /**
6571+ * Get the needed class from the PEAR installation
6572+ */
6573+ require_once 'XML/RPC.php';
6574+} else {
6575+ /**
6576+ * Get the needed class from the parent directory
6577+ */
6578+ require_once '../RPC.php';
6579+}
6580+
6581+/**
6582+ * Compare the test result to the expected result
6583+ *
6584+ * If the test fails, echo out the results.
6585+ *
6586+ * @param array $expect the array of object properties you expect
6587+ * from the test
6588+ * @param object $actual the object results from the test
6589+ * @param string $test_name the name of the test
6590+ *
6591+ * @return void
6592+ */
6593+function compare($expect, $actual, $test_name) {
6594+ $actual = get_object_vars($actual);
6595+ if (count(array_diff($actual, $expect))) {
6596+ echo "$test_name failed.\nExpect: ";
6597+ print_r($expect);
6598+ echo "Actual: ";
6599+ print_r($actual);
6600+ echo "\n";
6601+ }
6602+}
6603+
6604+if (php_sapi_name() != 'cli') {
6605+ echo "<pre>\n";
6606+}
6607+
6608+
6609+$x = array(
6610+ 'path' => 'thepath',
6611+ 'server' => 'theserver',
6612+ 'protocol' => 'http://',
6613+ 'port' => 80,
6614+ 'proxy' => '',
6615+ 'proxy_protocol' => 'http://',
6616+ 'proxy_port' => 8080,
6617+ 'proxy_user' => '',
6618+ 'proxy_pass' => '',
6619+ 'errno' => 0,
6620+ 'errstring' => '',
6621+ 'debug' => 0,
6622+ 'username' => '',
6623+ 'password' => '',
6624+);
6625+$c = new XML_RPC_Client('thepath', 'theserver');
6626+compare($x, $c, 'defaults');
6627+
6628+$x = array(
6629+ 'path' => 'thepath',
6630+ 'server' => 'theserver',
6631+ 'protocol' => 'http://',
6632+ 'port' => 80,
6633+ 'proxy' => '',
6634+ 'proxy_protocol' => 'http://',
6635+ 'proxy_port' => 8080,
6636+ 'proxy_user' => '',
6637+ 'proxy_pass' => '',
6638+ 'errno' => 0,
6639+ 'errstring' => '',
6640+ 'debug' => 0,
6641+ 'username' => '',
6642+ 'password' => '',
6643+);
6644+$c = new XML_RPC_Client('thepath', 'http://theserver');
6645+compare($x, $c, 'defaults with http');
6646+
6647+$x = array(
6648+ 'path' => 'thepath',
6649+ 'server' => 'theserver',
6650+ 'protocol' => 'ssl://',
6651+ 'port' => 443,
6652+ 'proxy' => '',
6653+ 'proxy_protocol' => 'http://',
6654+ 'proxy_port' => 8080,
6655+ 'proxy_user' => '',
6656+ 'proxy_pass' => '',
6657+ 'errno' => 0,
6658+ 'errstring' => '',
6659+ 'debug' => 0,
6660+ 'username' => '',
6661+ 'password' => '',
6662+);
6663+$c = new XML_RPC_Client('thepath', 'https://theserver');
6664+compare($x, $c, 'defaults with https');
6665+
6666+$x = array(
6667+ 'path' => 'thepath',
6668+ 'server' => 'theserver',
6669+ 'protocol' => 'ssl://',
6670+ 'port' => 443,
6671+ 'proxy' => '',
6672+ 'proxy_protocol' => 'http://',
6673+ 'proxy_port' => 8080,
6674+ 'proxy_user' => '',
6675+ 'proxy_pass' => '',
6676+ 'errno' => 0,
6677+ 'errstring' => '',
6678+ 'debug' => 0,
6679+ 'username' => '',
6680+ 'password' => '',
6681+);
6682+$c = new XML_RPC_Client('thepath', 'ssl://theserver');
6683+compare($x, $c, 'defaults with ssl');
6684+
6685+
6686+$x = array(
6687+ 'path' => 'thepath',
6688+ 'server' => 'theserver',
6689+ 'protocol' => 'http://',
6690+ 'port' => 65,
6691+ 'proxy' => '',
6692+ 'proxy_protocol' => 'http://',
6693+ 'proxy_port' => 8080,
6694+ 'proxy_user' => '',
6695+ 'proxy_pass' => '',
6696+ 'errno' => 0,
6697+ 'errstring' => '',
6698+ 'debug' => 0,
6699+ 'username' => '',
6700+ 'password' => '',
6701+);
6702+$c = new XML_RPC_Client('thepath', 'theserver', 65);
6703+compare($x, $c, 'port 65');
6704+
6705+$x = array(
6706+ 'path' => 'thepath',
6707+ 'server' => 'theserver',
6708+ 'protocol' => 'http://',
6709+ 'port' => 65,
6710+ 'proxy' => '',
6711+ 'proxy_protocol' => 'http://',
6712+ 'proxy_port' => 8080,
6713+ 'proxy_user' => '',
6714+ 'proxy_pass' => '',
6715+ 'errno' => 0,
6716+ 'errstring' => '',
6717+ 'debug' => 0,
6718+ 'username' => '',
6719+ 'password' => '',
6720+);
6721+$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
6722+compare($x, $c, 'port 65 with http');
6723+
6724+$x = array(
6725+ 'path' => 'thepath',
6726+ 'server' => 'theserver',
6727+ 'protocol' => 'ssl://',
6728+ 'port' => 65,
6729+ 'proxy' => '',
6730+ 'proxy_protocol' => 'http://',
6731+ 'proxy_port' => 8080,
6732+ 'proxy_user' => '',
6733+ 'proxy_pass' => '',
6734+ 'errno' => 0,
6735+ 'errstring' => '',
6736+ 'debug' => 0,
6737+ 'username' => '',
6738+ 'password' => '',
6739+);
6740+$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
6741+compare($x, $c, 'port 65 with https');
6742+
6743+$x = array(
6744+ 'path' => 'thepath',
6745+ 'server' => 'theserver',
6746+ 'protocol' => 'ssl://',
6747+ 'port' => 65,
6748+ 'proxy' => '',
6749+ 'proxy_protocol' => 'http://',
6750+ 'proxy_port' => 8080,
6751+ 'proxy_user' => '',
6752+ 'proxy_pass' => '',
6753+ 'errno' => 0,
6754+ 'errstring' => '',
6755+ 'debug' => 0,
6756+ 'username' => '',
6757+ 'password' => '',
6758+);
6759+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
6760+compare($x, $c, 'port 65 with ssl');
6761+
6762+
6763+$x = array(
6764+ 'path' => 'thepath',
6765+ 'server' => 'theserver',
6766+ 'protocol' => 'http://',
6767+ 'port' => 80,
6768+ 'proxy' => 'theproxy',
6769+ 'proxy_protocol' => 'http://',
6770+ 'proxy_port' => 8080,
6771+ 'proxy_user' => '',
6772+ 'proxy_pass' => '',
6773+ 'errno' => 0,
6774+ 'errstring' => '',
6775+ 'debug' => 0,
6776+ 'username' => '',
6777+ 'password' => '',
6778+);
6779+$c = new XML_RPC_Client('thepath', 'theserver', 0,
6780+ 'theproxy');
6781+compare($x, $c, 'defaults proxy');
6782+
6783+$x = array(
6784+ 'path' => 'thepath',
6785+ 'server' => 'theserver',
6786+ 'protocol' => 'http://',
6787+ 'port' => 80,
6788+ 'proxy' => 'theproxy',
6789+ 'proxy_protocol' => 'http://',
6790+ 'proxy_port' => 8080,
6791+ 'proxy_user' => '',
6792+ 'proxy_pass' => '',
6793+ 'errno' => 0,
6794+ 'errstring' => '',
6795+ 'debug' => 0,
6796+ 'username' => '',
6797+ 'password' => '',
6798+);
6799+$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
6800+ 'http://theproxy');
6801+compare($x, $c, 'defaults with http proxy');
6802+
6803+$x = array(
6804+ 'path' => 'thepath',
6805+ 'server' => 'theserver',
6806+ 'protocol' => 'ssl://',
6807+ 'port' => 443,
6808+ 'proxy' => 'theproxy',
6809+ 'proxy_protocol' => 'ssl://',
6810+ 'proxy_port' => 443,
6811+ 'proxy_user' => '',
6812+ 'proxy_pass' => '',
6813+ 'errno' => 0,
6814+ 'errstring' => '',
6815+ 'debug' => 0,
6816+ 'username' => '',
6817+ 'password' => '',
6818+);
6819+$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
6820+ 'https://theproxy');
6821+compare($x, $c, 'defaults with https proxy');
6822+
6823+$x = array(
6824+ 'path' => 'thepath',
6825+ 'server' => 'theserver',
6826+ 'protocol' => 'ssl://',
6827+ 'port' => 443,
6828+ 'proxy' => 'theproxy',
6829+ 'proxy_protocol' => 'ssl://',
6830+ 'proxy_port' => 443,
6831+ 'proxy_user' => '',
6832+ 'proxy_pass' => '',
6833+ 'errno' => 0,
6834+ 'errstring' => '',
6835+ 'debug' => 0,
6836+ 'username' => '',
6837+ 'password' => '',
6838+);
6839+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
6840+ 'ssl://theproxy');
6841+compare($x, $c, 'defaults with ssl proxy');
6842+
6843+
6844+$x = array(
6845+ 'path' => 'thepath',
6846+ 'server' => 'theserver',
6847+ 'protocol' => 'http://',
6848+ 'port' => 65,
6849+ 'proxy' => 'theproxy',
6850+ 'proxy_protocol' => 'http://',
6851+ 'proxy_port' => 6565,
6852+ 'proxy_user' => '',
6853+ 'proxy_pass' => '',
6854+ 'errno' => 0,
6855+ 'errstring' => '',
6856+ 'debug' => 0,
6857+ 'username' => '',
6858+ 'password' => '',
6859+);
6860+$c = new XML_RPC_Client('thepath', 'theserver', 65,
6861+ 'theproxy', 6565);
6862+compare($x, $c, 'port 65 proxy 6565');
6863+
6864+$x = array(
6865+ 'path' => 'thepath',
6866+ 'server' => 'theserver',
6867+ 'protocol' => 'http://',
6868+ 'port' => 65,
6869+ 'proxy' => 'theproxy',
6870+ 'proxy_protocol' => 'http://',
6871+ 'proxy_port' => 6565,
6872+ 'proxy_user' => '',
6873+ 'proxy_pass' => '',
6874+ 'errno' => 0,
6875+ 'errstring' => '',
6876+ 'debug' => 0,
6877+ 'username' => '',
6878+ 'password' => '',
6879+);
6880+$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
6881+ 'http://theproxy', 6565);
6882+compare($x, $c, 'port 65 with http proxy 6565');
6883+
6884+$x = array(
6885+ 'path' => 'thepath',
6886+ 'server' => 'theserver',
6887+ 'protocol' => 'ssl://',
6888+ 'port' => 65,
6889+ 'proxy' => 'theproxy',
6890+ 'proxy_protocol' => 'ssl://',
6891+ 'proxy_port' => 6565,
6892+ 'proxy_user' => '',
6893+ 'proxy_pass' => '',
6894+ 'errno' => 0,
6895+ 'errstring' => '',
6896+ 'debug' => 0,
6897+ 'username' => '',
6898+ 'password' => '',
6899+);
6900+$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
6901+ 'https://theproxy', 6565);
6902+compare($x, $c, 'port 65 with https proxy 6565');
6903+
6904+$x = array(
6905+ 'path' => 'thepath',
6906+ 'server' => 'theserver',
6907+ 'protocol' => 'ssl://',
6908+ 'port' => 65,
6909+ 'proxy' => 'theproxy',
6910+ 'proxy_protocol' => 'ssl://',
6911+ 'proxy_port' => 6565,
6912+ 'proxy_user' => '',
6913+ 'proxy_pass' => '',
6914+ 'errno' => 0,
6915+ 'errstring' => '',
6916+ 'debug' => 0,
6917+ 'username' => '',
6918+ 'password' => '',
6919+);
6920+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
6921+ 'ssl://theproxy', 6565);
6922+compare($x, $c, 'port 65 with ssl proxy 6565');
6923+
6924+
6925+$x = array(
6926+ 'path' => 'thepath',
6927+ 'server' => 'theserver',
6928+ 'protocol' => 'ssl://',
6929+ 'port' => 443,
6930+ 'proxy' => 'theproxy',
6931+ 'proxy_protocol' => 'ssl://',
6932+ 'proxy_port' => 443,
6933+ 'proxy_user' => '',
6934+ 'proxy_pass' => '',
6935+ 'errno' => 0,
6936+ 'errstring' => '',
6937+ 'debug' => 0,
6938+ 'username' => '',
6939+ 'password' => '',
6940+);
6941+$c = new XML_RPC_Client('thepath', 'theserver', 443,
6942+ 'theproxy', 443);
6943+compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
6944+
6945+$x = array(
6946+ 'path' => 'thepath',
6947+ 'server' => 'theserver',
6948+ 'protocol' => 'http://',
6949+ 'port' => 80,
6950+ 'proxy' => 'theproxy',
6951+ 'proxy_protocol' => 'ssl://',
6952+ 'proxy_port' => 6565,
6953+ 'proxy_user' => '',
6954+ 'proxy_pass' => '',
6955+ 'errno' => 0,
6956+ 'errstring' => '',
6957+ 'debug' => 0,
6958+ 'username' => '',
6959+ 'password' => '',
6960+);
6961+$c = new XML_RPC_Client('thepath', 'theserver', 0,
6962+ 'ssl://theproxy', 6565);
6963+compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
6964+
6965+
6966+/*
6967+ * If the package version number is found in the left hand
6968+ * portion of the if() expression below, that means this file has
6969+ * come from the PEAR installer. Therefore, let's test the
6970+ * installed version of XML_RPC which should be in the include path.
6971+ *
6972+ * If the version has not been substituted in the if() expression,
6973+ * this file has likely come from a CVS checkout or a .tar file.
6974+ * Therefore, we'll assume the tests should use the version of
6975+ * XML_RPC that has come from there as well.
6976+ */
6977+if ('1.3.1' != '@'.'package_version'.'@') {
6978+ /**
6979+ * Get the needed class from the PEAR installation
6980+ */
6981+ require_once 'XML/RPC/Dump.php';
6982+} else {
6983+ /**
6984+ * Get the needed class from the parent directory
6985+ */
6986+ require_once '../Dump.php';
6987+}
6988+
6989+$val = new XML_RPC_Value(array(
6990+ 'title' =>new XML_RPC_Value('das ist der Titel', 'string'),
6991+ 'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
6992+ 'endDate' =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
6993+ 'error' =>'string',
6994+ 'arkey' => new XML_RPC_Value( array(
6995+ new XML_RPC_Value('simple string'),
6996+ new XML_RPC_Value(12345, 'int')
6997+ ), 'array')
6998+ )
6999+ ,'struct');
7000+
7001+XML_RPC_Dump($val);
7002+
7003+echo '==============' . "\r\n";
7004+$val2 = new XML_RPC_Value(44353, 'int');
7005+XML_RPC_Dump($val2);
7006+
7007+echo '==============' . "\r\n";
7008+$val3 = new XML_RPC_Value('this should be a string', 'string');
7009+XML_RPC_Dump($val3);
7010+
7011+echo '==============' . "\r\n";
7012+$val4 = new XML_RPC_Value(true, 'boolean');
7013+XML_RPC_Dump($val4);
7014+
7015+
7016+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
7017+
7018+/**
7019+ * Function and class to dump XML_RPC_Value objects in a nice way
7020+ *
7021+ * Should be helpful as a normal var_dump(..) displays all internals which
7022+ * doesn't really give you an overview due to too much information.
7023+ *
7024+ * @category Web Services
7025+ * @package XML_RPC
7026+ * @author Christian Weiske <cweiske@php.net>
7027+ * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $
7028+ * @link http://pear.php.net/package/XML_RPC
7029+ */
7030+
7031+
7032+/**
7033+ * Pull in the XML_RPC class
7034+ */
7035+require_once 'XML/RPC.php';
7036+
7037+
7038+/**
7039+ * Generates the dump of the XML_RPC_Value and echoes it
7040+ *
7041+ * @param object $value the XML_RPC_Value object to dump
7042+ *
7043+ * @return void
7044+ */
7045+function XML_RPC_Dump($value)
7046+{
7047+ $dumper = new XML_RPC_Dump();
7048+ echo $dumper->generateDump($value);
7049+}
7050+
7051+
7052+/**
7053+ * Class which generates a dump of a XML_RPC_Value object
7054+ *
7055+ * @category Web Services
7056+ * @package XML_RPC
7057+ * @author Christian Weiske <cweiske@php.net>
7058+ * @version Release: 1.3.1
7059+ * @link http://pear.php.net/package/XML_RPC
7060+ */
7061+class XML_RPC_Dump
7062+{
7063+ /**
7064+ * The indentation array cache
7065+ * @var array
7066+ */
7067+ var $arIndent = array();
7068+
7069+ /**
7070+ * The spaces used for indenting the XML
7071+ * @var string
7072+ */
7073+ var $strBaseIndent = ' ';
7074+
7075+ /**
7076+ * Returns the dump in XML format without printing it out
7077+ *
7078+ * @param object $value the XML_RPC_Value object to dump
7079+ * @param int $nLevel the level of indentation
7080+ *
7081+ * @return string the dump
7082+ */
7083+ function generateDump($value, $nLevel = 0)
7084+ {
7085+ if (!is_object($value) && get_class($value) != 'xml_rpc_value') {
7086+ require_once 'PEAR.php';
7087+ PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n",
7088+ 0, PEAR_ERROR_PRINT);
7089+ if (is_object($value)) {
7090+ $strType = get_class($value);
7091+ } else {
7092+ $strType = gettype($value);
7093+ }
7094+ return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: '
7095+ . $strType . "\r\n";
7096+ }
7097+
7098+ switch ($value->kindOf()) {
7099+ case 'struct':
7100+ $ret = $this->genStruct($value, $nLevel);
7101+ break;
7102+ case 'array':
7103+ $ret = $this->genArray($value, $nLevel);
7104+ break;
7105+ case 'scalar':
7106+ $ret = $this->genScalar($value->scalarval(), $nLevel);
7107+ break;
7108+ default:
7109+ require_once 'PEAR.php';
7110+ PEAR::raiseError('Illegal type "' . $value->kindOf()
7111+ . '" in XML_RPC_Value' . "\r\n", 0,
7112+ PEAR_ERROR_PRINT);
7113+ }
7114+
7115+ return $ret;
7116+ }
7117+
7118+ /**
7119+ * Returns the scalar value dump
7120+ *
7121+ * @param object $value the scalar XML_RPC_Value object to dump
7122+ * @param int $nLevel the level of indentation
7123+ *
7124+ * @return string Dumped version of the scalar value
7125+ */
7126+ function genScalar($value, $nLevel)
7127+ {
7128+ if (gettype($value) == 'object') {
7129+ $strClass = ' ' . get_class($value);
7130+ } else {
7131+ $strClass = '';
7132+ }
7133+ return $this->getIndent($nLevel) . gettype($value) . $strClass
7134+ . ' ' . $value . "\r\n";
7135+ }
7136+
7137+ /**
7138+ * Returns the dump of a struct
7139+ *
7140+ * @param object $value the struct XML_RPC_Value object to dump
7141+ * @param int $nLevel the level of indentation
7142+ *
7143+ * @return string Dumped version of the scalar value
7144+ */
7145+ function genStruct($value, $nLevel)
7146+ {
7147+ $value->structreset();
7148+ $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n";
7149+ while (list($key, $keyval) = $value->structeach()) {
7150+ $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n";
7151+ $strOutput .= $this->generateDump($keyval, $nLevel + 2);
7152+ }
7153+ return $strOutput;
7154+ }
7155+
7156+ /**
7157+ * Returns the dump of an array
7158+ *
7159+ * @param object $value the array XML_RPC_Value object to dump
7160+ * @param int $nLevel the level of indentation
7161+ *
7162+ * @return string Dumped version of the scalar value
7163+ */
7164+ function genArray($value, $nLevel)
7165+ {
7166+ $nSize = $value->arraysize();
7167+ $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n";
7168+ for($nA = 0; $nA < $nSize; $nA++) {
7169+ $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n";
7170+ $strOutput .= $this->generateDump($value->arraymem($nA),
7171+ $nLevel + 2);
7172+ }
7173+ return $strOutput;
7174+ }
7175+
7176+ /**
7177+ * Returns the indent for a specific level and caches it for faster use
7178+ *
7179+ * @param int $nLevel the level
7180+ *
7181+ * @return string the indented string
7182+ */
7183+ function getIndent($nLevel)
7184+ {
7185+ if (!isset($this->arIndent[$nLevel])) {
7186+ $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel);
7187+ }
7188+ return $this->arIndent[$nLevel];
7189+ }
7190+}
7191+
7192+/*
7193+ * Local variables:
7194+ * tab-width: 4
7195+ * c-basic-offset: 4
7196+ * c-hanging-comment-ender-p: nil
7197+ * End:
7198+ */
7199+
7200+?>
7201+
7202+
7203+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
7204+
7205+/**
7206+ * PHP implementation of the XML-RPC protocol
7207+ *
7208+ * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
7209+ * It has support for HTTP transport, proxies and authentication.
7210+ *
7211+ * PHP versions 4 and 5
7212+ *
7213+ * LICENSE: License is granted to use or modify this software
7214+ * ("XML-RPC for PHP") for commercial or non-commercial use provided the
7215+ * copyright of the author is preserved in any distributed or derivative work.
7216+ *
7217+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
7218+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
7219+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
7220+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
7221+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
7222+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
7223+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7224+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7225+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
7226+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7227+ *
7228+ * @category Web Services
7229+ * @package XML_RPC
7230+ * @author Edd Dumbill <edd@usefulinc.com>
7231+ * @author Stig Bakken <stig@php.net>
7232+ * @author Martin Jansen <mj@php.net>
7233+ * @author Daniel Convissor <danielc@php.net>
7234+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7235+ * @version CVS: $Id: RPC.php,v 1.74 2005/05/09 20:51:54 danielc Exp $
7236+ * @link http://pear.php.net/package/XML_RPC
7237+ */
7238+
7239+
7240+if (!function_exists('xml_parser_create')) {
7241+ PEAR::loadExtension('xml');
7242+}
7243+
7244+/**#@+
7245+ * Error constants
7246+ */
7247+/**
7248+ * Parameter values don't match parameter types
7249+ */
7250+define('XML_RPC_ERROR_INVALID_TYPE', 101);
7251+/**
7252+ * Parameter declared to be numeric but the values are not
7253+ */
7254+define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
7255+/**
7256+ * Communication error
7257+ */
7258+define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
7259+/**
7260+ * The array or struct has already been started
7261+ */
7262+define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
7263+/**
7264+ * Incorrect parameters submitted
7265+ */
7266+define('XML_RPC_ERROR_INCORRECT_PARAMS', 105);
7267+/**
7268+ * Programming error by developer
7269+ */
7270+define('XML_RPC_ERROR_PROGRAMMING', 106);
7271+/**#@-*/
7272+
7273+
7274+/**
7275+ * Data types
7276+ * @global string $GLOBALS['XML_RPC_I4']
7277+ */
7278+$GLOBALS['XML_RPC_I4'] = 'i4';
7279+
7280+/**
7281+ * Data types
7282+ * @global string $GLOBALS['XML_RPC_Int']
7283+ */
7284+$GLOBALS['XML_RPC_Int'] = 'int';
7285+
7286+/**
7287+ * Data types
7288+ * @global string $GLOBALS['XML_RPC_Boolean']
7289+ */
7290+$GLOBALS['XML_RPC_Boolean'] = 'boolean';
7291+
7292+/**
7293+ * Data types
7294+ * @global string $GLOBALS['XML_RPC_Double']
7295+ */
7296+$GLOBALS['XML_RPC_Double'] = 'double';
7297+
7298+/**
7299+ * Data types
7300+ * @global string $GLOBALS['XML_RPC_String']
7301+ */
7302+$GLOBALS['XML_RPC_String'] = 'string';
7303+
7304+/**
7305+ * Data types
7306+ * @global string $GLOBALS['XML_RPC_DateTime']
7307+ */
7308+$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601';
7309+
7310+/**
7311+ * Data types
7312+ * @global string $GLOBALS['XML_RPC_Base64']
7313+ */
7314+$GLOBALS['XML_RPC_Base64'] = 'base64';
7315+
7316+/**
7317+ * Data types
7318+ * @global string $GLOBALS['XML_RPC_Array']
7319+ */
7320+$GLOBALS['XML_RPC_Array'] = 'array';
7321+
7322+/**
7323+ * Data types
7324+ * @global string $GLOBALS['XML_RPC_Struct']
7325+ */
7326+$GLOBALS['XML_RPC_Struct'] = 'struct';
7327+
7328+
7329+/**
7330+ * Data type meta-types
7331+ * @global array $GLOBALS['XML_RPC_Types']
7332+ */
7333+$GLOBALS['XML_RPC_Types'] = array(
7334+ $GLOBALS['XML_RPC_I4'] => 1,
7335+ $GLOBALS['XML_RPC_Int'] => 1,
7336+ $GLOBALS['XML_RPC_Boolean'] => 1,
7337+ $GLOBALS['XML_RPC_String'] => 1,
7338+ $GLOBALS['XML_RPC_Double'] => 1,
7339+ $GLOBALS['XML_RPC_DateTime'] => 1,
7340+ $GLOBALS['XML_RPC_Base64'] => 1,
7341+ $GLOBALS['XML_RPC_Array'] => 2,
7342+ $GLOBALS['XML_RPC_Struct'] => 3,
7343+);
7344+
7345+
7346+/**
7347+ * Error message numbers
7348+ * @global array $GLOBALS['XML_RPC_err']
7349+ */
7350+$GLOBALS['XML_RPC_err'] = array(
7351+ 'unknown_method' => 1,
7352+ 'invalid_return' => 2,
7353+ 'incorrect_params' => 3,
7354+ 'introspect_unknown' => 4,
7355+ 'http_error' => 5,
7356+ 'not_response_object' => 6,
7357+);
7358+
7359+/**
7360+ * Error message strings
7361+ * @global array $GLOBALS['XML_RPC_str']
7362+ */
7363+$GLOBALS['XML_RPC_str'] = array(
7364+ 'unknown_method' => 'Unknown method',
7365+ 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload',
7366+ 'incorrect_params' => 'Incorrect parameters passed to method',
7367+ 'introspect_unknown' => 'Can\'t introspect: method unknown',
7368+ 'http_error' => 'Didn\'t receive 200 OK from remote server.',
7369+ 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.',
7370+);
7371+
7372+
7373+/**
7374+ * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII)
7375+ * @global string $GLOBALS['XML_RPC_defencoding']
7376+ */
7377+$GLOBALS['XML_RPC_defencoding'] = 'UTF-8';
7378+
7379+/**
7380+ * User error codes start at 800
7381+ * @global int $GLOBALS['XML_RPC_erruser']
7382+ */
7383+$GLOBALS['XML_RPC_erruser'] = 800;
7384+
7385+/**
7386+ * XML parse error codes start at 100
7387+ * @global int $GLOBALS['XML_RPC_errxml']
7388+ */
7389+$GLOBALS['XML_RPC_errxml'] = 100;
7390+
7391+
7392+/**
7393+ * Compose backslashes for escaping regexp
7394+ * @global string $GLOBALS['XML_RPC_backslash']
7395+ */
7396+$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92);
7397+
7398+
7399+/**
7400+ * Stores state during parsing
7401+ *
7402+ * quick explanation of components:
7403+ * + st = builds up a string for evaluation
7404+ * + ac = accumulates values
7405+ * + qt = decides if quotes are needed for evaluation
7406+ * + cm = denotes struct or array (comma needed)
7407+ * + isf = indicates a fault
7408+ * + lv = indicates "looking for a value": implements the logic
7409+ * to allow values with no types to be strings
7410+ * + params = stores parameters in method calls
7411+ * + method = stores method name
7412+ *
7413+ * @global array $GLOBALS['XML_RPC_xh']
7414+ */
7415+$GLOBALS['XML_RPC_xh'] = array();
7416+
7417+
7418+/**
7419+ * Start element handler for the XML parser
7420+ *
7421+ * @return void
7422+ */
7423+function XML_RPC_se($parser_resource, $name, $attrs)
7424+{
7425+ global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String;
7426+ $parser = (int) $parser_resource;
7427+
7428+ switch ($name) {
7429+ case 'STRUCT':
7430+ case 'ARRAY':
7431+ $XML_RPC_xh[$parser]['st'] .= 'array(';
7432+ $XML_RPC_xh[$parser]['cm']++;
7433+ // this last line turns quoting off
7434+ // this means if we get an empty array we'll
7435+ // simply get a bit of whitespace in the eval
7436+ $XML_RPC_xh[$parser]['qt'] = 0;
7437+ break;
7438+
7439+ case 'NAME':
7440+ $XML_RPC_xh[$parser]['st'] .= '"';
7441+ $XML_RPC_xh[$parser]['ac'] = '';
7442+ break;
7443+
7444+ case 'FAULT':
7445+ $XML_RPC_xh[$parser]['isf'] = 1;
7446+ break;
7447+
7448+ case 'PARAM':
7449+ $XML_RPC_xh[$parser]['st'] = '';
7450+ break;
7451+
7452+ case 'VALUE':
7453+ $XML_RPC_xh[$parser]['st'] .= 'new XML_RPC_Value(';
7454+ $XML_RPC_xh[$parser]['lv'] = 1;
7455+ $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String;
7456+ $XML_RPC_xh[$parser]['ac'] = '';
7457+ $XML_RPC_xh[$parser]['qt'] = 0;
7458+ // look for a value: if this is still 1 by the
7459+ // time we reach the first data segment then the type is string
7460+ // by implication and we need to add in a quote
7461+ break;
7462+
7463+ case 'I4':
7464+ case 'INT':
7465+ case 'STRING':
7466+ case 'BOOLEAN':
7467+ case 'DOUBLE':
7468+ case 'DATETIME.ISO8601':
7469+ case 'BASE64':
7470+ $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator
7471+
7472+ if ($name == 'DATETIME.ISO8601' || $name == 'STRING') {
7473+ $XML_RPC_xh[$parser]['qt'] = 1;
7474+
7475+ if ($name == 'DATETIME.ISO8601') {
7476+ $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime;
7477+ }
7478+
7479+ } elseif ($name == 'BASE64') {
7480+ $XML_RPC_xh[$parser]['qt'] = 2;
7481+ } else {
7482+ // No quoting is required here -- but
7483+ // at the end of the element we must check
7484+ // for data format errors.
7485+ $XML_RPC_xh[$parser]['qt'] = 0;
7486+ }
7487+ break;
7488+
7489+ case 'MEMBER':
7490+ $XML_RPC_xh[$parser]['ac'] = '';
7491+ }
7492+
7493+ if ($name != 'VALUE') {
7494+ $XML_RPC_xh[$parser]['lv'] = 0;
7495+ }
7496+}
7497+
7498+/**
7499+ * End element handler for the XML parser
7500+ *
7501+ * @return void
7502+ */
7503+function XML_RPC_ee($parser_resource, $name)
7504+{
7505+ global $XML_RPC_xh, $XML_RPC_Types, $XML_RPC_String;
7506+ $parser = (int) $parser_resource;
7507+
7508+ switch ($name) {
7509+ case 'STRUCT':
7510+ case 'ARRAY':
7511+ if ($XML_RPC_xh[$parser]['cm']
7512+ && substr($XML_RPC_xh[$parser]['st'], -1) == ',')
7513+ {
7514+ $XML_RPC_xh[$parser]['st'] = substr($XML_RPC_xh[$parser]['st'], 0, -1);
7515+ }
7516+
7517+ $XML_RPC_xh[$parser]['st'] .= ')';
7518+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
7519+ $XML_RPC_xh[$parser]['cm']--;
7520+ break;
7521+
7522+ case 'NAME':
7523+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . '" => ';
7524+ break;
7525+
7526+ case 'BOOLEAN':
7527+ // special case here: we translate boolean 1 or 0 into PHP
7528+ // constants true or false
7529+ if ($XML_RPC_xh[$parser]['ac'] == '1') {
7530+ $XML_RPC_xh[$parser]['ac'] = 'true';
7531+ } else {
7532+ $XML_RPC_xh[$parser]['ac'] = 'false';
7533+ }
7534+
7535+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
7536+ // Drop through intentionally.
7537+
7538+ case 'I4':
7539+ case 'INT':
7540+ case 'STRING':
7541+ case 'DOUBLE':
7542+ case 'DATETIME.ISO8601':
7543+ case 'BASE64':
7544+ if ($XML_RPC_xh[$parser]['qt'] == 1) {
7545+ // we use double quotes rather than single so backslashification works OK
7546+ $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
7547+ } elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
7548+ $XML_RPC_xh[$parser]['st'] .= 'base64_decode("'
7549+ . $XML_RPC_xh[$parser]['ac'] . '")';
7550+ } elseif ($name == 'BOOLEAN') {
7551+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
7552+ } else {
7553+ // we have an I4, INT or a DOUBLE
7554+ // we must check that only 0123456789-.<space> are characters here
7555+ if (!ereg("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) {
7556+ XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE',
7557+ XML_RPC_ERROR_NON_NUMERIC_FOUND);
7558+ $XML_RPC_xh[$parser]['st'] .= 'XML_RPC_ERROR_NON_NUMERIC_FOUND';
7559+ } else {
7560+ // it's ok, add it on
7561+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
7562+ }
7563+ }
7564+
7565+ $XML_RPC_xh[$parser]['ac'] = '';
7566+ $XML_RPC_xh[$parser]['qt'] = 0;
7567+ $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value
7568+ break;
7569+
7570+ case 'VALUE':
7571+ // deal with a string value
7572+ if (strlen($XML_RPC_xh[$parser]['ac']) > 0 &&
7573+ $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) {
7574+
7575+ $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
7576+ }
7577+
7578+ // This if () detects if no scalar was inside <VALUE></VALUE>
7579+ // and pads an empty "".
7580+ if ($XML_RPC_xh[$parser]['st'][strlen($XML_RPC_xh[$parser]['st'])-1] == '(') {
7581+ $XML_RPC_xh[$parser]['st'] .= '""';
7582+ }
7583+ $XML_RPC_xh[$parser]['st'] .= ", '" . $XML_RPC_xh[$parser]['vt'] . "')";
7584+ if ($XML_RPC_xh[$parser]['cm']) {
7585+ $XML_RPC_xh[$parser]['st'] .= ',';
7586+ }
7587+ break;
7588+
7589+ case 'MEMBER':
7590+ $XML_RPC_xh[$parser]['ac'] = '';
7591+ $XML_RPC_xh[$parser]['qt'] = 0;
7592+ break;
7593+
7594+ case 'DATA':
7595+ $XML_RPC_xh[$parser]['ac'] = '';
7596+ $XML_RPC_xh[$parser]['qt'] = 0;
7597+ break;
7598+
7599+ case 'PARAM':
7600+ $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['st'];
7601+ break;
7602+
7603+ case 'METHODNAME':
7604+ case 'RPCMETHODNAME':
7605+ $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", '',
7606+ $XML_RPC_xh[$parser]['ac']);
7607+ break;
7608+ }
7609+
7610+ // if it's a valid type name, set the type
7611+ if (isset($XML_RPC_Types[strtolower($name)])) {
7612+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
7613+ }
7614+}
7615+
7616+/**
7617+ * Character data handler for the XML parser
7618+ *
7619+ * @return void
7620+ */
7621+function XML_RPC_cd($parser_resource, $data)
7622+{
7623+ global $XML_RPC_xh, $XML_RPC_backslash;
7624+ $parser = (int) $parser_resource;
7625+
7626+ if ($XML_RPC_xh[$parser]['lv'] != 3) {
7627+ // "lookforvalue==3" means that we've found an entire value
7628+ // and should discard any further character data
7629+
7630+ if ($XML_RPC_xh[$parser]['lv'] == 1) {
7631+ // if we've found text and we're just in a <value> then
7632+ // turn quoting on, as this will be a string
7633+ $XML_RPC_xh[$parser]['qt'] = 1;
7634+ // and say we've found a value
7635+ $XML_RPC_xh[$parser]['lv'] = 2;
7636+ }
7637+
7638+ // replace characters that eval would
7639+ // do special things with
7640+ if (!isset($XML_RPC_xh[$parser]['ac'])) {
7641+ $XML_RPC_xh[$parser]['ac'] = '';
7642+ }
7643+ $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$',
7644+ str_replace('"', '\"', str_replace(chr(92),
7645+ $XML_RPC_backslash, $data)));
7646+ }
7647+}
7648+
7649+/**
7650+ * The common methods and properties for all of the XML_RPC classes
7651+ *
7652+ * @category Web Services
7653+ * @package XML_RPC
7654+ * @author Edd Dumbill <edd@usefulinc.com>
7655+ * @author Stig Bakken <stig@php.net>
7656+ * @author Martin Jansen <mj@php.net>
7657+ * @author Daniel Convissor <danielc@php.net>
7658+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7659+ * @version Release: 1.3.1
7660+ * @link http://pear.php.net/package/XML_RPC
7661+ */
7662+class XML_RPC_Base {
7663+
7664+ /**
7665+ * PEAR Error handling
7666+ *
7667+ * @return object PEAR_Error object
7668+ */
7669+ function raiseError($msg, $code)
7670+ {
7671+ include_once 'PEAR.php';
7672+ if (is_object(@$this)) {
7673+ return PEAR::raiseError(get_class($this) . ': ' . $msg, $code);
7674+ } else {
7675+ return PEAR::raiseError('XML_RPC: ' . $msg, $code);
7676+ }
7677+ }
7678+
7679+ /**
7680+ * Tell whether something is a PEAR_Error object
7681+ *
7682+ * @param mixed $value the item to check
7683+ *
7684+ * @return bool whether $value is a PEAR_Error object or not
7685+ *
7686+ * @access public
7687+ */
7688+ function isError($value)
7689+ {
7690+ return is_a($value, 'PEAR_Error');
7691+ }
7692+}
7693+
7694+/**
7695+ * The methods and properties for submitting XML RPC requests
7696+ *
7697+ * @category Web Services
7698+ * @package XML_RPC
7699+ * @author Edd Dumbill <edd@usefulinc.com>
7700+ * @author Stig Bakken <stig@php.net>
7701+ * @author Martin Jansen <mj@php.net>
7702+ * @author Daniel Convissor <danielc@php.net>
7703+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7704+ * @version Release: 1.3.1
7705+ * @link http://pear.php.net/package/XML_RPC
7706+ */
7707+class XML_RPC_Client extends XML_RPC_Base {
7708+
7709+ /**
7710+ * The path and name of the RPC server script you want the request to go to
7711+ * @var string
7712+ */
7713+ var $path = '';
7714+
7715+ /**
7716+ * The name of the remote server to connect to
7717+ * @var string
7718+ */
7719+ var $server = '';
7720+
7721+ /**
7722+ * The protocol to use in contacting the remote server
7723+ * @var string
7724+ */
7725+ var $protocol = 'http://';
7726+
7727+ /**
7728+ * The port for connecting to the remote server
7729+ *
7730+ * The default is 80 for http:// connections
7731+ * and 443 for https:// and ssl:// connections.
7732+ *
7733+ * @var integer
7734+ */
7735+ var $port = 80;
7736+
7737+ /**
7738+ * A user name for accessing the RPC server
7739+ * @var string
7740+ * @see XML_RPC_Client::setCredentials()
7741+ */
7742+ var $username = '';
7743+
7744+ /**
7745+ * A password for accessing the RPC server
7746+ * @var string
7747+ * @see XML_RPC_Client::setCredentials()
7748+ */
7749+ var $password = '';
7750+
7751+ /**
7752+ * The name of the proxy server to use, if any
7753+ * @var string
7754+ */
7755+ var $proxy = '';
7756+
7757+ /**
7758+ * The protocol to use in contacting the proxy server, if any
7759+ * @var string
7760+ */
7761+ var $proxy_protocol = 'http://';
7762+
7763+ /**
7764+ * The port for connecting to the proxy server
7765+ *
7766+ * The default is 8080 for http:// connections
7767+ * and 443 for https:// and ssl:// connections.
7768+ *
7769+ * @var integer
7770+ */
7771+ var $proxy_port = 8080;
7772+
7773+ /**
7774+ * A user name for accessing the proxy server
7775+ * @var string
7776+ */
7777+ var $proxy_user = '';
7778+
7779+ /**
7780+ * A password for accessing the proxy server
7781+ * @var string
7782+ */
7783+ var $proxy_pass = '';
7784+
7785+ /**
7786+ * The error number, if any
7787+ * @var integer
7788+ */
7789+ var $errno = 0;
7790+
7791+ /**
7792+ * The error message, if any
7793+ * @var string
7794+ */
7795+ var $errstring = '';
7796+
7797+ /**
7798+ * The current debug mode (1 = on, 0 = off)
7799+ * @var integer
7800+ */
7801+ var $debug = 0;
7802+
7803+ /**
7804+ * The HTTP headers for the current request.
7805+ * @var string
7806+ */
7807+ var $headers = '';
7808+
7809+
7810+ /**
7811+ * Sets the object's properties
7812+ *
7813+ * @param string $path the path and name of the RPC server script
7814+ * you want the request to go to
7815+ * @param string $server the URL of the remote server to connect to.
7816+ * If this parameter doesn't specify a
7817+ * protocol and $port is 443, ssl:// is
7818+ * assumed.
7819+ * @param integer $port a port for connecting to the remote server.
7820+ * Defaults to 80 for http:// connections and
7821+ * 443 for https:// and ssl:// connections.
7822+ * @param string $proxy the URL of the proxy server to use, if any.
7823+ * If this parameter doesn't specify a
7824+ * protocol and $port is 443, ssl:// is
7825+ * assumed.
7826+ * @param integer $proxy_port a port for connecting to the remote server.
7827+ * Defaults to 8080 for http:// connections and
7828+ * 443 for https:// and ssl:// connections.
7829+ * @param string $proxy_user a user name for accessing the proxy server
7830+ * @param string $proxy_pass a password for accessing the proxy server
7831+ *
7832+ * @return void
7833+ */
7834+ function XML_RPC_Client($path, $server, $port = 0,
7835+ $proxy = '', $proxy_port = 0,
7836+ $proxy_user = '', $proxy_pass = '')
7837+ {
7838+ $this->path = $path;
7839+ $this->proxy_user = $proxy_user;
7840+ $this->proxy_pass = $proxy_pass;
7841+
7842+ preg_match('@^(http://|https://|ssl://)?(.*)$@', $server, $match);
7843+ if ($match[1] == '') {
7844+ if ($port == 443) {
7845+ $this->server = $match[2];
7846+ $this->protocol = 'ssl://';
7847+ $this->port = 443;
7848+ } else {
7849+ $this->server = $match[2];
7850+ if ($port) {
7851+ $this->port = $port;
7852+ }
7853+ }
7854+ } elseif ($match[1] == 'http://') {
7855+ $this->server = $match[2];
7856+ if ($port) {
7857+ $this->port = $port;
7858+ }
7859+ } else {
7860+ $this->server = $match[2];
7861+ $this->protocol = 'ssl://';
7862+ if ($port) {
7863+ $this->port = $port;
7864+ } else {
7865+ $this->port = 443;
7866+ }
7867+ }
7868+
7869+ if ($proxy) {
7870+ preg_match('@^(http://|https://|ssl://)?(.*)$@', $proxy, $match);
7871+ if ($match[1] == '') {
7872+ if ($proxy_port == 443) {
7873+ $this->proxy = $match[2];
7874+ $this->proxy_protocol = 'ssl://';
7875+ $this->proxy_port = 443;
7876+ } else {
7877+ $this->proxy = $match[2];
7878+ if ($proxy_port) {
7879+ $this->proxy_port = $proxy_port;
7880+ }
7881+ }
7882+ } elseif ($match[1] == 'http://') {
7883+ $this->proxy = $match[2];
7884+ if ($proxy_port) {
7885+ $this->proxy_port = $proxy_port;
7886+ }
7887+ } else {
7888+ $this->proxy = $match[2];
7889+ $this->proxy_protocol = 'ssl://';
7890+ if ($proxy_port) {
7891+ $this->proxy_port = $proxy_port;
7892+ } else {
7893+ $this->proxy_port = 443;
7894+ }
7895+ }
7896+ }
7897+ }
7898+
7899+ /**
7900+ * Change the current debug mode
7901+ *
7902+ * @param int $in where 1 = on, 0 = off
7903+ *
7904+ * @return void
7905+ */
7906+ function setDebug($in)
7907+ {
7908+ if ($in) {
7909+ $this->debug = 1;
7910+ } else {
7911+ $this->debug = 0;
7912+ }
7913+ }
7914+
7915+ /**
7916+ * Set username and password properties for connecting to the RPC server
7917+ *
7918+ * @param string $u the user name
7919+ * @param string $p the password
7920+ *
7921+ * @return void
7922+ *
7923+ * @see XML_RPC_Client::$username, XML_RPC_Client::$password
7924+ */
7925+ function setCredentials($u, $p)
7926+ {
7927+ $this->username = $u;
7928+ $this->password = $p;
7929+ }
7930+
7931+ /**
7932+ * Transmit the RPC request via HTTP 1.0 protocol
7933+ *
7934+ * @param object $msg the XML_RPC_Message object
7935+ * @param int $timeout how many seconds to wait for the request
7936+ *
7937+ * @return object an XML_RPC_Response object. 0 is returned if any
7938+ * problems happen.
7939+ *
7940+ * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(),
7941+ * XML_RPC_Client::setCredentials()
7942+ */
7943+ function send($msg, $timeout = 0)
7944+ {
7945+ if (strtolower(get_class($msg)) != 'xml_rpc_message') {
7946+ $this->errstr = 'send()\'s $msg parameter must be an'
7947+ . ' XML_RPC_Message object.';
7948+ $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING);
7949+ return 0;
7950+ }
7951+ $msg->debug = $this->debug;
7952+ return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
7953+ $timeout, $this->username,
7954+ $this->password);
7955+ }
7956+
7957+ /**
7958+ * Transmit the RPC request via HTTP 1.0 protocol
7959+ *
7960+ * Requests should be sent using XML_RPC_Client send() rather than
7961+ * calling this method directly.
7962+ *
7963+ * @param object $msg the XML_RPC_Message object
7964+ * @param string $server the server to send the request to
7965+ * @param int $port the server port send the request to
7966+ * @param int $timeout how many seconds to wait for the request
7967+ * before giving up
7968+ * @param string $username a user name for accessing the RPC server
7969+ * @param string $password a password for accessing the RPC server
7970+ *
7971+ * @return object an XML_RPC_Response object. 0 is returned if any
7972+ * problems happen.
7973+ *
7974+ * @access protected
7975+ * @see XML_RPC_Client::send()
7976+ */
7977+ function sendPayloadHTTP10($msg, $server, $port, $timeout = 0,
7978+ $username = '', $password = '')
7979+ {
7980+ /*
7981+ * If we're using a proxy open a socket to the proxy server
7982+ * instead to the xml-rpc server
7983+ */
7984+ if ($this->proxy) {
7985+ if ($this->proxy_protocol == 'http://') {
7986+ $protocol = '';
7987+ } else {
7988+ $protocol = $this->proxy_protocol;
7989+ }
7990+ if ($timeout > 0) {
7991+ $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
7992+ $this->errno, $this->errstr, $timeout);
7993+ } else {
7994+ $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
7995+ $this->errno, $this->errstr);
7996+ }
7997+ } else {
7998+ if ($this->protocol == 'http://') {
7999+ $protocol = '';
8000+ } else {
8001+ $protocol = $this->protocol;
8002+ }
8003+ if ($timeout > 0) {
8004+ $fp = @fsockopen($protocol . $server, $port,
8005+ $this->errno, $this->errstr, $timeout);
8006+ } else {
8007+ $fp = @fsockopen($protocol . $server, $port,
8008+ $this->errno, $this->errstr);
8009+ }
8010+ }
8011+
8012+ /*
8013+ * Just raising the error without returning it is strange,
8014+ * but keep it here for backwards compatibility.
8015+ */
8016+ if (!$fp && $this->proxy) {
8017+ $this->raiseError('Connection to proxy server '
8018+ . $this->proxy . ':' . $this->proxy_port
8019+ . ' failed. ' . $this->errstr,
8020+ XML_RPC_ERROR_CONNECTION_FAILED);
8021+ return 0;
8022+ } elseif (!$fp) {
8023+ $this->raiseError('Connection to RPC server '
8024+ . $server . ':' . $port
8025+ . ' failed. ' . $this->errstr,
8026+ XML_RPC_ERROR_CONNECTION_FAILED);
8027+ return 0;
8028+ }
8029+
8030+ if ($timeout) {
8031+ stream_set_timeout($fp, $timeout);
8032+ }
8033+
8034+ // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly
8035+ if ($username != $this->username) {
8036+ $this->setCredentials($username, $password);
8037+ }
8038+
8039+ // Only create the payload if it was not created previously
8040+ if (empty($msg->payload)) {
8041+ $msg->createPayload();
8042+ }
8043+ $this->createHeaders($msg);
8044+
8045+ $op = $this->headers . "\r\n\r\n";
8046+ $op .= $msg->payload;
8047+
8048+ if (!fputs($fp, $op, strlen($op))) {
8049+ $this->errstr = 'Write error';
8050+ return 0;
8051+ }
8052+ $resp = $msg->parseResponseFile($fp);
8053+
8054+ $meta = stream_get_meta_data($fp);
8055+ if ($meta['timed_out']) {
8056+ fclose($fp);
8057+ $this->errstr = 'RPC server did not send response before timeout.';
8058+ $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED);
8059+ return 0;
8060+ }
8061+
8062+ fclose($fp);
8063+ return $resp;
8064+ }
8065+
8066+ /**
8067+ * Determines the HTTP headers and puts it in the $headers property
8068+ *
8069+ * @param object $msg the XML_RPC_Message object
8070+ *
8071+ * @return boolean TRUE if okay, FALSE if the message payload isn't set.
8072+ *
8073+ * @access protected
8074+ */
8075+ function createHeaders($msg)
8076+ {
8077+ if (empty($msg->payload)) {
8078+ return false;
8079+ }
8080+ if ($this->proxy) {
8081+ $this->headers = 'POST ' . $this->protocol . $this->server;
8082+ if ($this->proxy_port) {
8083+ $this->headers .= ':' . $this->port;
8084+ }
8085+ } else {
8086+ $this->headers = 'POST ';
8087+ }
8088+ $this->headers .= $this->path. " HTTP/1.0\r\n";
8089+
8090+ $this->headers .= "User-Agent: PEAR XML_RPC\r\n";
8091+ $this->headers .= 'Host: ' . $this->server . "\r\n";
8092+
8093+ if ($this->proxy && $this->proxy_user) {
8094+ $this->headers .= 'Proxy-Authorization: Basic '
8095+ . base64_encode("$this->proxy_user:$this->proxy_pass")
8096+ . "\r\n";
8097+ }
8098+
8099+ // thanks to Grant Rauscher <grant7@firstworld.net> for this
8100+ if ($this->username) {
8101+ $this->headers .= 'Authorization: Basic '
8102+ . base64_encode("$this->username:$this->password")
8103+ . "\r\n";
8104+ }
8105+
8106+ $this->headers .= "Content-Type: text/xml\r\n";
8107+ $this->headers .= 'Content-Length: ' . strlen($msg->payload);
8108+ return true;
8109+ }
8110+}
8111+
8112+/**
8113+ * The methods and properties for interpreting responses to XML RPC requests
8114+ *
8115+ * @category Web Services
8116+ * @package XML_RPC
8117+ * @author Edd Dumbill <edd@usefulinc.com>
8118+ * @author Stig Bakken <stig@php.net>
8119+ * @author Martin Jansen <mj@php.net>
8120+ * @author Daniel Convissor <danielc@php.net>
8121+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
8122+ * @version Release: 1.3.1
8123+ * @link http://pear.php.net/package/XML_RPC
8124+ */
8125+class XML_RPC_Response extends XML_RPC_Base
8126+{
8127+ var $xv;
8128+ var $fn;
8129+ var $fs;
8130+ var $hdrs;
8131+
8132+ /**
8133+ * @return void
8134+ */
8135+ function XML_RPC_Response($val, $fcode = 0, $fstr = '')
8136+ {
8137+ if ($fcode != 0) {
8138+ $this->fn = $fcode;
8139+ $this->fs = htmlspecialchars($fstr);
8140+ } else {
8141+ $this->xv = $val;
8142+ }
8143+ }
8144+
8145+ /**
8146+ * @return int the error code
8147+ */
8148+ function faultCode()
8149+ {
8150+ if (isset($this->fn)) {
8151+ return $this->fn;
8152+ } else {
8153+ return 0;
8154+ }
8155+ }
8156+
8157+ /**
8158+ * @return string the error string
8159+ */
8160+ function faultString()
8161+ {
8162+ return $this->fs;
8163+ }
8164+
8165+ /**
8166+ * @return mixed the value
8167+ */
8168+ function value()
8169+ {
8170+ return $this->xv;
8171+ }
8172+
8173+ /**
8174+ * @return string the error message in XML format
8175+ */
8176+ function serialize()
8177+ {
8178+ $rs = "<methodResponse>\n";
8179+ if ($this->fn) {
8180+ $rs .= "<fault>
8181+ <value>
8182+ <struct>
8183+ <member>
8184+ <name>faultCode</name>
8185+ <value><int>" . $this->fn . "</int></value>
8186+ </member>
8187+ <member>
8188+ <name>faultString</name>
8189+ <value><string>" . $this->fs . "</string></value>
8190+ </member>
8191+ </struct>
8192+ </value>
8193+</fault>";
8194+ } else {
8195+ $rs .= "<params>\n<param>\n" . $this->xv->serialize() .
8196+ "</param>\n</params>";
8197+ }
8198+ $rs .= "\n</methodResponse>";
8199+ return $rs;
8200+ }
8201+}
8202+
8203+/**
8204+ * The methods and properties for composing XML RPC messages
8205+ *
8206+ * @category Web Services
8207+ * @package XML_RPC
8208+ * @author Edd Dumbill <edd@usefulinc.com>
8209+ * @author Stig Bakken <stig@php.net>
8210+ * @author Martin Jansen <mj@php.net>
8211+ * @author Daniel Convissor <danielc@php.net>
8212+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
8213+ * @version Release: 1.3.1
8214+ * @link http://pear.php.net/package/XML_RPC
8215+ */
8216+class XML_RPC_Message extends XML_RPC_Base
8217+{
8218+ /**
8219+ * The current debug mode (1 = on, 0 = off)
8220+ * @var integer
8221+ */
8222+ var $debug = 0;
8223+
8224+ /**
8225+ * The encoding to be used for outgoing messages
8226+ *
8227+ * Defaults to the value of <var>$GLOBALS['XML_RPC_defencoding']</var>
8228+ *
8229+ * @var string
8230+ * @see XML_RPC_Message::setSendEncoding(),
8231+ * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header()
8232+ */
8233+ var $send_encoding = '';
8234+
8235+ /**
8236+ * The method presently being evaluated
8237+ * @var string
8238+ */
8239+ var $methodname = '';
8240+
8241+ /**
8242+ * @var array
8243+ */
8244+ var $params = array();
8245+
8246+ /**
8247+ * The XML message being generated
8248+ * @var string
8249+ */
8250+ var $payload = '';
8251+
8252+ /**
8253+ * @return void
8254+ */
8255+ function XML_RPC_Message($meth, $pars = 0)
8256+ {
8257+ $this->methodname = $meth;
8258+ if (is_array($pars) && sizeof($pars) > 0) {
8259+ for ($i = 0; $i < sizeof($pars); $i++) {
8260+ $this->addParam($pars[$i]);
8261+ }
8262+ }
8263+ }
8264+
8265+ /**
8266+ * Produces the XML declaration including the encoding attribute
8267+ *
8268+ * The encoding is determined by this class' <var>$send_encoding</var>
8269+ * property. If the <var>$send_encoding</var> property is not set, use
8270+ * <var>$GLOBALS['XML_RPC_defencoding']</var>.
8271+ *
8272+ * @return string the XML declaration and <methodCall> element
8273+ *
8274+ * @see XML_RPC_Message::setSendEncoding(),
8275+ * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding']
8276+ */
8277+ function xml_header()
8278+ {
8279+ global $XML_RPC_defencoding;
8280+ if (!$this->send_encoding) {
8281+ $this->send_encoding = $XML_RPC_defencoding;
8282+ }
8283+ return '<?xml version="1.0" encoding="' . $this->send_encoding . '"?>'
8284+ . "\n<methodCall>\n";
8285+ }
8286+
8287+ /**
8288+ * @return string the closing </methodCall> tag
8289+ */
8290+ function xml_footer()
8291+ {
8292+ return "</methodCall>\n";
8293+ }
8294+
8295+ /**
8296+ * @return void
8297+ *
8298+ * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer()
8299+ */
8300+ function createPayload()
8301+ {
8302+ $this->payload = $this->xml_header();
8303+ $this->payload .= '<methodName>' . $this->methodname . "</methodName>\n";
8304+ $this->payload .= "<params>\n";
8305+ for ($i = 0; $i < sizeof($this->params); $i++) {
8306+ $p = $this->params[$i];
8307+ $this->payload .= "<param>\n" . $p->serialize() . "</param>\n";
8308+ }
8309+ $this->payload .= "</params>\n";
8310+ $this->payload .= $this->xml_footer();
8311+ $this->payload = ereg_replace("[\r\n]+", "\r\n", $this->payload);
8312+ }
8313+
8314+ /**
8315+ * @return string the name of the method
8316+ */
8317+ function method($meth = '')
8318+ {
8319+ if ($meth != '') {
8320+ $this->methodname = $meth;
8321+ }
8322+ return $this->methodname;
8323+ }
8324+
8325+ /**
8326+ * @return string the payload
8327+ */
8328+ function serialize()
8329+ {
8330+ $this->createPayload();
8331+ return $this->payload;
8332+ }
8333+
8334+ /**
8335+ * @return void
8336+ */
8337+ function addParam($par)
8338+ {
8339+ $this->params[] = $par;
8340+ }
8341+
8342+ /**
8343+ * Obtains an XML_RPC_Value object for the given parameter
8344+ *
8345+ * @param int $i the index number of the parameter to obtain
8346+ *
8347+ * @return object the XML_RPC_Value object.
8348+ * If the parameter doesn't exist, an XML_RPC_Response object.
8349+ *
8350+ * @since Returns XML_RPC_Response object on error since Release 1.3.0
8351+ */
8352+ function getParam($i)
8353+ {
8354+ global $XML_RPC_err, $XML_RPC_str;
8355+
8356+ if (isset($this->params[$i])) {
8357+ return $this->params[$i];
8358+ } else {
8359+ $this->raiseError('The submitted request did not contain this parameter',
8360+ XML_RPC_ERROR_INCORRECT_PARAMS);
8361+ return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
8362+ $XML_RPC_str['incorrect_params']);
8363+ }
8364+ }
8365+
8366+ /**
8367+ * @return int the number of parameters
8368+ */
8369+ function getNumParams()
8370+ {
8371+ return sizeof($this->params);
8372+ }
8373+
8374+ /**
8375+ * Sets the XML declaration's encoding attribute
8376+ *
8377+ * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII)
8378+ *
8379+ * @return void
8380+ *
8381+ * @see XML_RPC_Message::$send_encoding, XML_RPC_Message::xml_header()
8382+ * @since Method available since Release 1.2.0
8383+ */
8384+ function setSendEncoding($type)
8385+ {
8386+ $this->send_encoding = $type;
8387+ }
8388+
8389+ /**
8390+ * Determine the XML's encoding via the encoding attribute
8391+ * in the XML declaration
8392+ *
8393+ * If the encoding parameter is not set or is not ISO-8859-1, UTF-8
8394+ * or US-ASCII, $XML_RPC_defencoding will be returned.
8395+ *
8396+ * @param string $data the XML that will be parsed
8397+ *
8398+ * @return string the encoding to be used
8399+ *
8400+ * @link http://php.net/xml_parser_create
8401+ * @since Method available since Release 1.2.0
8402+ */
8403+ function getEncoding($data)
8404+ {
8405+ global $XML_RPC_defencoding;
8406+
8407+ if (preg_match('/<\?xml[^>]*\s*encoding\s*=\s*[\'"]([^"\']*)[\'"]/i',
8408+ $data, $match))
8409+ {
8410+ $match[1] = trim(strtoupper($match[1]));
8411+ switch ($match[1]) {
8412+ case 'ISO-8859-1':
8413+ case 'UTF-8':
8414+ case 'US-ASCII':
8415+ return $match[1];
8416+ break;
8417+
8418+ default:
8419+ return $XML_RPC_defencoding;
8420+ }
8421+ } else {
8422+ return $XML_RPC_defencoding;
8423+ }
8424+ }
8425+
8426+ /**
8427+ * @return object a new XML_RPC_Response object
8428+ */
8429+ function parseResponseFile($fp)
8430+ {
8431+ $ipd = '';
8432+ while ($data = @fread($fp, 8192)) {
8433+ $ipd .= $data;
8434+ }
8435+ return $this->parseResponse($ipd);
8436+ }
8437+
8438+ /**
8439+ * @return object a new XML_RPC_Response object
8440+ */
8441+ function parseResponse($data = '')
8442+ {
8443+ global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding;
8444+
8445+ $encoding = $this->getEncoding($data);
8446+ $parser_resource = xml_parser_create($encoding);
8447+ $parser = (int) $parser_resource;
8448+
8449+ $XML_RPC_xh[$parser] = array();
8450+
8451+ $XML_RPC_xh[$parser]['st'] = '';
8452+ $XML_RPC_xh[$parser]['cm'] = 0;
8453+ $XML_RPC_xh[$parser]['isf'] = 0;
8454+ $XML_RPC_xh[$parser]['ac'] = '';
8455+ $XML_RPC_xh[$parser]['qt'] = '';
8456+
8457+ xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
8458+ xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
8459+ xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
8460+
8461+ $hdrfnd = 0;
8462+ if ($this->debug) {
8463+ print "<PRE>---GOT---\n";
8464+ print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
8465+ print "\n---END---\n</PRE>";
8466+ }
8467+
8468+ // See if response is a 200 or a 100 then a 200, else raise error.
8469+ // But only do this if we're using the HTTP protocol.
8470+ if (ereg('^HTTP', $data) &&
8471+ !ereg('^HTTP/[0-9\.]+ 200 ', $data) &&
8472+ !preg_match('@^HTTP/[0-9\.]+ 10[0-9]([A-Za-z ]+)?[\r\n]+HTTP/[0-9\.]+ 200@', $data))
8473+ {
8474+ $errstr = substr($data, 0, strpos($data, "\n") - 1);
8475+ error_log('HTTP error, got response: ' . $errstr);
8476+ $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'],
8477+ $XML_RPC_str['http_error'] . ' (' .
8478+ $errstr . ')');
8479+ xml_parser_free($parser_resource);
8480+ return $r;
8481+ }
8482+ // gotta get rid of headers here
8483+
8484+
8485+ if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) {
8486+ $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
8487+ $data = substr($data, $brpos + 4);
8488+ $hdrfnd = 1;
8489+ }
8490+
8491+ /*
8492+ * be tolerant of junk after methodResponse
8493+ * (e.g. javascript automatically inserted by free hosts)
8494+ * thanks to Luca Mariano <luca.mariano@email.it>
8495+ */
8496+ $data = substr($data, 0, strpos($data, "</methodResponse>") + 17);
8497+
8498+ if (!xml_parse($parser_resource, $data, sizeof($data))) {
8499+ // thanks to Peter Kocks <peter.kocks@baygate.com>
8500+ if (xml_get_current_line_number($parser_resource) == 1) {
8501+ $errstr = 'XML error at line 1, check URL';
8502+ } else {
8503+ $errstr = sprintf('XML error: %s at line %d',
8504+ xml_error_string(xml_get_error_code($parser_resource)),
8505+ xml_get_current_line_number($parser_resource));
8506+ }
8507+ error_log($errstr);
8508+ $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
8509+ $XML_RPC_str['invalid_return']);
8510+ xml_parser_free($parser_resource);
8511+ return $r;
8512+ }
8513+ xml_parser_free($parser_resource);
8514+ if ($this->debug) {
8515+ print '<PRE>---EVALING---[' .
8516+ strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
8517+ htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---</PRE>";
8518+ }
8519+ if (strlen($XML_RPC_xh[$parser]['st']) == 0) {
8520+ // then something odd has happened
8521+ // and it's time to generate a client side error
8522+ // indicating something odd went on
8523+ $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
8524+ $XML_RPC_str['invalid_return']);
8525+ } else {
8526+ eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;');
8527+ if ($XML_RPC_xh[$parser]['isf']) {
8528+ $f = $v->structmem('faultCode');
8529+ $fs = $v->structmem('faultString');
8530+ $r = new XML_RPC_Response($v, $f->scalarval(),
8531+ $fs->scalarval());
8532+ } else {
8533+ $r = new XML_RPC_Response($v);
8534+ }
8535+ }
8536+ $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
8537+ return $r;
8538+ }
8539+}
8540+
8541+/**
8542+ * The methods and properties that represent data in XML RPC format
8543+ *
8544+ * @category Web Services
8545+ * @package XML_RPC
8546+ * @author Edd Dumbill <edd@usefulinc.com>
8547+ * @author Stig Bakken <stig@php.net>
8548+ * @author Martin Jansen <mj@php.net>
8549+ * @author Daniel Convissor <danielc@php.net>
8550+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
8551+ * @version Release: 1.3.1
8552+ * @link http://pear.php.net/package/XML_RPC
8553+ */
8554+class XML_RPC_Value extends XML_RPC_Base
8555+{
8556+ var $me = array();
8557+ var $mytype = 0;
8558+
8559+ /**
8560+ * @return void
8561+ */
8562+ function XML_RPC_Value($val = -1, $type = '')
8563+ {
8564+ global $XML_RPC_Types;
8565+ $this->me = array();
8566+ $this->mytype = 0;
8567+ if ($val != -1 || $type != '') {
8568+ if ($type == '') {
8569+ $type = 'string';
8570+ }
8571+ if (!array_key_exists($type, $XML_RPC_Types)) {
8572+ // XXX
8573+ // need some way to report this error
8574+ } elseif ($XML_RPC_Types[$type] == 1) {
8575+ $this->addScalar($val, $type);
8576+ } elseif ($XML_RPC_Types[$type] == 2) {
8577+ $this->addArray($val);
8578+ } elseif ($XML_RPC_Types[$type] == 3) {
8579+ $this->addStruct($val);
8580+ }
8581+ }
8582+ }
8583+
8584+ /**
8585+ * @return int returns 1 if successful or 0 if there are problems
8586+ */
8587+ function addScalar($val, $type = 'string')
8588+ {
8589+ global $XML_RPC_Types, $XML_RPC_Boolean;
8590+
8591+ if ($this->mytype == 1) {
8592+ $this->raiseError('Scalar can have only one value',
8593+ XML_RPC_ERROR_INVALID_TYPE);
8594+ return 0;
8595+ }
8596+ $typeof = $XML_RPC_Types[$type];
8597+ if ($typeof != 1) {
8598+ $this->raiseError("Not a scalar type (${typeof})",
8599+ XML_RPC_ERROR_INVALID_TYPE);
8600+ return 0;
8601+ }
8602+
8603+ if ($type == $XML_RPC_Boolean) {
8604+ if (strcasecmp($val, 'true') == 0
8605+ || $val == 1
8606+ || ($val == true && strcasecmp($val, 'false')))
8607+ {
8608+ $val = 1;
8609+ } else {
8610+ $val = 0;
8611+ }
8612+ }
8613+
8614+ if ($this->mytype == 2) {
8615+ // we're adding to an array here
8616+ $ar = $this->me['array'];
8617+ $ar[] = new XML_RPC_Value($val, $type);
8618+ $this->me['array'] = $ar;
8619+ } else {
8620+ // a scalar, so set the value and remember we're scalar
8621+ $this->me[$type] = $val;
8622+ $this->mytype = $typeof;
8623+ }
8624+ return 1;
8625+ }
8626+
8627+ /**
8628+ * @return int returns 1 if successful or 0 if there are problems
8629+ */
8630+ function addArray($vals)
8631+ {
8632+ global $XML_RPC_Types;
8633+ if ($this->mytype != 0) {
8634+ $this->raiseError(
8635+ 'Already initialized as a [' . $this->kindOf() . ']',
8636+ XML_RPC_ERROR_ALREADY_INITIALIZED);
8637+ return 0;
8638+ }
8639+ $this->mytype = $XML_RPC_Types['array'];
8640+ $this->me['array'] = $vals;
8641+ return 1;
8642+ }
8643+
8644+ /**
8645+ * @return int returns 1 if successful or 0 if there are problems
8646+ */
8647+ function addStruct($vals)
8648+ {
8649+ global $XML_RPC_Types;
8650+ if ($this->mytype != 0) {
8651+ $this->raiseError(
8652+ 'Already initialized as a [' . $this->kindOf() . ']',
8653+ XML_RPC_ERROR_ALREADY_INITIALIZED);
8654+ return 0;
8655+ }
8656+ $this->mytype = $XML_RPC_Types['struct'];
8657+ $this->me['struct'] = $vals;
8658+ return 1;
8659+ }
8660+
8661+ /**
8662+ * @return void
8663+ */
8664+ function dump($ar)
8665+ {
8666+ reset($ar);
8667+ foreach ($ar as $key => $val) {
8668+ echo "$key => $val<br />";
8669+ if ($key == 'array') {
8670+ foreach ($val as $key2 => $val2) {
8671+ echo "-- $key2 => $val2<br />";
8672+ }
8673+ }
8674+ }
8675+ }
8676+
8677+ /**
8678+ * @return string the data type of the current value
8679+ */
8680+ function kindOf()
8681+ {
8682+ switch ($this->mytype) {
8683+ case 3:
8684+ return 'struct';
8685+
8686+ case 2:
8687+ return 'array';
8688+
8689+ case 1:
8690+ return 'scalar';
8691+
8692+ default:
8693+ return 'undef';
8694+ }
8695+ }
8696+
8697+ /**
8698+ * @return string the data in XML format
8699+ */
8700+ function serializedata($typ, $val)
8701+ {
8702+ $rs = '';
8703+ global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
8704+ if (!array_key_exists($typ, $XML_RPC_Types)) {
8705+ // XXX
8706+ // need some way to report this error
8707+ return;
8708+ }
8709+ switch ($XML_RPC_Types[$typ]) {
8710+ case 3:
8711+ // struct
8712+ $rs .= "<struct>\n";
8713+ reset($val);
8714+ foreach ($val as $key2 => $val2) {
8715+ $rs .= "<member><name>${key2}</name>\n";
8716+ $rs .= $this->serializeval($val2);
8717+ $rs .= "</member>\n";
8718+ }
8719+ $rs .= '</struct>';
8720+ break;
8721+
8722+ case 2:
8723+ // array
8724+ $rs .= "<array>\n<data>\n";
8725+ for ($i = 0; $i < sizeof($val); $i++) {
8726+ $rs .= $this->serializeval($val[$i]);
8727+ }
8728+ $rs .= "</data>\n</array>";
8729+ break;
8730+
8731+ case 1:
8732+ switch ($typ) {
8733+ case $XML_RPC_Base64:
8734+ $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
8735+ break;
8736+ case $XML_RPC_Boolean:
8737+ $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
8738+ break;
8739+ case $XML_RPC_String:
8740+ $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
8741+ break;
8742+ default:
8743+ $rs .= "<${typ}>${val}</${typ}>";
8744+ }
8745+ }
8746+ return $rs;
8747+ }
8748+
8749+ /**
8750+ * @return string the data in XML format
8751+ */
8752+ function serialize()
8753+ {
8754+ return $this->serializeval($this);
8755+ }
8756+
8757+ /**
8758+ * @return string the data in XML format
8759+ */
8760+ function serializeval($o)
8761+ {
8762+ $rs = '';
8763+ $ar = $o->me;
8764+ reset($ar);
8765+ list($typ, $val) = each($ar);
8766+ $rs .= '<value>';
8767+ $rs .= $this->serializedata($typ, $val);
8768+ $rs .= "</value>\n";
8769+ return $rs;
8770+ }
8771+
8772+ /**
8773+ * @return mixed the contents of the element requested
8774+ */
8775+ function structmem($m)
8776+ {
8777+ return $this->me['struct'][$m];
8778+ }
8779+
8780+ /**
8781+ * @return void
8782+ */
8783+ function structreset()
8784+ {
8785+ reset($this->me['struct']);
8786+ }
8787+
8788+ /**
8789+ * @return the key/value pair of the struct's current element
8790+ */
8791+ function structeach()
8792+ {
8793+ return each($this->me['struct']);
8794+ }
8795+
8796+ /**
8797+ * @return mixed the current value
8798+ */
8799+ function getval()
8800+ {
8801+ // UNSTABLE
8802+ global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
8803+
8804+ reset($this->me);
8805+ $b = current($this->me);
8806+
8807+ // contributed by I Sofer, 2001-03-24
8808+ // add support for nested arrays to scalarval
8809+ // i've created a new method here, so as to
8810+ // preserve back compatibility
8811+
8812+ if (is_array($b)) {
8813+ foreach ($b as $id => $cont) {
8814+ $b[$id] = $cont->scalarval();
8815+ }
8816+ }
8817+
8818+ // add support for structures directly encoding php objects
8819+ if (is_object($b)) {
8820+ $t = get_object_vars($b);
8821+ foreach ($t as $id => $cont) {
8822+ $t[$id] = $cont->scalarval();
8823+ }
8824+ foreach ($t as $id => $cont) {
8825+ eval('$b->'.$id.' = $cont;');
8826+ }
8827+ }
8828+
8829+ // end contrib
8830+ return $b;
8831+ }
8832+
8833+ /**
8834+ * @return mixed
8835+ */
8836+ function scalarval()
8837+ {
8838+ global $XML_RPC_Boolean, $XML_RPC_Base64;
8839+ reset($this->me);
8840+ return current($this->me);
8841+ }
8842+
8843+ /**
8844+ * @return string
8845+ */
8846+ function scalartyp()
8847+ {
8848+ global $XML_RPC_I4, $XML_RPC_Int;
8849+ reset($this->me);
8850+ $a = key($this->me);
8851+ if ($a == $XML_RPC_I4) {
8852+ $a = $XML_RPC_Int;
8853+ }
8854+ return $a;
8855+ }
8856+
8857+ /**
8858+ * @return mixed the struct's current element
8859+ */
8860+ function arraymem($m)
8861+ {
8862+ return $this->me['array'][$m];
8863+ }
8864+
8865+ /**
8866+ * @return int the number of elements in the array
8867+ */
8868+ function arraysize()
8869+ {
8870+ reset($this->me);
8871+ list($a, $b) = each($this->me);
8872+ return sizeof($b);
8873+ }
8874+
8875+ /**
8876+ * Determines if the item submitted is an XML_RPC_Value object
8877+ *
8878+ * @param mixed $val the variable to be evaluated
8879+ *
8880+ * @return bool TRUE if the item is an XML_RPC_Value object
8881+ *
8882+ * @static
8883+ * @since Method available since Release 1.3.0
8884+ */
8885+ function isValue($val)
8886+ {
8887+ return (strtolower(get_class($val)) == 'xml_rpc_value');
8888+ }
8889+}
8890+
8891+/**
8892+ * Return an ISO8601 encoded string
8893+ *
8894+ * While timezones ought to be supported, the XML-RPC spec says:
8895+ *
8896+ * "Don't assume a timezone. It should be specified by the server in its
8897+ * documentation what assumptions it makes about timezones."
8898+ *
8899+ * This routine always assumes localtime unless $utc is set to 1, in which
8900+ * case UTC is assumed and an adjustment for locale is made when encoding.
8901+ *
8902+ * @return string the formatted date
8903+ */
8904+function XML_RPC_iso8601_encode($timet, $utc = 0)
8905+{
8906+ if (!$utc) {
8907+ $t = strftime('%Y%m%dT%H:%M:%S', $timet);
8908+ } else {
8909+ if (function_exists('gmstrftime')) {
8910+ // gmstrftime doesn't exist in some versions
8911+ // of PHP
8912+ $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet);
8913+ } else {
8914+ $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z'));
8915+ }
8916+ }
8917+ return $t;
8918+}
8919+
8920+/**
8921+ * Convert a datetime string into a Unix timestamp
8922+ *
8923+ * While timezones ought to be supported, the XML-RPC spec says:
8924+ *
8925+ * "Don't assume a timezone. It should be specified by the server in its
8926+ * documentation what assumptions it makes about timezones."
8927+ *
8928+ * This routine always assumes localtime unless $utc is set to 1, in which
8929+ * case UTC is assumed and an adjustment for locale is made when encoding.
8930+ *
8931+ * @return int the unix timestamp of the date submitted
8932+ */
8933+function XML_RPC_iso8601_decode($idate, $utc = 0)
8934+{
8935+ $t = 0;
8936+ if (ereg('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) {
8937+ if ($utc) {
8938+ $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
8939+ } else {
8940+ $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
8941+ }
8942+ }
8943+ return $t;
8944+}
8945+
8946+/**
8947+ * Converts an XML_RPC_Value object into native PHP types
8948+ *
8949+ * @param object $XML_RPC_val the XML_RPC_Value object to decode
8950+ *
8951+ * @return mixed the PHP values
8952+ */
8953+function XML_RPC_decode($XML_RPC_val)
8954+{
8955+ $kind = $XML_RPC_val->kindOf();
8956+
8957+ if ($kind == 'scalar') {
8958+ return $XML_RPC_val->scalarval();
8959+
8960+ } elseif ($kind == 'array') {
8961+ $size = $XML_RPC_val->arraysize();
8962+ $arr = array();
8963+ for ($i = 0; $i < $size; $i++) {
8964+ $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i));
8965+ }
8966+ return $arr;
8967+
8968+ } elseif ($kind == 'struct') {
8969+ $XML_RPC_val->structreset();
8970+ $arr = array();
8971+ while (list($key, $value) = $XML_RPC_val->structeach()) {
8972+ $arr[$key] = XML_RPC_decode($value);
8973+ }
8974+ return $arr;
8975+ }
8976+}
8977+
8978+/**
8979+ * Converts native PHP types into an XML_RPC_Value object
8980+ *
8981+ * @param mixed $php_val the PHP value or variable you want encoded
8982+ *
8983+ * @return object the XML_RPC_Value object
8984+ */
8985+function XML_RPC_encode($php_val)
8986+{
8987+ global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double, $XML_RPC_String,
8988+ $XML_RPC_Array, $XML_RPC_Struct;
8989+
8990+ $type = gettype($php_val);
8991+ $XML_RPC_val = new XML_RPC_Value;
8992+
8993+ switch ($type) {
8994+ case 'array':
8995+ if (empty($php_val)) {
8996+ $XML_RPC_val->addArray($php_val);
8997+ break;
8998+ }
8999+ $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1));
9000+ if (empty($tmp)) {
9001+ $arr = array();
9002+ foreach ($php_val as $k => $v) {
9003+ $arr[$k] = XML_RPC_encode($v);
9004+ }
9005+ $XML_RPC_val->addArray($arr);
9006+ break;
9007+ }
9008+ // fall though if it's not an enumerated array
9009+
9010+ case 'object':
9011+ $arr = array();
9012+ foreach ($php_val as $k => $v) {
9013+ $arr[$k] = XML_RPC_encode($v);
9014+ }
9015+ $XML_RPC_val->addStruct($arr);
9016+ break;
9017+
9018+ case 'integer':
9019+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
9020+ break;
9021+
9022+ case 'double':
9023+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
9024+ break;
9025+
9026+ case 'string':
9027+ case 'NULL':
9028+ $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
9029+ break;
9030+
9031+ case 'boolean':
9032+ // Add support for encoding/decoding of booleans, since they
9033+ // are supported in PHP
9034+ // by <G_Giunta_2001-02-29>
9035+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
9036+ break;
9037+
9038+ case 'unknown type':
9039+ default:
9040+ $XML_RPC_val = false;
9041+ }
9042+ return $XML_RPC_val;
9043+}
9044+
9045+/*
9046+ * Local variables:
9047+ * tab-width: 4
9048+ * c-basic-offset: 4
9049+ * c-hanging-comment-ender-p: nil
9050+ * End:
9051+ */
9052+
9053+?>
9054+
9055+
9056+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
9057+
9058+/**
9059+ * Server commands for our PHP implementation of the XML-RPC protocol
9060+ *
9061+ * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
9062+ * It has support for HTTP transport, proxies and authentication.
9063+ *
9064+ * PHP versions 4 and 5
9065+ *
9066+ * LICENSE: License is granted to use or modify this software
9067+ * ("XML-RPC for PHP") for commercial or non-commercial use provided the
9068+ * copyright of the author is preserved in any distributed or derivative work.
9069+ *
9070+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
9071+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
9072+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9073+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
9074+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
9075+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
9076+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9077+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9078+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
9079+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9080+ *
9081+ * @category Web Services
9082+ * @package XML_RPC
9083+ * @author Edd Dumbill <edd@usefulinc.com>
9084+ * @author Stig Bakken <stig@php.net>
9085+ * @author Martin Jansen <mj@php.net>
9086+ * @author Daniel Convissor <danielc@php.net>
9087+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
9088+ * @version CVS: $Id: Server.php,v 1.26 2005/05/09 21:39:47 danielc Exp $
9089+ * @link http://pear.php.net/package/XML_RPC
9090+ */
9091+
9092+
9093+/**
9094+ * Pull in the XML_RPC class
9095+ */
9096+require_once 'XML/RPC.php';
9097+
9098+
9099+/**
9100+ * signature for system.listMethods: return = array,
9101+ * parameters = a string or nothing
9102+ * @global array $GLOBALS['XML_RPC_Server_listMethods_sig']
9103+ */
9104+$GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
9105+ array($GLOBALS['XML_RPC_Array'],
9106+ $GLOBALS['XML_RPC_String']
9107+ ),
9108+ array($GLOBALS['XML_RPC_Array'])
9109+);
9110+
9111+/**
9112+ * docstring for system.listMethods
9113+ * @global string $GLOBALS['XML_RPC_Server_listMethods_doc']
9114+ */
9115+$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the'
9116+ . ' methods that the XML-RPC server knows how to dispatch';
9117+
9118+/**
9119+ * signature for system.methodSignature: return = array,
9120+ * parameters = string
9121+ * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig']
9122+ */
9123+$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
9124+ array($GLOBALS['XML_RPC_Array'],
9125+ $GLOBALS['XML_RPC_String']
9126+ )
9127+);
9128+
9129+/**
9130+ * docstring for system.methodSignature
9131+ * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc']
9132+ */
9133+$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
9134+ . ' signatures (an array of arrays) for the method name passed. If'
9135+ . ' no signatures are known, returns a none-array (test for type !='
9136+ . ' array to detect missing signature)';
9137+
9138+/**
9139+ * signature for system.methodHelp: return = string,
9140+ * parameters = string
9141+ * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig']
9142+ */
9143+$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
9144+ array($GLOBALS['XML_RPC_String'],
9145+ $GLOBALS['XML_RPC_String']
9146+ )
9147+);
9148+
9149+/**
9150+ * docstring for methodHelp
9151+ * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc']
9152+ */
9153+$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined'
9154+ . ' for the method passed, otherwise returns an empty string';
9155+
9156+/**
9157+ * dispatch map for the automatically declared XML-RPC methods.
9158+ * @global array $GLOBALS['XML_RPC_Server_dmap']
9159+ */
9160+$GLOBALS['XML_RPC_Server_dmap'] = array(
9161+ 'system.listMethods' => array(
9162+ 'function' => 'XML_RPC_Server_listMethods',
9163+ 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'],
9164+ 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc']
9165+ ),
9166+ 'system.methodHelp' => array(
9167+ 'function' => 'XML_RPC_Server_methodHelp',
9168+ 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'],
9169+ 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc']
9170+ ),
9171+ 'system.methodSignature' => array(
9172+ 'function' => 'XML_RPC_Server_methodSignature',
9173+ 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'],
9174+ 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc']
9175+ )
9176+);
9177+
9178+/**
9179+ * @global string $GLOBALS['XML_RPC_Server_debuginfo']
9180+ */
9181+$GLOBALS['XML_RPC_Server_debuginfo'] = '';
9182+
9183+
9184+/**
9185+ * Lists all the methods that the XML-RPC server knows how to dispatch
9186+ *
9187+ * @return object a new XML_RPC_Response object
9188+ */
9189+function XML_RPC_Server_listMethods($server, $m)
9190+{
9191+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
9192+
9193+ $v = new XML_RPC_Value();
9194+ $outAr = array();
9195+ foreach ($server->dmap as $key => $val) {
9196+ $outAr[] = new XML_RPC_Value($key, 'string');
9197+ }
9198+ foreach ($XML_RPC_Server_dmap as $key => $val) {
9199+ $outAr[] = new XML_RPC_Value($key, 'string');
9200+ }
9201+ $v->addArray($outAr);
9202+ return new XML_RPC_Response($v);
9203+}
9204+
9205+/**
9206+ * Returns an array of known signatures (an array of arrays)
9207+ * for the given method
9208+ *
9209+ * If no signatures are known, returns a none-array
9210+ * (test for type != array to detect missing signature)
9211+ *
9212+ * @return object a new XML_RPC_Response object
9213+ */
9214+function XML_RPC_Server_methodSignature($server, $m)
9215+{
9216+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
9217+
9218+ $methName = $m->getParam(0);
9219+ $methName = $methName->scalarval();
9220+ if (strpos($methName, 'system.') === 0) {
9221+ $dmap = $XML_RPC_Server_dmap;
9222+ $sysCall = 1;
9223+ } else {
9224+ $dmap = $server->dmap;
9225+ $sysCall = 0;
9226+ }
9227+ // print "<!-- ${methName} -->\n";
9228+ if (isset($dmap[$methName])) {
9229+ if ($dmap[$methName]['signature']) {
9230+ $sigs = array();
9231+ $thesigs = $dmap[$methName]['signature'];
9232+ for ($i = 0; $i < sizeof($thesigs); $i++) {
9233+ $cursig = array();
9234+ $inSig = $thesigs[$i];
9235+ for ($j = 0; $j < sizeof($inSig); $j++) {
9236+ $cursig[] = new XML_RPC_Value($inSig[$j], 'string');
9237+ }
9238+ $sigs[] = new XML_RPC_Value($cursig, 'array');
9239+ }
9240+ $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array'));
9241+ } else {
9242+ $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string'));
9243+ }
9244+ } else {
9245+ $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
9246+ $XML_RPC_str['introspect_unknown']);
9247+ }
9248+ return $r;
9249+}
9250+
9251+/**
9252+ * Returns help text if defined for the method passed, otherwise returns
9253+ * an empty string
9254+ *
9255+ * @return object a new XML_RPC_Response object
9256+ */
9257+function XML_RPC_Server_methodHelp($server, $m)
9258+{
9259+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
9260+
9261+ $methName = $m->getParam(0);
9262+ $methName = $methName->scalarval();
9263+ if (strpos($methName, 'system.') === 0) {
9264+ $dmap = $XML_RPC_Server_dmap;
9265+ $sysCall = 1;
9266+ } else {
9267+ $dmap = $server->dmap;
9268+ $sysCall = 0;
9269+ }
9270+ // print "<!-- ${methName} -->\n";
9271+ if (isset($dmap[$methName])) {
9272+ if ($dmap[$methName]['docstring']) {
9273+ $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']),
9274+ 'string');
9275+ } else {
9276+ $r = new XML_RPC_Response(new XML_RPC_Value('', 'string'));
9277+ }
9278+ } else {
9279+ $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
9280+ $XML_RPC_str['introspect_unknown']);
9281+ }
9282+ return $r;
9283+}
9284+
9285+/**
9286+ * @return void
9287+ */
9288+function XML_RPC_Server_debugmsg($m)
9289+{
9290+ global $XML_RPC_Server_debuginfo;
9291+ $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n";
9292+}
9293+
9294+
9295+/**
9296+ * A server for receiving and replying to XML RPC requests
9297+ *
9298+ * <code>
9299+ * $server = new XML_RPC_Server(
9300+ * array(
9301+ * 'isan8' =>
9302+ * array(
9303+ * 'function' => 'is_8',
9304+ * 'signature' =>
9305+ * array(
9306+ * array('boolean', 'int'),
9307+ * array('boolean', 'int', 'boolean'),
9308+ * array('boolean', 'string'),
9309+ * array('boolean', 'string', 'boolean'),
9310+ * ),
9311+ * 'docstring' => 'Is the value an 8?'
9312+ * ),
9313+ * ),
9314+ * 1,
9315+ * 0
9316+ * );
9317+ * </code>
9318+ *
9319+ * @category Web Services
9320+ * @package XML_RPC
9321+ * @author Edd Dumbill <edd@usefulinc.com>
9322+ * @author Stig Bakken <stig@php.net>
9323+ * @author Martin Jansen <mj@php.net>
9324+ * @author Daniel Convissor <danielc@php.net>
9325+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
9326+ * @version Release: 1.3.1
9327+ * @link http://pear.php.net/package/XML_RPC
9328+ */
9329+class XML_RPC_Server
9330+{
9331+ /**
9332+ * The dispatch map, listing the methods this server provides.
9333+ * @var array
9334+ */
9335+ var $dmap = array();
9336+
9337+ /**
9338+ * The present response's encoding
9339+ * @var string
9340+ * @see XML_RPC_Message::getEncoding()
9341+ */
9342+ var $encoding = '';
9343+
9344+ /**
9345+ * Debug mode (0 = off, 1 = on)
9346+ * @var integer
9347+ */
9348+ var $debug = 0;
9349+
9350+ /**
9351+ * The response's HTTP headers
9352+ * @var string
9353+ */
9354+ var $server_headers = '';
9355+
9356+ /**
9357+ * The response's XML payload
9358+ * @var string
9359+ */
9360+ var $server_payload = '';
9361+
9362+
9363+ /**
9364+ * Constructor for the XML_RPC_Server class
9365+ *
9366+ * @param array $dispMap the dispatch map. An associative array
9367+ * explaining each function. The keys of the main
9368+ * array are the procedure names used by the
9369+ * clients. The value is another associative array
9370+ * that contains up to three elements:
9371+ * + The 'function' element's value is the name
9372+ * of the function or method that gets called.
9373+ * To define a class' method: 'class::method'.
9374+ * + The 'signature' element (optional) is an
9375+ * array describing the return values and
9376+ * parameters
9377+ * + The 'docstring' element (optional) is a
9378+ * string describing what the method does
9379+ * @param int $serviceNow should the HTTP response be sent now?
9380+ * (1 = yes, 0 = no)
9381+ * @param int $debug should debug output be displayed?
9382+ * (1 = yes, 0 = no)
9383+ *
9384+ * @return void
9385+ */
9386+ function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0)
9387+ {
9388+ global $HTTP_RAW_POST_DATA;
9389+
9390+ if ($debug) {
9391+ $this->debug = 1;
9392+ } else {
9393+ $this->debug = 0;
9394+ }
9395+
9396+ $this->dmap = $dispMap;
9397+
9398+ if ($serviceNow) {
9399+ $this->service();
9400+ } else {
9401+ $this->createServerPayload();
9402+ $this->createServerHeaders();
9403+ }
9404+ }
9405+
9406+ /**
9407+ * @return string the debug information if debug debug mode is on
9408+ */
9409+ function serializeDebug()
9410+ {
9411+ global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA;
9412+
9413+ if ($this->debug) {
9414+ XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n"
9415+ . $HTTP_RAW_POST_DATA
9416+ . "\n" . '^^^ END POST DATA ^^^');
9417+ }
9418+
9419+ if ($XML_RPC_Server_debuginfo != '') {
9420+ return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n"
9421+ . preg_replace('/-(?=-)/', '- ', $XML_RPC_Server_debuginfo)
9422+ . "-->\n";
9423+ } else {
9424+ return '';
9425+ }
9426+ }
9427+
9428+ /**
9429+ * Sends the response
9430+ *
9431+ * The encoding and content-type are determined by
9432+ * XML_RPC_Message::getEncoding()
9433+ *
9434+ * @return void
9435+ *
9436+ * @uses XML_RPC_Server::createServerPayload(),
9437+ * XML_RPC_Server::createServerHeaders()
9438+ */
9439+ function service()
9440+ {
9441+ $this->createServerPayload();
9442+ $this->createServerHeaders();
9443+ header($this->server_headers);
9444+ print $this->server_payload;
9445+ }
9446+
9447+ /**
9448+ * Generates the payload and puts it in the $server_payload property
9449+ *
9450+ * @return void
9451+ *
9452+ * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding,
9453+ * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug()
9454+ */
9455+ function createServerPayload()
9456+ {
9457+ $r = $this->parseRequest();
9458+ $this->server_payload = '<?xml version="1.0" encoding="'
9459+ . $this->encoding . '"?>' . "\n"
9460+ . $this->serializeDebug()
9461+ . $r->serialize();
9462+ }
9463+
9464+ /**
9465+ * Determines the HTTP headers and puts them in the $server_headers
9466+ * property
9467+ *
9468+ * @return boolean TRUE if okay, FALSE if $server_payload isn't set.
9469+ *
9470+ * @uses XML_RPC_Server::createServerPayload(),
9471+ * XML_RPC_Server::$server_headers
9472+ */
9473+ function createServerHeaders()
9474+ {
9475+ if (!$this->server_payload) {
9476+ return false;
9477+ }
9478+ $this->server_headers = 'Content-Length: '
9479+ . strlen($this->server_payload) . "\r\n"
9480+ . 'Content-Type: text/xml;'
9481+ . ' charset=' . $this->encoding;
9482+ return true;
9483+ }
9484+
9485+ /**
9486+ * @return array
9487+ */
9488+ function verifySignature($in, $sig)
9489+ {
9490+ for ($i = 0; $i < sizeof($sig); $i++) {
9491+ // check each possible signature in turn
9492+ $cursig = $sig[$i];
9493+ if (sizeof($cursig) == $in->getNumParams() + 1) {
9494+ $itsOK = 1;
9495+ for ($n = 0; $n < $in->getNumParams(); $n++) {
9496+ $p = $in->getParam($n);
9497+ // print "<!-- $p -->\n";
9498+ if ($p->kindOf() == 'scalar') {
9499+ $pt = $p->scalartyp();
9500+ } else {
9501+ $pt = $p->kindOf();
9502+ }
9503+ // $n+1 as first type of sig is return type
9504+ if ($pt != $cursig[$n+1]) {
9505+ $itsOK = 0;
9506+ $pno = $n+1;
9507+ $wanted = $cursig[$n+1];
9508+ $got = $pt;
9509+ break;
9510+ }
9511+ }
9512+ if ($itsOK) {
9513+ return array(1);
9514+ }
9515+ }
9516+ }
9517+ if (isset($wanted)) {
9518+ return array(0, "Wanted ${wanted}, got ${got} at param ${pno}");
9519+ } else {
9520+ $allowed = array();
9521+ foreach ($sig as $val) {
9522+ end($val);
9523+ $allowed[] = key($val);
9524+ }
9525+ $allowed = array_unique($allowed);
9526+ $last = count($allowed) - 1;
9527+ if ($last > 0) {
9528+ $allowed[$last] = 'or ' . $allowed[$last];
9529+ }
9530+ return array(0,
9531+ 'Signature permits ' . implode(', ', $allowed)
9532+ . ' parameters but the request had '
9533+ . $in->getNumParams());
9534+ }
9535+ }
9536+
9537+ /**
9538+ * @return object a new XML_RPC_Response object
9539+ *
9540+ * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding
9541+ */
9542+ function parseRequest($data = '')
9543+ {
9544+ global $XML_RPC_xh, $HTTP_RAW_POST_DATA,
9545+ $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml,
9546+ $XML_RPC_defencoding, $XML_RPC_Server_dmap;
9547+
9548+ if ($data == '') {
9549+ $data = $HTTP_RAW_POST_DATA;
9550+ }
9551+
9552+ $this->encoding = XML_RPC_Message::getEncoding($data);
9553+ $parser_resource = xml_parser_create($this->encoding);
9554+ $parser = (int) $parser_resource;
9555+
9556+ $XML_RPC_xh[$parser] = array();
9557+ $XML_RPC_xh[$parser]['st'] = '';
9558+ $XML_RPC_xh[$parser]['cm'] = 0;
9559+ $XML_RPC_xh[$parser]['isf'] = 0;
9560+ $XML_RPC_xh[$parser]['params'] = array();
9561+ $XML_RPC_xh[$parser]['method'] = '';
9562+
9563+ $plist = '';
9564+
9565+ // decompose incoming XML into request structure
9566+
9567+ xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
9568+ xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
9569+ xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
9570+ if (!xml_parse($parser_resource, $data, 1)) {
9571+ // return XML error as a faultCode
9572+ $r = new XML_RPC_Response(0,
9573+ $XML_RPC_errxml+xml_get_error_code($parser_resource),
9574+ sprintf('XML error: %s at line %d',
9575+ xml_error_string(xml_get_error_code($parser_resource)),
9576+ xml_get_current_line_number($parser_resource)));
9577+ xml_parser_free($parser_resource);
9578+ } else {
9579+ xml_parser_free($parser_resource);
9580+ $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']);
9581+ // now add parameters in
9582+ for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) {
9583+ // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n";
9584+ $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n";
9585+ eval('$m->addParam(' . $XML_RPC_xh[$parser]['params'][$i] . ');');
9586+ }
9587+ XML_RPC_Server_debugmsg($plist);
9588+
9589+ // now to deal with the method
9590+ $methName = $XML_RPC_xh[$parser]['method'];
9591+ if (strpos($methName, 'system.') === 0) {
9592+ $dmap = $XML_RPC_Server_dmap;
9593+ $sysCall = 1;
9594+ } else {
9595+ $dmap = $this->dmap;
9596+ $sysCall = 0;
9597+ }
9598+
9599+ if (isset($dmap[$methName]['function'])
9600+ && is_string($dmap[$methName]['function'])
9601+ && strpos($dmap[$methName]['function'], '::') !== false)
9602+ {
9603+ $dmap[$methName]['function'] =
9604+ explode('::', $dmap[$methName]['function']);
9605+ }
9606+
9607+ if (isset($dmap[$methName]['function'])
9608+ && is_callable($dmap[$methName]['function']))
9609+ {
9610+ // dispatch if exists
9611+ if (isset($dmap[$methName]['signature'])) {
9612+ $sr = $this->verifySignature($m,
9613+ $dmap[$methName]['signature'] );
9614+ }
9615+ if (!isset($dmap[$methName]['signature']) || $sr[0]) {
9616+ // if no signature or correct signature
9617+ if ($sysCall) {
9618+ $r = call_user_func($dmap[$methName]['function'], $this, $m);
9619+ } else {
9620+ $r = call_user_func($dmap[$methName]['function'], $m);
9621+ }
9622+ if (!is_a($r, 'XML_RPC_Response')) {
9623+ $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'],
9624+ $XML_RPC_str['not_response_object']);
9625+ }
9626+ } else {
9627+ $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
9628+ $XML_RPC_str['incorrect_params']
9629+ . ': ' . $sr[1]);
9630+ }
9631+ } else {
9632+ // else prepare error response
9633+ $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'],
9634+ $XML_RPC_str['unknown_method']);
9635+ }
9636+ }
9637+ return $r;
9638+ }
9639+
9640+ /**
9641+ * Echos back the input packet as a string value
9642+ *
9643+ * @return void
9644+ *
9645+ * Useful for debugging.
9646+ */
9647+ function echoInput()
9648+ {
9649+ global $HTTP_RAW_POST_DATA;
9650+
9651+ $r = new XML_RPC_Response(0);
9652+ $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string');
9653+ print $r->serialize();
9654+ }
9655+}
9656+
9657+/*
9658+ * Local variables:
9659+ * tab-width: 4
9660+ * c-basic-offset: 4
9661+ * c-hanging-comment-ender-p: nil
9662+ * End:
9663+ */
9664+
9665+?>
9666+
9667+<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
9668+<package version="1.0" packagerversion="1.4.0a12">
9669+ <name>XML_RPC</name>
9670+ <summary>PHP implementation of the XML-RPC protocol</summary>
9671+ <description>A PEAR-ified version of Useful Inc's XML-RPC for PHP.
9672+
9673+It has support for HTTP/HTTPS transport, proxies and authentication.
9674+ </description>
9675+ <maintainers>
9676+ <maintainer>
9677+ <user>ssb</user>
9678+ <name>Stig Bakken</name>
9679+ <email>stig@php.net</email>
9680+ <role>lead</role>
9681+ </maintainer>
9682+ <maintainer>
9683+ <user>danielc</user>
9684+ <name>Daniel Convissor</name>
9685+ <email>danielc@php.net</email>
9686+ <role>lead</role>
9687+ </maintainer>
9688+ </maintainers>
9689+ <release>
9690+ <version>1.3.1</version>
9691+ <date>2005-06-29</date>
9692+ <license>PHP License</license>
9693+ <state>stable</state>
9694+ <notes>* Security fix. Update highly recommended!
9695+ </notes>
9696+ <filelist>
9697+ <file role="php" baseinstalldir="XML" name="RPC.php">
9698+ <replace from="@package_version@" to="version" type="package-info"/>
9699+ </file>
9700+ <file role="php" baseinstalldir="XML/RPC" name="Server.php">
9701+ <replace from="@package_version@" to="version" type="package-info"/>
9702+ </file>
9703+ <file role="php" baseinstalldir="XML/RPC" name="Dump.php">
9704+ <replace from="@package_version@" to="version" type="package-info"/>
9705+ </file>
9706+ <file role="test" name="tests/protoport.php">
9707+ <replace from="@package_version@" to="version" type="package-info"/>
9708+ </file>
9709+ <file role="test" name="tests/test_Dump.php">
9710+ <replace from="@package_version@" to="version" type="package-info"/>
9711+ </file>
9712+ </filelist>
9713+ </release>
9714+ <changelog>
9715+ <release>
9716+ <version>1.3.0RC3</version>
9717+ <date>2005-05-10</date>
9718+ <state>beta</state>
9719+ <notes>* When verifying requests against function signatures, if the number of parameters don't match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
9720+* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
9721+* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
9722+* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
9723+* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
9724+* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().
9725+ </notes>
9726+ </release>
9727+ <release>
9728+ <version>1.3.0RC2</version>
9729+ <date>2005-05-05</date>
9730+ <state>beta</state>
9731+ <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
9732+* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
9733+* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
9734+* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.
9735+ </notes>
9736+ </release>
9737+ <release>
9738+ <version>1.3.0RC1</version>
9739+ <date>2005-04-07</date>
9740+ <state>beta</state>
9741+ <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
9742+* Add Fault Code 6: &quot;The requested method didn't return an XML_RPC_Response object.&quot; Request 4032.
9743+* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
9744+* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
9745+* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
9746+* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.
9747+ </notes>
9748+ </release>
9749+ <release>
9750+ <version>1.2.2</version>
9751+ <date>2005-03-07</date>
9752+ <state>stable</state>
9753+ <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.
9754+ </notes>
9755+ </release>
9756+ <release>
9757+ <version>1.2.1</version>
9758+ <date>2005-03-01</date>
9759+ <state>stable</state>
9760+ <notes>* Add isset() check before examining the dispatch map. Bug 3658.
9761+ </notes>
9762+ </release>
9763+ <release>
9764+ <version>1.2.0</version>
9765+ <date>2005-02-27</date>
9766+ <state>stable</state>
9767+ <notes>* Provide the &quot;stable&quot; release.
9768+* Add package2.xml for compatibility with PEAR 1.4.0.
9769+* For changes since 1.1.0, see the changelogs for the various RC releases.
9770+ </notes>
9771+ </release>
9772+ <release>
9773+ <version>1.2.0RC7</version>
9774+ <date>2005-02-22</date>
9775+ <state>beta</state>
9776+ <notes>* Add the setSendEncoding() method and $send_encoding
9777+ property to XML_RPC_Message. Request 3537.
9778+* Allow class methods to be mapped using either syntax:
9779+ 'function' =&gt; 'hello::sayHello',
9780+ or
9781+ 'function' =&gt; array('hello', 'sayhello'),
9782+ Bug 3363.
9783+* Use 8192 instead of 32768 for bytes in fread()
9784+ in parseResponseFile(). Bug 3340.
9785+ </notes>
9786+ </release>
9787+ <release>
9788+ <version>1.2.0RC6</version>
9789+ <date>2005-01-25</date>
9790+ <state>beta</state>
9791+ <notes>* Don't put the protocol in the Host field of the POST data. (danielc)
9792+ </notes>
9793+ </release>
9794+ <release>
9795+ <version>1.2.0RC5</version>
9796+ <date>2005-01-24</date>
9797+ <state>beta</state>
9798+ <notes>* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
9799+ </notes>
9800+ </release>
9801+ <release>
9802+ <version>1.2.0RC4</version>
9803+ <date>2005-01-24</date>
9804+ <state>beta</state>
9805+ <notes>* When a connection attempt fails, have the method return 0. (danielc)
9806+* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
9807+* Add tests for setting the client properties. (danielc)
9808+* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc)
9809+* Bundle the tests with the package. (danielc)
9810+ </notes>
9811+ </release>
9812+ <release>
9813+ <version>1.2.0RC3</version>
9814+ <date>2005-01-19</date>
9815+ <state>beta</state>
9816+ <notes>* ssl uses port 443, not 445.
9817+ </notes>
9818+ </release>
9819+ <release>
9820+ <version>1.2.0RC2</version>
9821+ <date>2005-01-11</date>
9822+ <state>beta</state>
9823+ <notes>* Handle ssl:// in the $server string. (danielc)
9824+* Also default to port 445 for ssl:// requests as well. (danielc)
9825+* Enhance debugging in the server. (danielc)
9826+ </notes>
9827+ </release>
9828+ <release>
9829+ <version>1.2.0RC1</version>
9830+ <date>2004-12-30</date>
9831+ <state>beta</state>
9832+ <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
9833+* Allow array function callbacks (Matt Kane)
9834+* Some minor speed-ups (Matt Kane)
9835+* Add Dump.php to the package (Christian Weiske)
9836+* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
9837+* Silence fsockopen() errors. Bug 1714. (danielc)
9838+* Encode empty arrays as an array. Bug 1493. (danielc)
9839+* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
9840+* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
9841+* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc)
9842+* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
9843+* Allow raiseError() to be called statically. (danielc)
9844+* Stop double escaping of character entities. Bug 987. (danielc)
9845+ NOTICE: the following have been removed:
9846+ * XML_RPC_dh()
9847+ * $GLOBALS['XML_RPC_entities']
9848+ * XML_RPC_entity_decode()
9849+ * XML_RPC_lookup_entity()
9850+* Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)
9851+ </notes>
9852+ </release>
9853+ <release>
9854+ <version>1.1.0</version>
9855+ <date>2004-03-15</date>
9856+ <state>stable</state>
9857+ <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
9858+* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
9859+* Remove &quot;require_once 'PEAR.php'&quot;, include only when needed to raise an error
9860+* Replace echo and error_log() with raiseError() (mroch)
9861+* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
9862+* be tolerant of junk after methodResponse (Luca Mariano, mroch)
9863+* Silent notice even in the error log (pierre)
9864+* fix include of shared xml extension on win32 (pierre)
9865+ </notes>
9866+ </release>
9867+ <release>
9868+ <version>1.0.4</version>
9869+ <date>2002-10-02</date>
9870+ <state>stable</state>
9871+ <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)
9872+ </notes>
9873+ </release>
9874+ <release>
9875+ <version>1.0.3</version>
9876+ <date>2002-05-19</date>
9877+ <state>stable</state>
9878+ <notes>* fix bug when parsing responses with boolean types
9879+ </notes>
9880+ </release>
9881+ <release>
9882+ <version>1.0.2</version>
9883+ <date>2002-04-16</date>
9884+ <state>stable</state>
9885+ <notes>* E_ALL fixes
9886+* fix HTTP response header parsing
9887+ </notes>
9888+ </release>
9889+ <release>
9890+ <version>1.0.1</version>
9891+ <date>2001-09-25</date>
9892+ <state>stable</state>
9893+ <notes>This is a PEAR-ified version of Useful Inc's 1.0.1 release.
9894+Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.
9895+ </notes>
9896+ </release>
9897+ </changelog>
9898+</package>
9899+
9900\ Kein Zeilenumbruch am Dateiende.
9901diff -Naur php-5.0.4/php.ini-dist hardening-patch-5.0.4-0.3.2/php.ini-dist
9902--- php-5.0.4/php.ini-dist 2005-03-01 01:25:09.000000000 +0100
9903+++ hardening-patch-5.0.4-0.3.2/php.ini-dist 2005-07-02 13:37:27.000000000 +0200
9904@@ -1187,6 +1187,177 @@
9905 ; instead of original one.
9906 soap.wsdl_cache_ttl=86400
9907
9908+[hardening-patch]
9909+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9910+; Hardening-Patch's logging ;
9911+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9912+
9913+;
9914+; hphp.log.syslog - Configures level for alerts reported through syslog
9915+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
9916+; hphp.log.script - Configures level for alerts reported through external script
9917+;
9918+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
9919+; Or each number up to get desired Hardening-Patch's reporting level
9920+;
9921+; S_ALL - All alerts
9922+; S_MEMORY - All canary violations and the safe unlink protection use this class
9923+; S_VARS - All variable filters trigger this class
9924+; S_FILES - All violation of uploaded files filter use this class
9925+; S_INCLUDE - The protection against malicious include filenames use this class
9926+; S_SQL - Failed SQL queries in MySQL are logged with this class
9927+; S_EXECUTOR - The execution depth protection uses this logging class
9928+; S_MISC - All other log messages (f.e. format string protection) use this class
9929+;
9930+; Example:
9931+;
9932+; - Report all alerts (except memory alerts) to the SAPI errorlog,
9933+; memory alerts through syslog and SQL+Include alerts fo the script
9934+;
9935+;hphp.log.syslog = S_MEMORY
9936+;hphp.log.sapi = S_ALL & ~S_MEMORY
9937+;hphp.log.script = S_INCLUDE | S_SQL
9938+;
9939+; Syslog logging:
9940+;
9941+; - Facility configuration: one of the following facilities
9942+;
9943+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
9944+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
9945+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
9946+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
9947+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
9948+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
9949+; LOG_PERROR
9950+;
9951+; - Priority configuration: one of the followinf priorities
9952+;
9953+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
9954+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
9955+;
9956+hphp.log.syslog.priority = LOG_ALERT
9957+hphp.log.syslog.facility = LOG_USER
9958+;
9959+; Script logging:
9960+;
9961+;hphp.log.script.name = /home/hphp/log_script
9962+;
9963+; Alert configuration:
9964+;
9965+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
9966+;
9967+;hphp.log.use-x-forwarded-for = On
9968+;
9969+
9970+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9971+; Hardening-Patch's logging ;
9972+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9973+
9974+; Execution depth limit
9975+;hphp.executor.max_depth = 8000
9976+
9977+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9978+; Hardening-Patch's REQUEST variable filters ;
9979+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9980+
9981+; Limits the number of REQUEST variables
9982+hphp.request.max_vars = 200
9983+
9984+; Limits the length of variable names (without indices)
9985+hphp.request.max_varname_length = 64
9986+
9987+; Limits the length of complete variable names (with indices)
9988+hphp.request.max_totalname_length = 256
9989+
9990+; Limits the length of array indices
9991+hphp.request.max_array_index_length = 64
9992+
9993+; Limits the depth of arrays
9994+hphp.request.max_array_depth = 100
9995+
9996+; Limits the length of variable values
9997+hphp.request.max_value_length = 65000
9998+
9999+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10000+; Hardening-Patch's COOKIE variable filters ;
10001+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10002+
10003+; Limits the number of COOKIE variables
10004+hphp.cookie.max_vars = 100
10005+
10006+; Limits the length of variable names (without indices)
10007+hphp.cookie.max_name_length = 64
10008+
10009+; Limits the length of complete variable names (with indices)
10010+hphp.cookie.max_totalname_length = 256
10011+
10012+; Limits the length of array indices
10013+hphp.cookie.max_array_index_length = 64
10014+
10015+; Limits the depth of arrays
10016+hphp.cookie.max_array_depth = 100
10017+
10018+; Limits the length of variable values
10019+hphp.cookie.max_value_length = 10000
10020+
10021+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10022+; Hardening-Patch's GET variable filters ;
10023+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10024+
10025+; Limits the number of COOKIE variables
10026+hphp.get.max_vars = 100
10027+
10028+; Limits the length of variable names (without indices)
10029+hphp.get.max_name_length = 64
10030+
10031+; Limits the length of complete variable names (with indices)
10032+hphp.get.max_totalname_length = 256
10033+
10034+; Limits the length of array indices
10035+hphp.get.max_array_index_length = 64
10036+
10037+; Limits the depth of arrays
10038+hphp.get.max_array_depth = 50
10039+
10040+; Limits the length of variable values
10041+hphp.get.max_value_length = 512
10042+
10043+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10044+; Hardening-Patch's POST variable filters ;
10045+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10046+
10047+; Limits the number of POST variables
10048+hphp.post.max_vars = 200
10049+
10050+; Limits the length of variable names (without indices)
10051+hphp.post.max_name_length = 64
10052+
10053+; Limits the length of complete variable names (with indices)
10054+hphp.post.max_totalname_length = 256
10055+
10056+; Limits the length of array indices
10057+hphp.post.max_array_index_length = 64
10058+
10059+; Limits the depth of arrays
10060+hphp.post.max_array_depth = 100
10061+
10062+; Limits the length of variable values
10063+hphp.post.max_value_length = 65000
10064+
10065+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10066+; Hardening-Patch's fileupload variable filters ;
10067+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10068+
10069+; Limits the number of uploadable files
10070+hphp.upload.max_uploads = 25
10071+
10072+; Filter out the upload of ELF executables
10073+hphp.upload.disallow_elf_files = On
10074+
10075+; External filterscript for upload verification
10076+;hphp.upload.verification_script = /home/hphp/verify_script
10077+
10078+
10079 ; Local Variables:
10080 ; tab-width: 4
10081 ; End:
10082diff -Naur php-5.0.4/php.ini-recommended hardening-patch-5.0.4-0.3.2/php.ini-recommended
10083--- php-5.0.4/php.ini-recommended 2005-03-01 01:25:09.000000000 +0100
10084+++ hardening-patch-5.0.4-0.3.2/php.ini-recommended 2005-07-02 13:38:04.000000000 +0200
10085@@ -1245,6 +1245,176 @@
10086 ; instead of original one.
10087 soap.wsdl_cache_ttl=86400
10088
10089+[hardening-patch]
10090+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10091+; Hardening-Patch's logging ;
10092+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10093+
10094+;
10095+; hphp.log.syslog - Configures level for alerts reported through syslog
10096+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
10097+; hphp.log.script - Configures level for alerts reported through external script
10098+;
10099+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
10100+; Or each number up to get desired Hardening-Patch's reporting level
10101+;
10102+; S_ALL - All alerts
10103+; S_MEMORY - All canary violations and the safe unlink protection use this class
10104+; S_VARS - All variable filters trigger this class
10105+; S_FILES - All violation of uploaded files filter use this class
10106+; S_INCLUDE - The protection against malicious include filenames use this class
10107+; S_SQL - Failed SQL queries in MySQL are logged with this class
10108+; S_EXECUTOR - The execution depth protection uses this logging class
10109+; S_MISC - All other log messages (f.e. format string protection) use this class
10110+;
10111+; Example:
10112+;
10113+; - Report all alerts (except memory alerts) to the SAPI errorlog,
10114+; memory alerts through syslog and SQL+Include alerts fo the script
10115+;
10116+;hphp.log.syslog = S_MEMORY
10117+;hphp.log.sapi = S_ALL & ~S_MEMORY
10118+;hphp.log.script = S_INCLUDE | S_SQL
10119+;
10120+; Syslog logging:
10121+;
10122+; - Facility configuration: one of the following facilities
10123+;
10124+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
10125+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
10126+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
10127+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
10128+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
10129+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
10130+; LOG_PERROR
10131+;
10132+; - Priority configuration: one of the followinf priorities
10133+;
10134+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
10135+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
10136+;
10137+hphp.log.syslog.priority = LOG_ALERT
10138+hphp.log.syslog.facility = LOG_USER
10139+;
10140+; Script logging:
10141+;
10142+;hphp.log.script.name = /home/hphp/log_script
10143+;
10144+; Alert configuration:
10145+;
10146+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
10147+;
10148+;hphp.log.use-x-forwarded-for = On
10149+;
10150+
10151+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10152+; Hardening-Patch's logging ;
10153+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10154+
10155+; Execution depth limit
10156+;hphp.executor.max_depth = 8000
10157+
10158+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10159+; Hardening-Patch's REQUEST variable filters ;
10160+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10161+
10162+; Limits the number of REQUEST variables
10163+hphp.request.max_vars = 200
10164+
10165+; Limits the length of variable names (without indices)
10166+hphp.request.max_varname_length = 64
10167+
10168+; Limits the length of complete variable names (with indices)
10169+hphp.request.max_totalname_length = 256
10170+
10171+; Limits the length of array indices
10172+hphp.request.max_array_index_length = 64
10173+
10174+; Limits the depth of arrays
10175+hphp.request.max_array_depth = 100
10176+
10177+; Limits the length of variable values
10178+hphp.request.max_value_length = 65000
10179+
10180+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10181+; Hardening-Patch's COOKIE variable filters ;
10182+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10183+
10184+; Limits the number of COOKIE variables
10185+hphp.cookie.max_vars = 100
10186+
10187+; Limits the length of variable names (without indices)
10188+hphp.cookie.max_name_length = 64
10189+
10190+; Limits the length of complete variable names (with indices)
10191+hphp.cookie.max_totalname_length = 256
10192+
10193+; Limits the length of array indices
10194+hphp.cookie.max_array_index_length = 64
10195+
10196+; Limits the depth of arrays
10197+hphp.cookie.max_array_depth = 100
10198+
10199+; Limits the length of variable values
10200+hphp.cookie.max_value_length = 10000
10201+
10202+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10203+; Hardening-Patch's GET variable filters ;
10204+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10205+
10206+; Limits the number of COOKIE variables
10207+hphp.get.max_vars = 100
10208+
10209+; Limits the length of variable names (without indices)
10210+hphp.get.max_name_length = 64
10211+
10212+; Limits the length of complete variable names (with indices)
10213+hphp.get.max_totalname_length = 256
10214+
10215+; Limits the length of array indices
10216+hphp.get.max_array_index_length = 64
10217+
10218+; Limits the depth of arrays
10219+hphp.get.max_array_depth = 50
10220+
10221+; Limits the length of variable values
10222+hphp.get.max_value_length = 512
10223+
10224+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10225+; Hardening-Patch's POST variable filters ;
10226+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10227+
10228+; Limits the number of POST variables
10229+hphp.post.max_vars = 200
10230+
10231+; Limits the length of variable names (without indices)
10232+hphp.post.max_name_length = 64
10233+
10234+; Limits the length of complete variable names (with indices)
10235+hphp.post.max_totalname_length = 256
10236+
10237+; Limits the length of array indices
10238+hphp.post.max_array_index_length = 64
10239+
10240+; Limits the depth of arrays
10241+hphp.post.max_array_depth = 100
10242+
10243+; Limits the length of variable values
10244+hphp.post.max_value_length = 65000
10245+
10246+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10247+; Hardening-Patch's fileupload variable filters ;
10248+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10249+
10250+; Limits the number of uploadable files
10251+hphp.upload.max_uploads = 25
10252+
10253+; Filter out the upload of ELF executables
10254+hphp.upload.disallow_elf_files = On
10255+
10256+; External filterscript for upload verification
10257+;hphp.upload.verification_script = /home/hphp/verify_script
10258+
10259 ; Local Variables:
10260 ; tab-width: 4
10261 ; End:
10262diff -Naur php-5.0.4/sapi/apache/mod_php5.c hardening-patch-5.0.4-0.3.2/sapi/apache/mod_php5.c
10263--- php-5.0.4/sapi/apache/mod_php5.c 2004-07-14 11:43:26.000000000 +0200
10264+++ hardening-patch-5.0.4-0.3.2/sapi/apache/mod_php5.c 2005-06-26 21:58:33.000000000 +0200
10265@@ -447,7 +447,7 @@
10266 sapi_apache_get_fd,
10267 sapi_apache_force_http_10,
10268 sapi_apache_get_target_uid,
10269- sapi_apache_get_target_gid
10270+ sapi_apache_get_target_gid,
10271 };
10272 /* }}} */
10273
10274@@ -899,7 +899,11 @@
10275 {
10276 TSRMLS_FETCH();
10277 if (PG(expose_php)) {
10278+#if HARDENING_PATCH
10279+ ap_add_version_component("PHP/" PHP_VERSION " with Hardening-Patch");
10280+#else
10281 ap_add_version_component("PHP/" PHP_VERSION);
10282+#endif
10283 }
10284 }
10285 #endif
10286diff -Naur php-5.0.4/sapi/apache2filter/sapi_apache2.c hardening-patch-5.0.4-0.3.2/sapi/apache2filter/sapi_apache2.c
10287--- php-5.0.4/sapi/apache2filter/sapi_apache2.c 2005-01-07 07:28:24.000000000 +0100
10288+++ hardening-patch-5.0.4-0.3.2/sapi/apache2filter/sapi_apache2.c 2005-06-26 21:56:59.000000000 +0200
10289@@ -572,7 +572,11 @@
10290 {
10291 TSRMLS_FETCH();
10292 if (PG(expose_php)) {
10293+#if HARDENING_PATCH
10294+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
10295+#else
10296 ap_add_version_component(p, "PHP/" PHP_VERSION);
10297+#endif
10298 }
10299 }
10300
10301diff -Naur php-5.0.4/sapi/apache2handler/sapi_apache2.c hardening-patch-5.0.4-0.3.2/sapi/apache2handler/sapi_apache2.c
10302--- php-5.0.4/sapi/apache2handler/sapi_apache2.c 2005-03-10 12:23:57.000000000 +0100
10303+++ hardening-patch-5.0.4-0.3.2/sapi/apache2handler/sapi_apache2.c 2005-06-26 21:56:13.000000000 +0200
10304@@ -340,7 +340,11 @@
10305 {
10306 TSRMLS_FETCH();
10307 if (PG(expose_php)) {
10308+#if HARDENING_PATCH
10309+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
10310+#else
10311 ap_add_version_component(p, "PHP/" PHP_VERSION);
10312+#endif
10313 }
10314 }
10315
10316diff -Naur php-5.0.4/sapi/cgi/cgi_main.c hardening-patch-5.0.4-0.3.2/sapi/cgi/cgi_main.c
10317--- php-5.0.4/sapi/cgi/cgi_main.c 2005-02-11 03:06:48.000000000 +0100
10318+++ hardening-patch-5.0.4-0.3.2/sapi/cgi/cgi_main.c 2005-06-26 22:01:33.000000000 +0200
10319@@ -1414,11 +1414,19 @@
10320 SG(headers_sent) = 1;
10321 SG(request_info).no_headers = 1;
10322 }
10323+#if HARDENING_PATCH
10324+#if ZEND_DEBUG
10325+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10326+#else
10327+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10328+#endif
10329+#else
10330 #if ZEND_DEBUG
10331 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10332 #else
10333 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10334 #endif
10335+#endif
10336 php_end_ob_buffers(1 TSRMLS_CC);
10337 exit(1);
10338 break;
10339diff -Naur php-5.0.4/sapi/cli/php_cli.c hardening-patch-5.0.4-0.3.2/sapi/cli/php_cli.c
10340--- php-5.0.4/sapi/cli/php_cli.c 2005-03-22 16:09:20.000000000 +0100
10341+++ hardening-patch-5.0.4-0.3.2/sapi/cli/php_cli.c 2005-06-28 01:08:04.000000000 +0200
10342@@ -694,11 +694,19 @@
10343 if (php_request_startup(TSRMLS_C)==FAILURE) {
10344 goto err;
10345 }
10346+#if HARDENING_PATCH
10347+#if ZEND_DEBUG
10348+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10349+#else
10350+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10351+#endif
10352+#else
10353 #if ZEND_DEBUG
10354 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10355 #else
10356 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10357 #endif
10358+#endif
10359 php_end_ob_buffers(1 TSRMLS_CC);
10360 exit_status=1;
10361 goto out;
10362diff -Naur php-5.0.4/TSRM/TSRM.h hardening-patch-5.0.4-0.3.2/TSRM/TSRM.h
10363--- php-5.0.4/TSRM/TSRM.h 2005-03-11 12:12:07.000000000 +0100
10364+++ hardening-patch-5.0.4-0.3.2/TSRM/TSRM.h 2005-06-26 22:07:33.000000000 +0200
10365@@ -33,6 +33,13 @@
10366 # define TSRM_API
10367 #endif
10368
10369+#if HARDENING_PATCH
10370+# if HAVE_REALPATH
10371+# undef realpath
10372+# define realpath php_realpath
10373+# endif
10374+#endif
10375+
10376 /* Only compile multi-threading functions if we're in ZTS mode */
10377 #ifdef ZTS
10378
10379@@ -88,6 +95,7 @@
10380
10381 #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
10382
10383+
10384 #ifdef __cplusplus
10385 extern "C" {
10386 #endif
10387diff -Naur php-5.0.4/TSRM/tsrm_virtual_cwd.c hardening-patch-5.0.4-0.3.2/TSRM/tsrm_virtual_cwd.c
10388--- php-5.0.4/TSRM/tsrm_virtual_cwd.c 2005-03-11 12:09:42.000000000 +0100
10389+++ hardening-patch-5.0.4-0.3.2/TSRM/tsrm_virtual_cwd.c 2005-06-26 22:07:48.000000000 +0200
10390@@ -197,6 +197,165 @@
10391 return p;
10392 }
10393
10394+#if HARDENING_PATCH
10395+CWD_API char *php_realpath(const char *path, char *resolved)
10396+{
10397+ struct stat sb;
10398+ char *p, *q, *s;
10399+ size_t left_len, resolved_len;
10400+ unsigned symlinks;
10401+ int serrno, slen;
10402+ int is_dir = 1;
10403+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
10404+
10405+ serrno = errno;
10406+ symlinks = 0;
10407+ if (path[0] == '/') {
10408+ resolved[0] = '/';
10409+ resolved[1] = '\0';
10410+ if (path[1] == '\0')
10411+ return (resolved);
10412+ resolved_len = 1;
10413+ left_len = strlcpy(left, path + 1, sizeof(left));
10414+ } else {
10415+ if (getcwd(resolved, PATH_MAX) == NULL) {
10416+ strlcpy(resolved, ".", PATH_MAX);
10417+ return (NULL);
10418+ }
10419+ resolved_len = strlen(resolved);
10420+ left_len = strlcpy(left, path, sizeof(left));
10421+ }
10422+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
10423+ errno = ENAMETOOLONG;
10424+ return (NULL);
10425+ }
10426+
10427+ /*
10428+ * Iterate over path components in `left'.
10429+ */
10430+ while (left_len != 0) {
10431+ /*
10432+ * Extract the next path component and adjust `left'
10433+ * and its length.
10434+ */
10435+ p = strchr(left, '/');
10436+ s = p ? p : left + left_len;
10437+ if (s - left >= sizeof(next_token)) {
10438+ errno = ENAMETOOLONG;
10439+ return (NULL);
10440+ }
10441+ memcpy(next_token, left, s - left);
10442+ next_token[s - left] = '\0';
10443+ left_len -= s - left;
10444+ if (p != NULL)
10445+ memmove(left, s + 1, left_len + 1);
10446+ if (resolved[resolved_len - 1] != '/') {
10447+ if (resolved_len + 1 >= PATH_MAX) {
10448+ errno = ENAMETOOLONG;
10449+ return (NULL);
10450+ }
10451+ resolved[resolved_len++] = '/';
10452+ resolved[resolved_len] = '\0';
10453+ }
10454+ if (next_token[0] == '\0')
10455+ continue;
10456+ else if (strcmp(next_token, ".") == 0)
10457+ continue;
10458+ else if (strcmp(next_token, "..") == 0) {
10459+ /*
10460+ * Strip the last path component except when we have
10461+ * single "/"
10462+ */
10463+ if (!is_dir) {
10464+ errno = ENOENT;
10465+ return (NULL);
10466+ }
10467+ if (resolved_len > 1) {
10468+ resolved[resolved_len - 1] = '\0';
10469+ q = strrchr(resolved, '/');
10470+ *q = '\0';
10471+ resolved_len = q - resolved;
10472+ }
10473+ continue;
10474+ }
10475+
10476+ /*
10477+ * Append the next path component and lstat() it. If
10478+ * lstat() fails we still can return successfully if
10479+ * there are no more path components left.
10480+ */
10481+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
10482+ if (resolved_len >= PATH_MAX) {
10483+ errno = ENAMETOOLONG;
10484+ return (NULL);
10485+ }
10486+ if (lstat(resolved, &sb) != 0) {
10487+ if (errno == ENOENT && p == NULL) {
10488+ errno = serrno;
10489+ return (resolved);
10490+ }
10491+ return (NULL);
10492+ }
10493+ if (S_ISLNK(sb.st_mode)) {
10494+ if (symlinks++ > MAXSYMLINKS) {
10495+ errno = ELOOP;
10496+ return (NULL);
10497+ }
10498+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
10499+ if (slen < 0)
10500+ return (NULL);
10501+ symlink[slen] = '\0';
10502+ if (symlink[0] == '/') {
10503+ resolved[1] = 0;
10504+ resolved_len = 1;
10505+ } else if (resolved_len > 1) {
10506+ /* Strip the last path component. */
10507+ resolved[resolved_len - 1] = '\0';
10508+ q = strrchr(resolved, '/');
10509+ *q = '\0';
10510+ resolved_len = q - resolved;
10511+ }
10512+
10513+ /*
10514+ * If there are any path components left, then
10515+ * append them to symlink. The result is placed
10516+ * in `left'.
10517+ */
10518+ if (p != NULL) {
10519+ if (symlink[slen - 1] != '/') {
10520+ if (slen + 1 >= sizeof(symlink)) {
10521+ errno = ENAMETOOLONG;
10522+ return (NULL);
10523+ }
10524+ symlink[slen] = '/';
10525+ symlink[slen + 1] = 0;
10526+ }
10527+ left_len = strlcat(symlink, left, sizeof(left));
10528+ if (left_len >= sizeof(left)) {
10529+ errno = ENAMETOOLONG;
10530+ return (NULL);
10531+ }
10532+ }
10533+ left_len = strlcpy(left, symlink, sizeof(left));
10534+ } else {
10535+ if (S_ISDIR(sb.st_mode)) {
10536+ is_dir = 1;
10537+ } else {
10538+ is_dir = 0;
10539+ }
10540+ }
10541+ }
10542+
10543+ /*
10544+ * Remove trailing slash except when the resolved pathname
10545+ * is a single "/".
10546+ */
10547+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
10548+ resolved[resolved_len - 1] = '\0';
10549+ return (resolved);
10550+}
10551+#endif
10552+
10553 CWD_API void virtual_cwd_startup(void)
10554 {
10555 char cwd[MAXPATHLEN];
10556@@ -321,8 +480,7 @@
10557 path = resolved_path;
10558 path_length = strlen(path);
10559 } else {
10560- /* disable for now
10561- return 1; */
10562+ return 1;
10563 }
10564 }
10565 } else { /* Concat current directory with relative path and then run realpath() on it */
10566@@ -348,9 +506,8 @@
10567 path = resolved_path;
10568 path_length = strlen(path);
10569 } else {
10570- /* disable for now
10571 free(tmp);
10572- return 1; */
10573+ return 1;
10574 }
10575 }
10576 free(tmp);
10577diff -Naur php-5.0.4/TSRM/tsrm_virtual_cwd.h hardening-patch-5.0.4-0.3.2/TSRM/tsrm_virtual_cwd.h
10578--- php-5.0.4/TSRM/tsrm_virtual_cwd.h 2005-03-11 12:07:17.000000000 +0100
10579+++ hardening-patch-5.0.4-0.3.2/TSRM/tsrm_virtual_cwd.h 2005-06-26 22:07:57.000000000 +0200
10580@@ -128,6 +128,22 @@
10581
10582 typedef int (*verify_path_func)(const cwd_state *);
10583
10584+#ifndef HAVE_STRLCPY
10585+CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz);
10586+#undef strlcpy
10587+#define strlcpy php_strlcpy
10588+#endif
10589+
10590+#ifndef HAVE_STRLCAT
10591+CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz);
10592+#undef strlcat
10593+#define strlcat php_strlcat
10594+#endif
10595+
10596+
10597+#if HARDENING_PATCH
10598+CWD_API char *php_realpath(const char *path, char *resolved);
10599+#endif
10600 CWD_API void virtual_cwd_startup(void);
10601 CWD_API void virtual_cwd_shutdown(void);
10602 CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC);
10603diff -Naur php-5.0.4/Zend/zend_alloc.c hardening-patch-5.0.4-0.3.2/Zend/zend_alloc.c
10604--- php-5.0.4/Zend/zend_alloc.c 2004-08-27 18:49:54.000000000 +0200
10605+++ hardening-patch-5.0.4-0.3.2/Zend/zend_alloc.c 2005-06-26 22:52:59.000000000 +0200
10606@@ -64,6 +64,11 @@
10607 # define END_MAGIC_SIZE 0
10608 #endif
10609
10610+#if HARDENING_PATCH_MM_PROTECT
10611+# define CANARY_SIZE sizeof(unsigned int)
10612+#else
10613+# define CANARY_SIZE 0
10614+#endif
10615
10616 # if MEMORY_LIMIT
10617 # if ZEND_DEBUG
10618@@ -104,9 +109,17 @@
10619 if (p==AG(head)) { \
10620 AG(head) = p->pNext; \
10621 } else { \
10622+ if (p != p->pLast->pNext) { \
10623+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
10624+ exit(1); \
10625+ } \
10626 p->pLast->pNext = p->pNext; \
10627 } \
10628 if (p->pNext) { \
10629+ if (p != p->pNext->pLast) { \
10630+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
10631+ exit(1); \
10632+ } \
10633 p->pNext->pLast = p->pLast; \
10634 }
10635 #else
10636@@ -145,6 +158,12 @@
10637 DECLARE_CACHE_VARS();
10638 TSRMLS_FETCH();
10639
10640+#if HARDENING_PATCH_MM_PROTECT
10641+ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) {
10642+ zend_security_log(S_MEMORY, "emalloc() - requested size would result in integer overflow");
10643+ exit(1);
10644+ }
10645+#endif
10646 CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);
10647
10648 #if !ZEND_DISABLE_MEMORY_CACHE
10649@@ -163,6 +182,10 @@
10650 AG(cache_stats)[CACHE_INDEX][1]++;
10651 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
10652 #endif
10653+#if HARDENING_PATCH_MM_PROTECT
10654+ p->canary = HG(canary_1);
10655+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
10656+#endif
10657 p->cached = 0;
10658 p->size = size;
10659 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
10660@@ -179,7 +202,7 @@
10661 AG(allocated_memory_peak) = AG(allocated_memory);
10662 }
10663 #endif
10664- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE);
10665+ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE);
10666 #if !ZEND_DISABLE_MEMORY_CACHE
10667 }
10668 #endif
10669@@ -211,7 +234,10 @@
10670 # endif
10671 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
10672 #endif
10673-
10674+#if HARDENING_PATCH_MM_PROTECT
10675+ p->canary = HG(canary_1);
10676+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
10677+#endif
10678 HANDLE_UNBLOCK_INTERRUPTIONS();
10679 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
10680 }
10681@@ -239,6 +265,10 @@
10682 }
10683 }
10684
10685+
10686+#if HARDENING_PATCH
10687+ zend_security_log(S_MEMORY, "Possible integer overflow catched by safe_emalloc()");
10688+#endif
10689 zend_error(E_ERROR, "Possible integer overflow in memory allocation (%zd * %zd + %zd)", nmemb, size, offset);
10690 return 0;
10691 }
10692@@ -247,9 +277,22 @@
10693
10694 ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
10695 {
10696+#if HARDENING_PATCH_MM_PROTECT
10697+ unsigned int *canary_2;
10698+#endif
10699 zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING);
10700 DECLARE_CACHE_VARS();
10701 TSRMLS_FETCH();
10702+
10703+#if HARDENING_PATCH_MM_PROTECT
10704+ canary_2 = (unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
10705+ if (p->canary != HG(canary_1) || *canary_2 != HG(canary_2)) {
10706+ zend_security_log(S_MEMORY, "canary mismatch on efree() - heap overflow or double efree detected");
10707+ exit(1);
10708+ }
10709+ /* to catch double efree()s */
10710+ *canary_2 = p->canary = 0;
10711+#endif
10712
10713 #if defined(ZTS) && TSRM_DEBUG
10714 if (p->thread_id != tsrm_thread_id()) {
10715@@ -291,23 +334,35 @@
10716
10717 ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
10718 {
10719- void *p;
10720- int final_size = size*nmemb;
10721+ char *p;
10722+ size_t _size = nmemb * size;
10723+
10724+ if (nmemb && (_size/nmemb!=size)) {
10725+#if HARDENING_PATCH
10726+ zend_security_log(S_MEMORY, "Possible integer overflow catched by ecalloc()");
10727+#endif
10728+ fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size);
10729+#if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID
10730+ kill(getpid(), SIGSEGV);
10731+#else
10732+ exit(1);
10733+#endif
10734+ }
10735
10736- HANDLE_BLOCK_INTERRUPTIONS();
10737- p = _emalloc(final_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
10738- if (!p) {
10739- HANDLE_UNBLOCK_INTERRUPTIONS();
10740- return (void *) p;
10741+ p = (char *) _emalloc(_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
10742+ if (p) {
10743+ memset(p, 0, _size);
10744 }
10745- memset(p, 0, final_size);
10746- HANDLE_UNBLOCK_INTERRUPTIONS();
10747- return p;
10748+
10749+ return ((void *)p);
10750 }
10751
10752
10753 ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
10754 {
10755+#if HARDENING_PATCH_MM_PROTECT
10756+ unsigned int canary_2;
10757+#endif
10758 zend_mem_header *p;
10759 zend_mem_header *orig;
10760 DECLARE_CACHE_VARS();
10761@@ -319,6 +374,14 @@
10762
10763 p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING);
10764
10765+#if HARDENING_PATCH_MM_PROTECT
10766+ canary_2 = *(unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
10767+ if (p->canary != HG(canary_1) || canary_2 != HG(canary_2)) {
10768+ zend_security_log(S_MEMORY, "canary mismatch on erealloc() - heap overflow detected");
10769+ exit(1);
10770+ }
10771+#endif
10772+
10773 #if defined(ZTS) && TSRM_DEBUG
10774 if (p->thread_id != tsrm_thread_id()) {
10775 void *new_p;
10776@@ -342,7 +405,7 @@
10777 }
10778 #endif
10779 REMOVE_POINTER_FROM_LIST(p);
10780- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE);
10781+ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE);
10782 if (!p) {
10783 if (!allow_failure) {
10784 fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size);
10785@@ -364,6 +427,9 @@
10786 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
10787 #endif
10788
10789+#if HARDENING_PATCH_MM_PROTECT
10790+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
10791+#endif
10792 p->size = size;
10793
10794 HANDLE_UNBLOCK_INTERRUPTIONS();
10795@@ -439,6 +505,10 @@
10796 {
10797 AG(head) = NULL;
10798
10799+#if HARDENING_PATCH_MM_PROTECT
10800+ HG(canary_1) = zend_canary();
10801+ HG(canary_2) = zend_canary();
10802+#endif
10803 #if MEMORY_LIMIT
10804 AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */
10805 AG(allocated_memory) = 0;
10806diff -Naur php-5.0.4/Zend/zend_alloc.h hardening-patch-5.0.4-0.3.2/Zend/zend_alloc.h
10807--- php-5.0.4/Zend/zend_alloc.h 2004-08-11 08:13:12.000000000 +0200
10808+++ hardening-patch-5.0.4-0.3.2/Zend/zend_alloc.h 2005-06-26 22:16:00.000000000 +0200
10809@@ -35,6 +35,9 @@
10810 #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL
10811
10812 typedef struct _zend_mem_header {
10813+#if HARDENING_PATCH_MM_PROTECT
10814+ unsigned int canary;
10815+#endif
10816 #if ZEND_DEBUG
10817 long magic;
10818 char *filename;
10819diff -Naur php-5.0.4/Zend/zend_API.h hardening-patch-5.0.4-0.3.2/Zend/zend_API.h
10820--- php-5.0.4/Zend/zend_API.h 2005-01-22 13:29:13.000000000 +0100
10821+++ hardening-patch-5.0.4-0.3.2/Zend/zend_API.h 2005-06-26 20:59:20.000000000 +0200
10822@@ -47,6 +47,7 @@
10823 #define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_FN(classname##_##name))
10824
10825 #define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
10826+#define ZEND_STATIC_FE(zend_name, name, arg_info) { zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), 0 },
10827
10828 #define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_FENTRY(zend_name, name, arg_info, 0)
10829 #define ZEND_FE(name, arg_info) ZEND_FENTRY(name, ZEND_FN(name), arg_info, 0)
10830diff -Naur php-5.0.4/Zend/zend_builtin_functions.c hardening-patch-5.0.4-0.3.2/Zend/zend_builtin_functions.c
10831--- php-5.0.4/Zend/zend_builtin_functions.c 2005-03-14 10:13:14.000000000 +0100
10832+++ hardening-patch-5.0.4-0.3.2/Zend/zend_builtin_functions.c 2005-06-26 22:15:50.000000000 +0200
10833@@ -52,6 +52,9 @@
10834 static ZEND_FUNCTION(crash);
10835 #endif
10836 #endif
10837+#if HARDENING_PATCH_MM_PROTECT_DEBUG
10838+static ZEND_FUNCTION(heap_overflow);
10839+#endif
10840 static ZEND_FUNCTION(get_included_files);
10841 static ZEND_FUNCTION(is_subclass_of);
10842 static ZEND_FUNCTION(is_a);
10843@@ -111,6 +114,9 @@
10844 ZEND_FE(crash, NULL)
10845 #endif
10846 #endif
10847+#if HARDENING_PATCH_MM_PROTECT_DEBUG
10848+ ZEND_FE(heap_overflow, NULL)
10849+#endif
10850 ZEND_FE(get_included_files, NULL)
10851 ZEND_FALIAS(get_required_files, get_included_files, NULL)
10852 ZEND_FE(is_subclass_of, NULL)
10853@@ -999,6 +1005,19 @@
10854
10855 #endif /* ZEND_DEBUG */
10856
10857+
10858+#if HARDENING_PATCH_MM_PROTECT_DEBUG
10859+ZEND_FUNCTION(heap_overflow)
10860+{
10861+ char *nowhere = emalloc(10);
10862+
10863+ memcpy(nowhere, "something1234567890", sizeof("something1234567890"));
10864+
10865+ efree(nowhere);
10866+}
10867+#endif
10868+
10869+
10870 /* {{{ proto array get_included_files(void)
10871 Returns an array with the file names that were include_once()'d */
10872 ZEND_FUNCTION(get_included_files)
10873diff -Naur php-5.0.4/Zend/zend.c hardening-patch-5.0.4-0.3.2/Zend/zend.c
10874--- php-5.0.4/Zend/zend.c 2005-03-16 00:47:12.000000000 +0100
10875+++ hardening-patch-5.0.4-0.3.2/Zend/zend.c 2005-07-05 18:32:04.000000000 +0200
10876@@ -54,6 +54,12 @@
10877 ZEND_API void (*zend_unblock_interruptions)(void);
10878 ZEND_API void (*zend_ticks_function)(int ticks);
10879 ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
10880+#if HARDENING_PATCH
10881+ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
10882+#endif
10883+#if HARDENING_PATCH_INC_PROTECT
10884+ZEND_API int (*zend_is_valid_include)(zval *z);
10885+#endif
10886 int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
10887
10888 void (*zend_on_timeout)(int seconds TSRMLS_DC);
10889@@ -72,9 +78,80 @@
10890 return SUCCESS;
10891 }
10892
10893+#if HARDENING_PATCH
10894+static ZEND_INI_MH(OnUpdateHPHP_log_syslog)
10895+{
10896+ if (!new_value) {
10897+ EG(hphp_log_syslog) = S_ALL & ~S_SQL | S_MEMORY;
10898+ } else {
10899+ EG(hphp_log_syslog) = atoi(new_value) | S_MEMORY;
10900+ }
10901+ return SUCCESS;
10902+}
10903+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_facility)
10904+{
10905+ if (!new_value) {
10906+ EG(hphp_log_syslog_facility) = LOG_USER;
10907+ } else {
10908+ EG(hphp_log_syslog_facility) = atoi(new_value);
10909+ }
10910+ return SUCCESS;
10911+}
10912+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_priority)
10913+{
10914+ if (!new_value) {
10915+ EG(hphp_log_syslog_priority) = LOG_ALERT;
10916+ } else {
10917+ EG(hphp_log_syslog_priority) = atoi(new_value);
10918+ }
10919+ return SUCCESS;
10920+}
10921+static ZEND_INI_MH(OnUpdateHPHP_log_sapi)
10922+{
10923+ if (!new_value) {
10924+ EG(hphp_log_sapi) = S_ALL & ~S_SQL;
10925+ } else {
10926+ EG(hphp_log_sapi) = atoi(new_value);
10927+ }
10928+ return SUCCESS;
10929+}
10930+static ZEND_INI_MH(OnUpdateHPHP_log_script)
10931+{
10932+ if (!new_value) {
10933+ EG(hphp_log_script) = S_ALL & ~S_MEMORY;
10934+ } else {
10935+ EG(hphp_log_script) = atoi(new_value) & ~S_MEMORY;
10936+ }
10937+ return SUCCESS;
10938+}
10939+static ZEND_INI_MH(OnUpdateHPHP_log_scriptname)
10940+{
10941+ if (!new_value) {
10942+ EG(hphp_log_scriptname) = NULL;
10943+ } else {
10944+ if (EG(hphp_log_scriptname)) {
10945+ pefree(EG(hphp_log_scriptname),1);
10946+ }
10947+ EG(hphp_log_scriptname) = pestrdup(new_value,1);
10948+ }
10949+ return SUCCESS;
10950+}
10951+#endif
10952
10953 ZEND_INI_BEGIN()
10954 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
10955+#if HARDENING_PATCH
10956+ ZEND_INI_ENTRY("hphp.log.syslog", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog)
10957+ ZEND_INI_ENTRY("hphp.log.syslog.facility", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_facility)
10958+ ZEND_INI_ENTRY("hphp.log.syslog.priority", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_priority)
10959+ ZEND_INI_ENTRY("hphp.log.sapi", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_sapi)
10960+ ZEND_INI_ENTRY("hphp.log.script", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_script)
10961+ ZEND_INI_ENTRY("hphp.log.script.name", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_scriptname)
10962+ STD_ZEND_INI_BOOLEAN("hphp.log.use-x-forwarded-for", "0", ZEND_INI_SYSTEM, OnUpdateBool, hphp_log_use_x_forwarded_for, zend_executor_globals, executor_globals)
10963+ STD_ZEND_INI_ENTRY("hphp.executor.max_depth", "0", ZEND_INI_PERDIR, OnUpdateLong, hphp_executor_max_depth, zend_executor_globals, executor_globals)
10964+ STD_ZEND_INI_BOOLEAN("hphp.sql.bailout_on_error", "0", ZEND_INI_PERDIR, OnUpdateBool, hphp_sql_bailout_on_error, hardened_globals_struct, hardened_globals)
10965+ STD_ZEND_INI_BOOLEAN("hphp.multiheader", "0", ZEND_INI_PERDIR, OnUpdateBool, hphp_multiheader, hardened_globals_struct, hardened_globals)
10966+#endif
10967 STD_ZEND_INI_BOOLEAN("zend.ze1_compatibility_mode", "0", ZEND_INI_ALL, OnUpdateBool, ze1_compatibility_mode, zend_executor_globals, executor_globals)
10968 ZEND_INI_END()
10969
10970@@ -476,6 +553,7 @@
10971 EG(user_error_handler) = NULL;
10972 EG(user_exception_handler) = NULL;
10973 EG(in_execution) = 0;
10974+ EG(in_code_type) = 0;
10975 EG(in_autoload) = NULL;
10976 EG(current_execute_data) = NULL;
10977 EG(current_module) = NULL;
10978@@ -545,6 +623,14 @@
10979 extern zend_scanner_globals language_scanner_globals;
10980 #endif
10981
10982+ /* Set up Hardening-Patch utility functions first */
10983+#if HARDENING_PATCH
10984+ zend_security_log = utility_functions->security_log_function;
10985+#endif
10986+#if HARDENING_PATCH_INC_PROTECT
10987+ zend_is_valid_include = utility_functions->is_valid_include;
10988+#endif
10989+
10990 #ifdef ZTS
10991 ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
10992 #else
10993@@ -747,6 +833,7 @@
10994 }
10995 CG(unclean_shutdown) = 1;
10996 CG(in_compilation) = EG(in_execution) = 0;
10997+ EG(in_code_type) = 0;
10998 EG(current_execute_data) = NULL;
10999 longjmp(EG(bailout), FAILURE);
11000 }
11001diff -Naur php-5.0.4/Zend/zend_canary.c hardening-patch-5.0.4-0.3.2/Zend/zend_canary.c
11002--- php-5.0.4/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
11003+++ hardening-patch-5.0.4-0.3.2/Zend/zend_canary.c 2005-06-26 22:13:40.000000000 +0200
11004@@ -0,0 +1,58 @@
11005+/*
11006+ +----------------------------------------------------------------------+
11007+ | Hardening-Patch for PHP |
11008+ +----------------------------------------------------------------------+
11009+ | Copyright (c) 2004-2005 Stefan Esser |
11010+ +----------------------------------------------------------------------+
11011+ | This source file is subject to version 2.02 of the PHP license, |
11012+ | that is bundled with this package in the file LICENSE, and is |
11013+ | available at through the world-wide-web at |
11014+ | http://www.php.net/license/2_02.txt. |
11015+ | If you did not receive a copy of the PHP license and are unable to |
11016+ | obtain it through the world-wide-web, please send a note to |
11017+ | license@php.net so we can mail you a copy immediately. |
11018+ +----------------------------------------------------------------------+
11019+ | Author: Stefan Esser <sesser@hardened-php.net> |
11020+ +----------------------------------------------------------------------+
11021+ */
11022+/* $Id: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */
11023+
11024+#include "zend.h"
11025+
11026+#include <stdio.h>
11027+#include <stdlib.h>
11028+
11029+
11030+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
11031+
11032+/* will be replaced later with more compatible method */
11033+ZEND_API unsigned int zend_canary()
11034+{
11035+ time_t t;
11036+ unsigned int canary;
11037+ int fd;
11038+
11039+ fd = open("/dev/urandom", 0);
11040+ if (fd != -1) {
11041+ int r = read(fd, &canary, sizeof(canary));
11042+ close(fd);
11043+ if (r == sizeof(canary)) {
11044+ return (canary);
11045+ }
11046+ }
11047+ /* not good but we never want to do this */
11048+ time(&t);
11049+ canary = *(unsigned int *)&t + getpid() << 16;
11050+ return (canary);
11051+}
11052+#endif
11053+
11054+
11055+/*
11056+ * Local variables:
11057+ * tab-width: 4
11058+ * c-basic-offset: 4
11059+ * End:
11060+ * vim600: sw=4 ts=4 fdm=marker
11061+ * vim<600: sw=4 ts=4
11062+ */
11063diff -Naur php-5.0.4/Zend/zend_compile.c hardening-patch-5.0.4-0.3.2/Zend/zend_compile.c
11064--- php-5.0.4/Zend/zend_compile.c 2005-03-10 14:24:32.000000000 +0100
11065+++ hardening-patch-5.0.4-0.3.2/Zend/zend_compile.c 2005-06-27 00:23:42.000000000 +0200
11066@@ -1455,7 +1455,7 @@
11067 zend_op *opline;
11068
11069 if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) {
11070- return 0;
11071+ return (switch_entry->cond.op_type == IS_UNUSED);
11072 }
11073
11074 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
11075diff -Naur php-5.0.4/Zend/zend_compile.h hardening-patch-5.0.4-0.3.2/Zend/zend_compile.h
11076--- php-5.0.4/Zend/zend_compile.h 2004-09-16 02:44:12.000000000 +0200
11077+++ hardening-patch-5.0.4-0.3.2/Zend/zend_compile.h 2005-06-27 23:31:04.000000000 +0200
11078@@ -275,6 +275,8 @@
11079 zval *object;
11080 union _temp_variable *Ts;
11081 zend_bool original_in_execution;
11082+ zend_uint original_in_code_type;
11083+ zend_uint execute_depth;
11084 zend_class_entry *calling_scope;
11085 struct _zend_execute_data *prev_execute_data;
11086 };
11087@@ -767,6 +769,7 @@
11088 #define ZEND_OVERLOADED_FUNCTION 3
11089 #define ZEND_EVAL_CODE 4
11090 #define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5
11091+#define ZEND_SANDBOX_CODE 6
11092
11093 #define ZEND_INTERNAL_CLASS 1
11094 #define ZEND_USER_CLASS 2
11095diff -Naur php-5.0.4/Zend/zend_constants.c hardening-patch-5.0.4-0.3.2/Zend/zend_constants.c
11096--- php-5.0.4/Zend/zend_constants.c 2004-07-13 21:22:11.000000000 +0200
11097+++ hardening-patch-5.0.4-0.3.2/Zend/zend_constants.c 2005-07-01 18:17:57.000000000 +0200
11098@@ -107,6 +107,72 @@
11099 REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
11100
11101 REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
11102+#if HARDENING_PATCH
11103+ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
11104+ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
11105+ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_VARS, CONST_PERSISTENT | CONST_CS);
11106+ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
11107+ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
11108+ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
11109+ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
11110+ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
11111+
11112+ /* error levels */
11113+ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
11114+ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
11115+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
11116+ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
11117+ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
11118+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
11119+ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
11120+ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
11121+ /* facility: type of program logging the message */
11122+ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
11123+ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
11124+ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
11125+ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
11126+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
11127+ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
11128+ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
11129+#ifdef LOG_NEWS
11130+ /* No LOG_NEWS on HP-UX */
11131+ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
11132+#endif
11133+#ifdef LOG_UUCP
11134+ /* No LOG_UUCP on HP-UX */
11135+ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
11136+#endif
11137+#ifdef LOG_CRON
11138+ /* apparently some systems don't have this one */
11139+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
11140+#endif
11141+#ifdef LOG_AUTHPRIV
11142+ /* AIX doesn't have LOG_AUTHPRIV */
11143+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
11144+#endif
11145+#if !defined(PHP_WIN32) && !defined(NETWARE)
11146+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
11147+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
11148+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
11149+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
11150+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
11151+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
11152+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
11153+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
11154+#endif
11155+ /* options */
11156+ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
11157+ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
11158+ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
11159+ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
11160+#ifdef LOG_NOWAIT
11161+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
11162+#endif
11163+#ifdef LOG_PERROR
11164+ /* AIX doesn't have LOG_PERROR */
11165+ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
11166+#endif
11167+#endif
11168
11169 /* true/false constants */
11170 {
11171diff -Naur php-5.0.4/Zend/zend_errors.h hardening-patch-5.0.4-0.3.2/Zend/zend_errors.h
11172--- php-5.0.4/Zend/zend_errors.h 2004-01-08 18:31:47.000000000 +0100
11173+++ hardening-patch-5.0.4-0.3.2/Zend/zend_errors.h 2005-06-28 00:03:24.000000000 +0200
11174@@ -38,6 +38,17 @@
11175 #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE)
11176 #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
11177
11178+#if HARDENING_PATCH
11179+#define S_MEMORY (1<<0L)
11180+#define S_VARS (1<<1L)
11181+#define S_FILES (1<<2L)
11182+#define S_INCLUDE (1<<3L)
11183+#define S_SQL (1<<4L)
11184+#define S_EXECUTOR (1<<5L)
11185+#define S_MISC (1<<30L)
11186+#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MISC | S_SQL | S_EXECUTOR)
11187+#endif
11188+
11189 #endif /* ZEND_ERRORS_H */
11190
11191 /*
11192diff -Naur php-5.0.4/Zend/zend_execute_API.c hardening-patch-5.0.4-0.3.2/Zend/zend_execute_API.c
11193--- php-5.0.4/Zend/zend_execute_API.c 2005-03-19 15:29:18.000000000 +0100
11194+++ hardening-patch-5.0.4-0.3.2/Zend/zend_execute_API.c 2005-07-03 10:40:05.000000000 +0200
11195@@ -137,6 +137,7 @@
11196 EG(class_table) = CG(class_table);
11197
11198 EG(in_execution) = 0;
11199+ EG(in_code_type) = 0;
11200 EG(in_autoload) = NULL;
11201
11202 zend_ptr_stack_init(&EG(argument_stack));
11203@@ -966,7 +967,7 @@
11204 return retval;
11205 }
11206
11207-ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
11208+ZEND_API int zend_eval_string_ex_ex(char *str, zval *retval_ptr, char *string_name, int type TSRMLS_DC)
11209 {
11210 zval pv;
11211 zend_op_array *new_op_array;
11212@@ -999,6 +1000,7 @@
11213 zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
11214 zend_op **original_opline_ptr = EG(opline_ptr);
11215
11216+ new_op_array->type = type;
11217 EG(return_value_ptr_ptr) = &local_retval_ptr;
11218 EG(active_op_array) = new_op_array;
11219 EG(no_extensions)=1;
11220@@ -1033,6 +1035,12 @@
11221 }
11222
11223
11224+ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
11225+{
11226+ return (zend_eval_string_ex_ex(str, retval_ptr, string_name, ZEND_EVAL_CODE TSRMLS_CC));
11227+}
11228+
11229+
11230 ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
11231 {
11232 int result;
11233diff -Naur php-5.0.4/Zend/zend_execute.c hardening-patch-5.0.4-0.3.2/Zend/zend_execute.c
11234--- php-5.0.4/Zend/zend_execute.c 2005-03-21 17:22:10.000000000 +0100
11235+++ hardening-patch-5.0.4-0.3.2/Zend/zend_execute.c 2005-06-28 00:08:12.000000000 +0200
11236@@ -1343,6 +1343,7 @@
11237 efree(EX(Ts)); \
11238 } \
11239 EG(in_execution) = EX(original_in_execution); \
11240+ EG(in_code_type) = EX(original_in_code_type); \
11241 EG(current_execute_data) = EX(prev_execute_data); \
11242 return 1; /* CHECK_ME */
11243
11244@@ -1369,6 +1370,16 @@
11245 EX(original_in_execution) = EG(in_execution);
11246 EX(prev_execute_data) = EG(current_execute_data);
11247 EG(current_execute_data) = &execute_data;
11248+#if HARDENING_PATCH
11249+ EX(execute_depth) = 0;
11250+
11251+ if (op_array->type == ZEND_EVAL_CODE && EG(in_code_type) != ZEND_SANDBOX_CODE) {
11252+ EG(in_code_type) = ZEND_EVAL_CODE;
11253+ } else if (op_array->type == ZEND_SANDBOX_CODE) {
11254+ EG(in_code_type) = ZEND_SANDBOX_CODE;
11255+ op_array->type = ZEND_EVAL_CODE;
11256+ }
11257+#endif
11258
11259 EG(in_execution) = 1;
11260 if (op_array->start_op) {
11261@@ -1395,6 +1406,19 @@
11262 EX(function_state).function_symbol_table = NULL;
11263 #endif
11264
11265+#if HARDENING_PATCH
11266+ if (EX(prev_execute_data) == NULL) {
11267+ EX(execute_depth) = 0;
11268+ } else {
11269+ EX(execute_depth) = EX(prev_execute_data)->execute_depth + 1;
11270+ }
11271+
11272+ if (EG(hphp_executor_max_depth) > 0 && EX(execute_depth) > EG(hphp_executor_max_depth)) {
11273+ zend_security_log(S_EXECUTOR, "Maximum execution depth of %u violated", EG(hphp_executor_max_depth));
11274+ zend_bailout();
11275+ }
11276+#endif
11277+
11278 while (1) {
11279 #ifdef ZEND_WIN32
11280 if (EG(timed_out)) {
11281@@ -3523,7 +3547,12 @@
11282 int dummy = 1;
11283 zend_file_handle file_handle;
11284
11285+#if HARDENING_PATCH_INC_PROTECT
11286+ if (zend_is_valid_include(inc_filename)
11287+ && (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC))) {
11288+#else
11289 if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
11290+#endif
11291
11292 if (!file_handle.opened_path) {
11293 file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len);
11294@@ -3548,6 +3577,11 @@
11295 break;
11296 case ZEND_INCLUDE:
11297 case ZEND_REQUIRE:
11298+#if HARDENING_PATCH_INC_PROTECT
11299+ if (!zend_is_valid_include(inc_filename)) {
11300+ break;
11301+ }
11302+#endif
11303 new_op_array = compile_filename(opline->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
11304 break;
11305 case ZEND_EVAL: {
11306diff -Naur php-5.0.4/Zend/zend_extensions.h hardening-patch-5.0.4-0.3.2/Zend/zend_extensions.h
11307--- php-5.0.4/Zend/zend_extensions.h 2004-11-25 21:26:48.000000000 +0100
11308+++ hardening-patch-5.0.4-0.3.2/Zend/zend_extensions.h 2005-06-28 14:46:24.000000000 +0200
11309@@ -24,10 +24,11 @@
11310
11311 #include "zend_compile.h"
11312
11313-/* The first number is the engine version and the rest is the date.
11314+/* The first number is a flag saying that Hardening-Patch is used
11315+ * the second number is the engine version and the rest is the date.
11316 * This way engine 2 API no. is always greater than engine 1 API no..
11317 */
11318-#define ZEND_EXTENSION_API_NO 220040412
11319+#define ZEND_EXTENSION_API_NO 1220050627
11320
11321 typedef struct _zend_extension_version_info {
11322 int zend_extension_api_no;
11323diff -Naur php-5.0.4/Zend/zend_globals.h hardening-patch-5.0.4-0.3.2/Zend/zend_globals.h
11324--- php-5.0.4/Zend/zend_globals.h 2004-11-04 00:14:31.000000000 +0100
11325+++ hardening-patch-5.0.4-0.3.2/Zend/zend_globals.h 2005-06-30 12:41:57.000000000 +0200
11326@@ -174,6 +174,16 @@
11327
11328 int error_reporting;
11329 int orig_error_reporting;
11330+#if HARDENING_PATCH
11331+ int hphp_log_syslog;
11332+ int hphp_log_syslog_facility;
11333+ int hphp_log_syslog_priority;
11334+ int hphp_log_sapi;
11335+ int hphp_log_script;
11336+ char *hphp_log_scriptname;
11337+ zend_bool hphp_log_use_x_forwarded_for;
11338+ long hphp_executor_max_depth;
11339+#endif
11340 int exit_status;
11341
11342 zend_op_array *active_op_array;
11343@@ -191,6 +201,7 @@
11344 int ticks_count;
11345
11346 zend_bool in_execution;
11347+ zend_uint in_code_type;
11348 HashTable *in_autoload;
11349 zend_bool bailout_set;
11350 zend_bool full_tables_cleanup;
11351diff -Naur php-5.0.4/Zend/zend.h hardening-patch-5.0.4-0.3.2/Zend/zend.h
11352--- php-5.0.4/Zend/zend.h 2005-03-10 12:30:44.000000000 +0100
11353+++ hardening-patch-5.0.4-0.3.2/Zend/zend.h 2005-07-03 10:41:35.000000000 +0200
11354@@ -290,6 +290,7 @@
11355 /* Variable information */
11356 zvalue_value value; /* value */
11357 zend_uint refcount;
11358+ zend_ushort flags;
11359 zend_uchar type; /* active type */
11360 zend_uchar is_ref;
11361 };
11362@@ -359,6 +360,12 @@
11363 void (*on_timeout)(int seconds TSRMLS_DC);
11364 int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
11365 int (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap);
11366+#if HARDENING_PATCH
11367+ void (*security_log_function)(int loglevel, char *fmt, ...);
11368+#endif
11369+#if HARDENING_PATCH_INC_PROTECT
11370+ int (*is_valid_include)(zval *z);
11371+#endif
11372 } zend_utility_functions;
11373
11374
11375@@ -496,6 +503,16 @@
11376 extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
11377 extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
11378 extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
11379+#if HARDENING_PATCH
11380+extern ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
11381+#endif
11382+#if HARDENING_PATCH_INC_PROTECT
11383+extern ZEND_API int (*zend_is_valid_include)(zval *z);
11384+#endif
11385+
11386+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
11387+ZEND_API unsigned int zend_canary(void);
11388+#endif
11389
11390
11391 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
11392@@ -620,6 +637,11 @@
11393 #define ZEND_MAX_RESERVED_RESOURCES 4
11394
11395
11396+#if HARDENING_PATCH
11397+#include "hardened_globals.h"
11398+#include "php_syslog.h"
11399+#endif
11400+
11401 #endif /* ZEND_H */
11402
11403 /*
11404diff -Naur php-5.0.4/Zend/zend_hash.c hardening-patch-5.0.4-0.3.2/Zend/zend_hash.c
11405--- php-5.0.4/Zend/zend_hash.c 2004-07-10 09:45:49.000000000 +0200
11406+++ hardening-patch-5.0.4-0.3.2/Zend/zend_hash.c 2005-06-26 22:51:36.000000000 +0200
11407@@ -21,6 +21,18 @@
11408
11409 #include "zend.h"
11410
11411+#if HARDENING_PATCH_HASH_PROTECT
11412+ unsigned int zend_hash_canary = 0x1234567;
11413+ zend_bool zend_hash_canary_inited = 0;
11414+#endif
11415+
11416+#define CHECK_HASH_CANARY(hash) \
11417+ if (zend_hash_canary != (hash)->canary) { \
11418+ zend_security_log(S_MEMORY, "Zend HashTable canary was overwritten"); \
11419+ exit(1); \
11420+ }
11421+
11422+
11423 #define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
11424 (element)->pNext = (list_head); \
11425 (element)->pLast = NULL; \
11426@@ -138,6 +150,9 @@
11427 {
11428 uint i = 3;
11429 Bucket **tmp;
11430+#if HARDENING_PATCH_HASH_PROTECT
11431+ TSRMLS_FETCH();
11432+#endif
11433
11434 SET_INCONSISTENT(HT_OK);
11435
11436@@ -147,6 +162,13 @@
11437
11438 ht->nTableSize = 1 << i;
11439 ht->nTableMask = ht->nTableSize - 1;
11440+#if HARDENING_PATCH_HASH_PROTECT
11441+ if (zend_hash_canary_inited==0) {
11442+ zend_hash_canary = zend_canary();
11443+ zend_hash_canary_inited = 1;
11444+ }
11445+ ht->canary = zend_hash_canary;
11446+#endif
11447 ht->pDestructor = pDestructor;
11448 ht->arBuckets = NULL;
11449 ht->pListHead = NULL;
11450@@ -226,6 +248,9 @@
11451 }
11452 #endif
11453 if (ht->pDestructor) {
11454+#if HARDENING_PATCH_HASH_PROTECT
11455+ CHECK_HASH_CANARY(ht);
11456+#endif
11457 ht->pDestructor(p->pData);
11458 }
11459 UPDATE_DATA(ht, p, pData, nDataSize);
11460@@ -291,6 +316,9 @@
11461 }
11462 #endif
11463 if (ht->pDestructor) {
11464+#if HARDENING_PATCH_HASH_PROTECT
11465+ CHECK_HASH_CANARY(ht);
11466+#endif
11467 ht->pDestructor(p->pData);
11468 }
11469 UPDATE_DATA(ht, p, pData, nDataSize);
11470@@ -366,6 +394,9 @@
11471 }
11472 #endif
11473 if (ht->pDestructor) {
11474+#if HARDENING_PATCH_HASH_PROTECT
11475+ CHECK_HASH_CANARY(ht);
11476+#endif
11477 ht->pDestructor(p->pData);
11478 }
11479 UPDATE_DATA(ht, p, pData, nDataSize);
11480@@ -414,7 +445,7 @@
11481 IS_CONSISTENT(ht);
11482
11483 if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */
11484- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
11485+ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
11486 if (t) {
11487 HANDLE_BLOCK_INTERRUPTIONS();
11488 ht->arBuckets = t;
11489@@ -424,6 +455,7 @@
11490 HANDLE_UNBLOCK_INTERRUPTIONS();
11491 return SUCCESS;
11492 }
11493+ zend_error(E_ERROR, "zend_hash_do_resize - out of memory");
11494 return FAILURE;
11495 }
11496 return SUCCESS;
11497@@ -487,6 +519,9 @@
11498 ht->pInternalPointer = p->pListNext;
11499 }
11500 if (ht->pDestructor) {
11501+#if HARDENING_PATCH_HASH_PROTECT
11502+ CHECK_HASH_CANARY(ht);
11503+#endif
11504 ht->pDestructor(p->pData);
11505 }
11506 if (!p->pDataPtr) {
11507@@ -516,6 +551,9 @@
11508 q = p;
11509 p = p->pListNext;
11510 if (ht->pDestructor) {
11511+#if HARDENING_PATCH_HASH_PROTECT
11512+ CHECK_HASH_CANARY(ht);
11513+#endif
11514 ht->pDestructor(q->pData);
11515 }
11516 if (!q->pDataPtr && q->pData) {
11517@@ -542,6 +580,9 @@
11518 q = p;
11519 p = p->pListNext;
11520 if (ht->pDestructor) {
11521+#if HARDENING_PATCH_HASH_PROTECT
11522+ CHECK_HASH_CANARY(ht);
11523+#endif
11524 ht->pDestructor(q->pData);
11525 }
11526 if (!q->pDataPtr && q->pData) {
11527@@ -571,6 +612,9 @@
11528 HANDLE_BLOCK_INTERRUPTIONS();
11529
11530 if (ht->pDestructor) {
11531+#if HARDENING_PATCH_HASH_PROTECT
11532+ CHECK_HASH_CANARY(ht);
11533+#endif
11534 ht->pDestructor(p->pData);
11535 }
11536 if (!p->pDataPtr) {
11537diff -Naur php-5.0.4/Zend/zend_hash.h hardening-patch-5.0.4-0.3.2/Zend/zend_hash.h
11538--- php-5.0.4/Zend/zend_hash.h 2004-01-08 18:31:47.000000000 +0100
11539+++ hardening-patch-5.0.4-0.3.2/Zend/zend_hash.h 2005-06-26 22:20:57.000000000 +0200
11540@@ -58,6 +58,9 @@
11541 } Bucket;
11542
11543 typedef struct _hashtable {
11544+#if HARDENING_PATCH_HASH_PROTECT
11545+ unsigned int canary;
11546+#endif
11547 uint nTableSize;
11548 uint nTableMask;
11549 uint nNumOfElements;
11550diff -Naur php-5.0.4/Zend/zend_llist.c hardening-patch-5.0.4-0.3.2/Zend/zend_llist.c
11551--- php-5.0.4/Zend/zend_llist.c 2004-01-08 18:31:47.000000000 +0100
11552+++ hardening-patch-5.0.4-0.3.2/Zend/zend_llist.c 2005-06-26 22:51:54.000000000 +0200
11553@@ -22,9 +22,34 @@
11554 #include "zend.h"
11555 #include "zend_llist.h"
11556 #include "zend_qsort.h"
11557+#include "zend_globals.h"
11558+
11559+#define CHECK_LIST_CANARY(list) \
11560+ if (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t) { \
11561+ zend_security_log(S_MEMORY, "linked list canary was overwritten"); \
11562+ exit(1); \
11563+ }
11564+
11565+#define CHECK_LISTELEMENT_CANARY(elem) \
11566+ if (HG(canary_3) != (elem)->canary) { \
11567+ zend_security_log(S_MEMORY, "linked list element canary was overwritten"); \
11568+ exit(1); \
11569+ }
11570+
11571
11572 ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
11573 {
11574+#if HARDENING_PATCH_LL_PROTECT
11575+ TSRMLS_FETCH();
11576+
11577+ if (!HG(ll_canary_inited)) {
11578+ HG(canary_3) = zend_canary();
11579+ HG(canary_4) = zend_canary();
11580+ HG(ll_canary_inited) = 1;
11581+ }
11582+ l->canary_h = HG(canary_3);
11583+ l->canary_t = HG(canary_4);
11584+#endif
11585 l->head = NULL;
11586 l->tail = NULL;
11587 l->count = 0;
11588@@ -38,6 +63,11 @@
11589 {
11590 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
11591
11592+#if HARDENING_PATCH_LL_PROTECT
11593+ TSRMLS_FETCH();
11594+ CHECK_LIST_CANARY(l)
11595+ tmp->canary = HG(canary_3);
11596+#endif
11597 tmp->prev = l->tail;
11598 tmp->next = NULL;
11599 if (l->tail) {
11600@@ -56,6 +86,11 @@
11601 {
11602 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
11603
11604+#if HARDENING_PATCH_LL_PROTECT
11605+ TSRMLS_FETCH();
11606+ CHECK_LIST_CANARY(l)
11607+ tmp->canary = HG(canary_3);
11608+#endif
11609 tmp->next = l->head;
11610 tmp->prev = NULL;
11611 if (l->head) {
11612@@ -93,10 +128,20 @@
11613 zend_llist_element *current=l->head;
11614 zend_llist_element *next;
11615
11616+#if HARDENING_PATCH_LL_PROTECT
11617+ TSRMLS_FETCH();
11618+ CHECK_LIST_CANARY(l)
11619+#endif
11620 while (current) {
11621+#if HARDENING_PATCH_LL_PROTECT
11622+ CHECK_LISTELEMENT_CANARY(current)
11623+#endif
11624 next = current->next;
11625 if (compare(current->data, element)) {
11626 DEL_LLIST_ELEMENT(current, l);
11627+#if HARDENING_PATCH_LL_PROTECT
11628+ current->canary = 0;
11629+#endif
11630 break;
11631 }
11632 current = next;
11633@@ -108,7 +153,14 @@
11634 {
11635 zend_llist_element *current=l->head, *next;
11636
11637+#if HARDENING_PATCH_LL_PROTECT
11638+ TSRMLS_FETCH();
11639+ CHECK_LIST_CANARY(l)
11640+#endif
11641 while (current) {
11642+#if HARDENING_PATCH_LL_PROTECT
11643+ CHECK_LISTELEMENT_CANARY(current)
11644+#endif
11645 next = current->next;
11646 if (l->dtor) {
11647 l->dtor(current->data);
11648@@ -133,7 +185,14 @@
11649 zend_llist_element *old_tail;
11650 void *data;
11651
11652+#if HARDENING_PATCH_LL_PROTECT
11653+ TSRMLS_FETCH();
11654+ CHECK_LIST_CANARY(l)
11655+#endif
11656 if ((old_tail = l->tail)) {
11657+#if HARDENING_PATCH_LL_PROTECT
11658+ CHECK_LISTELEMENT_CANARY(old_tail)
11659+#endif
11660 if (l->tail->prev) {
11661 l->tail->prev->next = NULL;
11662 }
11663@@ -159,9 +218,16 @@
11664 {
11665 zend_llist_element *ptr;
11666
11667+#if HARDENING_PATCH_LL_PROTECT
11668+ TSRMLS_FETCH();
11669+ CHECK_LIST_CANARY(src)
11670+#endif
11671 zend_llist_init(dst, src->size, src->dtor, src->persistent);
11672 ptr = src->head;
11673 while (ptr) {
11674+#if HARDENING_PATCH_LL_PROTECT
11675+ CHECK_LISTELEMENT_CANARY(ptr)
11676+#endif
11677 zend_llist_add_element(dst, ptr->data);
11678 ptr = ptr->next;
11679 }
11680@@ -172,11 +238,21 @@
11681 {
11682 zend_llist_element *element, *next;
11683
11684+#if HARDENING_PATCH_LL_PROTECT
11685+ TSRMLS_FETCH();
11686+ CHECK_LIST_CANARY(l)
11687+#endif
11688 element=l->head;
11689 while (element) {
11690+#if HARDENING_PATCH_LL_PROTECT
11691+ CHECK_LISTELEMENT_CANARY(element)
11692+#endif
11693 next = element->next;
11694 if (func(element->data)) {
11695 DEL_LLIST_ELEMENT(element, l);
11696+#if HARDENING_PATCH_LL_PROTECT
11697+ element->canary = 0;
11698+#endif
11699 }
11700 element = next;
11701 }
11702@@ -187,7 +263,13 @@
11703 {
11704 zend_llist_element *element;
11705
11706+#if HARDENING_PATCH_LL_PROTECT
11707+ CHECK_LIST_CANARY(l)
11708+#endif
11709 for (element=l->head; element; element=element->next) {
11710+#if HARDENING_PATCH_LL_PROTECT
11711+ CHECK_LISTELEMENT_CANARY(element)
11712+#endif
11713 func(element->data TSRMLS_CC);
11714 }
11715 }
11716@@ -199,6 +281,9 @@
11717 zend_llist_element **elements;
11718 zend_llist_element *element, **ptr;
11719
11720+#if HARDENING_PATCH_LL_PROTECT
11721+ CHECK_LIST_CANARY(l)
11722+#endif
11723 if (l->count <= 0) {
11724 return;
11725 }
11726@@ -208,6 +293,9 @@
11727 ptr = &elements[0];
11728
11729 for (element=l->head; element; element=element->next) {
11730+#if HARDENING_PATCH_LL_PROTECT
11731+ CHECK_LISTELEMENT_CANARY(element)
11732+#endif
11733 *ptr++ = element;
11734 }
11735
11736@@ -230,7 +318,13 @@
11737 {
11738 zend_llist_element *element;
11739
11740+#if HARDENING_PATCH_LL_PROTECT
11741+ CHECK_LIST_CANARY(l)
11742+#endif
11743 for (element=l->head; element; element=element->next) {
11744+#if HARDENING_PATCH_LL_PROTECT
11745+ CHECK_LISTELEMENT_CANARY(element)
11746+#endif
11747 func(element->data, arg TSRMLS_CC);
11748 }
11749 }
11750@@ -241,8 +335,14 @@
11751 zend_llist_element *element;
11752 va_list args;
11753
11754+#if HARDENING_PATCH_LL_PROTECT
11755+ CHECK_LIST_CANARY(l)
11756+#endif
11757 va_start(args, num_args);
11758 for (element=l->head; element; element=element->next) {
11759+#if HARDENING_PATCH_LL_PROTECT
11760+ CHECK_LISTELEMENT_CANARY(element)
11761+#endif
11762 func(element->data, num_args, args TSRMLS_CC);
11763 }
11764 va_end(args);
11765@@ -251,6 +351,10 @@
11766
11767 ZEND_API int zend_llist_count(zend_llist *l)
11768 {
11769+#if HARDENING_PATCH_LL_PROTECT
11770+ TSRMLS_FETCH();
11771+ CHECK_LIST_CANARY(l)
11772+#endif
11773 return l->count;
11774 }
11775
11776@@ -259,8 +363,15 @@
11777 {
11778 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
11779
11780+#if HARDENING_PATCH_LL_PROTECT
11781+ TSRMLS_FETCH();
11782+ CHECK_LIST_CANARY(l)
11783+#endif
11784 *current = l->head;
11785 if (*current) {
11786+#if HARDENING_PATCH_LL_PROTECT
11787+ CHECK_LISTELEMENT_CANARY(*current)
11788+#endif
11789 return (*current)->data;
11790 } else {
11791 return NULL;
11792@@ -272,8 +383,15 @@
11793 {
11794 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
11795
11796+#if HARDENING_PATCH_LL_PROTECT
11797+ TSRMLS_FETCH();
11798+ CHECK_LIST_CANARY(l)
11799+#endif
11800 *current = l->tail;
11801 if (*current) {
11802+#if HARDENING_PATCH_LL_PROTECT
11803+ CHECK_LISTELEMENT_CANARY(*current)
11804+#endif
11805 return (*current)->data;
11806 } else {
11807 return NULL;
11808@@ -285,9 +403,19 @@
11809 {
11810 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
11811
11812+#if HARDENING_PATCH_LL_PROTECT
11813+ TSRMLS_FETCH();
11814+ CHECK_LIST_CANARY(l)
11815+#endif
11816 if (*current) {
11817+#if HARDENING_PATCH_LL_PROTECT
11818+ CHECK_LISTELEMENT_CANARY(*current)
11819+#endif
11820 *current = (*current)->next;
11821 if (*current) {
11822+#if HARDENING_PATCH_LL_PROTECT
11823+ CHECK_LISTELEMENT_CANARY(*current)
11824+#endif
11825 return (*current)->data;
11826 }
11827 }
11828@@ -299,9 +427,19 @@
11829 {
11830 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
11831
11832+#if HARDENING_PATCH_LL_PROTECT
11833+ TSRMLS_FETCH();
11834+ CHECK_LIST_CANARY(l)
11835+#endif
11836 if (*current) {
11837+#if HARDENING_PATCH_LL_PROTECT
11838+ CHECK_LISTELEMENT_CANARY(*current)
11839+#endif
11840 *current = (*current)->prev;
11841 if (*current) {
11842+#if HARDENING_PATCH_LL_PROTECT
11843+ CHECK_LISTELEMENT_CANARY(*current)
11844+#endif
11845 return (*current)->data;
11846 }
11847 }
11848diff -Naur php-5.0.4/Zend/zend_llist.h hardening-patch-5.0.4-0.3.2/Zend/zend_llist.h
11849--- php-5.0.4/Zend/zend_llist.h 2004-01-08 18:31:47.000000000 +0100
11850+++ hardening-patch-5.0.4-0.3.2/Zend/zend_llist.h 2005-06-26 22:17:28.000000000 +0200
11851@@ -23,6 +23,9 @@
11852 #define ZEND_LLIST_H
11853
11854 typedef struct _zend_llist_element {
11855+#if HARDENING_PATCH_LL_PROTECT
11856+ unsigned int canary;
11857+#endif
11858 struct _zend_llist_element *next;
11859 struct _zend_llist_element *prev;
11860 char data[1]; /* Needs to always be last in the struct */
11861@@ -35,6 +38,9 @@
11862 typedef void (*llist_apply_func_t)(void * TSRMLS_DC);
11863
11864 typedef struct _zend_llist {
11865+#if HARDENING_PATCH_LL_PROTECT
11866+ unsigned int canary_h; /* head */
11867+#endif
11868 zend_llist_element *head;
11869 zend_llist_element *tail;
11870 size_t count;
11871@@ -42,6 +48,9 @@
11872 llist_dtor_func_t dtor;
11873 unsigned char persistent;
11874 zend_llist_element *traverse_ptr;
11875+#if HARDENING_PATCH_LL_PROTECT
11876+ unsigned int canary_t; /* tail */
11877+#endif
11878 } zend_llist;
11879
11880 typedef zend_llist_element* zend_llist_position;
11881diff -Naur php-5.0.4/Zend/zend_modules.h hardening-patch-5.0.4-0.3.2/Zend/zend_modules.h
11882--- php-5.0.4/Zend/zend_modules.h 2005-03-16 00:47:12.000000000 +0100
11883+++ hardening-patch-5.0.4-0.3.2/Zend/zend_modules.h 2005-06-28 14:48:10.000000000 +0200
11884@@ -38,7 +38,7 @@
11885 extern struct _zend_arg_info fourth_arg_force_ref[5];
11886 extern struct _zend_arg_info all_args_by_ref[1];
11887
11888-#define ZEND_MODULE_API_NO 20041030
11889+#define ZEND_MODULE_API_NO 1020050627
11890 #ifdef ZTS
11891 #define USING_ZTS 1
11892 #else