summaryrefslogtreecommitdiff
path: root/0.3.2/hardening-patch-5.0.4-0.3.2.patch
diff options
context:
space:
mode:
authorjvoisin2019-10-13 12:35:52 +0200
committerjvoisin2019-10-13 12:35:52 +0200
commit7ce0f98b0be3ad15a664e506dff461cf6d633a69 (patch)
tree1aae4c7d8fa8ac62609824629db9ba46add728cc /0.3.2/hardening-patch-5.0.4-0.3.2.patch
parentd24fe97bf9a1614acf4e7431d17b762a73642e15 (diff)
Add more patches
Diffstat (limited to '0.3.2/hardening-patch-5.0.4-0.3.2.patch')
-rw-r--r--0.3.2/hardening-patch-5.0.4-0.3.2.patch11892
1 files changed, 11892 insertions, 0 deletions
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