summaryrefslogtreecommitdiff
path: root/0.3.2/hardening-patch-4.3.11-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-4.3.11-0.3.2.patch
parentd24fe97bf9a1614acf4e7431d17b762a73642e15 (diff)
Add more patches
Diffstat (limited to '0.3.2/hardening-patch-4.3.11-0.3.2.patch')
-rw-r--r--0.3.2/hardening-patch-4.3.11-0.3.2.patch12205
1 files changed, 12205 insertions, 0 deletions
diff --git a/0.3.2/hardening-patch-4.3.11-0.3.2.patch b/0.3.2/hardening-patch-4.3.11-0.3.2.patch
new file mode 100644
index 0000000..f3ecb0f
--- /dev/null
+++ b/0.3.2/hardening-patch-4.3.11-0.3.2.patch
@@ -0,0 +1,12205 @@
1diff -Naur php-4.3.11/acinclude.m4 hardening-patch-4.3.11-0.3.2/acinclude.m4
2--- php-4.3.11/acinclude.m4 2005-01-25 14:03:06.000000000 +0100
3+++ hardening-patch-4.3.11-0.3.2/acinclude.m4 2005-07-09 08:53:02.427369648 +0200
4@@ -1173,6 +1173,36 @@
5 fi
6 ])
7
8+dnl
9+dnl Check for broken realpath()
10+dnl
11+dnl realpath("/etc/hosts/../passwd",XXX) should not return
12+dnl "/etc/passwd"
13+dnl
14+AC_DEFUN([PHP_AC_BROKEN_REALPATH],[
15+ AC_CACHE_CHECK(whether realpath is broken, ac_cv_broken_realpath,[
16+ AC_TRY_RUN([
17+main() {
18+ char buf[4096+1];
19+ buf[0] = 0;
20+ realpath("/etc/hosts/../passwd", buf);
21+ exit(strcmp(buf, "/etc/passwd")==0);
22+}
23+ ],[
24+ ac_cv_broken_realpath=no
25+ ],[
26+ ac_cv_broken_realpath=yes
27+ ],[
28+ ac_cv_broken_realpath=no
29+ ])
30+ ])
31+ if test "$ac_cv_broken_realpath" = "yes"; then
32+ AC_DEFINE(PHP_BROKEN_REALPATH, 1, [Whether realpath is broken])
33+ else
34+ AC_DEFINE(PHP_BROKEN_REALPATH, 0, [Whether realpath is broken])
35+ fi
36+])
37+
38 dnl PHP_SHARED_MODULE(module-name, object-var, build-dir, cxx)
39 dnl
40 dnl Basically sets up the link-stage for building module-name
41diff -Naur php-4.3.11/configure hardening-patch-4.3.11-0.3.2/configure
42--- php-4.3.11/configure 2005-03-30 16:35:34.000000000 +0200
43+++ hardening-patch-4.3.11-0.3.2/configure 2005-07-09 08:53:02.464364024 +0200
44@@ -394,6 +394,16 @@
45 ac_default_prefix=/usr/local
46 # Any additions from configure.in:
47 ac_help="$ac_help
48+ --disable-hardening-patch-mm-protect Disable the Memory Manager protection."
49+ac_help="$ac_help
50+ --disable-hardening-patch-ll-protect Disable the Linked List protection."
51+ac_help="$ac_help
52+ --disable-hardening-patch-inc-protect Disable include/require protection."
53+ac_help="$ac_help
54+ --disable-hardening-patch-fmt-protect Disable format string protection."
55+ac_help="$ac_help
56+ --disable-hardening-patch-hash-protect Disable Zend HashTable DTOR protection."
57+ac_help="$ac_help
58
59 SAPI modules:
60 "
61@@ -846,6 +856,8 @@
62 ac_help="$ac_help
63 --disable-tokenizer Disable tokenizer support"
64 ac_help="$ac_help
65+ --disable-varfilter Disable Hardening-Patch's variable filter"
66+ac_help="$ac_help
67 --enable-wddx Enable WDDX support."
68 ac_help="$ac_help
69 --disable-xml Disable XML support using bundled expat lib"
70@@ -2669,6 +2681,157 @@
71
72
73
74+# Check whether --enable-hardening-patch-mm-protect or --disable-hardening-patch-mm-protect was given.
75+if test "${enable_hardening_patch_mm_protect+set}" = set; then
76+ enableval="$enable_hardening_patch_mm_protect"
77+
78+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
79+
80+else
81+
82+ DO_HARDENING_PATCH_MM_PROTECT=yes
83+
84+fi
85+
86+
87+# Check whether --enable-hardening-patch-ll-protect or --disable-hardening-patch-ll-protect was given.
88+if test "${enable_hardening_patch_ll_protect+set}" = set; then
89+ enableval="$enable_hardening_patch_ll_protect"
90+
91+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
92+
93+else
94+
95+ DO_HARDENING_PATCH_LL_PROTECT=yes
96+
97+fi
98+
99+
100+# Check whether --enable-hardening-patch-inc-protect or --disable-hardening-patch-inc-protect was given.
101+if test "${enable_hardening_patch_inc_protect+set}" = set; then
102+ enableval="$enable_hardening_patch_inc_protect"
103+
104+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
105+
106+else
107+
108+ DO_HARDENING_PATCH_INC_PROTECT=yes
109+
110+fi
111+
112+
113+# Check whether --enable-hardening-patch-fmt-protect or --disable-hardening-patch-fmt-protect was given.
114+if test "${enable_hardening_patch_fmt_protect+set}" = set; then
115+ enableval="$enable_hardening_patch_fmt_protect"
116+
117+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
118+
119+else
120+
121+ DO_HARDENING_PATCH_FMT_PROTECT=yes
122+
123+fi
124+
125+
126+# Check whether --enable-hardening-patch-hash-protect or --disable-hardening-patch-hash-protect was given.
127+if test "${enable_hardening_patch_hash_protect+set}" = set; then
128+ enableval="$enable_hardening_patch_hash_protect"
129+
130+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
131+
132+else
133+
134+ DO_HARDENING_PATCH_HASH_PROTECT=yes
135+
136+fi
137+
138+
139+echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6
140+echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5
141+echo "$ac_t""$DO_HARDENING_PATCH_MM_PROTECT" 1>&6
142+
143+echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6
144+echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5
145+echo "$ac_t""$DO_HARDENING_PATCH_LL_PROTECT" 1>&6
146+
147+echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6
148+echo "configure:2733: checking whether to protect include/require statements" >&5
149+echo "$ac_t""$DO_HARDENING_PATCH_INC_PROTECT" 1>&6
150+
151+echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6
152+echo "configure:2737: checking whether to protect PHP Format String functions" >&5
153+echo "$ac_t""$DO_HARDENING_PATCH_FMT_PROTECT" 1>&6
154+
155+echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6
156+echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5
157+echo "$ac_t""$DO_HARDENING_PATCH_HASH_PROTECT" 1>&6
158+
159+
160+cat >> confdefs.h <<\EOF
161+#define HARDENING_PATCH 1
162+EOF
163+
164+
165+
166+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
167+ cat >> confdefs.h <<\EOF
168+#define HARDENING_PATCH_MM_PROTECT 1
169+EOF
170+
171+else
172+ cat >> confdefs.h <<\EOF
173+#define HARDENING_PATCH_MM_PROTECT 0
174+EOF
175+
176+fi
177+
178+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
179+ cat >> confdefs.h <<\EOF
180+#define HARDENING_PATCH_LL_PROTECT 1
181+EOF
182+
183+else
184+ cat >> confdefs.h <<\EOF
185+#define HARDENING_PATCH_LL_PROTECT 0
186+EOF
187+
188+fi
189+
190+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
191+ cat >> confdefs.h <<\EOF
192+#define HARDENING_PATCH_INC_PROTECT 1
193+EOF
194+
195+else
196+ cat >> confdefs.h <<\EOF
197+#define HARDENING_PATCH_INC_PROTECT 0
198+EOF
199+
200+fi
201+
202+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
203+ cat >> confdefs.h <<\EOF
204+#define HARDENING_PATCH_FMT_PROTECT 1
205+EOF
206+
207+else
208+ cat >> confdefs.h <<\EOF
209+#define HARDENING_PATCH_FMT_PROTECT 0
210+EOF
211+
212+fi
213+
214+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
215+ cat >> confdefs.h <<\EOF
216+#define HARDENING_PATCH_HASH_PROTECT 1
217+EOF
218+
219+else
220+ cat >> confdefs.h <<\EOF
221+#define HARDENING_PATCH_HASH_PROTECT 0
222+EOF
223+
224+fi
225
226
227
228@@ -15486,6 +15649,62 @@
229 fi
230
231
232+ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6
233+echo "configure:14928: checking whether realpath is broken" >&5
234+if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then
235+ echo $ac_n "(cached) $ac_c" 1>&6
236+else
237+
238+ if test "$cross_compiling" = yes; then
239+
240+ ac_cv_broken_realpath=no
241+
242+else
243+ cat > conftest.$ac_ext <<EOF
244+#line 14939 "configure"
245+#include "confdefs.h"
246+
247+main() {
248+ char buf[4096+1];
249+ buf[0] = 0;
250+ realpath("/etc/hosts/../passwd", buf);
251+ exit(strcmp(buf, "/etc/passwd")==0);
252+}
253+
254+EOF
255+if { (eval echo configure:14958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
256+then
257+
258+ ac_cv_broken_realpath=no
259+
260+else
261+ echo "configure: failed program was:" >&5
262+ cat conftest.$ac_ext >&5
263+ rm -fr conftest*
264+
265+ ac_cv_broken_realpath=yes
266+
267+fi
268+rm -fr conftest*
269+fi
270+
271+
272+fi
273+
274+echo "$ac_t""$ac_cv_broken_realpath" 1>&6
275+ if test "$ac_cv_broken_realpath" = "yes"; then
276+ cat >> confdefs.h <<\EOF
277+#define PHP_BROKEN_REALPATH 1
278+EOF
279+
280+ else
281+ cat >> confdefs.h <<\EOF
282+#define PHP_BROKEN_REALPATH 0
283+EOF
284+
285+ fi
286+
287+
288 echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
289 echo "configure:15491: checking for declared timezone" >&5
290 if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then
291@@ -85975,6 +86194,265 @@
292 fi
293
294
295+echo $ac_n "checking whether to enable Hardening-Patch's variable filter""... $ac_c" 1>&6
296+echo "configure:82041: checking whether to enable Hardening-Patch's variable filter" >&5
297+# Check whether --enable-varfilter or --disable-varfilter was given.
298+if test "${enable_varfilter+set}" = set; then
299+ enableval="$enable_varfilter"
300+ PHP_VARFILTER=$enableval
301+else
302+
303+ PHP_VARFILTER=yes
304+
305+ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then
306+ PHP_VARFILTER=$PHP_ENABLE_ALL
307+ fi
308+
309+fi
310+
311+
312+
313+ext_output="yes, shared"
314+ext_shared=yes
315+case $PHP_VARFILTER in
316+shared,*)
317+ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'`
318+ ;;
319+shared)
320+ PHP_VARFILTER=yes
321+ ;;
322+no)
323+ ext_output=no
324+ ext_shared=no
325+ ;;
326+*)
327+ ext_output=yes
328+ ext_shared=no
329+ ;;
330+esac
331+
332+
333+
334+echo "$ac_t""$ext_output" 1>&6
335+
336+
337+
338+
339+if test "$PHP_VARFILTER" != "no"; then
340+ cat >> confdefs.h <<\EOF
341+#define HAVE_VARFILTER 1
342+EOF
343+
344+
345+ ext_builddir=ext/varfilter
346+ ext_srcdir=$abs_srcdir/ext/varfilter
347+
348+ ac_extra=
349+
350+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then
351+
352+
353+
354+ case ext/varfilter in
355+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
356+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
357+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
358+ esac
359+
360+
361+
362+ b_c_pre=$php_c_pre
363+ b_cxx_pre=$php_cxx_pre
364+ b_c_meta=$php_c_meta
365+ b_cxx_meta=$php_cxx_meta
366+ b_c_post=$php_c_post
367+ b_cxx_post=$php_cxx_post
368+ b_lo=$php_lo
369+
370+
371+ old_IFS=$IFS
372+ for ac_src in varfilter.c; do
373+
374+ IFS=.
375+ set $ac_src
376+ ac_obj=$1
377+ IFS=$old_IFS
378+
379+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
380+
381+ case $ac_src in
382+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
383+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
384+ esac
385+
386+ cat >>Makefile.objects<<EOF
387+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
388+ $ac_comp
389+EOF
390+ done
391+
392+
393+ EXT_STATIC="$EXT_STATIC varfilter"
394+ if test "$ext_shared" != "nocli"; then
395+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
396+ fi
397+ else
398+ if test "$ext_shared" = "shared" || test "$ext_shared" = "yes"; then
399+
400+ case ext/varfilter in
401+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
402+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
403+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
404+ esac
405+
406+
407+
408+ b_c_pre=$shared_c_pre
409+ b_cxx_pre=$shared_cxx_pre
410+ b_c_meta=$shared_c_meta
411+ b_cxx_meta=$shared_cxx_meta
412+ b_c_post=$shared_c_post
413+ b_cxx_post=$shared_cxx_post
414+ b_lo=$shared_lo
415+
416+
417+ old_IFS=$IFS
418+ for ac_src in varfilter.c; do
419+
420+ IFS=.
421+ set $ac_src
422+ ac_obj=$1
423+ IFS=$old_IFS
424+
425+ shared_objects_varfilter="$shared_objects_varfilter $ac_bdir$ac_obj.lo"
426+
427+ case $ac_src in
428+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
429+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
430+ esac
431+
432+ cat >>Makefile.objects<<EOF
433+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
434+ $ac_comp
435+EOF
436+ done
437+
438+
439+ install_modules="install-modules"
440+ PHP_MODULES="$PHP_MODULES \$(phplibdir)/varfilter.la"
441+
442+ PHP_VAR_SUBST="$PHP_VAR_SUBST shared_objects_varfilter"
443+
444+ cat >>Makefile.objects<<EOF
445+\$(phplibdir)/varfilter.la: $ext_builddir/varfilter.la
446+ \$(LIBTOOL) --mode=install cp $ext_builddir/varfilter.la \$(phplibdir)
447+
448+$ext_builddir/varfilter.la: \$(shared_objects_varfilter) \$(VARFILTER_SHARED_DEPENDENCIES)
449+ \$(LIBTOOL) --mode=link \$(CC) \$(COMMON_FLAGS) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(LDFLAGS) -o \$@ -export-dynamic -avoid-version -prefer-pic -module -rpath \$(phplibdir) \$(EXTRA_LDFLAGS) \$(shared_objects_varfilter) \$(VARFILTER_SHARED_LIBADD)
450+
451+EOF
452+
453+ cat >> confdefs.h <<EOF
454+#define COMPILE_DL_VARFILTER 1
455+EOF
456+
457+ fi
458+ fi
459+
460+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" = "cli"; then
461+ if test "$PHP_SAPI" = "cgi"; then
462+
463+
464+ case ext/varfilter in
465+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
466+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
467+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
468+ esac
469+
470+
471+
472+ b_c_pre=$php_c_pre
473+ b_cxx_pre=$php_cxx_pre
474+ b_c_meta=$php_c_meta
475+ b_cxx_meta=$php_cxx_meta
476+ b_c_post=$php_c_post
477+ b_cxx_post=$php_cxx_post
478+ b_lo=$php_lo
479+
480+
481+ old_IFS=$IFS
482+ for ac_src in varfilter.c; do
483+
484+ IFS=.
485+ set $ac_src
486+ ac_obj=$1
487+ IFS=$old_IFS
488+
489+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
490+
491+ case $ac_src in
492+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
493+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
494+ esac
495+
496+ cat >>Makefile.objects<<EOF
497+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
498+ $ac_comp
499+EOF
500+ done
501+
502+
503+ EXT_STATIC="$EXT_STATIC varfilter"
504+ else
505+
506+
507+ case ext/varfilter in
508+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
509+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
510+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
511+ esac
512+
513+
514+
515+ b_c_pre=$php_c_pre
516+ b_cxx_pre=$php_cxx_pre
517+ b_c_meta=$php_c_meta
518+ b_cxx_meta=$php_cxx_meta
519+ b_c_post=$php_c_post
520+ b_cxx_post=$php_cxx_post
521+ b_lo=$php_lo
522+
523+
524+ old_IFS=$IFS
525+ for ac_src in varfilter.c; do
526+
527+ IFS=.
528+ set $ac_src
529+ ac_obj=$1
530+ IFS=$old_IFS
531+
532+ PHP_CLI_OBJS="$PHP_CLI_OBJS $ac_bdir$ac_obj.lo"
533+
534+ case $ac_src in
535+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
536+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
537+ esac
538+
539+ cat >>Makefile.objects<<EOF
540+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
541+ $ac_comp
542+EOF
543+ done
544+
545+
546+ fi
547+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
548+ fi
549+
550+ BUILD_DIR="$BUILD_DIR $ext_builddir"
551+
552+
553+fi
554
555
556 echo $ac_n "checking whether to enable WDDX support""... $ac_c" 1>&6
557@@ -98629,7 +99107,7 @@
558 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
559 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
560 streams.c network.c php_open_temporary_file.c php_logos.c \
561- output.c memory_streams.c user_streams.c; do
562+ output.c memory_streams.c user_streams.c hardening_patch.c; do
563
564 IFS=.
565 set $ac_src
566@@ -98802,7 +99280,7 @@
567 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
568 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
569 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
570- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c; do
571+ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c; do
572
573 IFS=.
574 set $ac_src
575diff -Naur php-4.3.11/configure.in hardening-patch-4.3.11-0.3.2/configure.in
576--- php-4.3.11/configure.in 2005-03-30 16:18:36.000000000 +0200
577+++ hardening-patch-4.3.11-0.3.2/configure.in 2005-07-09 08:53:02.466363720 +0200
578@@ -227,7 +227,7 @@
579 sinclude(Zend/acinclude.m4)
580 sinclude(Zend/Zend.m4)
581 sinclude(TSRM/tsrm.m4)
582-
583+sinclude(main/hardening_patch.m4)
584
585
586 divert(2)
587@@ -595,6 +595,7 @@
588 AC_FUNC_ALLOCA
589 dnl PHP_AC_BROKEN_SPRINTF
590 dnl PHP_AC_BROKEN_SNPRINTF
591+PHP_AC_BROKEN_REALPATH
592 PHP_DECLARED_TIMEZONE
593 PHP_TIME_R_TYPE
594 PHP_READDIR_R_TYPE
595@@ -1224,7 +1225,7 @@
596 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
597 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
598 streams.c network.c php_open_temporary_file.c php_logos.c \
599- output.c memory_streams.c user_streams.c)
600+ output.c memory_streams.c user_streams.c hardening_patch.c)
601 PHP_ADD_SOURCES(/main, internal_functions.c,, sapi)
602 PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli)
603
604@@ -1237,7 +1238,7 @@
605 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
606 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
607 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
608- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c)
609+ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c )
610
611 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
612 PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c)
613diff -Naur php-4.3.11/ext/calendar/calendar.c hardening-patch-4.3.11-0.3.2/ext/calendar/calendar.c
614--- php-4.3.11/ext/calendar/calendar.c 2003-08-28 22:01:24.000000000 +0200
615+++ hardening-patch-4.3.11-0.3.2/ext/calendar/calendar.c 2005-07-09 08:53:02.466363720 +0200
616@@ -300,7 +300,7 @@
617 {
618 pval **julday;
619 int year, month, day;
620- char date[10];
621+ char date[16];
622
623 if (zend_get_parameters_ex(1, &julday) != SUCCESS) {
624 WRONG_PARAM_COUNT;
625@@ -341,7 +341,7 @@
626 {
627 pval **julday;
628 int year, month, day;
629- char date[10];
630+ char date[16];
631
632 if (zend_get_parameters_ex(1, &julday) != SUCCESS) {
633 WRONG_PARAM_COUNT;
634@@ -453,7 +453,7 @@
635 {
636 long julday, fl;
637 int year, month, day;
638- char date[10], hebdate[25];
639+ char date[16], hebdate[25];
640 char *dayp, *yearp;
641
642 if (ZEND_NUM_ARGS() == 1) {
643@@ -521,7 +521,7 @@
644 {
645 pval **julday;
646 int year, month, day;
647- char date[10];
648+ char date[16];
649
650 if (zend_get_parameters_ex(1, &julday) != SUCCESS) {
651 WRONG_PARAM_COUNT;
652diff -Naur php-4.3.11/ext/fbsql/php_fbsql.c hardening-patch-4.3.11-0.3.2/ext/fbsql/php_fbsql.c
653--- php-4.3.11/ext/fbsql/php_fbsql.c 2005-02-09 20:33:32.000000000 +0100
654+++ hardening-patch-4.3.11-0.3.2/ext/fbsql/php_fbsql.c 2005-07-09 08:53:02.468363416 +0200
655@@ -1797,8 +1797,24 @@
656 }
657 else if (fbcmdErrorsFound(md))
658 {
659+#if HARDENING_PATCH
660+ char* query_copy;
661+ int i;
662+#endif
663 FBCErrorMetaData* emd = fbcdcErrorMetaData(c, md);
664 char* emg = fbcemdAllErrorMessages(emd);
665+#if HARDENING_PATCH
666+ query_copy=estrdup(query_copy);
667+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
668+ php_security_log(S_SQL, "fbsql error: %s - query: %s", emg, query_copy);
669+ efree(query_copy);
670+ if (HG(hphp_sql_bailout_on_error)) {
671+ free(emg);
672+ fbcemdRelease(emd);
673+ result = 0;
674+ zend_bailout();
675+ }
676+#endif
677 if (FB_SQL_G(generateWarnings))
678 {
679 if (emg)
680diff -Naur php-4.3.11/ext/mbstring/mbstring.c hardening-patch-4.3.11-0.3.2/ext/mbstring/mbstring.c
681--- php-4.3.11/ext/mbstring/mbstring.c 2005-02-21 09:03:47.000000000 +0100
682+++ hardening-patch-4.3.11-0.3.2/ext/mbstring/mbstring.c 2005-07-09 08:53:02.469363264 +0200
683@@ -1487,6 +1487,7 @@
684 char *strtok_buf = NULL, **val_list;
685 zval *array_ptr = (zval *) arg;
686 int n, num, val_len, *len_list;
687+ unsigned int new_val_len;
688 enum mbfl_no_encoding from_encoding;
689 mbfl_string string, resvar, resval;
690 mbfl_encoding_detector *identd = NULL;
691@@ -1609,8 +1610,14 @@
692 val_len = len_list[n];
693 }
694 n++;
695- /* add variable to symbol table */
696- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
697+ /* we need val to be emalloc()ed */
698+ val = estrndup(val, val_len);
699+ if (sapi_module.input_filter(info->data_type, var, &val, val_len, &new_val_len TSRMLS_CC)) {
700+ /* add variable to symbol table */
701+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
702+ }
703+ efree(val);
704+
705 if (convd != NULL){
706 mbfl_string_clear(&resvar);
707 mbfl_string_clear(&resval);
708diff -Naur php-4.3.11/ext/mysql/php_mysql.c hardening-patch-4.3.11-0.3.2/ext/mysql/php_mysql.c
709--- php-4.3.11/ext/mysql/php_mysql.c 2005-02-22 16:00:49.000000000 +0100
710+++ hardening-patch-4.3.11-0.3.2/ext/mysql/php_mysql.c 2005-07-09 08:53:02.471362960 +0200
711@@ -1215,6 +1215,8 @@
712 {
713 php_mysql_conn *mysql;
714 MYSQL_RES *mysql_result;
715+ char *copy_query;
716+ int i;
717
718 ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, link_id, "MySQL-Link", le_link, le_plink);
719
720@@ -1265,6 +1267,13 @@
721 php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
722 }
723 }
724+ copy_query = estrdup(Z_STRVAL_PP(query));
725+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
726+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
727+ efree(copy_query);
728+ if (HG(hphp_sql_bailout_on_error)) {
729+ zend_bailout();
730+ }
731 RETURN_FALSE;
732 }
733 #else
734@@ -1272,12 +1281,20 @@
735 /* check possible error */
736 if (MySG(trace_mode)){
737 if (mysql_errno(&mysql->conn)){
738- php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, mysql_error(&mysql->conn));
739+ php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
740 }
741 }
742+ copy_query = estrdup(Z_STRVAL_PP(query));
743+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
744+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
745+ efree(copy_query);
746+ if (HG(hphp_sql_bailout_on_error)) {
747+ zend_bailout();
748+ }
749 RETURN_FALSE;
750 }
751 #endif
752+
753 if(use_store == MYSQL_USE_RESULT) {
754 mysql_result=mysql_use_result(&mysql->conn);
755 } else {
756diff -Naur php-4.3.11/ext/pgsql/pgsql.c hardening-patch-4.3.11-0.3.2/ext/pgsql/pgsql.c
757--- php-4.3.11/ext/pgsql/pgsql.c 2004-05-12 18:49:56.000000000 +0200
758+++ hardening-patch-4.3.11-0.3.2/ext/pgsql/pgsql.c 2005-07-09 08:53:02.473362656 +0200
759@@ -997,10 +997,28 @@
760 case PGRES_EMPTY_QUERY:
761 case PGRES_BAD_RESPONSE:
762 case PGRES_NONFATAL_ERROR:
763- case PGRES_FATAL_ERROR:
764- PHP_PQ_ERROR("Query failed: %s", pgsql);
765- PQclear(pgsql_result);
766- RETURN_FALSE;
767+ case PGRES_FATAL_ERROR:
768+ {
769+#if HARDENING_PATCH
770+ int i;
771+ char *query_copy;
772+#endif
773+ char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
774+ PQclear(pgsql_result);
775+#if HARDENING_PATCH
776+ query_copy = estrdup(Z_STRVAL_PP(query));
777+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
778+ php_security_log(S_SQL, "PgSQL error: %s - query: %s", msgbuf, query_copy);
779+ efree(query_copy);
780+ if (HG(hphp_sql_bailout_on_error)) {
781+ efree(msgbuf);
782+ zend_bailout();
783+ }
784+#endif
785+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", msgbuf);
786+ efree(msgbuf);
787+ RETURN_FALSE;
788+ }
789 break;
790 case PGRES_COMMAND_OK: /* successful command that did not return rows */
791 default:
792diff -Naur php-4.3.11/ext/standard/array.c hardening-patch-4.3.11-0.3.2/ext/standard/array.c
793--- php-4.3.11/ext/standard/array.c 2004-12-23 17:40:03.000000000 +0100
794+++ hardening-patch-4.3.11-0.3.2/ext/standard/array.c 2005-07-09 08:53:02.474362504 +0200
795@@ -1153,6 +1153,32 @@
796 }
797 }
798 }
799+
800+ if (var_name[0] == 'H') {
801+ if ((strcmp(var_name, "HTTP_GET_VARS")==0)||
802+ (strcmp(var_name, "HTTP_POST_VARS")==0)||
803+ (strcmp(var_name, "HTTP_POST_FILES")==0)||
804+ (strcmp(var_name, "HTTP_ENV_VARS")==0)||
805+ (strcmp(var_name, "HTTP_SERVER_VARS")==0)||
806+ (strcmp(var_name, "HTTP_SESSION_VARS")==0)||
807+ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)||
808+ (strcmp(var_name, "HTTP_RAW_POST_DATA")==0)) {
809+ return 0;
810+ }
811+ } else if (var_name[0] == '_') {
812+ if ((strcmp(var_name, "_COOKIE")==0)||
813+ (strcmp(var_name, "_ENV")==0)||
814+ (strcmp(var_name, "_FILES")==0)||
815+ (strcmp(var_name, "_GET")==0)||
816+ (strcmp(var_name, "_POST")==0)||
817+ (strcmp(var_name, "_REQUEST")==0)||
818+ (strcmp(var_name, "_SESSION")==0)||
819+ (strcmp(var_name, "_SERVER")==0)) {
820+ return 0;
821+ }
822+ } else if (strcmp(var_name, "GLOBALS")==0) {
823+ return 0;
824+ }
825
826 return 1;
827 }
828diff -Naur php-4.3.11/ext/standard/basic_functions.c hardening-patch-4.3.11-0.3.2/ext/standard/basic_functions.c
829--- php-4.3.11/ext/standard/basic_functions.c 2005-01-18 12:01:20.000000000 +0100
830+++ hardening-patch-4.3.11-0.3.2/ext/standard/basic_functions.c 2005-07-09 08:53:02.476362200 +0200
831@@ -687,7 +687,7 @@
832 PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL)
833
834 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
835- PHP_FE(realpath, NULL)
836+ PHP_STATIC_FE("realpath", zif_real_path, NULL)
837 #endif
838
839 #ifdef HAVE_FNMATCH
840@@ -3020,6 +3020,35 @@
841 memcpy(new_key, prefix, prefix_len);
842 memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength);
843
844+ if (new_key[0] == 'H') {
845+ if ((strcmp(new_key, "HTTP_GET_VARS")==0)||
846+ (strcmp(new_key, "HTTP_POST_VARS")==0)||
847+ (strcmp(new_key, "HTTP_POST_FILES")==0)||
848+ (strcmp(new_key, "HTTP_ENV_VARS")==0)||
849+ (strcmp(new_key, "HTTP_SERVER_VARS")==0)||
850+ (strcmp(new_key, "HTTP_SESSION_VARS")==0)||
851+ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)||
852+ (strcmp(new_key, "HTTP_RAW_POST_DATA")==0)) {
853+ efree(new_key);
854+ return 0;
855+ }
856+ } else if (new_key[0] == '_') {
857+ if ((strcmp(new_key, "_COOKIE")==0)||
858+ (strcmp(new_key, "_ENV")==0)||
859+ (strcmp(new_key, "_FILES")==0)||
860+ (strcmp(new_key, "_GET")==0)||
861+ (strcmp(new_key, "_POST")==0)||
862+ (strcmp(new_key, "_REQUEST")==0)||
863+ (strcmp(new_key, "_SESSION")==0)||
864+ (strcmp(new_key, "_SERVER")==0)) {
865+ efree(new_key);
866+ return 0;
867+ }
868+ } else if (strcmp(new_key, "GLOBALS")==0) {
869+ efree(new_key);
870+ return 0;
871+ }
872+
873 zend_hash_del(&EG(symbol_table), new_key, new_key_len);
874 ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0);
875
876diff -Naur php-4.3.11/ext/standard/file.c hardening-patch-4.3.11-0.3.2/ext/standard/file.c
877--- php-4.3.11/ext/standard/file.c 2005-03-27 17:53:59.000000000 +0200
878+++ hardening-patch-4.3.11-0.3.2/ext/standard/file.c 2005-07-09 08:53:02.478361896 +0200
879@@ -2469,7 +2469,7 @@
880 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
881 /* {{{ proto string realpath(string path)
882 Return the resolved path */
883-PHP_FUNCTION(realpath)
884+PHP_FUNCTION(real_path)
885 {
886 zval **path;
887 char resolved_path_buff[MAXPATHLEN];
888diff -Naur php-4.3.11/ext/standard/file.h hardening-patch-4.3.11-0.3.2/ext/standard/file.h
889--- php-4.3.11/ext/standard/file.h 2004-06-21 21:33:47.000000000 +0200
890+++ hardening-patch-4.3.11-0.3.2/ext/standard/file.h 2005-07-09 08:53:02.478361896 +0200
891@@ -64,7 +64,7 @@
892 PHP_FUNCTION(fd_set);
893 PHP_FUNCTION(fd_isset);
894 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
895-PHP_FUNCTION(realpath);
896+PHP_FUNCTION(real_path);
897 #endif
898 #ifdef HAVE_FNMATCH
899 PHP_FUNCTION(fnmatch);
900diff -Naur php-4.3.11/ext/standard/ftp_fopen_wrapper.c hardening-patch-4.3.11-0.3.2/ext/standard/ftp_fopen_wrapper.c
901--- php-4.3.11/ext/standard/ftp_fopen_wrapper.c 2003-08-26 00:26:37.000000000 +0200
902+++ hardening-patch-4.3.11-0.3.2/ext/standard/ftp_fopen_wrapper.c 2005-07-09 08:53:02.479361744 +0200
903@@ -17,7 +17,7 @@
904 | Hartmut Holzgraefe <hholzgra@php.net> |
905 +----------------------------------------------------------------------+
906 */
907-/* $Id: ftp_fopen_wrapper.c,v 1.38.2.6 2003/08/25 22:26:37 pollita Exp $ */
908+/* $Id: ftp_fopen_wrapper.c,v 1.38.2.8.2.1 2005/06/27 08:27:23 sesser Exp $ */
909
910 #include "php.h"
911 #include "php_globals.h"
912@@ -142,7 +142,7 @@
913 unsigned short portno;
914 char *scratch;
915 int result;
916- int i, use_ssl;
917+ int i, use_ssl, tmp_len;
918 #ifdef HAVE_OPENSSL_EXT
919 int use_ssl_on_data=0;
920 php_stream *reuseid=NULL;
921@@ -243,10 +243,25 @@
922
923 #endif
924
925+#define PHP_FTP_CNTRL_CHK(val, val_len, err_msg) { \
926+ unsigned char *s = val, *e = s + val_len; \
927+ while (s < e) { \
928+ if (iscntrl(*s)) { \
929+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, err_msg, val); \
930+ goto errexit; \
931+ } \
932+ s++; \
933+ } \
934+}
935+
936 /* send the user name */
937 php_stream_write_string(stream, "USER ");
938 if (resource->user != NULL) {
939- php_raw_url_decode(resource->user, strlen(resource->user));
940+ unsigned char *s, *e;
941+ tmp_len = php_raw_url_decode(resource->user, strlen(resource->user));
942+
943+ PHP_FTP_CNTRL_CHK(resource->user, tmp_len, "Invalid login %s")
944+
945 php_stream_write_string(stream, resource->user);
946 } else {
947 php_stream_write_string(stream, "anonymous");
948@@ -262,7 +277,10 @@
949
950 php_stream_write_string(stream, "PASS ");
951 if (resource->pass != NULL) {
952- php_raw_url_decode(resource->pass, strlen(resource->pass));
953+ tmp_len = php_raw_url_decode(resource->pass, strlen(resource->pass));
954+
955+ PHP_FTP_CNTRL_CHK(resource->pass, tmp_len, "Invalid password %s")
956+
957 php_stream_write_string(stream, resource->pass);
958 } else {
959 /* if the user has configured who they are,
960diff -Naur php-4.3.11/ext/standard/head.c hardening-patch-4.3.11-0.3.2/ext/standard/head.c
961--- php-4.3.11/ext/standard/head.c 2005-01-07 22:14:23.000000000 +0100
962+++ hardening-patch-4.3.11-0.3.2/ext/standard/head.c 2005-07-09 08:53:02.479361744 +0200
963@@ -45,10 +45,31 @@
964 {
965 zend_bool rep = 1;
966 sapi_header_line ctr = {0};
967+#if HARDENING_PATCH
968+ int i;
969+#endif
970
971 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &ctr.line,
972 &ctr.line_len, &rep, &ctr.response_code) == FAILURE)
973 return;
974+
975+#if HARDENING_PATCH
976+ if (!HG(hphp_multiheader)) {
977+ for (i=0; i<ctr.line_len; i++) {
978+ if (ctr.line[i]==0) {
979+ php_security_log(S_MISC, "header(): headerline truncated by an ASCII-NUL char");
980+ ctr.line_len=i;
981+ break;
982+ } else if (ctr.line[i]=='\n') {
983+ if (i>0 && (i<ctr.line_len-1) && (ctr.line[i+1]==' ' || ctr.line[i+1]=='\t')) {
984+ continue;
985+ }
986+ php_security_log(S_MISC, "header(): headerline contains more than one header");
987+ ctr.line_len=i;
988+ }
989+ }
990+ }
991+#endif
992
993 sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr TSRMLS_CC);
994 }
995diff -Naur php-4.3.11/ext/standard/info.c hardening-patch-4.3.11-0.3.2/ext/standard/info.c
996--- php-4.3.11/ext/standard/info.c 2004-06-09 17:10:19.000000000 +0200
997+++ hardening-patch-4.3.11-0.3.2/ext/standard/info.c 2005-07-09 08:53:02.480361592 +0200
998@@ -397,7 +397,7 @@
999
1000 if (flag & PHP_INFO_GENERAL) {
1001 char *zend_version = get_zend_version();
1002- char temp_api[9];
1003+ char temp_api[11];
1004
1005 php_uname = php_get_uname('a');
1006
1007@@ -417,11 +417,22 @@
1008 }
1009 }
1010
1011+#if HARDENING_PATCH
1012+ if (!sapi_module.phpinfo_as_text) {
1013+ php_printf("<h1 class=\"p\">PHP Version %s with Hardening-Patch %s</h1>\n", PHP_VERSION, HARDENING_PATCH_VERSION);
1014+ } else {
1015+ char temp_ver[40];
1016+
1017+ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENING_PATCH_VERSION);
1018+ php_info_print_table_row(2, "PHP/Hardening-Patch Version", temp_ver);
1019+ }
1020+#else
1021 if (!sapi_module.phpinfo_as_text) {
1022 php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
1023 } else {
1024 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1025 }
1026+#endif
1027 php_info_print_box_end();
1028 php_info_print_table_start();
1029 php_info_print_table_row(2, "System", php_uname );
1030diff -Naur php-4.3.11/ext/standard/syslog.c hardening-patch-4.3.11-0.3.2/ext/standard/syslog.c
1031--- php-4.3.11/ext/standard/syslog.c 2004-07-30 16:38:29.000000000 +0200
1032+++ hardening-patch-4.3.11-0.3.2/ext/standard/syslog.c 2005-07-09 08:53:02.480361592 +0200
1033@@ -42,6 +42,7 @@
1034 */
1035 PHP_MINIT_FUNCTION(syslog)
1036 {
1037+#if !HARDENING_PATCH
1038 /* error levels */
1039 REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
1040 REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
1041@@ -97,7 +98,7 @@
1042 /* AIX doesn't have LOG_PERROR */
1043 REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
1044 #endif
1045-
1046+#endif
1047 return SUCCESS;
1048 }
1049 /* }}} */
1050diff -Naur php-4.3.11/ext/varfilter/config.m4 hardening-patch-4.3.11-0.3.2/ext/varfilter/config.m4
1051--- php-4.3.11/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100
1052+++ hardening-patch-4.3.11-0.3.2/ext/varfilter/config.m4 2005-07-09 08:53:02.481361440 +0200
1053@@ -0,0 +1,11 @@
1054+dnl
1055+dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $
1056+dnl
1057+
1058+PHP_ARG_ENABLE(varfilter, whether to enable Hardening-Patch's variable filter,
1059+[ --disable-varfilter Disable Hardening-Patch's variable filter], yes)
1060+
1061+if test "$PHP_VARFILTER" != "no"; then
1062+ AC_DEFINE(HAVE_VARFILTER, 1, [ ])
1063+ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared)
1064+fi
1065diff -Naur php-4.3.11/ext/varfilter/CREDITS hardening-patch-4.3.11-0.3.2/ext/varfilter/CREDITS
1066--- php-4.3.11/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100
1067+++ hardening-patch-4.3.11-0.3.2/ext/varfilter/CREDITS 2005-07-09 08:53:02.481361440 +0200
1068@@ -0,0 +1,2 @@
1069+varfilter
1070+Stefan Esser
1071\ Kein Zeilenumbruch am Dateiende.
1072diff -Naur php-4.3.11/ext/varfilter/php_varfilter.h hardening-patch-4.3.11-0.3.2/ext/varfilter/php_varfilter.h
1073--- php-4.3.11/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100
1074+++ hardening-patch-4.3.11-0.3.2/ext/varfilter/php_varfilter.h 2005-07-09 08:53:02.481361440 +0200
1075@@ -0,0 +1,111 @@
1076+/*
1077+ +----------------------------------------------------------------------+
1078+ | Hardened-PHP Project's varfilter extension |
1079+ +----------------------------------------------------------------------+
1080+ | Copyright (c) 2004-2005 Stefan Esser |
1081+ +----------------------------------------------------------------------+
1082+ | This source file is subject to version 2.02 of the PHP license, |
1083+ | that is bundled with this package in the file LICENSE, and is |
1084+ | available at through the world-wide-web at |
1085+ | http://www.php.net/license/2_02.txt. |
1086+ | If you did not receive a copy of the PHP license and are unable to |
1087+ | obtain it through the world-wide-web, please send a note to |
1088+ | license@php.net so we can mail you a copy immediately. |
1089+ +----------------------------------------------------------------------+
1090+ | Author: Stefan Esser <sesser@hardened-php.net> |
1091+ +----------------------------------------------------------------------+
1092+
1093+ $Id: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $
1094+*/
1095+
1096+#ifndef PHP_VARFILTER_H
1097+#define PHP_VARFILTER_H
1098+
1099+extern zend_module_entry varfilter_module_entry;
1100+#define phpext_varfilter_ptr &varfilter_module_entry
1101+
1102+#ifdef PHP_WIN32
1103+#define PHP_VARFILTER_API __declspec(dllexport)
1104+#else
1105+#define PHP_VARFILTER_API
1106+#endif
1107+
1108+#ifdef ZTS
1109+#include "TSRM.h"
1110+#endif
1111+
1112+#include "SAPI.h"
1113+
1114+#include "php_variables.h"
1115+
1116+
1117+PHP_MINIT_FUNCTION(varfilter);
1118+PHP_MSHUTDOWN_FUNCTION(varfilter);
1119+PHP_RINIT_FUNCTION(varfilter);
1120+PHP_RSHUTDOWN_FUNCTION(varfilter);
1121+PHP_MINFO_FUNCTION(varfilter);
1122+
1123+
1124+ZEND_BEGIN_MODULE_GLOBALS(varfilter)
1125+// request variables
1126+ long max_request_variables;
1127+ long cur_request_variables;
1128+ long max_varname_length;
1129+ long max_totalname_length;
1130+ long max_value_length;
1131+ long max_array_depth;
1132+ long max_array_index_length;
1133+// cookie variables
1134+ long max_cookie_vars;
1135+ long cur_cookie_vars;
1136+ long max_cookie_name_length;
1137+ long max_cookie_totalname_length;
1138+ long max_cookie_value_length;
1139+ long max_cookie_array_depth;
1140+ long max_cookie_array_index_length;
1141+// get variables
1142+ long max_get_vars;
1143+ long cur_get_vars;
1144+ long max_get_name_length;
1145+ long max_get_totalname_length;
1146+ long max_get_value_length;
1147+ long max_get_array_depth;
1148+ long max_get_array_index_length;
1149+// post variables
1150+ long max_post_vars;
1151+ long cur_post_vars;
1152+ long max_post_name_length;
1153+ long max_post_totalname_length;
1154+ long max_post_value_length;
1155+ long max_post_array_depth;
1156+ long max_post_array_index_length;
1157+// fileupload
1158+ long max_uploads;
1159+ long cur_uploads;
1160+ zend_bool disallow_elf_files;
1161+ char *verification_script;
1162+
1163+ZEND_END_MODULE_GLOBALS(varfilter)
1164+
1165+
1166+#ifdef ZTS
1167+#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v)
1168+#else
1169+#define VARFILTER_G(v) (varfilter_globals.v)
1170+#endif
1171+
1172+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter);
1173+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter);
1174+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter);
1175+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter);
1176+
1177+#endif /* PHP_VARFILTER_H */
1178+
1179+
1180+/*
1181+ * Local variables:
1182+ * tab-width: 4
1183+ * c-basic-offset: 4
1184+ * indent-tabs-mode: t
1185+ * End:
1186+ */
1187diff -Naur php-4.3.11/ext/varfilter/varfilter.c hardening-patch-4.3.11-0.3.2/ext/varfilter/varfilter.c
1188--- php-4.3.11/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100
1189+++ hardening-patch-4.3.11-0.3.2/ext/varfilter/varfilter.c 2005-07-09 08:57:24.526524520 +0200
1190@@ -0,0 +1,604 @@
1191+/*
1192+ +----------------------------------------------------------------------+
1193+ | Hardened-PHP Project's varfilter extension |
1194+ +----------------------------------------------------------------------+
1195+ | Copyright (c) 2004-2005 Stefan Esser |
1196+ +----------------------------------------------------------------------+
1197+ | This source file is subject to version 2.02 of the PHP license, |
1198+ | that is bundled with this package in the file LICENSE, and is |
1199+ | available at through the world-wide-web at |
1200+ | http://www.php.net/license/2_02.txt. |
1201+ | If you did not receive a copy of the PHP license and are unable to |
1202+ | obtain it through the world-wide-web, please send a note to |
1203+ | license@php.net so we can mail you a copy immediately. |
1204+ +----------------------------------------------------------------------+
1205+ | Author: Stefan Esser <sesser@hardened-php.net> |
1206+ +----------------------------------------------------------------------+
1207+
1208+ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $
1209+*/
1210+
1211+#ifdef HAVE_CONFIG_H
1212+#include "config.h"
1213+#endif
1214+
1215+#include "php.h"
1216+#include "php_ini.h"
1217+#include "ext/standard/info.h"
1218+#include "php_varfilter.h"
1219+#include "hardening_patch.h"
1220+
1221+ZEND_DECLARE_MODULE_GLOBALS(varfilter)
1222+
1223+/* True global resources - no need for thread safety here */
1224+static int le_varfilter;
1225+
1226+/* {{{ varfilter_module_entry
1227+ */
1228+zend_module_entry varfilter_module_entry = {
1229+#if ZEND_MODULE_API_NO >= 20010901
1230+ STANDARD_MODULE_HEADER,
1231+#endif
1232+ "varfilter",
1233+ NULL,
1234+ PHP_MINIT(varfilter),
1235+ PHP_MSHUTDOWN(varfilter),
1236+ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */
1237+ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */
1238+ PHP_MINFO(varfilter),
1239+#if ZEND_MODULE_API_NO >= 20010901
1240+ "0.3.2", /* Replace with version number for your extension */
1241+#endif
1242+ STANDARD_MODULE_PROPERTIES
1243+};
1244+/* }}} */
1245+
1246+#ifdef COMPILE_DL_VARFILTER
1247+ZEND_GET_MODULE(varfilter)
1248+#endif
1249+
1250+/* {{{ PHP_INI
1251+ */
1252+PHP_INI_BEGIN()
1253+ /* for backward compatibility */
1254+ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
1255+ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
1256+ STD_PHP_INI_ENTRY("varfilter.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
1257+ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
1258+ STD_PHP_INI_ENTRY("varfilter.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
1259+ STD_PHP_INI_ENTRY("varfilter.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
1260+
1261+ STD_PHP_INI_ENTRY("hphp.request.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
1262+ STD_PHP_INI_ENTRY("hphp.request.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
1263+ STD_PHP_INI_ENTRY("hphp.request.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
1264+ STD_PHP_INI_ENTRY("hphp.request.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
1265+ STD_PHP_INI_ENTRY("hphp.request.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
1266+ STD_PHP_INI_ENTRY("hphp.request.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
1267+
1268+ STD_PHP_INI_ENTRY("hphp.cookie.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_vars, zend_varfilter_globals, varfilter_globals)
1269+ STD_PHP_INI_ENTRY("hphp.cookie.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_name_length, zend_varfilter_globals, varfilter_globals)
1270+ STD_PHP_INI_ENTRY("hphp.cookie.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_cookie_totalname_length, zend_varfilter_globals, varfilter_globals)
1271+ STD_PHP_INI_ENTRY("hphp.cookie.max_value_length", "10000", PHP_INI_PERDIR, OnUpdateLong, max_cookie_value_length, zend_varfilter_globals, varfilter_globals)
1272+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_depth, zend_varfilter_globals, varfilter_globals)
1273+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_index_length, zend_varfilter_globals, varfilter_globals)
1274+
1275+ STD_PHP_INI_ENTRY("hphp.get.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_get_vars, zend_varfilter_globals, varfilter_globals)
1276+ STD_PHP_INI_ENTRY("hphp.get.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_name_length, zend_varfilter_globals, varfilter_globals)
1277+ STD_PHP_INI_ENTRY("hphp.get.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_get_totalname_length, zend_varfilter_globals, varfilter_globals)
1278+ STD_PHP_INI_ENTRY("hphp.get.max_value_length", "512", PHP_INI_PERDIR, OnUpdateLong, max_get_value_length, zend_varfilter_globals, varfilter_globals)
1279+ STD_PHP_INI_ENTRY("hphp.get.max_array_depth", "50", PHP_INI_PERDIR, OnUpdateLong, max_get_array_depth, zend_varfilter_globals, varfilter_globals)
1280+ STD_PHP_INI_ENTRY("hphp.get.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_array_index_length, zend_varfilter_globals, varfilter_globals)
1281+
1282+ STD_PHP_INI_ENTRY("hphp.post.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_post_vars, zend_varfilter_globals, varfilter_globals)
1283+ STD_PHP_INI_ENTRY("hphp.post.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_name_length, zend_varfilter_globals, varfilter_globals)
1284+ STD_PHP_INI_ENTRY("hphp.post.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_post_totalname_length, zend_varfilter_globals, varfilter_globals)
1285+ STD_PHP_INI_ENTRY("hphp.post.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_post_value_length, zend_varfilter_globals, varfilter_globals)
1286+ STD_PHP_INI_ENTRY("hphp.post.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_post_array_depth, zend_varfilter_globals, varfilter_globals)
1287+ STD_PHP_INI_ENTRY("hphp.post.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_array_index_length, zend_varfilter_globals, varfilter_globals)
1288+
1289+ STD_PHP_INI_ENTRY("hphp.upload.max_uploads", "25", PHP_INI_PERDIR, OnUpdateLong, max_uploads, zend_varfilter_globals, varfilter_globals)
1290+ STD_PHP_INI_ENTRY("hphp.upload.disallow_elf_files", "1", PHP_INI_SYSTEM, OnUpdateBool, disallow_elf_files, zend_varfilter_globals, varfilter_globals)
1291+ STD_PHP_INI_ENTRY("hphp.upload.verification_script", NULL, PHP_INI_SYSTEM, OnUpdateString, verification_script, zend_varfilter_globals, varfilter_globals)
1292+
1293+
1294+PHP_INI_END()
1295+/* }}} */
1296+
1297+/* {{{ php_varfilter_init_globals
1298+ */
1299+static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals)
1300+{
1301+ varfilter_globals->max_request_variables = 200;
1302+ varfilter_globals->max_varname_length = 64;
1303+ varfilter_globals->max_value_length = 10000;
1304+ varfilter_globals->max_array_depth = 100;
1305+ varfilter_globals->max_totalname_length = 256;
1306+ varfilter_globals->max_array_index_length = 64;
1307+
1308+ varfilter_globals->max_cookie_vars = 100;
1309+ varfilter_globals->max_cookie_name_length = 64;
1310+ varfilter_globals->max_cookie_totalname_length = 256;
1311+ varfilter_globals->max_cookie_value_length = 10000;
1312+ varfilter_globals->max_cookie_array_depth = 100;
1313+ varfilter_globals->max_cookie_array_index_length = 64;
1314+
1315+ varfilter_globals->max_get_vars = 100;
1316+ varfilter_globals->max_get_name_length = 64;
1317+ varfilter_globals->max_get_totalname_length = 256;
1318+ varfilter_globals->max_get_value_length = 512;
1319+ varfilter_globals->max_get_array_depth = 50;
1320+ varfilter_globals->max_get_array_index_length = 64;
1321+
1322+ varfilter_globals->max_post_vars = 200;
1323+ varfilter_globals->max_post_name_length = 64;
1324+ varfilter_globals->max_post_totalname_length = 256;
1325+ varfilter_globals->max_post_value_length = 65000;
1326+ varfilter_globals->max_post_array_depth = 100;
1327+ varfilter_globals->max_post_array_index_length = 64;
1328+
1329+ varfilter_globals->max_uploads = 25;
1330+ varfilter_globals->disallow_elf_files = 1;
1331+ varfilter_globals->verification_script = NULL;
1332+}
1333+/* }}} */
1334+
1335+/* {{{ PHP_MINIT_FUNCTION
1336+ */
1337+PHP_MINIT_FUNCTION(varfilter)
1338+{
1339+ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL);
1340+ REGISTER_INI_ENTRIES();
1341+
1342+ sapi_register_input_filter(varfilter_input_filter);
1343+ sapi_register_pre_upload_filter(varfilter_pre_upload_filter);
1344+ sapi_register_upload_content_filter(varfilter_upload_content_filter);
1345+ sapi_register_post_upload_filter(varfilter_post_upload_filter);
1346+
1347+ return SUCCESS;
1348+}
1349+/* }}} */
1350+
1351+/* {{{ PHP_MSHUTDOWN_FUNCTION
1352+ */
1353+PHP_MSHUTDOWN_FUNCTION(varfilter)
1354+{
1355+// zend_hash_apply_with_arguments(&HG(lists.functionlists), (apply_func_args_t) show_stuff, 0);
1356+
1357+ UNREGISTER_INI_ENTRIES();
1358+
1359+ return SUCCESS;
1360+}
1361+/* }}} */
1362+
1363+/* Remove if there's nothing to do at request start */
1364+/* {{{ PHP_RINIT_FUNCTION
1365+ */
1366+PHP_RINIT_FUNCTION(varfilter)
1367+{
1368+ VARFILTER_G(cur_request_variables) = 0;
1369+ VARFILTER_G(cur_get_vars) = 0;
1370+ VARFILTER_G(cur_post_vars) = 0;
1371+ VARFILTER_G(cur_cookie_vars) = 0;
1372+
1373+ VARFILTER_G(cur_uploads) = 0;
1374+
1375+ return SUCCESS;
1376+}
1377+/* }}} */
1378+
1379+/* Remove if there's nothing to do at request end */
1380+/* {{{ PHP_RSHUTDOWN_FUNCTION
1381+ */
1382+PHP_RSHUTDOWN_FUNCTION(varfilter)
1383+{
1384+ return SUCCESS;
1385+}
1386+/* }}} */
1387+
1388+/* {{{ PHP_MINFO_FUNCTION
1389+ */
1390+PHP_MINFO_FUNCTION(varfilter)
1391+{
1392+ php_info_print_table_start();
1393+ php_info_print_table_header(2, "Hardening-Patch's variable filter support", "enabled");
1394+ php_info_print_table_end();
1395+
1396+ DISPLAY_INI_ENTRIES();
1397+}
1398+/* }}} */
1399+
1400+/* {{{ normalize_varname
1401+ */
1402+static void normalize_varname(char *varname)
1403+{
1404+ char *s=varname, *index=NULL, *indexend=NULL, *p;
1405+
1406+ /* overjump leading space */
1407+ while (*s == ' ') {
1408+ s++;
1409+ }
1410+
1411+ /* and remove it */
1412+ if (s != varname) {
1413+ memmove(varname, s, strlen(s)+1);
1414+ }
1415+
1416+ for (p=varname; *p && *p != '['; p++) {
1417+ switch(*p) {
1418+ case ' ':
1419+ case '.':
1420+ *p='_';
1421+ break;
1422+ }
1423+ }
1424+
1425+ /* find index */
1426+ index = strchr(varname, '[');
1427+ if (index) {
1428+ index++;
1429+ s=index;
1430+ } else {
1431+ return;
1432+ }
1433+
1434+ /* done? */
1435+ while (index) {
1436+
1437+ while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
1438+ index++;
1439+ }
1440+ indexend = strchr(index, ']');
1441+ indexend = indexend ? indexend + 1 : index + strlen(index);
1442+
1443+ if (s != index) {
1444+ memmove(s, index, strlen(index)+1);
1445+ s += indexend-index;
1446+ } else {
1447+ s = indexend;
1448+ }
1449+
1450+ if (*s == '[') {
1451+ s++;
1452+ index = s;
1453+ } else {
1454+ index = NULL;
1455+ }
1456+ }
1457+ *s++='\0';
1458+}
1459+/* }}} */
1460+
1461+/* {{{ SAPI_PRE_UPLOAD_FILTER_FUNC
1462+ */
1463+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter)
1464+{
1465+ /* Drop this fileupload if the limit is reached */
1466+ if (VARFILTER_G(max_uploads) && VARFILTER_G(max_uploads) <= VARFILTER_G(cur_uploads)) {
1467+ php_security_log(S_FILES, "configured fileupload limit exceeded - file dropped");
1468+ return FAILURE;
1469+ }
1470+
1471+ return SUCCESS;
1472+}
1473+/* }}} */
1474+
1475+/* {{{ SAPI_UPLOAD_CONTENT_FILTER_FUNC
1476+ */
1477+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter)
1478+{
1479+
1480+ if (VARFILTER_G(disallow_elf_files)) {
1481+
1482+ if (offset == 0 && buffer_len > 10) {
1483+
1484+ if (buffer[0] == 0x7F && buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'F') {
1485+ php_security_log(S_FILES, "uploaded file is an ELF executable - file dropped");
1486+ return FAILURE;
1487+ }
1488+ }
1489+
1490+ }
1491+
1492+ return SUCCESS;
1493+}
1494+/* }}} */
1495+
1496+/* {{{ SAPI_POST_UPLOAD_FILTER_FUNC
1497+ */
1498+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter)
1499+{
1500+ int retval = SUCCESS;
1501+
1502+ if (VARFILTER_G(verification_script)) {
1503+ char cmd[8192];
1504+ FILE *in;
1505+ int first=1;
1506+
1507+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s", VARFILTER_G(verification_script), tmpfilename);
1508+
1509+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
1510+ php_security_log(S_FILES, "unable to execute fileupload verification script - file dropped");
1511+ return FAILURE;
1512+ }
1513+
1514+ retval = FAILURE;
1515+
1516+ /* read and forget the result */
1517+ while (1) {
1518+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
1519+ if (readbytes<=0) {
1520+ break;
1521+ }
1522+ if (first) {
1523+ retval = atoi(cmd) == 1 ? SUCCESS : FAILURE;
1524+ first = 0;
1525+ }
1526+ }
1527+ pclose(in);
1528+ }
1529+
1530+ if (retval != SUCCESS) {
1531+ php_security_log(S_FILES, "fileupload verification script disallows file - file dropped");
1532+ return FAILURE;
1533+ }
1534+
1535+ VARFILTER_G(cur_uploads)++;
1536+ return SUCCESS;
1537+}
1538+/* }}} */
1539+
1540+/* {{{ SAPI_INPUT_FILTER_FUNC
1541+ */
1542+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter)
1543+{
1544+ char *index, *prev_index = NULL, *copy_var;
1545+ unsigned int var_len, total_len, depth = 0, rv;
1546+
1547+ /* Drop this variable if the limit is reached */
1548+ if (VARFILTER_G(max_request_variables) && VARFILTER_G(max_request_variables) <= VARFILTER_G(cur_request_variables)) {
1549+ php_security_log(S_VARS, "configured request variable limit exceeded - dropped %s", var);
1550+ return 0;
1551+ }
1552+ switch (arg) {
1553+ case PARSE_GET:
1554+ if (VARFILTER_G(max_get_vars) && VARFILTER_G(max_get_vars) <= VARFILTER_G(cur_get_vars)) {
1555+ php_security_log(S_VARS, "configured GET variable limit exceeded - dropped %s", var);
1556+ return 0;
1557+ }
1558+ break;
1559+ case PARSE_COOKIE:
1560+ if (VARFILTER_G(max_cookie_vars) && VARFILTER_G(max_cookie_vars) <= VARFILTER_G(cur_cookie_vars)) {
1561+ php_security_log(S_VARS, "configured COOKIE variable limit exceeded - dropped %s", var);
1562+ return 0;
1563+ }
1564+ break;
1565+ case PARSE_POST:
1566+ if (VARFILTER_G(max_post_vars) && VARFILTER_G(max_post_vars) <= VARFILTER_G(cur_post_vars)) {
1567+ php_security_log(S_VARS, "configured POST variable limit exceeded - dropped %s", var);
1568+ return 0;
1569+ }
1570+ break;
1571+ }
1572+
1573+
1574+ /* Drop this variable if it exceeds the value length limit */
1575+ if (VARFILTER_G(max_value_length) && VARFILTER_G(max_value_length) < val_len) {
1576+ php_security_log(S_VARS, "configured request variable value length limit exceeded - dropped %s", var);
1577+ return 0;
1578+ }
1579+ switch (arg) {
1580+ case PARSE_GET:
1581+ if (VARFILTER_G(max_get_value_length) && VARFILTER_G(max_get_value_length) < val_len) {
1582+ php_security_log(S_VARS, "configured GET variable value length limit exceeded - dropped %s", var);
1583+ return 0;
1584+ }
1585+ break;
1586+ case PARSE_COOKIE:
1587+ if (VARFILTER_G(max_cookie_value_length) && VARFILTER_G(max_cookie_value_length) < val_len) {
1588+ php_security_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped %s", var);
1589+ return 0;
1590+ }
1591+ break;
1592+ case PARSE_POST:
1593+ if (VARFILTER_G(max_post_value_length) && VARFILTER_G(max_post_value_length) < val_len) {
1594+ php_security_log(S_VARS, "configured POST variable value length limit exceeded - dropped %s", var);
1595+ return 0;
1596+ }
1597+ break;
1598+ }
1599+
1600+ /* Normalize the variable name */
1601+ normalize_varname(var);
1602+
1603+ /* Find length of variable name */
1604+ index = strchr(var, '[');
1605+ total_len = strlen(var);
1606+ var_len = index ? index-var : total_len;
1607+
1608+ /* Drop this variable if it exceeds the varname/total length limit */
1609+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
1610+ php_security_log(S_VARS, "configured request variable name length limit exceeded - dropped %s", var);
1611+ return 0;
1612+ }
1613+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
1614+ php_security_log(S_VARS, "configured request variable total name length limit exceeded - dropped %s", var);
1615+ return 0;
1616+ }
1617+ switch (arg) {
1618+ case PARSE_GET:
1619+ if (VARFILTER_G(max_get_name_length) && VARFILTER_G(max_get_name_length) < var_len) {
1620+ php_security_log(S_VARS, "configured GET variable name length limit exceeded - dropped %s", var);
1621+ return 0;
1622+ }
1623+ if (VARFILTER_G(max_get_totalname_length) && VARFILTER_G(max_get_totalname_length) < var_len) {
1624+ php_security_log(S_VARS, "configured GET variable total name length limit exceeded - dropped %s", var);
1625+ return 0;
1626+ }
1627+ break;
1628+ case PARSE_COOKIE:
1629+ if (VARFILTER_G(max_cookie_name_length) && VARFILTER_G(max_cookie_name_length) < var_len) {
1630+ php_security_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped %s", var);
1631+ return 0;
1632+ }
1633+ if (VARFILTER_G(max_cookie_totalname_length) && VARFILTER_G(max_cookie_totalname_length) < var_len) {
1634+ php_security_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped %s", var);
1635+ return 0;
1636+ }
1637+ break;
1638+ case PARSE_POST:
1639+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
1640+ php_security_log(S_VARS, "configured POST variable name length limit exceeded - dropped %s", var);
1641+ return 0;
1642+ }
1643+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
1644+ php_security_log(S_VARS, "configured POST variable total name length limit exceeded - dropped %s", var);
1645+ return 0;
1646+ }
1647+ break;
1648+ }
1649+
1650+ /* Find out array depth */
1651+ while (index) {
1652+ unsigned int index_length;
1653+
1654+ depth++;
1655+ index = strchr(index+1, '[');
1656+
1657+ if (prev_index) {
1658+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
1659+
1660+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
1661+ php_security_log(S_VARS, "configured request variable array index length limit exceeded - dropped %s", var);
1662+ return 0;
1663+ }
1664+ switch (arg) {
1665+ case PARSE_GET:
1666+ if (VARFILTER_G(max_get_array_index_length) && VARFILTER_G(max_get_array_index_length) < index_length) {
1667+ php_security_log(S_VARS, "configured GET variable array index length limit exceeded - dropped %s", var);
1668+ return 0;
1669+ }
1670+ break;
1671+ case PARSE_COOKIE:
1672+ if (VARFILTER_G(max_cookie_array_index_length) && VARFILTER_G(max_cookie_array_index_length) < index_length) {
1673+ php_security_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped %s", var);
1674+ return 0;
1675+ }
1676+ break;
1677+ case PARSE_POST:
1678+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
1679+ php_security_log(S_VARS, "configured POST variable array index length limit exceeded - dropped %s", var);
1680+ return 0;
1681+ }
1682+ break;
1683+ }
1684+ prev_index = index;
1685+ }
1686+
1687+ }
1688+
1689+ /* Drop this variable if it exceeds the array depth limit */
1690+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
1691+ php_security_log(S_VARS, "configured request variable array depth limit exceeded - dropped %s", var);
1692+ return 0;
1693+ }
1694+ switch (arg) {
1695+ case PARSE_GET:
1696+ if (VARFILTER_G(max_get_array_depth) && VARFILTER_G(max_get_array_depth) < depth) {
1697+ php_security_log(S_VARS, "configured GET variable array depth limit exceeded - dropped %s", var);
1698+ return 0;
1699+ }
1700+ break;
1701+ case PARSE_COOKIE:
1702+ if (VARFILTER_G(max_cookie_array_depth) && VARFILTER_G(max_cookie_array_depth) < depth) {
1703+ php_security_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped %s", var);
1704+ return 0;
1705+ }
1706+ break;
1707+ case PARSE_POST:
1708+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
1709+ php_security_log(S_VARS, "configured POST variable array depth limit exceeded - dropped %s", var);
1710+ return 0;
1711+ }
1712+ break;
1713+ }
1714+
1715+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
1716+ /* This is to protect several silly scripts that do globalizing themself */
1717+
1718+ switch (var_len) {
1719+ case 18:
1720+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname;
1721+ break;
1722+ case 17:
1723+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname;
1724+ break;
1725+ case 16:
1726+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname;
1727+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname;
1728+ break;
1729+ case 15:
1730+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname;
1731+ break;
1732+ case 14:
1733+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname;
1734+ break;
1735+ case 13:
1736+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname;
1737+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname;
1738+ break;
1739+ case 8:
1740+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname;
1741+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname;
1742+ break;
1743+ case 7:
1744+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname;
1745+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname;
1746+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname;
1747+ break;
1748+ case 6:
1749+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname;
1750+ break;
1751+ case 5:
1752+ if (memcmp(var, "_POST", 5)==0) goto protected_varname;
1753+ break;
1754+ case 4:
1755+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname;
1756+ if (memcmp(var, "_GET", 4)==0) goto protected_varname;
1757+ break;
1758+ }
1759+
1760+ /* Okay let PHP register this variable */
1761+ VARFILTER_G(cur_request_variables)++;
1762+ switch (arg) {
1763+ case PARSE_GET:
1764+ VARFILTER_G(cur_get_vars)++;
1765+ break;
1766+ case PARSE_COOKIE:
1767+ VARFILTER_G(cur_cookie_vars)++;
1768+ break;
1769+ case PARSE_POST:
1770+ VARFILTER_G(cur_post_vars)++;
1771+ break;
1772+ }
1773+
1774+ if (new_val_len) {
1775+ *new_val_len = val_len;
1776+ }
1777+
1778+ return 1;
1779+protected_varname:
1780+ php_security_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
1781+ return 0;
1782+}
1783+/* }}} */
1784+
1785+/*
1786+ * Local variables:
1787+ * tab-width: 4
1788+ * c-basic-offset: 4
1789+ * End:
1790+ * vim600: noet sw=4 ts=4 fdm=marker
1791+ * vim<600: noet sw=4 ts=4
1792+ */
1793+
1794+
1795diff -Naur php-4.3.11/main/fopen_wrappers.c hardening-patch-4.3.11-0.3.2/main/fopen_wrappers.c
1796--- php-4.3.11/main/fopen_wrappers.c 2005-02-03 00:44:07.000000000 +0100
1797+++ hardening-patch-4.3.11-0.3.2/main/fopen_wrappers.c 2005-07-09 08:53:02.483361136 +0200
1798@@ -166,6 +166,21 @@
1799 char *pathbuf;
1800 char *ptr;
1801 char *end;
1802+ char path_copy[MAXPATHLEN];
1803+ int path_len;
1804+
1805+ /* Special case path ends with a trailing slash */
1806+ path_len = strlen(path);
1807+ if (path_len >= MAXPATHLEN) {
1808+ errno = EPERM; /* we deny permission to open it */
1809+ return -1;
1810+ }
1811+ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) {
1812+ memcpy(path_copy, path, path_len+1);
1813+ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--;
1814+ path_copy[path_len] = '\0';
1815+ path = (const char *)&path_copy;
1816+ }
1817
1818 pathbuf = estrdup(PG(open_basedir));
1819
1820diff -Naur php-4.3.11/main/hardened_globals.h hardening-patch-4.3.11-0.3.2/main/hardened_globals.h
1821--- php-4.3.11/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100
1822+++ hardening-patch-4.3.11-0.3.2/main/hardened_globals.h 2005-07-09 08:53:02.483361136 +0200
1823@@ -0,0 +1,56 @@
1824+/*
1825+ +----------------------------------------------------------------------+
1826+ | Hardening-Patch for PHP |
1827+ +----------------------------------------------------------------------+
1828+ | Copyright (c) 2004-2005 Stefan Esser |
1829+ +----------------------------------------------------------------------+
1830+ | This source file is subject to version 2.02 of the PHP license, |
1831+ | that is bundled with this package in the file LICENSE, and is |
1832+ | available at through the world-wide-web at |
1833+ | http://www.php.net/license/2_02.txt. |
1834+ | If you did not receive a copy of the PHP license and are unable to |
1835+ | obtain it through the world-wide-web, please send a note to |
1836+ | license@php.net so we can mail you a copy immediately. |
1837+ +----------------------------------------------------------------------+
1838+ | Author: Stefan Esser <sesser@hardened-php.net> |
1839+ +----------------------------------------------------------------------+
1840+ */
1841+
1842+#ifndef HARDENED_GLOBALS_H
1843+#define HARDENED_GLOBALS_H
1844+
1845+typedef struct _hardened_globals hardened_globals_struct;
1846+
1847+#ifdef ZTS
1848+# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v)
1849+extern int hardened_globals_id;
1850+#else
1851+# define HG(v) (hardened_globals.v)
1852+extern struct _hardened_globals hardened_globals;
1853+#endif
1854+
1855+
1856+struct _hardened_globals {
1857+#if HARDENING_PATCH_MM_PROTECT
1858+ unsigned int canary_1;
1859+ unsigned int canary_2;
1860+#endif
1861+#if HARDENING_PATCH_LL_PROTECT
1862+ unsigned int canary_3;
1863+ unsigned int canary_4;
1864+ unsigned int ll_canary_inited;
1865+#endif
1866+ zend_bool hphp_sql_bailout_on_error;
1867+ zend_bool hphp_multiheader;
1868+ unsigned int dummy;
1869+};
1870+
1871+
1872+#endif /* HARDENED_GLOBALS_H */
1873+
1874+/*
1875+ * Local variables:
1876+ * tab-width: 4
1877+ * c-basic-offset: 4
1878+ * End:
1879+ */
1880diff -Naur php-4.3.11/main/hardening_patch.c hardening-patch-4.3.11-0.3.2/main/hardening_patch.c
1881--- php-4.3.11/main/hardening_patch.c 1970-01-01 01:00:00.000000000 +0100
1882+++ hardening-patch-4.3.11-0.3.2/main/hardening_patch.c 2005-07-09 08:53:02.484360984 +0200
1883@@ -0,0 +1,322 @@
1884+/*
1885+ +----------------------------------------------------------------------+
1886+ | Hardening Patch for PHP |
1887+ +----------------------------------------------------------------------+
1888+ | Copyright (c) 2004-2005 Stefan Esser |
1889+ +----------------------------------------------------------------------+
1890+ | This source file is subject to version 2.02 of the PHP license, |
1891+ | that is bundled with this package in the file LICENSE, and is |
1892+ | available at through the world-wide-web at |
1893+ | http://www.php.net/license/2_02.txt. |
1894+ | If you did not receive a copy of the PHP license and are unable to |
1895+ | obtain it through the world-wide-web, please send a note to |
1896+ | license@php.net so we can mail you a copy immediately. |
1897+ +----------------------------------------------------------------------+
1898+ | Author: Stefan Esser <sesser@hardened-php.net> |
1899+ +----------------------------------------------------------------------+
1900+ */
1901+/* $Id: hardening_patch.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */
1902+
1903+#include "php.h"
1904+
1905+#include <stdio.h>
1906+#include <stdlib.h>
1907+
1908+#if HAVE_UNISTD_H
1909+#include <unistd.h>
1910+#endif
1911+#include "SAPI.h"
1912+#include "php_globals.h"
1913+
1914+#if HARDENING_PATCH
1915+
1916+#ifdef HAVE_SYS_SOCKET_H
1917+#include <sys/socket.h>
1918+#endif
1919+
1920+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
1921+#undef AF_UNIX
1922+#endif
1923+
1924+#if defined(AF_UNIX)
1925+#include <sys/un.h>
1926+#endif
1927+
1928+#define SYSLOG_PATH "/dev/log"
1929+
1930+#include "snprintf.h"
1931+
1932+#include "hardening_patch.h"
1933+
1934+#ifdef ZTS
1935+#include "hardened_globals.h"
1936+int hardened_globals_id;
1937+#else
1938+struct _hardened_globals hardened_globals;
1939+#endif
1940+
1941+static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC)
1942+{
1943+ memset(hardened_globals, 0, sizeof(*hardened_globals));
1944+}
1945+
1946+
1947+PHPAPI void hardened_startup()
1948+{
1949+#ifdef ZTS
1950+ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL);
1951+#else
1952+ hardened_globals_ctor(&hardened_globals TSRMLS_CC);
1953+#endif
1954+}
1955+
1956+char *loglevel2string(int loglevel)
1957+{
1958+ switch (loglevel) {
1959+ case S_FILES:
1960+ return "FILES";
1961+ case S_INCLUDE:
1962+ return "INCLUDE";
1963+ case S_MEMORY:
1964+ return "MEMORY";
1965+ case S_MISC:
1966+ return "MISC";
1967+ case S_SQL:
1968+ return "SQL";
1969+ case S_EXECUTOR:
1970+ return "EXECUTOR";
1971+ case S_VARS:
1972+ return "VARS";
1973+ default:
1974+ return "UNKNOWN";
1975+ }
1976+}
1977+
1978+PHPAPI void php_security_log(int loglevel, char *fmt, ...)
1979+{
1980+#if defined(AF_UNIX)
1981+ int s, r, i=0;
1982+ struct sockaddr_un saun;
1983+ char buf[4096+64];
1984+ char error[4096+100];
1985+ char *ip_address;
1986+ char *fname;
1987+ int lineno;
1988+ va_list ap;
1989+ TSRMLS_FETCH();
1990+
1991+ if (EG(hphp_log_use_x_forwarded_for)) {
1992+ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
1993+ if (ip_address == NULL) {
1994+ ip_address = "X-FORWARDED-FOR not set";
1995+ }
1996+ } else {
1997+ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
1998+ if (ip_address == NULL) {
1999+ ip_address = "REMOTE_ADDR not set";
2000+ }
2001+ }
2002+
2003+
2004+ va_start(ap, fmt);
2005+ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
2006+ va_end(ap);
2007+ while (error[i]) {
2008+ if (error[i] < 32) error[i] = '.';
2009+ i++;
2010+ }
2011+
2012+ if (zend_is_executing(TSRMLS_C)) {
2013+ lineno = zend_get_executed_lineno(TSRMLS_C);
2014+ fname = zend_get_executed_filename(TSRMLS_C);
2015+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s', line %u)", error, ip_address, fname, lineno);
2016+ } else {
2017+ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
2018+ if (fname==NULL) {
2019+ fname = "unknown";
2020+ }
2021+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s')", error, ip_address, fname);
2022+ }
2023+
2024+ /* Syslog-Logging disabled? */
2025+ if ((EG(hphp_log_syslog) & loglevel)==0) {
2026+ goto log_sapi;
2027+ }
2028+
2029+ ap_php_snprintf(error, sizeof(error), "<%u>hphp[%u]: %s\n", EG(hphp_log_syslog_facility)|EG(hphp_log_syslog_priority),getpid(),buf);
2030+
2031+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
2032+ if (s == -1) {
2033+ goto log_sapi;
2034+ }
2035+
2036+ memset(&saun, 0, sizeof(saun));
2037+ saun.sun_family = AF_UNIX;
2038+ strcpy(saun.sun_path, SYSLOG_PATH);
2039+ /*saun.sun_len = sizeof(saun);*/
2040+
2041+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
2042+ if (r) {
2043+ close(s);
2044+ s = socket(AF_UNIX, SOCK_STREAM, 0);
2045+ if (s == -1) {
2046+ goto log_sapi;
2047+ }
2048+
2049+ memset(&saun, 0, sizeof(saun));
2050+ saun.sun_family = AF_UNIX;
2051+ strcpy(saun.sun_path, SYSLOG_PATH);
2052+ /*saun.sun_len = sizeof(saun);*/
2053+
2054+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
2055+ if (r) {
2056+ close(s);
2057+ goto log_sapi;
2058+ }
2059+ }
2060+ send(s, error, strlen(error), 0);
2061+
2062+ close(s);
2063+
2064+log_sapi:
2065+ /* SAPI Logging activated? */
2066+ if ((EG(hphp_log_syslog) & loglevel)!=0) {
2067+ sapi_module.log_message(buf);
2068+ }
2069+
2070+log_script:
2071+ /* script logging activaed? */
2072+ if (((EG(hphp_log_script) & loglevel)!=0) && EG(hphp_log_scriptname)!=NULL) {
2073+ char cmd[8192], *cmdpos, *bufpos;
2074+ FILE *in;
2075+ int space;
2076+
2077+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", EG(hphp_log_scriptname), loglevel2string(loglevel));
2078+ space = sizeof(cmd) - strlen(cmd);
2079+ cmdpos = cmd + strlen(cmd);
2080+ bufpos = buf;
2081+ if (space <= 1) return;
2082+ while (space > 2 && *bufpos) {
2083+ if (*bufpos == '\'') {
2084+ if (space<=5) break;
2085+ *cmdpos++ = '\'';
2086+ *cmdpos++ = '\\';
2087+ *cmdpos++ = '\'';
2088+ *cmdpos++ = '\'';
2089+ bufpos++;
2090+ space-=4;
2091+ } else {
2092+ *cmdpos++ = *bufpos++;
2093+ space--;
2094+ }
2095+ }
2096+ *cmdpos++ = '\'';
2097+ *cmdpos = 0;
2098+
2099+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
2100+ return;
2101+ }
2102+ /* read and forget the result */
2103+ while (1) {
2104+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
2105+ if (readbytes<=0) {
2106+ break;
2107+ }
2108+ }
2109+ pclose(in);
2110+ }
2111+
2112+#endif
2113+}
2114+#endif
2115+
2116+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
2117+
2118+/* will be replaced later with more compatible method */
2119+PHPAPI unsigned int php_canary()
2120+{
2121+ time_t t;
2122+ unsigned int canary;
2123+ int fd;
2124+
2125+ fd = open("/dev/urandom", 0);
2126+ if (fd != -1) {
2127+ int r = read(fd, &canary, sizeof(canary));
2128+ close(fd);
2129+ if (r == sizeof(canary)) {
2130+ return (canary);
2131+ }
2132+ }
2133+ /* not good but we never want to do this */
2134+ time(&t);
2135+ canary = *(unsigned int *)&t + getpid() << 16;
2136+ return (canary);
2137+}
2138+#endif
2139+
2140+#if HARDENING_PATCH_INC_PROTECT
2141+
2142+PHPAPI int php_is_valid_include(zval *z)
2143+{
2144+ char *filename;
2145+ int len, i;
2146+ TSRMLS_FETCH();
2147+
2148+ /* must be of type string */
2149+ if (z->type != IS_STRING || z->value.str.val == NULL) {
2150+ return (0);
2151+ }
2152+
2153+ /* short cut */
2154+ filename = z->value.str.val;
2155+ len = z->value.str.len;
2156+
2157+ /* 1. must be shorter than MAXPATHLEN */
2158+ if (len > MAXPATHLEN) {
2159+ char *fname = estrndup(filename, len);
2160+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
2161+ php_security_log(S_INCLUDE, "Include filename ('%s') longer than MAXPATHLEN chars", fname);
2162+ efree(fname);
2163+ return (0);
2164+ }
2165+
2166+ /* 2. must not be cutted */
2167+ if (len != strlen(filename)) {
2168+ char *fname = estrndup(filename, len);
2169+ for (i=0; fname[i]; i++) if (fname[i] < 32) fname[i]='.';
2170+ php_security_log(S_INCLUDE, "Include filename truncated by a \\0 after '%s'", fname);
2171+ efree(fname);
2172+ return (0);
2173+ }
2174+
2175+ /* 3. must not be a URL */
2176+ if (strstr(filename, "://")) {
2177+ char *fname = estrndup(filename, len);
2178+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
2179+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL", fname);
2180+ efree(fname);
2181+ return (0);
2182+ }
2183+
2184+ /* 4. must not be an uploaded file */
2185+ if (SG(rfc1867_uploaded_files)) {
2186+ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) {
2187+ php_security_log(S_INCLUDE, "Include filename is an uploaded file");
2188+ return (0);
2189+ }
2190+ }
2191+
2192+ /* passed all tests */
2193+ return (1);
2194+}
2195+
2196+#endif
2197+
2198+/*
2199+ * Local variables:
2200+ * tab-width: 4
2201+ * c-basic-offset: 4
2202+ * End:
2203+ * vim600: sw=4 ts=4 fdm=marker
2204+ * vim<600: sw=4 ts=4
2205+ */
2206diff -Naur php-4.3.11/main/hardening_patch.h hardening-patch-4.3.11-0.3.2/main/hardening_patch.h
2207--- php-4.3.11/main/hardening_patch.h 1970-01-01 01:00:00.000000000 +0100
2208+++ hardening-patch-4.3.11-0.3.2/main/hardening_patch.h 2005-07-09 08:57:24.527524368 +0200
2209@@ -0,0 +1,46 @@
2210+/*
2211+ +----------------------------------------------------------------------+
2212+ | Hardening Patch for PHP |
2213+ +----------------------------------------------------------------------+
2214+ | Copyright (c) 2004-2005 Stefan Esser |
2215+ +----------------------------------------------------------------------+
2216+ | This source file is subject to version 2.02 of the PHP license, |
2217+ | that is bundled with this package in the file LICENSE, and is |
2218+ | available at through the world-wide-web at |
2219+ | http://www.php.net/license/2_02.txt. |
2220+ | If you did not receive a copy of the PHP license and are unable to |
2221+ | obtain it through the world-wide-web, please send a note to |
2222+ | license@php.net so we can mail you a copy immediately. |
2223+ +----------------------------------------------------------------------+
2224+ | Author: Stefan Esser <sesser@hardened-php.net> |
2225+ +----------------------------------------------------------------------+
2226+ */
2227+
2228+#ifndef HARDENING_PATCH_H
2229+#define HARDENING_PATCH_H
2230+
2231+#include "zend.h"
2232+
2233+#if HARDENING_PATCH
2234+PHPAPI void php_security_log(int loglevel, char *fmt, ...);
2235+PHPAPI void hardened_startup();
2236+#define HARDENING_PATCH_VERSION "0.3.2"
2237+
2238+#endif
2239+
2240+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
2241+PHPAPI unsigned int php_canary();
2242+#endif
2243+
2244+#if HARDENING_PATCH_INC_PROTECT
2245+PHPAPI int php_is_valid_include(zval *z);
2246+#endif
2247+
2248+#endif /* HARDENING_PATCH_H */
2249+
2250+/*
2251+ * Local variables:
2252+ * tab-width: 4
2253+ * c-basic-offset: 4
2254+ * End:
2255+ */
2256diff -Naur php-4.3.11/main/hardening_patch.m4 hardening-patch-4.3.11-0.3.2/main/hardening_patch.m4
2257--- php-4.3.11/main/hardening_patch.m4 1970-01-01 01:00:00.000000000 +0100
2258+++ hardening-patch-4.3.11-0.3.2/main/hardening_patch.m4 2005-07-09 08:53:02.485360832 +0200
2259@@ -0,0 +1,95 @@
2260+dnl
2261+dnl $Id: hardening_patch.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $
2262+dnl
2263+dnl This file contains Hardening Patch for PHP specific autoconf functions.
2264+dnl
2265+
2266+AC_ARG_ENABLE(hardening-patch-mm-protect,
2267+[ --disable-hardening-patch-mm-protect Disable the Memory Manager protection.],[
2268+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
2269+],[
2270+ DO_HARDENING_PATCH_MM_PROTECT=yes
2271+])
2272+
2273+AC_ARG_ENABLE(hardening-patch-ll-protect,
2274+[ --disable-hardening-patch-ll-protect Disable the Linked List protection.],[
2275+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
2276+],[
2277+ DO_HARDENING_PATCH_LL_PROTECT=yes
2278+])
2279+
2280+AC_ARG_ENABLE(hardening-patch-inc-protect,
2281+[ --disable-hardening-patch-inc-protect Disable include/require protection.],[
2282+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
2283+],[
2284+ DO_HARDENING_PATCH_INC_PROTECT=yes
2285+])
2286+
2287+AC_ARG_ENABLE(hardening-patch-fmt-protect,
2288+[ --disable-hardening-patch-fmt-protect Disable format string protection.],[
2289+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
2290+],[
2291+ DO_HARDENING_PATCH_FMT_PROTECT=yes
2292+])
2293+
2294+AC_ARG_ENABLE(hardening-patch-hash-protect,
2295+[ --disable-hardening-patch-hash-protect Disable HashTable destructor protection.],[
2296+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
2297+],[
2298+ DO_HARDENING_PATCH_HASH_PROTECT=yes
2299+])
2300+
2301+AC_MSG_CHECKING(whether to protect the Zend Memory Manager)
2302+AC_MSG_RESULT($DO_HARDENING_PATCH_MM_PROTECT)
2303+
2304+AC_MSG_CHECKING(whether to protect the Zend Linked Lists)
2305+AC_MSG_RESULT($DO_HARDENING_PATCH_LL_PROTECT)
2306+
2307+AC_MSG_CHECKING(whether to protect include/require statements)
2308+AC_MSG_RESULT($DO_HARDENING_PATCH_INC_PROTECT)
2309+
2310+AC_MSG_CHECKING(whether to protect PHP Format String functions)
2311+AC_MSG_RESULT($DO_HARDENING_PATCH_FMT_PROTECT)
2312+
2313+AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables)
2314+AC_MSG_RESULT($DO_HARDENING_PATCH_HASH_PROTECT)
2315+
2316+
2317+AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2318+
2319+
2320+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
2321+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2322+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 1, [Memory Manager Protection])
2323+else
2324+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 0, [Memory Manager Protection])
2325+fi
2326+
2327+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
2328+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2329+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 1, [Linked List Protection])
2330+else
2331+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 0, [Linked List Protection])
2332+fi
2333+
2334+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
2335+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2336+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 1, [Include/Require Protection])
2337+else
2338+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 0, [Include/Require Protection])
2339+fi
2340+
2341+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
2342+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2343+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 1, [Fmt String Protection])
2344+else
2345+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 0, [Fmt String Protection])
2346+fi
2347+
2348+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
2349+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
2350+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 1, [HashTable DTOR Protection])
2351+else
2352+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 0, [HashTable DTOR Protection])
2353+fi
2354+
2355diff -Naur php-4.3.11/main/main.c hardening-patch-4.3.11-0.3.2/main/main.c
2356--- php-4.3.11/main/main.c 2005-03-08 22:45:51.000000000 +0100
2357+++ hardening-patch-4.3.11-0.3.2/main/main.c 2005-07-09 08:53:02.486360680 +0200
2358@@ -100,6 +100,10 @@
2359 PHPAPI int core_globals_id;
2360 #endif
2361
2362+#if HARDENING_PATCH
2363+#include "hardened_globals.h"
2364+#endif
2365+
2366 #define ERROR_BUF_LEN 1024
2367
2368 typedef struct {
2369@@ -150,10 +154,33 @@
2370 */
2371 static PHP_INI_MH(OnChangeMemoryLimit)
2372 {
2373+#if HARDENING_PATCH
2374+ long orig_memory_limit;
2375+
2376+ if (entry->modified) {
2377+ orig_memory_limit = zend_atoi(entry->orig_value, entry->orig_value_length);
2378+ } else {
2379+ orig_memory_limit = 1<<30;
2380+ }
2381+ if (orig_memory_limit < 0 || orig_memory_limit > (1<<30)) {
2382+ orig_memory_limit = 1<<30;
2383+ }
2384+#endif
2385 if (new_value) {
2386 PG(memory_limit) = zend_atoi(new_value, new_value_length);
2387+#if HARDENING_PATCH
2388+ if (PG(memory_limit) > orig_memory_limit) {
2389+ PG(memory_limit) = orig_memory_limit;
2390+ php_security_log(S_MISC, "script tried to increase memory_limit above allowed value");
2391+ return FAILURE;
2392+ }
2393+#endif
2394 } else {
2395+#if HARDENING_PATCH
2396+ PG(memory_limit) = orig_memory_limit;
2397+#else
2398 PG(memory_limit) = 1<<30; /* effectively, no limit */
2399+#endif
2400 }
2401 return zend_set_memory_limit(PG(memory_limit));
2402 }
2403@@ -1092,6 +1119,10 @@
2404 tsrm_ls = ts_resource(0);
2405 #endif
2406
2407+#if HARDENING_PATCH
2408+ hardened_startup();
2409+#endif
2410+
2411 sapi_initialize_empty_request(TSRMLS_C);
2412 sapi_activate(TSRMLS_C);
2413
2414@@ -1104,6 +1135,12 @@
2415 php_output_startup();
2416 php_output_activate(TSRMLS_C);
2417
2418+#if HARDENING_PATCH_INC_PROTECT
2419+ zuf.is_valid_include = php_is_valid_include;
2420+#endif
2421+#if HARDENING_PATCH
2422+ zuf.security_log_function = php_security_log;
2423+#endif
2424 zuf.error_function = php_error_cb;
2425 zuf.printf_function = php_printf;
2426 zuf.write_function = php_body_write_wrapper;
2427@@ -1205,6 +1242,10 @@
2428 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, sizeof(PHP_CONFIG_FILE_PATH)-1, CONST_PERSISTENT | CONST_CS);
2429 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
2430 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
2431+#if HARDENING_PATCH
2432+ REGISTER_MAIN_LONG_CONSTANT("HARDENING_PATCH", 1, CONST_PERSISTENT | CONST_CS);
2433+ REGISTER_MAIN_STRINGL_CONSTANT("HARDENING_PATCH_VERSION", HARDENING_PATCH_VERSION, sizeof(HARDENING_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
2434+#endif
2435 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
2436 php_output_register_constants(TSRMLS_C);
2437 php_rfc1867_register_constants(TSRMLS_C);
2438@@ -1310,7 +1351,7 @@
2439 */
2440 static inline void php_register_server_variables(TSRMLS_D)
2441 {
2442- zval *array_ptr=NULL;
2443+ zval *array_ptr=NULL, *vptr;
2444
2445 ALLOC_ZVAL(array_ptr);
2446 array_init(array_ptr);
2447@@ -1320,6 +1361,16 @@
2448 /* Server variables */
2449 if (sapi_module.register_server_variables) {
2450 sapi_module.register_server_variables(array_ptr TSRMLS_CC);
2451+ if (zend_hash_find(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"), (void **)&vptr)==SUCCESS) {
2452+ char *str;
2453+ if (vptr->type != IS_STRING) {
2454+ str = "Array";
2455+ } else {
2456+ str = vptr->value.str.val;
2457+ }
2458+ php_security_log(S_VARS, "Attacker tried to overwrite HTTP_RAW_POST_DATA with '%s' through a HTTP header", str);
2459+ zend_hash_del(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
2460+ }
2461 }
2462
2463 /* PHP Authentication support */
2464diff -Naur php-4.3.11/main/php_config.h.in hardening-patch-4.3.11-0.3.2/main/php_config.h.in
2465--- php-4.3.11/main/php_config.h.in 2005-03-30 16:35:47.000000000 +0200
2466+++ hardening-patch-4.3.11-0.3.2/main/php_config.h.in 2005-07-09 08:53:02.487360528 +0200
2467@@ -839,6 +839,39 @@
2468 /* Enabling BIND8 compatibility for Panther */
2469 #undef BIND_8_COMPAT
2470
2471+/* Hardening-Patch */
2472+#undef HARDENING_PATCH
2473+
2474+/* Memory Manager Protection */
2475+#undef HARDENING_PATCH_MM_PROTECT
2476+
2477+/* Memory Manager Protection */
2478+#undef HARDENING_PATCH_MM_PROTECT
2479+
2480+/* Linked List Protection */
2481+#undef HARDENING_PATCH_LL_PROTECT
2482+
2483+/* Linked List Protection */
2484+#undef HARDENING_PATCH_LL_PROTECT
2485+
2486+/* Include/Require Protection */
2487+#undef HARDENING_PATCH_INC_PROTECT
2488+
2489+/* Include/Require Protection */
2490+#undef HARDENING_PATCH_INC_PROTECT
2491+
2492+/* Fmt String Protection */
2493+#undef HARDENING_PATCH_FMT_PROTECT
2494+
2495+/* Fmt String Protection */
2496+#undef HARDENING_PATCH_FMT_PROTECT
2497+
2498+/* HashTable DTOR Protection */
2499+#undef HARDENING_PATCH_HASH_PROTECT
2500+
2501+/* HashTable DTOR Protection */
2502+#undef HARDENING_PATCH_HASH_PROTECT
2503+
2504 /* Whether you have AOLserver */
2505 #undef HAVE_AOLSERVER
2506
2507@@ -1122,6 +1155,12 @@
2508 /* Define if you have the getaddrinfo function */
2509 #undef HAVE_GETADDRINFO
2510
2511+/* Whether realpath is broken */
2512+#undef PHP_BROKEN_REALPATH
2513+
2514+/* Whether realpath is broken */
2515+#undef PHP_BROKEN_REALPATH
2516+
2517 /* Whether system headers declare timezone */
2518 #undef HAVE_DECLARED_TIMEZONE
2519
2520diff -Naur php-4.3.11/main/php_content_types.c hardening-patch-4.3.11-0.3.2/main/php_content_types.c
2521--- php-4.3.11/main/php_content_types.c 2002-12-31 17:26:14.000000000 +0100
2522+++ hardening-patch-4.3.11-0.3.2/main/php_content_types.c 2005-07-09 08:53:02.487360528 +0200
2523@@ -77,6 +77,7 @@
2524 sapi_register_post_entries(php_post_entries);
2525 sapi_register_default_post_reader(php_default_post_reader);
2526 sapi_register_treat_data(php_default_treat_data);
2527+ sapi_register_input_filter(php_default_input_filter);
2528 return SUCCESS;
2529 }
2530 /* }}} */
2531diff -Naur php-4.3.11/main/php.h hardening-patch-4.3.11-0.3.2/main/php.h
2532--- php-4.3.11/main/php.h 2005-03-08 22:45:51.000000000 +0100
2533+++ hardening-patch-4.3.11-0.3.2/main/php.h 2005-07-09 08:53:02.488360376 +0200
2534@@ -26,7 +26,7 @@
2535 #include <dmalloc.h>
2536 #endif
2537
2538-#define PHP_API_VERSION 20020918
2539+#define PHP_API_VERSION 1020050626
2540 #define PHP_HAVE_STREAMS
2541 #define YYDEBUG 0
2542
2543@@ -35,11 +35,19 @@
2544 #include "zend_qsort.h"
2545 #include "php_compat.h"
2546
2547+
2548 #include "zend_API.h"
2549
2550 #undef sprintf
2551 #define sprintf php_sprintf
2552
2553+#if HARDENING_PATCH
2554+#if HAVE_REALPATH
2555+#undef realpath
2556+#define realpath php_realpath
2557+#endif
2558+#endif
2559+
2560 /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */
2561 #undef PHP_DEBUG
2562 #define PHP_DEBUG ZEND_DEBUG
2563@@ -436,6 +444,10 @@
2564 #endif
2565 #endif /* !XtOffsetOf */
2566
2567+#if HARDENING_PATCH
2568+#include "hardening_patch.h"
2569+#endif
2570+
2571 #endif
2572
2573 /*
2574diff -Naur php-4.3.11/main/php_variables.c hardening-patch-4.3.11-0.3.2/main/php_variables.c
2575--- php-4.3.11/main/php_variables.c 2004-10-18 17:08:46.000000000 +0200
2576+++ hardening-patch-4.3.11-0.3.2/main/php_variables.c 2005-07-09 08:53:02.488360376 +0200
2577@@ -211,17 +211,28 @@
2578 while (var) {
2579 val = strchr(var, '=');
2580 if (val) { /* have a value */
2581- int val_len;
2582+ unsigned int val_len, new_val_len;
2583
2584 *val++ = '\0';
2585 php_url_decode(var, strlen(var));
2586 val_len = php_url_decode(val, strlen(val));
2587- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
2588+ val = estrndup(val, val_len);
2589+ if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) {
2590+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
2591+ }
2592+ efree(val);
2593 }
2594 var = php_strtok_r(NULL, "&", &strtok_buf);
2595 }
2596 }
2597
2598+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter)
2599+{
2600+ /* TODO: check .ini setting here and apply user-defined input filter */
2601+ *new_val_len = val_len;
2602+ return 1;
2603+}
2604+
2605 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
2606 {
2607 char *res = NULL, *var, *val, *separator=NULL;
2608@@ -299,15 +310,26 @@
2609 while (var) {
2610 val = strchr(var, '=');
2611 if (val) { /* have a value */
2612- int val_len;
2613+ unsigned int val_len, new_val_len;
2614
2615 *val++ = '\0';
2616 php_url_decode(var, strlen(var));
2617 val_len = php_url_decode(val, strlen(val));
2618- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
2619+ val = estrndup(val, val_len);
2620+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
2621+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
2622+ }
2623+ efree(val);
2624 } else {
2625+ unsigned int val_len, new_val_len;
2626+
2627 php_url_decode(var, strlen(var));
2628- php_register_variable_safe(var, "", 0, array_ptr TSRMLS_CC);
2629+ val_len = 0;
2630+ val = estrndup("", 0);
2631+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
2632+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
2633+ }
2634+ efree(val);
2635 }
2636 var = php_strtok_r(NULL, separator, &strtok_buf);
2637 }
2638diff -Naur php-4.3.11/main/rfc1867.c hardening-patch-4.3.11-0.3.2/main/rfc1867.c
2639--- php-4.3.11/main/rfc1867.c 2005-02-15 01:28:39.000000000 +0100
2640+++ hardening-patch-4.3.11-0.3.2/main/rfc1867.c 2005-07-09 08:53:02.489360224 +0200
2641@@ -127,6 +127,7 @@
2642 #define UPLOAD_ERROR_C 3 /* Partially uploaded */
2643 #define UPLOAD_ERROR_D 4 /* No file uploaded */
2644 #define UPLOAD_ERROR_E 6 /* Missing /tmp or similar directory */
2645+#define UPLOAD_ERROR_F 7 /* Filter forbids upload */
2646
2647 void php_rfc1867_register_constants(TSRMLS_D)
2648 {
2649@@ -136,6 +137,7 @@
2650 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_PARTIAL", UPLOAD_ERROR_C, CONST_CS | CONST_PERSISTENT);
2651 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE", UPLOAD_ERROR_D, CONST_CS | CONST_PERSISTENT);
2652 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E, CONST_CS | CONST_PERSISTENT);
2653+ REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FILTER", UPLOAD_ERROR_F, CONST_CS | CONST_PERSISTENT);
2654 }
2655
2656 static void normalize_protected_variable(char *varname TSRMLS_DC)
2657@@ -844,6 +846,7 @@
2658 char buff[FILLUNIT];
2659 char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL;
2660 int blen=0, wlen=0;
2661+ unsigned long offset;
2662
2663 zend_llist_clean(&header);
2664
2665@@ -891,21 +894,24 @@
2666 if (!filename && param) {
2667
2668 char *value = multipart_buffer_read_body(mbuff TSRMLS_CC);
2669+ unsigned int new_val_len; /* Dummy variable */
2670
2671 if (!value) {
2672 value = estrdup("");
2673 }
2674
2675+ if (sapi_module.input_filter(PARSE_POST, param, &value, strlen(value), &new_val_len TSRMLS_CC)) {
2676 #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
2677- if (php_mb_encoding_translation(TSRMLS_C)) {
2678- php_mb_gpc_stack_variable(param, value, &val_list, &len_list,
2679- &num_vars, &num_vars_max TSRMLS_CC);
2680- } else {
2681- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2682- }
2683+ if (php_mb_encoding_translation(TSRMLS_C)) {
2684+ php_mb_gpc_stack_variable(param, value, &val_list, &len_list,
2685+ &num_vars, &num_vars_max TSRMLS_CC);
2686+ } else {
2687+ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2688+ }
2689 #else
2690- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2691+ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
2692 #endif
2693+ }
2694 if (!strcasecmp(param, "MAX_FILE_SIZE")) {
2695 max_file_size = atol(value);
2696 }
2697@@ -981,6 +987,11 @@
2698 cancel_upload = UPLOAD_ERROR_D;
2699 }
2700
2701+ if (sapi_module.pre_upload_filter && sapi_module.pre_upload_filter(param, filename TSRMLS_CC)==FAILURE) {
2702+ cancel_upload = UPLOAD_ERROR_F;
2703+ }
2704+
2705+ offset = 0;
2706 while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff) TSRMLS_CC)))
2707 {
2708 if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) {
2709@@ -990,6 +1001,11 @@
2710 sapi_module.sapi_error(E_WARNING, "MAX_FILE_SIZE of %ld bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename);
2711 cancel_upload = UPLOAD_ERROR_B;
2712 } else if (blen > 0) {
2713+
2714+ if (sapi_module.upload_content_filter && sapi_module.upload_content_filter(offset, buff, blen, &blen TSRMLS_CC)==FAILURE) {
2715+ cancel_upload = UPLOAD_ERROR_F;
2716+ }
2717+
2718 wlen = fwrite(buff, 1, blen, fp);
2719
2720 if (wlen < blen) {
2721@@ -997,6 +1013,7 @@
2722 cancel_upload = UPLOAD_ERROR_C;
2723 } else {
2724 total_bytes += wlen;
2725+ offset += wlen;
2726 }
2727 }
2728 }
2729@@ -1011,6 +1028,10 @@
2730 }
2731 #endif
2732
2733+ if (!cancel_upload && sapi_module.post_upload_filter && sapi_module.post_upload_filter(temp_filename TSRMLS_CC)==FAILURE) {
2734+ cancel_upload = UPLOAD_ERROR_F;
2735+ }
2736+
2737 if (cancel_upload) {
2738 if (temp_filename) {
2739 if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
2740diff -Naur php-4.3.11/main/SAPI.c hardening-patch-4.3.11-0.3.2/main/SAPI.c
2741--- php-4.3.11/main/SAPI.c 2005-02-22 15:46:24.000000000 +0100
2742+++ hardening-patch-4.3.11-0.3.2/main/SAPI.c 2005-07-09 08:53:02.490360072 +0200
2743@@ -831,6 +831,31 @@
2744 return SUCCESS;
2745 }
2746
2747+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
2748+{
2749+ sapi_module.input_filter = input_filter;
2750+ return SUCCESS;
2751+}
2752+
2753+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC))
2754+{
2755+ sapi_module.pre_upload_filter = pre_upload_filter;
2756+ return SUCCESS;
2757+}
2758+
2759+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC))
2760+{
2761+ sapi_module.upload_content_filter = upload_content_filter;
2762+ return SUCCESS;
2763+}
2764+
2765+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC))
2766+{
2767+ sapi_module.post_upload_filter = post_upload_filter;
2768+ return SUCCESS;
2769+}
2770+
2771+
2772
2773 SAPI_API int sapi_flush(TSRMLS_D)
2774 {
2775diff -Naur php-4.3.11/main/SAPI.h hardening-patch-4.3.11-0.3.2/main/SAPI.h
2776--- php-4.3.11/main/SAPI.h 2003-04-09 22:27:55.000000000 +0200
2777+++ hardening-patch-4.3.11-0.3.2/main/SAPI.h 2005-07-09 08:53:02.491359920 +0200
2778@@ -101,9 +101,10 @@
2779 char *current_user;
2780 int current_user_length;
2781
2782- /* this is necessary for CLI module */
2783- int argc;
2784- char **argv;
2785+ /* this is necessary for CLI module */
2786+ int argc;
2787+ char **argv;
2788+
2789 } sapi_request_info;
2790
2791
2792@@ -177,6 +178,10 @@
2793 SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry);
2794 SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D));
2795 SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC));
2796+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC));
2797+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC));
2798+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC));
2799+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC));
2800
2801 SAPI_API int sapi_flush(TSRMLS_D);
2802 SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
2803@@ -238,8 +243,15 @@
2804 int (*get_target_uid)(uid_t * TSRMLS_DC);
2805 int (*get_target_gid)(gid_t * TSRMLS_DC);
2806
2807+ unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
2808+
2809+ unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC);
2810+ unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC);
2811+ unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC);
2812+
2813 void (*ini_defaults)(HashTable *configuration_hash);
2814 int phpinfo_as_text;
2815+
2816 };
2817
2818
2819@@ -262,16 +274,26 @@
2820
2821 #define SAPI_DEFAULT_MIMETYPE "text/html"
2822 #define SAPI_DEFAULT_CHARSET ""
2823+
2824+#if HARDENING_PATCH
2825+#define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION " with Hardening-Patch"
2826+#else
2827 #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION
2828+#endif
2829
2830 #define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D)
2831 #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC)
2832
2833 #define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC)
2834+#define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
2835+#define SAPI_PRE_UPLOAD_FILTER_FUNC(pre_upload_filter) unsigned int pre_upload_filter(char *varname, char *filename TSRMLS_DC)
2836+#define SAPI_UPLOAD_CONTENT_FILTER_FUNC(upload_content_filter) unsigned int upload_content_filter(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC)
2837+#define SAPI_POST_UPLOAD_FILTER_FUNC(post_upload_filter) unsigned int post_upload_filter(char *tmpfilename TSRMLS_DC)
2838
2839 SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
2840 SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader);
2841 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data);
2842+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter);
2843
2844 #define STANDARD_SAPI_MODULE_PROPERTIES
2845
2846diff -Naur php-4.3.11/main/snprintf.c hardening-patch-4.3.11-0.3.2/main/snprintf.c
2847--- php-4.3.11/main/snprintf.c 2004-11-16 00:27:26.000000000 +0100
2848+++ hardening-patch-4.3.11-0.3.2/main/snprintf.c 2005-07-09 08:53:02.491359920 +0200
2849@@ -850,7 +850,11 @@
2850
2851
2852 case 'n':
2853+#if HARDENING_PATCH_FMT_PROTECT
2854+ php_security_log(S_MISC, "'n' specifier within format string");
2855+#else
2856 *(va_arg(ap, int *)) = cc;
2857+#endif
2858 break;
2859
2860 /*
2861diff -Naur php-4.3.11/main/spprintf.c hardening-patch-4.3.11-0.3.2/main/spprintf.c
2862--- php-4.3.11/main/spprintf.c 2003-09-29 03:09:36.000000000 +0200
2863+++ hardening-patch-4.3.11-0.3.2/main/spprintf.c 2005-07-09 08:53:02.492359768 +0200
2864@@ -531,7 +531,11 @@
2865
2866
2867 case 'n':
2868+#if HARDENING_PATCH_FMT_PROTECT
2869+ php_security_log(S_MISC, "'n' specifier within format string");
2870+#else
2871 *(va_arg(ap, int *)) = cc;
2872+#endif
2873 break;
2874
2875 /*
2876diff -Naur php-4.3.11/pear/go-pear-list.php hardening-patch-4.3.11-0.3.2/pear/go-pear-list.php
2877--- php-4.3.11/pear/go-pear-list.php 2005-03-18 02:58:20.000000000 +0100
2878+++ hardening-patch-4.3.11-0.3.2/pear/go-pear-list.php 2005-07-09 08:53:02.492359768 +0200
2879@@ -8,7 +8,7 @@
2880 $packages = array(
2881 // required packages for the installer
2882 "PEAR" => "1.3.5",
2883-"XML_RPC" => "1.2.2",
2884+"XML_RPC" => "1.3.1",
2885 "Console_Getopt" => "1.2",
2886 "Archive_Tar" => "1.3.1",
2887
2888diff -Naur php-4.3.11/pear/packages/XML_RPC-1.2.2.tar hardening-patch-4.3.11-0.3.2/pear/packages/XML_RPC-1.2.2.tar
2889--- php-4.3.11/pear/packages/XML_RPC-1.2.2.tar 2005-03-28 19:02:28.000000000 +0200
2890+++ hardening-patch-4.3.11-0.3.2/pear/packages/XML_RPC-1.2.2.tar 1970-01-01 01:00:00.000000000 +0100
2891@@ -1,3393 +0,0 @@
2892-package2.xml
2893-<package packagerversion="1.4.0a1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
2894- <name>XML_RPC</name>
2895- <channel>pear.php.net</channel>
2896- <summary>PHP implementation of the XML-RPC protocol</summary>
2897- <description>A PEAR-ified version of Useful Inc&apos;s XML-RPC for PHP.
2898-
2899-It has support for HTTP/HTTPS transport, proxies and authentication.</description>
2900- <lead>
2901- <name>Stig Bakken</name>
2902- <user>ssb</user>
2903- <email>stig@php.net</email>
2904- <active>no</active>
2905- </lead>
2906- <lead>
2907- <name>Daniel Convissor</name>
2908- <user>danielc</user>
2909- <email>danielc@php.net</email>
2910- <active>yes</active>
2911- </lead>
2912- <date>2005-03-07</date>
2913- <time>12:54:49</time>
2914- <version>
2915- <release>1.2.2</release>
2916- <api>1.2.0</api>
2917- </version>
2918- <stability>
2919- <release>stable</release>
2920- <api>stable</api>
2921- </stability>
2922- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2923- <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.</notes>
2924- <contents>
2925- <dir name="/">
2926- <file md5sum="9aca4434f486b517a75c7f2878fb1e9c" name="tests/protoport.php" role="test">
2927- <tasks:replace from="@package_version@" to="version" type="package-info" />
2928- </file>
2929- <file md5sum="49639b76a2296777a1dfa076ae41024a" name="tests/test_Dump.php" role="test">
2930- <tasks:replace from="@package_version@" to="version" type="package-info" />
2931- </file>
2932- <file baseinstalldir="XML/RPC" md5sum="2fb141b1f8927ef27ab0c222f2117d77" name="Dump.php" role="php">
2933- <tasks:replace from="@package_version@" to="version" type="package-info" />
2934- </file>
2935- <file baseinstalldir="XML" md5sum="fbfa3c674175786cc95893cc5192d910" name="RPC.php" role="php">
2936- <tasks:replace from="@package_version@" to="version" type="package-info" />
2937- </file>
2938- <file baseinstalldir="XML/RPC" md5sum="6fc2498def65f09d4ae535fa5f987f62" name="Server.php" role="php">
2939- <tasks:replace from="@package_version@" to="version" type="package-info" />
2940- </file>
2941- </dir>
2942- </contents>
2943- <compatible>
2944- <name>PEAR</name>
2945- <channel>pear.php.net</channel>
2946- <min>1.4.0a1</min>
2947- <max>1.4.0a4</max>
2948- </compatible>
2949- <dependencies>
2950- <required>
2951- <php>
2952- <min>4.2.0</min>
2953- <max>6.0.0</max>
2954- </php>
2955- <pearinstaller>
2956- <min>1.4.0a1</min>
2957- </pearinstaller>
2958- </required>
2959- </dependencies>
2960- <phprelease />
2961- <changelog>
2962- <release>
2963- <version>
2964- <release>1.2.1</release>
2965- <api>1.2.0</api>
2966- </version>
2967- <stability>
2968- <release>stable</release>
2969- <api>stable</api>
2970- </stability>
2971- <date>2005-03-01</date>
2972- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2973- <notes>* Add isset() check before examining the dispatch map. Bug 3658.</notes>
2974- </release>
2975- <release>
2976- <version>
2977- <release>1.2.0</release>
2978- <api>1.2.0</api>
2979- </version>
2980- <stability>
2981- <release>stable</release>
2982- <api>stable</api>
2983- </stability>
2984- <date>2005-02-27</date>
2985- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
2986- <notes>* Provide the &quot;stable&quot; release.
2987-* Add package2.xml for compatibility with PEAR 1.4.0.
2988-* For changes since 1.1.0, see the changelogs for the various RC releases.</notes>
2989- </release>
2990- <release>
2991- <version>
2992- <release>1.2.0RC7</release>
2993- <api>1.2.0RC7</api>
2994- </version>
2995- <stability>
2996- <release>beta</release>
2997- <api>beta</api>
2998- </stability>
2999- <date>2005-02-22</date>
3000- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3001- <notes>* Add the setSendEncoding() method and $send_encoding
3002- property to XML_RPC_Message. Request 3537.
3003-* Allow class methods to be mapped using either syntax:
3004- &apos;function&apos; =&gt; &apos;hello::sayHello&apos;,
3005- or
3006- &apos;function&apos; =&gt; array(&apos;hello&apos;, &apos;sayhello&apos;),
3007- Bug 3363.
3008-* Use 8192 instead of 32768 for bytes in fread()
3009- in parseResponseFile(). Bug 3340.</notes>
3010- </release>
3011- <release>
3012- <version>
3013- <release>1.2.0RC6</release>
3014- <api>1.2.0RC6</api>
3015- </version>
3016- <stability>
3017- <release>beta</release>
3018- <api>beta</api>
3019- </stability>
3020- <date>2005-01-25</date>
3021- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3022- <notes>* Don&apos;t put the protocol in the Host field of the POST data. (danielc)</notes>
3023- </release>
3024- <release>
3025- <version>
3026- <release>1.2.0RC5</release>
3027- <api>1.2.0RC5</api>
3028- </version>
3029- <stability>
3030- <release>beta</release>
3031- <api>beta</api>
3032- </stability>
3033- <date>2005-01-24</date>
3034- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3035- <notes>* If $port is 443 but a protocol isn&apos;t specified in $server, assume ssl:// is the protocol.</notes>
3036- </release>
3037- <release>
3038- <version>
3039- <release>1.2.0RC4</release>
3040- <api>1.2.0RC4</api>
3041- </version>
3042- <stability>
3043- <release>beta</release>
3044- <api>beta</api>
3045- </stability>
3046- <date>2005-01-24</date>
3047- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3048- <notes>* When a connection attempt fails, have the method return 0. (danielc)
3049-* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
3050-* Add tests for setting the client properties. (danielc)
3051-* Remove $GLOBALS[&apos;XML_RPC_twoslash&apos;] since it&apos;s not used. (danielc)
3052-* Bundle the tests with the package. (danielc)</notes>
3053- </release>
3054- <release>
3055- <version>
3056- <release>1.2.0RC3</release>
3057- <api>1.2.0RC3</api>
3058- </version>
3059- <stability>
3060- <release>beta</release>
3061- <api>beta</api>
3062- </stability>
3063- <date>2005-01-19</date>
3064- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3065- <notes>* ssl uses port 443, not 445.</notes>
3066- </release>
3067- <release>
3068- <version>
3069- <release>1.2.0RC2</release>
3070- <api>1.2.0RC2</api>
3071- </version>
3072- <stability>
3073- <release>beta</release>
3074- <api>beta</api>
3075- </stability>
3076- <date>2005-01-11</date>
3077- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3078- <notes>* Handle ssl:// in the $server string. (danielc)
3079-* Also default to port 445 for ssl:// requests as well. (danielc)
3080-* Enhance debugging in the server. (danielc)</notes>
3081- </release>
3082- <release>
3083- <version>
3084- <release>1.2.0RC1</release>
3085- <api>1.2.0RC1</api>
3086- </version>
3087- <stability>
3088- <release>beta</release>
3089- <api>beta</api>
3090- </stability>
3091- <date>2004-12-30</date>
3092- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3093- <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
3094-* Allow array function callbacks (Matt Kane)
3095-* Some minor speed-ups (Matt Kane)
3096-* Add Dump.php to the package (Christian Weiske)
3097-* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
3098-* Silence fsockopen() errors. Bug 1714. (danielc)
3099-* Encode empty arrays as an array. Bug 1493. (danielc)
3100-* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
3101-* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
3102-* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()&apos;ing error messages. (danielc)
3103-* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
3104-* Allow raiseError() to be called statically. (danielc)
3105-* Stop double escaping of character entities. Bug 987. (danielc)
3106- NOTICE: the following have been removed:
3107- * XML_RPC_dh()
3108- * $GLOBALS[&apos;XML_RPC_entities&apos;]
3109- * XML_RPC_entity_decode()
3110- * XML_RPC_lookup_entity()
3111-* Determine the XML&apos;s encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)</notes>
3112- </release>
3113- <release>
3114- <version>
3115- <release>1.1.0</release>
3116- <api>1.1.0</api>
3117- </version>
3118- <stability>
3119- <release>stable</release>
3120- <api>stable</api>
3121- </stability>
3122- <date>2004-03-15</date>
3123- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3124- <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
3125-* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
3126-* Remove &quot;require_once &apos;PEAR.php&apos;&quot;, include only when needed to raise an error
3127-* Replace echo and error_log() with raiseError() (mroch)
3128-* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
3129-* be tolerant of junk after methodResponse (Luca Mariano, mroch)
3130-* Silent notice even in the error log (pierre)
3131-* fix include of shared xml extension on win32 (pierre)</notes>
3132- </release>
3133- <release>
3134- <version>
3135- <release>1.0.4</release>
3136- <api>1.0.4</api>
3137- </version>
3138- <stability>
3139- <release>stable</release>
3140- <api>stable</api>
3141- </stability>
3142- <date>2002-10-02</date>
3143- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3144- <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)</notes>
3145- </release>
3146- <release>
3147- <version>
3148- <release>1.0.3</release>
3149- <api>1.0.3</api>
3150- </version>
3151- <stability>
3152- <release>stable</release>
3153- <api>stable</api>
3154- </stability>
3155- <date>2002-05-19</date>
3156- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3157- <notes>* fix bug when parsing responses with boolean types</notes>
3158- </release>
3159- <release>
3160- <version>
3161- <release>1.0.2</release>
3162- <api>1.0.2</api>
3163- </version>
3164- <stability>
3165- <release>stable</release>
3166- <api>stable</api>
3167- </stability>
3168- <date>2002-04-16</date>
3169- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3170- <notes>* E_ALL fixes
3171-* fix HTTP response header parsing</notes>
3172- </release>
3173- <release>
3174- <version>
3175- <release>1.0.1</release>
3176- <api>1.0.1</api>
3177- </version>
3178- <stability>
3179- <release>stable</release>
3180- <api>stable</api>
3181- </stability>
3182- <date>2001-09-25</date>
3183- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
3184- <notes>This is a PEAR-ified version of Useful Inc&apos;s 1.0.1 release.
3185-Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.</notes>
3186- </release>
3187- </changelog>
3188-</package>
3189-
3190-/**
3191- * Tests that properties of XML_RPC_Client get properly set
3192- *
3193- * Any individual tests that fail will have their name, expected result
3194- * and actual result printed out. So seeing no output when executing
3195- * this file is a good thing.
3196- *
3197- * Can be run via CLI or a web server.
3198- *
3199- * PHP versions 4 and 5
3200- *
3201- * LICENSE: This source file is subject to version 3.0 of the PHP license
3202- * that is available through the world-wide-web at the following URI:
3203- * http://www.php.net/license/3_0.txt. If you did not receive a copy of
3204- * the PHP License and are unable to obtain it through the web, please
3205- * send a note to license@php.net so we can mail you a copy immediately.
3206- *
3207- * @category Web Services
3208- * @package XML_RPC
3209- * @author Daniel Convissor <danielc@php.net>
3210- * @copyright 2005 The PHP Group
3211- * @license http://www.php.net/license/3_0.txt PHP License
3212- * @version CVS: $Id: protoport.php,v 1.4 2005/01/24 17:48:47 danielc Exp $
3213- * @link http://pear.php.net/package/XML_RPC
3214- * @since File available since Release 1.2
3215- */
3216-
3217-/*
3218- * If the package version number is found in the left hand
3219- * portion of the if() expression below, that means this file has
3220- * come from the PEAR installer. Therefore, let's test the
3221- * installed version of XML_RPC which should be in the include path.
3222- *
3223- * If the version has not been substituted in the if() expression,
3224- * this file has likely come from a CVS checkout or a .tar file.
3225- * Therefore, we'll assume the tests should use the version of
3226- * XML_RPC that has come from there as well.
3227- */
3228-if ('1.2.2' != '@'.'package_version'.'@') {
3229- /**
3230- * Get the needed class from the PEAR installation
3231- */
3232- require_once 'XML/RPC.php';
3233-} else {
3234- /**
3235- * Get the needed class from the parent directory
3236- */
3237- require_once '../RPC.php';
3238-}
3239-
3240-/**
3241- * Compare the test result to the expected result
3242- *
3243- * If the test fails, echo out the results.
3244- *
3245- * @param array $expect the array of object properties you expect
3246- * from the test
3247- * @param object $actual the object results from the test
3248- * @param string $test_name the name of the test
3249- *
3250- * @return void
3251- */
3252-function compare($expect, $actual, $test_name) {
3253- $actual = get_object_vars($actual);
3254- if (count(array_diff($actual, $expect))) {
3255- echo "$test_name failed.\nExpect: ";
3256- print_r($expect);
3257- echo "Actual: ";
3258- print_r($actual);
3259- echo "\n";
3260- }
3261-}
3262-
3263-if (php_sapi_name() != 'cli') {
3264- echo "<pre>\n";
3265-}
3266-
3267-
3268-$x = array(
3269- 'path' => 'thepath',
3270- 'server' => 'theserver',
3271- 'protocol' => 'http://',
3272- 'port' => 80,
3273- 'proxy' => '',
3274- 'proxy_protocol' => 'http://',
3275- 'proxy_port' => 8080,
3276- 'proxy_user' => '',
3277- 'proxy_pass' => '',
3278- 'errno' => 0,
3279- 'errstring' => '',
3280- 'debug' => 0,
3281- 'username' => '',
3282- 'password' => '',
3283-);
3284-$c = new XML_RPC_Client('thepath', 'theserver');
3285-compare($x, $c, 'defaults');
3286-
3287-$x = array(
3288- 'path' => 'thepath',
3289- 'server' => 'theserver',
3290- 'protocol' => 'http://',
3291- 'port' => 80,
3292- 'proxy' => '',
3293- 'proxy_protocol' => 'http://',
3294- 'proxy_port' => 8080,
3295- 'proxy_user' => '',
3296- 'proxy_pass' => '',
3297- 'errno' => 0,
3298- 'errstring' => '',
3299- 'debug' => 0,
3300- 'username' => '',
3301- 'password' => '',
3302-);
3303-$c = new XML_RPC_Client('thepath', 'http://theserver');
3304-compare($x, $c, 'defaults with http');
3305-
3306-$x = array(
3307- 'path' => 'thepath',
3308- 'server' => 'theserver',
3309- 'protocol' => 'ssl://',
3310- 'port' => 443,
3311- 'proxy' => '',
3312- 'proxy_protocol' => 'http://',
3313- 'proxy_port' => 8080,
3314- 'proxy_user' => '',
3315- 'proxy_pass' => '',
3316- 'errno' => 0,
3317- 'errstring' => '',
3318- 'debug' => 0,
3319- 'username' => '',
3320- 'password' => '',
3321-);
3322-$c = new XML_RPC_Client('thepath', 'https://theserver');
3323-compare($x, $c, 'defaults with https');
3324-
3325-$x = array(
3326- 'path' => 'thepath',
3327- 'server' => 'theserver',
3328- 'protocol' => 'ssl://',
3329- 'port' => 443,
3330- 'proxy' => '',
3331- 'proxy_protocol' => 'http://',
3332- 'proxy_port' => 8080,
3333- 'proxy_user' => '',
3334- 'proxy_pass' => '',
3335- 'errno' => 0,
3336- 'errstring' => '',
3337- 'debug' => 0,
3338- 'username' => '',
3339- 'password' => '',
3340-);
3341-$c = new XML_RPC_Client('thepath', 'ssl://theserver');
3342-compare($x, $c, 'defaults with ssl');
3343-
3344-
3345-$x = array(
3346- 'path' => 'thepath',
3347- 'server' => 'theserver',
3348- 'protocol' => 'http://',
3349- 'port' => 65,
3350- 'proxy' => '',
3351- 'proxy_protocol' => 'http://',
3352- 'proxy_port' => 8080,
3353- 'proxy_user' => '',
3354- 'proxy_pass' => '',
3355- 'errno' => 0,
3356- 'errstring' => '',
3357- 'debug' => 0,
3358- 'username' => '',
3359- 'password' => '',
3360-);
3361-$c = new XML_RPC_Client('thepath', 'theserver', 65);
3362-compare($x, $c, 'port 65');
3363-
3364-$x = array(
3365- 'path' => 'thepath',
3366- 'server' => 'theserver',
3367- 'protocol' => 'http://',
3368- 'port' => 65,
3369- 'proxy' => '',
3370- 'proxy_protocol' => 'http://',
3371- 'proxy_port' => 8080,
3372- 'proxy_user' => '',
3373- 'proxy_pass' => '',
3374- 'errno' => 0,
3375- 'errstring' => '',
3376- 'debug' => 0,
3377- 'username' => '',
3378- 'password' => '',
3379-);
3380-$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
3381-compare($x, $c, 'port 65 with http');
3382-
3383-$x = array(
3384- 'path' => 'thepath',
3385- 'server' => 'theserver',
3386- 'protocol' => 'ssl://',
3387- 'port' => 65,
3388- 'proxy' => '',
3389- 'proxy_protocol' => 'http://',
3390- 'proxy_port' => 8080,
3391- 'proxy_user' => '',
3392- 'proxy_pass' => '',
3393- 'errno' => 0,
3394- 'errstring' => '',
3395- 'debug' => 0,
3396- 'username' => '',
3397- 'password' => '',
3398-);
3399-$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
3400-compare($x, $c, 'port 65 with https');
3401-
3402-$x = array(
3403- 'path' => 'thepath',
3404- 'server' => 'theserver',
3405- 'protocol' => 'ssl://',
3406- 'port' => 65,
3407- 'proxy' => '',
3408- 'proxy_protocol' => 'http://',
3409- 'proxy_port' => 8080,
3410- 'proxy_user' => '',
3411- 'proxy_pass' => '',
3412- 'errno' => 0,
3413- 'errstring' => '',
3414- 'debug' => 0,
3415- 'username' => '',
3416- 'password' => '',
3417-);
3418-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
3419-compare($x, $c, 'port 65 with ssl');
3420-
3421-
3422-$x = array(
3423- 'path' => 'thepath',
3424- 'server' => 'theserver',
3425- 'protocol' => 'http://',
3426- 'port' => 80,
3427- 'proxy' => 'theproxy',
3428- 'proxy_protocol' => 'http://',
3429- 'proxy_port' => 8080,
3430- 'proxy_user' => '',
3431- 'proxy_pass' => '',
3432- 'errno' => 0,
3433- 'errstring' => '',
3434- 'debug' => 0,
3435- 'username' => '',
3436- 'password' => '',
3437-);
3438-$c = new XML_RPC_Client('thepath', 'theserver', 0,
3439- 'theproxy');
3440-compare($x, $c, 'defaults proxy');
3441-
3442-$x = array(
3443- 'path' => 'thepath',
3444- 'server' => 'theserver',
3445- 'protocol' => 'http://',
3446- 'port' => 80,
3447- 'proxy' => 'theproxy',
3448- 'proxy_protocol' => 'http://',
3449- 'proxy_port' => 8080,
3450- 'proxy_user' => '',
3451- 'proxy_pass' => '',
3452- 'errno' => 0,
3453- 'errstring' => '',
3454- 'debug' => 0,
3455- 'username' => '',
3456- 'password' => '',
3457-);
3458-$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
3459- 'http://theproxy');
3460-compare($x, $c, 'defaults with http proxy');
3461-
3462-$x = array(
3463- 'path' => 'thepath',
3464- 'server' => 'theserver',
3465- 'protocol' => 'ssl://',
3466- 'port' => 443,
3467- 'proxy' => 'theproxy',
3468- 'proxy_protocol' => 'ssl://',
3469- 'proxy_port' => 443,
3470- 'proxy_user' => '',
3471- 'proxy_pass' => '',
3472- 'errno' => 0,
3473- 'errstring' => '',
3474- 'debug' => 0,
3475- 'username' => '',
3476- 'password' => '',
3477-);
3478-$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
3479- 'https://theproxy');
3480-compare($x, $c, 'defaults with https proxy');
3481-
3482-$x = array(
3483- 'path' => 'thepath',
3484- 'server' => 'theserver',
3485- 'protocol' => 'ssl://',
3486- 'port' => 443,
3487- 'proxy' => 'theproxy',
3488- 'proxy_protocol' => 'ssl://',
3489- 'proxy_port' => 443,
3490- 'proxy_user' => '',
3491- 'proxy_pass' => '',
3492- 'errno' => 0,
3493- 'errstring' => '',
3494- 'debug' => 0,
3495- 'username' => '',
3496- 'password' => '',
3497-);
3498-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
3499- 'ssl://theproxy');
3500-compare($x, $c, 'defaults with ssl proxy');
3501-
3502-
3503-$x = array(
3504- 'path' => 'thepath',
3505- 'server' => 'theserver',
3506- 'protocol' => 'http://',
3507- 'port' => 65,
3508- 'proxy' => 'theproxy',
3509- 'proxy_protocol' => 'http://',
3510- 'proxy_port' => 6565,
3511- 'proxy_user' => '',
3512- 'proxy_pass' => '',
3513- 'errno' => 0,
3514- 'errstring' => '',
3515- 'debug' => 0,
3516- 'username' => '',
3517- 'password' => '',
3518-);
3519-$c = new XML_RPC_Client('thepath', 'theserver', 65,
3520- 'theproxy', 6565);
3521-compare($x, $c, 'port 65 proxy 6565');
3522-
3523-$x = array(
3524- 'path' => 'thepath',
3525- 'server' => 'theserver',
3526- 'protocol' => 'http://',
3527- 'port' => 65,
3528- 'proxy' => 'theproxy',
3529- 'proxy_protocol' => 'http://',
3530- 'proxy_port' => 6565,
3531- 'proxy_user' => '',
3532- 'proxy_pass' => '',
3533- 'errno' => 0,
3534- 'errstring' => '',
3535- 'debug' => 0,
3536- 'username' => '',
3537- 'password' => '',
3538-);
3539-$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
3540- 'http://theproxy', 6565);
3541-compare($x, $c, 'port 65 with http proxy 6565');
3542-
3543-$x = array(
3544- 'path' => 'thepath',
3545- 'server' => 'theserver',
3546- 'protocol' => 'ssl://',
3547- 'port' => 65,
3548- 'proxy' => 'theproxy',
3549- 'proxy_protocol' => 'ssl://',
3550- 'proxy_port' => 6565,
3551- 'proxy_user' => '',
3552- 'proxy_pass' => '',
3553- 'errno' => 0,
3554- 'errstring' => '',
3555- 'debug' => 0,
3556- 'username' => '',
3557- 'password' => '',
3558-);
3559-$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
3560- 'https://theproxy', 6565);
3561-compare($x, $c, 'port 65 with https proxy 6565');
3562-
3563-$x = array(
3564- 'path' => 'thepath',
3565- 'server' => 'theserver',
3566- 'protocol' => 'ssl://',
3567- 'port' => 65,
3568- 'proxy' => 'theproxy',
3569- 'proxy_protocol' => 'ssl://',
3570- 'proxy_port' => 6565,
3571- 'proxy_user' => '',
3572- 'proxy_pass' => '',
3573- 'errno' => 0,
3574- 'errstring' => '',
3575- 'debug' => 0,
3576- 'username' => '',
3577- 'password' => '',
3578-);
3579-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
3580- 'ssl://theproxy', 6565);
3581-compare($x, $c, 'port 65 with ssl proxy 6565');
3582-
3583-
3584-$x = array(
3585- 'path' => 'thepath',
3586- 'server' => 'theserver',
3587- 'protocol' => 'ssl://',
3588- 'port' => 443,
3589- 'proxy' => 'theproxy',
3590- 'proxy_protocol' => 'ssl://',
3591- 'proxy_port' => 443,
3592- 'proxy_user' => '',
3593- 'proxy_pass' => '',
3594- 'errno' => 0,
3595- 'errstring' => '',
3596- 'debug' => 0,
3597- 'username' => '',
3598- 'password' => '',
3599-);
3600-$c = new XML_RPC_Client('thepath', 'theserver', 443,
3601- 'theproxy', 443);
3602-compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
3603-
3604-$x = array(
3605- 'path' => 'thepath',
3606- 'server' => 'theserver',
3607- 'protocol' => 'http://',
3608- 'port' => 80,
3609- 'proxy' => 'theproxy',
3610- 'proxy_protocol' => 'ssl://',
3611- 'proxy_port' => 6565,
3612- 'proxy_user' => '',
3613- 'proxy_pass' => '',
3614- 'errno' => 0,
3615- 'errstring' => '',
3616- 'debug' => 0,
3617- 'username' => '',
3618- 'password' => '',
3619-);
3620-$c = new XML_RPC_Client('thepath', 'theserver', 0,
3621- 'ssl://theproxy', 6565);
3622-compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
3623-
3624-
3625-/*
3626- * If the package version number is found in the left hand
3627- * portion of the if() expression below, that means this file has
3628- * come from the PEAR installer. Therefore, let's test the
3629- * installed version of XML_RPC which should be in the include path.
3630- *
3631- * If the version has not been substituted in the if() expression,
3632- * this file has likely come from a CVS checkout or a .tar file.
3633- * Therefore, we'll assume the tests should use the version of
3634- * XML_RPC that has come from there as well.
3635- */
3636-if ('1.2.2' != '@'.'package_version'.'@') {
3637- /**
3638- * Get the needed class from the PEAR installation
3639- */
3640- require_once 'XML/RPC/Dump.php';
3641-} else {
3642- /**
3643- * Get the needed class from the parent directory
3644- */
3645- require_once '../Dump.php';
3646-}
3647-
3648-$val = new XML_RPC_Value(array(
3649- 'title' =>new XML_RPC_Value('das ist der Titel', 'string'),
3650- 'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
3651- 'endDate' =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
3652- 'error' =>'string',
3653- 'arkey' => new XML_RPC_Value( array(
3654- new XML_RPC_Value('simple string'),
3655- new XML_RPC_Value(12345, 'int')
3656- ), 'array')
3657- )
3658- ,'struct');
3659-
3660-XML_RPC_Dump($val);
3661-
3662-echo '==============' . "\r\n";
3663-$val2 = new XML_RPC_Value(44353, 'int');
3664-XML_RPC_Dump($val2);
3665-
3666-echo '==============' . "\r\n";
3667-$val3 = new XML_RPC_Value('this should be a string', 'string');
3668-XML_RPC_Dump($val3);
3669-
3670-echo '==============' . "\r\n";
3671-$val4 = new XML_RPC_Value(true, 'boolean');
3672-XML_RPC_Dump($val4);
3673-
3674-
3675-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3676-
3677-/**
3678- * Function and class to dump XML_RPC_Value objects in a nice way
3679- *
3680- * Should be helpful as a normal var_dump(..) displays all internals which
3681- * doesn't really give you an overview due to too much information.
3682- *
3683- * @category Web Services
3684- * @package XML_RPC
3685- * @author Christian Weiske <cweiske@php.net>
3686- * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $
3687- * @link http://pear.php.net/package/XML_RPC
3688- */
3689-
3690-
3691-/**
3692- * Pull in the XML_RPC class
3693- */
3694-require_once 'XML/RPC.php';
3695-
3696-
3697-/**
3698- * Generates the dump of the XML_RPC_Value and echoes it
3699- *
3700- * @param object $value the XML_RPC_Value object to dump
3701- *
3702- * @return void
3703- */
3704-function XML_RPC_Dump($value)
3705-{
3706- $dumper = new XML_RPC_Dump();
3707- echo $dumper->generateDump($value);
3708-}
3709-
3710-
3711-/**
3712- * Class which generates a dump of a XML_RPC_Value object
3713- *
3714- * @category Web Services
3715- * @package XML_RPC
3716- * @author Christian Weiske <cweiske@php.net>
3717- * @version Release: 1.2.2
3718- * @link http://pear.php.net/package/XML_RPC
3719- */
3720-class XML_RPC_Dump
3721-{
3722- /**
3723- * The indentation array cache
3724- * @var array
3725- */
3726- var $arIndent = array();
3727-
3728- /**
3729- * The spaces used for indenting the XML
3730- * @var string
3731- */
3732- var $strBaseIndent = ' ';
3733-
3734- /**
3735- * Returns the dump in XML format without printing it out
3736- *
3737- * @param object $value the XML_RPC_Value object to dump
3738- * @param int $nLevel the level of indentation
3739- *
3740- * @return string the dump
3741- */
3742- function generateDump($value, $nLevel = 0)
3743- {
3744- if (!is_object($value) && get_class($value) != 'xml_rpc_value') {
3745- require_once 'PEAR.php';
3746- PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n",
3747- 0, PEAR_ERROR_PRINT);
3748- if (is_object($value)) {
3749- $strType = get_class($value);
3750- } else {
3751- $strType = gettype($value);
3752- }
3753- return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: '
3754- . $strType . "\r\n";
3755- }
3756-
3757- switch ($value->kindOf()) {
3758- case 'struct':
3759- $ret = $this->genStruct($value, $nLevel);
3760- break;
3761- case 'array':
3762- $ret = $this->genArray($value, $nLevel);
3763- break;
3764- case 'scalar':
3765- $ret = $this->genScalar($value->scalarval(), $nLevel);
3766- break;
3767- default:
3768- require_once 'PEAR.php';
3769- PEAR::raiseError('Illegal type "' . $value->kindOf()
3770- . '" in XML_RPC_Value' . "\r\n", 0,
3771- PEAR_ERROR_PRINT);
3772- }
3773-
3774- return $ret;
3775- }
3776-
3777- /**
3778- * Returns the scalar value dump
3779- *
3780- * @param object $value the scalar XML_RPC_Value object to dump
3781- * @param int $nLevel the level of indentation
3782- *
3783- * @return string Dumped version of the scalar value
3784- */
3785- function genScalar($value, $nLevel)
3786- {
3787- if (gettype($value) == 'object') {
3788- $strClass = ' ' . get_class($value);
3789- } else {
3790- $strClass = '';
3791- }
3792- return $this->getIndent($nLevel) . gettype($value) . $strClass
3793- . ' ' . $value . "\r\n";
3794- }
3795-
3796- /**
3797- * Returns the dump of a struct
3798- *
3799- * @param object $value the struct XML_RPC_Value object to dump
3800- * @param int $nLevel the level of indentation
3801- *
3802- * @return string Dumped version of the scalar value
3803- */
3804- function genStruct($value, $nLevel)
3805- {
3806- $value->structreset();
3807- $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n";
3808- while (list($key, $keyval) = $value->structeach()) {
3809- $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n";
3810- $strOutput .= $this->generateDump($keyval, $nLevel + 2);
3811- }
3812- return $strOutput;
3813- }
3814-
3815- /**
3816- * Returns the dump of an array
3817- *
3818- * @param object $value the array XML_RPC_Value object to dump
3819- * @param int $nLevel the level of indentation
3820- *
3821- * @return string Dumped version of the scalar value
3822- */
3823- function genArray($value, $nLevel)
3824- {
3825- $nSize = $value->arraysize();
3826- $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n";
3827- for($nA = 0; $nA < $nSize; $nA++) {
3828- $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n";
3829- $strOutput .= $this->generateDump($value->arraymem($nA),
3830- $nLevel + 2);
3831- }
3832- return $strOutput;
3833- }
3834-
3835- /**
3836- * Returns the indent for a specific level and caches it for faster use
3837- *
3838- * @param int $nLevel the level
3839- *
3840- * @return string the indented string
3841- */
3842- function getIndent($nLevel)
3843- {
3844- if (!isset($this->arIndent[$nLevel])) {
3845- $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel);
3846- }
3847- return $this->arIndent[$nLevel];
3848- }
3849-}
3850-
3851-/*
3852- * Local variables:
3853- * tab-width: 4
3854- * c-basic-offset: 4
3855- * c-hanging-comment-ender-p: nil
3856- * End:
3857- */
3858-
3859-?>
3860-
3861-
3862-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3863-
3864-/**
3865- * PHP implementation of the XML-RPC protocol
3866- *
3867- * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
3868- * It has support for HTTP transport, proxies and authentication.
3869- *
3870- * PHP versions 4 and 5
3871- *
3872- * LICENSE: License is granted to use or modify this software
3873- * ("XML-RPC for PHP") for commercial or non-commercial use provided the
3874- * copyright of the author is preserved in any distributed or derivative work.
3875- *
3876- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
3877- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3878- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3879- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3880- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3881- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3882- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3883- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3884- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3885- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3886- *
3887- * @category Web Services
3888- * @package XML_RPC
3889- * @author Edd Dumbill <edd@usefulinc.com>
3890- * @author Stig Bakken <stig@php.net>
3891- * @author Martin Jansen <mj@php.net>
3892- * @author Daniel Convissor <danielc@php.net>
3893- * @copyright 1999-2001 Edd Dumbill
3894- * @version CVS: $Id: RPC.php,v 1.60 2005/03/07 17:45:08 danielc Exp $
3895- * @link http://pear.php.net/package/XML_RPC
3896- */
3897-
3898-
3899-if (!function_exists('xml_parser_create')) {
3900- // Win 32 fix. From: "Leo West" <lwest@imaginet.fr>
3901- if ($WINDIR) {
3902- dl('php_xml.dll');
3903- } else {
3904- dl('xml.so');
3905- }
3906-}
3907-
3908-/**#@+
3909- * Error constants
3910- */
3911-define('XML_RPC_ERROR_INVALID_TYPE', 101);
3912-define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
3913-define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
3914-define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
3915-/**#@-*/
3916-
3917-
3918-/**
3919- * Data types
3920- * @global string $GLOBALS['XML_RPC_I4']
3921- */
3922-$GLOBALS['XML_RPC_I4'] = 'i4';
3923-
3924-/**
3925- * Data types
3926- * @global string $GLOBALS['XML_RPC_Int']
3927- */
3928-$GLOBALS['XML_RPC_Int'] = 'int';
3929-
3930-/**
3931- * Data types
3932- * @global string $GLOBALS['XML_RPC_Boolean']
3933- */
3934-$GLOBALS['XML_RPC_Boolean'] = 'boolean';
3935-
3936-/**
3937- * Data types
3938- * @global string $GLOBALS['XML_RPC_Double']
3939- */
3940-$GLOBALS['XML_RPC_Double'] = 'double';
3941-
3942-/**
3943- * Data types
3944- * @global string $GLOBALS['XML_RPC_String']
3945- */
3946-$GLOBALS['XML_RPC_String'] = 'string';
3947-
3948-/**
3949- * Data types
3950- * @global string $GLOBALS['XML_RPC_DateTime']
3951- */
3952-$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601';
3953-
3954-/**
3955- * Data types
3956- * @global string $GLOBALS['XML_RPC_Base64']
3957- */
3958-$GLOBALS['XML_RPC_Base64'] = 'base64';
3959-
3960-/**
3961- * Data types
3962- * @global string $GLOBALS['XML_RPC_Array']
3963- */
3964-$GLOBALS['XML_RPC_Array'] = 'array';
3965-
3966-/**
3967- * Data types
3968- * @global string $GLOBALS['XML_RPC_Struct']
3969- */
3970-$GLOBALS['XML_RPC_Struct'] = 'struct';
3971-
3972-
3973-/**
3974- * Data type meta-types
3975- * @global array $GLOBALS['XML_RPC_Types']
3976- */
3977-$GLOBALS['XML_RPC_Types'] = array(
3978- $GLOBALS['XML_RPC_I4'] => 1,
3979- $GLOBALS['XML_RPC_Int'] => 1,
3980- $GLOBALS['XML_RPC_Boolean'] => 1,
3981- $GLOBALS['XML_RPC_String'] => 1,
3982- $GLOBALS['XML_RPC_Double'] => 1,
3983- $GLOBALS['XML_RPC_DateTime'] => 1,
3984- $GLOBALS['XML_RPC_Base64'] => 1,
3985- $GLOBALS['XML_RPC_Array'] => 2,
3986- $GLOBALS['XML_RPC_Struct'] => 3,
3987-);
3988-
3989-
3990-/**
3991- * Error message numbers
3992- * @global array $GLOBALS['XML_RPC_err']
3993- */
3994-$GLOBALS['XML_RPC_err'] = array(
3995- 'unknown_method' => 1,
3996- 'invalid_return' => 2,
3997- 'incorrect_params' => 3,
3998- 'introspect_unknown' => 4,
3999- 'http_error' => 5,
4000-);
4001-
4002-/**
4003- * Error message strings
4004- * @global array $GLOBALS['XML_RPC_str']
4005- */
4006-$GLOBALS['XML_RPC_str'] = array(
4007- 'unknown_method' => 'Unknown method',
4008- 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload',
4009- 'incorrect_params' => 'Incorrect parameters passed to method',
4010- 'introspect_unknown' => 'Can\'t introspect: method unknown',
4011- 'http_error' => 'Didn\'t receive 200 OK from remote server.',
4012-);
4013-
4014-
4015-/**
4016- * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII)
4017- * @global string $GLOBALS['XML_RPC_defencoding']
4018- */
4019-$GLOBALS['XML_RPC_defencoding'] = 'UTF-8';
4020-
4021-/**
4022- * User error codes start at 800
4023- * @global int $GLOBALS['XML_RPC_erruser']
4024- */
4025-$GLOBALS['XML_RPC_erruser'] = 800;
4026-
4027-/**
4028- * XML parse error codes start at 100
4029- * @global int $GLOBALS['XML_RPC_errxml']
4030- */
4031-$GLOBALS['XML_RPC_errxml'] = 100;
4032-
4033-
4034-/**
4035- * Compose backslashes for escaping regexp
4036- * @global string $GLOBALS['XML_RPC_backslash']
4037- */
4038-$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92);
4039-
4040-
4041-/**
4042- * Stores state during parsing
4043- *
4044- * quick explanation of components:
4045- * + st = builds up a string for evaluation
4046- * + ac = accumulates values
4047- * + qt = decides if quotes are needed for evaluation
4048- * + cm = denotes struct or array (comma needed)
4049- * + isf = indicates a fault
4050- * + lv = indicates "looking for a value": implements the logic
4051- * to allow values with no types to be strings
4052- * + params = stores parameters in method calls
4053- * + method = stores method name
4054- *
4055- * @global array $GLOBALS['XML_RPC_xh']
4056- */
4057-$GLOBALS['XML_RPC_xh'] = array();
4058-
4059-
4060-/**
4061- * Start element handler for the XML parser
4062- *
4063- * @return void
4064- */
4065-function XML_RPC_se($parser, $name, $attrs)
4066-{
4067- global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String;
4068-
4069- switch ($name) {
4070- case 'STRUCT':
4071- case 'ARRAY':
4072- $XML_RPC_xh[$parser]['st'] .= 'array(';
4073- $XML_RPC_xh[$parser]['cm']++;
4074- // this last line turns quoting off
4075- // this means if we get an empty array we'll
4076- // simply get a bit of whitespace in the eval
4077- $XML_RPC_xh[$parser]['qt'] = 0;
4078- break;
4079-
4080- case 'NAME':
4081- $XML_RPC_xh[$parser]['st'] .= "'";
4082- $XML_RPC_xh[$parser]['ac'] = '';
4083- break;
4084-
4085- case 'FAULT':
4086- $XML_RPC_xh[$parser]['isf'] = 1;
4087- break;
4088-
4089- case 'PARAM':
4090- $XML_RPC_xh[$parser]['st'] = '';
4091- break;
4092-
4093- case 'VALUE':
4094- $XML_RPC_xh[$parser]['st'] .= 'new XML_RPC_Value(';
4095- $XML_RPC_xh[$parser]['lv'] = 1;
4096- $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String;
4097- $XML_RPC_xh[$parser]['ac'] = '';
4098- $XML_RPC_xh[$parser]['qt'] = 0;
4099- // look for a value: if this is still 1 by the
4100- // time we reach the first data segment then the type is string
4101- // by implication and we need to add in a quote
4102- break;
4103-
4104- case 'I4':
4105- case 'INT':
4106- case 'STRING':
4107- case 'BOOLEAN':
4108- case 'DOUBLE':
4109- case 'DATETIME.ISO8601':
4110- case 'BASE64':
4111- $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator
4112-
4113- if ($name == 'DATETIME.ISO8601' || $name == 'STRING') {
4114- $XML_RPC_xh[$parser]['qt'] = 1;
4115-
4116- if ($name == 'DATETIME.ISO8601') {
4117- $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime;
4118- }
4119-
4120- } elseif ($name == 'BASE64') {
4121- $XML_RPC_xh[$parser]['qt'] = 2;
4122- } else {
4123- // No quoting is required here -- but
4124- // at the end of the element we must check
4125- // for data format errors.
4126- $XML_RPC_xh[$parser]['qt'] = 0;
4127- }
4128- break;
4129-
4130- case 'MEMBER':
4131- $XML_RPC_xh[$parser]['ac'] = '';
4132- }
4133-
4134- if ($name != 'VALUE') {
4135- $XML_RPC_xh[$parser]['lv'] = 0;
4136- }
4137-}
4138-
4139-/**
4140- * End element handler for the XML parser
4141- *
4142- * @return void
4143- */
4144-function XML_RPC_ee($parser, $name)
4145-{
4146- global $XML_RPC_xh, $XML_RPC_Types, $XML_RPC_String;
4147-
4148- switch ($name) {
4149- case 'STRUCT':
4150- case 'ARRAY':
4151- if ($XML_RPC_xh[$parser]['cm']
4152- && substr($XML_RPC_xh[$parser]['st'], -1) == ',')
4153- {
4154- $XML_RPC_xh[$parser]['st'] = substr($XML_RPC_xh[$parser]['st'], 0, -1);
4155- }
4156-
4157- $XML_RPC_xh[$parser]['st'] .= ')';
4158- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4159- $XML_RPC_xh[$parser]['cm']--;
4160- break;
4161-
4162- case 'NAME':
4163- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . "' => ";
4164- break;
4165-
4166- case 'BOOLEAN':
4167- // special case here: we translate boolean 1 or 0 into PHP
4168- // constants true or false
4169- if ($XML_RPC_xh[$parser]['ac'] == '1') {
4170- $XML_RPC_xh[$parser]['ac'] = 'true';
4171- } else {
4172- $XML_RPC_xh[$parser]['ac'] = 'false';
4173- }
4174-
4175- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4176- // Drop through intentionally.
4177-
4178- case 'I4':
4179- case 'INT':
4180- case 'STRING':
4181- case 'DOUBLE':
4182- case 'DATETIME.ISO8601':
4183- case 'BASE64':
4184- if ($XML_RPC_xh[$parser]['qt'] == 1) {
4185- // we use double quotes rather than single so backslashification works OK
4186- $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
4187- } elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
4188- $XML_RPC_xh[$parser]['st'] .= "base64_decode('"
4189- . $XML_RPC_xh[$parser]['ac'] . "')";
4190- } elseif ($name == 'BOOLEAN') {
4191- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
4192- } else {
4193- // we have an I4, INT or a DOUBLE
4194- // we must check that only 0123456789-.<space> are characters here
4195- if (!ereg("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) {
4196- XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE',
4197- XML_RPC_ERROR_NON_NUMERIC_FOUND);
4198- $XML_RPC_xh[$parser]['st'] .= 'XML_RPC_ERROR_NON_NUMERIC_FOUND';
4199- } else {
4200- // it's ok, add it on
4201- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
4202- }
4203- }
4204-
4205- $XML_RPC_xh[$parser]['ac'] = '';
4206- $XML_RPC_xh[$parser]['qt'] = 0;
4207- $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value
4208- break;
4209-
4210- case 'VALUE':
4211- // deal with a string value
4212- if (strlen($XML_RPC_xh[$parser]['ac']) > 0 &&
4213- $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) {
4214-
4215- $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
4216- }
4217-
4218- // This if () detects if no scalar was inside <VALUE></VALUE>
4219- // and pads an empty "".
4220- if ($XML_RPC_xh[$parser]['st'][strlen($XML_RPC_xh[$parser]['st'])-1] == '(') {
4221- $XML_RPC_xh[$parser]['st'] .= '""';
4222- }
4223- $XML_RPC_xh[$parser]['st'] .= ", '" . $XML_RPC_xh[$parser]['vt'] . "')";
4224- if ($XML_RPC_xh[$parser]['cm']) {
4225- $XML_RPC_xh[$parser]['st'] .= ',';
4226- }
4227- break;
4228-
4229- case 'MEMBER':
4230- $XML_RPC_xh[$parser]['ac'] = '';
4231- $XML_RPC_xh[$parser]['qt'] = 0;
4232- break;
4233-
4234- case 'DATA':
4235- $XML_RPC_xh[$parser]['ac'] = '';
4236- $XML_RPC_xh[$parser]['qt'] = 0;
4237- break;
4238-
4239- case 'PARAM':
4240- $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['st'];
4241- break;
4242-
4243- case 'METHODNAME':
4244- $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", '',
4245- $XML_RPC_xh[$parser]['ac']);
4246- break;
4247-
4248- case 'BOOLEAN':
4249- // special case here: we translate boolean 1 or 0 into PHP
4250- // constants true or false
4251- if ($XML_RPC_xh[$parser]['ac'] == '1') {
4252- $XML_RPC_xh[$parser]['ac'] = 'true';
4253- } else {
4254- $XML_RPC_xh[$parser]['ac'] = 'false';
4255- }
4256-
4257- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4258- }
4259-
4260- // if it's a valid type name, set the type
4261- if (isset($XML_RPC_Types[strtolower($name)])) {
4262- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
4263- }
4264-}
4265-
4266-/**
4267- * Character data handler for the XML parser
4268- *
4269- * @return void
4270- */
4271-function XML_RPC_cd($parser, $data)
4272-{
4273- global $XML_RPC_xh, $XML_RPC_backslash;
4274-
4275- if ($XML_RPC_xh[$parser]['lv'] != 3) {
4276- // "lookforvalue==3" means that we've found an entire value
4277- // and should discard any further character data
4278-
4279- if ($XML_RPC_xh[$parser]['lv'] == 1) {
4280- // if we've found text and we're just in a <value> then
4281- // turn quoting on, as this will be a string
4282- $XML_RPC_xh[$parser]['qt'] = 1;
4283- // and say we've found a value
4284- $XML_RPC_xh[$parser]['lv'] = 2;
4285- }
4286-
4287- // replace characters that eval would
4288- // do special things with
4289- if (!isset($XML_RPC_xh[$parser]['ac'])) {
4290- $XML_RPC_xh[$parser]['ac'] = '';
4291- }
4292- $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$',
4293- str_replace('"', '\"', str_replace(chr(92),
4294- $XML_RPC_backslash, $data)));
4295- }
4296-}
4297-
4298-/**
4299- * Base class
4300- *
4301- * This class provides common functions for all of the XML_RPC classes.
4302- *
4303- * @category Web Services
4304- * @package XML_RPC
4305- * @author Edd Dumbill <edd@usefulinc.com>
4306- * @author Stig Bakken <stig@php.net>
4307- * @author Martin Jansen <mj@php.net>
4308- * @copyright 1999-2001 Edd Dumbill
4309- * @version Release: 1.2.2
4310- * @link http://pear.php.net/package/XML_RPC
4311- */
4312-class XML_RPC_Base {
4313-
4314- /**
4315- * PEAR Error handling
4316- *
4317- * @return object PEAR_Error object
4318- */
4319- function raiseError($msg, $code)
4320- {
4321- include_once 'PEAR.php';
4322- if (is_object(@$this)) {
4323- return PEAR::raiseError(get_class($this) . ': ' . $msg, $code);
4324- } else {
4325- return PEAR::raiseError('XML_RPC: ' . $msg, $code);
4326- }
4327- }
4328-
4329- /**
4330- * Tell whether something is a PEAR_Error object
4331- *
4332- * @param mixed $value the item to check
4333- *
4334- * @return bool whether $value is a PEAR_Error object or not
4335- *
4336- * @access public
4337- */
4338- function isError($value)
4339- {
4340- return is_a($value, 'PEAR_Error');
4341- }
4342-}
4343-
4344-/**
4345- *
4346- *
4347- * @category Web Services
4348- * @package XML_RPC
4349- * @author Edd Dumbill <edd@usefulinc.com>
4350- * @author Stig Bakken <stig@php.net>
4351- * @author Martin Jansen <mj@php.net>
4352- * @author Daniel Convissor <danielc@php.net>
4353- * @copyright 1999-2001 Edd Dumbill
4354- * @version Release: 1.2.2
4355- * @link http://pear.php.net/package/XML_RPC
4356- */
4357-class XML_RPC_Client extends XML_RPC_Base {
4358-
4359- /**
4360- * The path and name of the RPC server script you want the request to go to
4361- * @var string
4362- */
4363- var $path = '';
4364-
4365- /**
4366- * The name of the remote server to connect to
4367- * @var string
4368- */
4369- var $server = '';
4370-
4371- /**
4372- * The protocol to use in contacting the remote server
4373- * @var string
4374- */
4375- var $protocol = 'http://';
4376-
4377- /**
4378- * The port for connecting to the remote server
4379- *
4380- * The default is 80 for http:// connections
4381- * and 443 for https:// and ssl:// connections.
4382- *
4383- * @var integer
4384- */
4385- var $port = 80;
4386-
4387- /**
4388- * A user name for accessing the RPC server
4389- * @var string
4390- * @see XML_RPC_Client::setCredentials()
4391- */
4392- var $username = '';
4393-
4394- /**
4395- * A password for accessing the RPC server
4396- * @var string
4397- * @see XML_RPC_Client::setCredentials()
4398- */
4399- var $password = '';
4400-
4401- /**
4402- * The name of the proxy server to use, if any
4403- * @var string
4404- */
4405- var $proxy = '';
4406-
4407- /**
4408- * The protocol to use in contacting the proxy server, if any
4409- * @var string
4410- */
4411- var $proxy_protocol = 'http://';
4412-
4413- /**
4414- * The port for connecting to the proxy server
4415- *
4416- * The default is 8080 for http:// connections
4417- * and 443 for https:// and ssl:// connections.
4418- *
4419- * @var integer
4420- */
4421- var $proxy_port = 8080;
4422-
4423- /**
4424- * A user name for accessing the proxy server
4425- * @var string
4426- */
4427- var $proxy_user = '';
4428-
4429- /**
4430- * A password for accessing the proxy server
4431- * @var string
4432- */
4433- var $proxy_pass = '';
4434-
4435- /**
4436- * The error number, if any
4437- * @var integer
4438- */
4439- var $errno = 0;
4440-
4441- /**
4442- * The error message, if any
4443- * @var string
4444- */
4445- var $errstring = '';
4446-
4447- /**
4448- * The current debug mode (1 = on, 0 = off)
4449- * @var integer
4450- */
4451- var $debug = 0;
4452-
4453-
4454- /**
4455- * Sets the object's properties
4456- *
4457- * @param string $path the path and name of the RPC server script
4458- * you want the request to go to
4459- * @param string $server the URL of the remote server to connect to.
4460- * If this parameter doesn't specify a
4461- * protocol and $port is 443, ssl:// is
4462- * assumed.
4463- * @param integer $port a port for connecting to the remote server.
4464- * Defaults to 80 for http:// connections and
4465- * 443 for https:// and ssl:// connections.
4466- * @param string $proxy the URL of the proxy server to use, if any.
4467- * If this parameter doesn't specify a
4468- * protocol and $port is 443, ssl:// is
4469- * assumed.
4470- * @param integer $proxy_port a port for connecting to the remote server.
4471- * Defaults to 8080 for http:// connections and
4472- * 443 for https:// and ssl:// connections.
4473- * @param string $proxy_user a user name for accessing the proxy server
4474- * @param string $proxy_pass a password for accessing the proxy server
4475- *
4476- * @return void
4477- */
4478- function XML_RPC_Client($path, $server, $port = 0,
4479- $proxy = '', $proxy_port = 0,
4480- $proxy_user = '', $proxy_pass = '')
4481- {
4482- $this->path = $path;
4483- $this->proxy_user = $proxy_user;
4484- $this->proxy_pass = $proxy_pass;
4485-
4486- preg_match('@^(http://|https://|ssl://)?(.*)$@', $server, $match);
4487- if ($match[1] == '') {
4488- if ($port == 443) {
4489- $this->server = $match[2];
4490- $this->protocol = 'ssl://';
4491- $this->port = 443;
4492- } else {
4493- $this->server = $match[2];
4494- if ($port) {
4495- $this->port = $port;
4496- }
4497- }
4498- } elseif ($match[1] == 'http://') {
4499- $this->server = $match[2];
4500- if ($port) {
4501- $this->port = $port;
4502- }
4503- } else {
4504- $this->server = $match[2];
4505- $this->protocol = 'ssl://';
4506- if ($port) {
4507- $this->port = $port;
4508- } else {
4509- $this->port = 443;
4510- }
4511- }
4512-
4513- if ($proxy) {
4514- preg_match('@^(http://|https://|ssl://)?(.*)$@', $proxy, $match);
4515- if ($match[1] == '') {
4516- if ($proxy_port == 443) {
4517- $this->proxy = $match[2];
4518- $this->proxy_protocol = 'ssl://';
4519- $this->proxy_port = 443;
4520- } else {
4521- $this->proxy = $match[2];
4522- if ($proxy_port) {
4523- $this->proxy_port = $proxy_port;
4524- }
4525- }
4526- } elseif ($match[1] == 'http://') {
4527- $this->proxy = $match[2];
4528- if ($proxy_port) {
4529- $this->proxy_port = $proxy_port;
4530- }
4531- } else {
4532- $this->proxy = $match[2];
4533- $this->proxy_protocol = 'ssl://';
4534- if ($proxy_port) {
4535- $this->proxy_port = $proxy_port;
4536- } else {
4537- $this->proxy_port = 443;
4538- }
4539- }
4540- }
4541- }
4542-
4543- /**
4544- * Change the current debug mode
4545- *
4546- * @param int $in where 1 = on, 0 = off
4547- *
4548- * @return void
4549- */
4550- function setDebug($in)
4551- {
4552- if ($in) {
4553- $this->debug = 1;
4554- } else {
4555- $this->debug = 0;
4556- }
4557- }
4558-
4559- /**
4560- * Set username and password properties for connecting to the RPC server
4561- *
4562- * @param string $u the user name
4563- * @param string $p the password
4564- *
4565- * @return void
4566- *
4567- * @see XML_RPC_Client::$username, XML_RPC_Client::$password
4568- */
4569- function setCredentials($u, $p)
4570- {
4571- $this->username = $u;
4572- $this->password = $p;
4573- }
4574-
4575- /**
4576- * Transmit the RPC request via HTTP 1.0 protocol
4577- *
4578- * @param object $msg the XML_RPC_Message object
4579- * @param int $timeout how many seconds to wait for the request
4580- *
4581- * @return object an XML_RPC_Response object. 0 is returned if any
4582- * problems happen.
4583- *
4584- * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(),
4585- * XML_RPC_Client::setCredentials()
4586- */
4587- function send($msg, $timeout = 0)
4588- {
4589- $msg->debug = $this->debug;
4590- return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
4591- $timeout, $this->username,
4592- $this->password);
4593- }
4594-
4595- /**
4596- * Transmit the RPC request via HTTP 1.0 protocol
4597- *
4598- * Requests should be sent using XML_RPC_Client send() rather than
4599- * calling this method directly.
4600- *
4601- * @param object $msg the XML_RPC_Message object
4602- * @param string $server the server to send the request to
4603- * @param int $port the server port send the request to
4604- * @param int $timeout how many seconds to wait for the request
4605- * before giving up
4606- * @param string $username a user name for accessing the RPC server
4607- * @param string $password a password for accessing the RPC server
4608- *
4609- * @return object an XML_RPC_Response object. 0 is returned if any
4610- * problems happen.
4611- *
4612- * @see XML_RPC_Client::send()
4613- */
4614- function sendPayloadHTTP10($msg, $server, $port, $timeout = 0,
4615- $username = '', $password = '')
4616- {
4617- /*
4618- * If we're using a proxy open a socket to the proxy server
4619- * instead to the xml-rpc server
4620- */
4621- if ($this->proxy) {
4622- if ($this->proxy_protocol == 'http://') {
4623- $protocol = '';
4624- } else {
4625- $protocol = $this->proxy_protocol;
4626- }
4627- if ($timeout > 0) {
4628- $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
4629- $this->errno, $this->errstr, $timeout);
4630- } else {
4631- $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
4632- $this->errno, $this->errstr);
4633- }
4634- } else {
4635- if ($this->protocol == 'http://') {
4636- $protocol = '';
4637- } else {
4638- $protocol = $this->protocol;
4639- }
4640- if ($timeout > 0) {
4641- $fp = @fsockopen($protocol . $server, $port,
4642- $this->errno, $this->errstr, $timeout);
4643- } else {
4644- $fp = @fsockopen($protocol . $server, $port,
4645- $this->errno, $this->errstr);
4646- }
4647- }
4648-
4649- /*
4650- * Just raising the error without returning it is strange,
4651- * but keep it here for backwards compatibility.
4652- */
4653- if (!$fp && $this->proxy) {
4654- $this->raiseError('Connection to proxy server '
4655- . $this->proxy . ':' . $this->proxy_port
4656- . ' failed. ' . $this->errstr,
4657- XML_RPC_ERROR_CONNECTION_FAILED);
4658- return 0;
4659- } elseif (!$fp) {
4660- $this->raiseError('Connection to RPC server '
4661- . $server . ':' . $port
4662- . ' failed. ' . $this->errstr,
4663- XML_RPC_ERROR_CONNECTION_FAILED);
4664- return 0;
4665- }
4666-
4667- // Only create the payload if it was not created previously
4668- if (empty($msg->payload)) {
4669- $msg->createPayload();
4670- }
4671-
4672- // thanks to Grant Rauscher <grant7@firstworld.net> for this
4673- $credentials = '';
4674- if ($username != '') {
4675- $credentials = 'Authorization: Basic ' .
4676- base64_encode($username . ':' . $password) . "\r\n";
4677- }
4678-
4679- if ($this->proxy) {
4680- $op = 'POST ' . $this->protocol . $server;
4681- if ($this->proxy_port) {
4682- $op .= ':' . $this->port;
4683- }
4684- } else {
4685- $op = 'POST ';
4686- }
4687-
4688- $op .= $this->path. " HTTP/1.0\r\n" .
4689- "User-Agent: PEAR XML_RPC\r\n" .
4690- 'Host: ' . $server . "\r\n";
4691- if ($this->proxy && $this->proxy_user != '') {
4692- $op .= 'Proxy-Authorization: Basic ' .
4693- base64_encode($this->proxy_user . ':' . $this->proxy_pass) .
4694- "\r\n";
4695- }
4696- $op .= $credentials .
4697- "Content-Type: text/xml\r\n" .
4698- 'Content-Length: ' . strlen($msg->payload) . "\r\n\r\n" .
4699- $msg->payload;
4700-
4701- if (!fputs($fp, $op, strlen($op))) {
4702- $this->errstr = 'Write error';
4703- return 0;
4704- }
4705- $resp = $msg->parseResponseFile($fp);
4706- fclose($fp);
4707- return $resp;
4708- }
4709-}
4710-
4711-/**
4712- *
4713- *
4714- * @category Web Services
4715- * @package XML_RPC
4716- * @author Edd Dumbill <edd@usefulinc.com>
4717- * @author Stig Bakken <stig@php.net>
4718- * @author Martin Jansen <mj@php.net>
4719- * @copyright 1999-2001 Edd Dumbill
4720- * @version Release: 1.2.2
4721- * @link http://pear.php.net/package/XML_RPC
4722- */
4723-class XML_RPC_Response extends XML_RPC_Base
4724-{
4725- var $xv;
4726- var $fn;
4727- var $fs;
4728- var $hdrs;
4729-
4730- /**
4731- * @return void
4732- */
4733- function XML_RPC_Response($val, $fcode = 0, $fstr = '')
4734- {
4735- if ($fcode != 0) {
4736- $this->fn = $fcode;
4737- $this->fs = htmlspecialchars($fstr);
4738- } else {
4739- $this->xv = $val;
4740- }
4741- }
4742-
4743- /**
4744- * @return int the error code
4745- */
4746- function faultCode()
4747- {
4748- if (isset($this->fn)) {
4749- return $this->fn;
4750- } else {
4751- return 0;
4752- }
4753- }
4754-
4755- /**
4756- * @return string the error string
4757- */
4758- function faultString()
4759- {
4760- return $this->fs;
4761- }
4762-
4763- /**
4764- * @return mixed the value
4765- */
4766- function value()
4767- {
4768- return $this->xv;
4769- }
4770-
4771- /**
4772- * @return string the error message in XML format
4773- */
4774- function serialize()
4775- {
4776- $rs = "<methodResponse>\n";
4777- if ($this->fn) {
4778- $rs .= "<fault>
4779- <value>
4780- <struct>
4781- <member>
4782- <name>faultCode</name>
4783- <value><int>" . $this->fn . "</int></value>
4784- </member>
4785- <member>
4786- <name>faultString</name>
4787- <value><string>" . $this->fs . "</string></value>
4788- </member>
4789- </struct>
4790- </value>
4791-</fault>";
4792- } else {
4793- $rs .= "<params>\n<param>\n" . $this->xv->serialize() .
4794- "</param>\n</params>";
4795- }
4796- $rs .= "\n</methodResponse>";
4797- return $rs;
4798- }
4799-}
4800-
4801-/**
4802- *
4803- *
4804- * @category Web Services
4805- * @package XML_RPC
4806- * @author Edd Dumbill <edd@usefulinc.com>
4807- * @author Stig Bakken <stig@php.net>
4808- * @author Martin Jansen <mj@php.net>
4809- * @author Daniel Convissor <danielc@php.net>
4810- * @copyright 1999-2001 Edd Dumbill
4811- * @version Release: 1.2.2
4812- * @link http://pear.php.net/package/XML_RPC
4813- */
4814-class XML_RPC_Message extends XML_RPC_Base
4815-{
4816- /**
4817- * The current debug mode (1 = on, 0 = off)
4818- * @var integer
4819- */
4820- var $debug = 0;
4821-
4822- /**
4823- * The encoding to be used for outgoing messages
4824- *
4825- * Defaults to the value of <var>$GLOBALS['XML_RPC_defencoding']</var>
4826- *
4827- * @var string
4828- * @see XML_RPC_Message::setSendEncoding(),
4829- * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header()
4830- */
4831- var $send_encoding = '';
4832-
4833- /**
4834- * The method presently being evaluated
4835- * @var string
4836- */
4837- var $methodname = '';
4838-
4839- /**
4840- * @var array
4841- */
4842- var $params = array();
4843-
4844- /**
4845- * The XML message being generated
4846- * @var string
4847- */
4848- var $payload = '';
4849-
4850- /**
4851- * @return void
4852- */
4853- function XML_RPC_Message($meth, $pars = 0)
4854- {
4855- $this->methodname = $meth;
4856- if (is_array($pars) && sizeof($pars) > 0) {
4857- for ($i = 0; $i < sizeof($pars); $i++) {
4858- $this->addParam($pars[$i]);
4859- }
4860- }
4861- }
4862-
4863- /**
4864- * Produces the XML declaration including the encoding attribute
4865- *
4866- * The encoding is determined by this class' <var>$send_encoding</var>
4867- * property. If the <var>$send_encoding</var> property is not set, use
4868- * <var>$GLOBALS['XML_RPC_defencoding']</var>.
4869- *
4870- * @return string the XML declaration and <methodCall> element
4871- *
4872- * @see XML_RPC_Message::setSendEncoding(),
4873- * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding']
4874- */
4875- function xml_header()
4876- {
4877- global $XML_RPC_defencoding;
4878- if (!$this->send_encoding) {
4879- $this->send_encoding = $XML_RPC_defencoding;
4880- }
4881- return '<?xml version="1.0" encoding="' . $this->send_encoding . '"?>'
4882- . "\n<methodCall>\n";
4883- }
4884-
4885- /**
4886- * @return string the closing </methodCall> tag
4887- */
4888- function xml_footer()
4889- {
4890- return "</methodCall>\n";
4891- }
4892-
4893- /**
4894- * @return void
4895- *
4896- * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer()
4897- */
4898- function createPayload()
4899- {
4900- $this->payload = $this->xml_header();
4901- $this->payload .= '<methodName>' . $this->methodname . "</methodName>\n";
4902- $this->payload .= "<params>\n";
4903- for ($i = 0; $i < sizeof($this->params); $i++) {
4904- $p = $this->params[$i];
4905- $this->payload .= "<param>\n" . $p->serialize() . "</param>\n";
4906- }
4907- $this->payload .= "</params>\n";
4908- $this->payload .= $this->xml_footer();
4909- $this->payload = ereg_replace("[\r\n]+", "\r\n", $this->payload);
4910- }
4911-
4912- /**
4913- * @return string the name of the method
4914- */
4915- function method($meth = '')
4916- {
4917- if ($meth != '') {
4918- $this->methodname = $meth;
4919- }
4920- return $this->methodname;
4921- }
4922-
4923- /**
4924- * @return string the payload
4925- */
4926- function serialize()
4927- {
4928- $this->createPayload();
4929- return $this->payload;
4930- }
4931-
4932- /**
4933- * @return void
4934- */
4935- function addParam($par)
4936- {
4937- $this->params[] = $par;
4938- }
4939-
4940- /**
4941- * @return void
4942- */
4943- function getParam($i)
4944- {
4945- return $this->params[$i];
4946- }
4947-
4948- /**
4949- * @return int the number of parameters
4950- */
4951- function getNumParams()
4952- {
4953- return sizeof($this->params);
4954- }
4955-
4956- /**
4957- * Sets the XML declaration's encoding attribute
4958- *
4959- * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII)
4960- *
4961- * @return void
4962- *
4963- * @see XML_RPC_Message::$send_encoding, XML_RPC_Message::xml_header()
4964- * @since Method available since Release 1.2.0
4965- */
4966- function setSendEncoding($type)
4967- {
4968- $this->send_encoding = $type;
4969- }
4970-
4971- /**
4972- * Determine the XML's encoding via the encoding attribute
4973- * in the XML declaration
4974- *
4975- * If the encoding parameter is not set or is not ISO-8859-1, UTF-8
4976- * or US-ASCII, $XML_RPC_defencoding will be returned.
4977- *
4978- * @param string $data the XML that will be parsed
4979- *
4980- * @return string the encoding to be used
4981- *
4982- * @link http://php.net/xml_parser_create
4983- * @since Method available since Release 1.2.0
4984- */
4985- function getEncoding($data)
4986- {
4987- global $XML_RPC_defencoding;
4988-
4989- if (preg_match('/<\?xml[^>]*\s*encoding\s*=\s*[\'"]([^"\']*)[\'"]/i',
4990- $data, $match))
4991- {
4992- $match[1] = trim(strtoupper($match[1]));
4993- switch ($match[1]) {
4994- case 'ISO-8859-1':
4995- case 'UTF-8':
4996- case 'US-ASCII':
4997- return $match[1];
4998- break;
4999-
5000- default:
5001- return $XML_RPC_defencoding;
5002- }
5003- } else {
5004- return $XML_RPC_defencoding;
5005- }
5006- }
5007-
5008- /**
5009- * @return object a new XML_RPC_Response object
5010- */
5011- function parseResponseFile($fp)
5012- {
5013- $ipd = '';
5014- while ($data = @fread($fp, 8192)) {
5015- $ipd .= $data;
5016- }
5017- return $this->parseResponse($ipd);
5018- }
5019-
5020- /**
5021- * @return object a new XML_RPC_Response object
5022- */
5023- function parseResponse($data = '')
5024- {
5025- global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding;
5026-
5027- $encoding = $this->getEncoding($data);
5028- $parser = xml_parser_create($encoding);
5029-
5030- $XML_RPC_xh[$parser] = array();
5031-
5032- $XML_RPC_xh[$parser]['st'] = '';
5033- $XML_RPC_xh[$parser]['cm'] = 0;
5034- $XML_RPC_xh[$parser]['isf'] = 0;
5035- $XML_RPC_xh[$parser]['ac'] = '';
5036- $XML_RPC_xh[$parser]['qt'] = '';
5037-
5038- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
5039- xml_set_element_handler($parser, 'XML_RPC_se', 'XML_RPC_ee');
5040- xml_set_character_data_handler($parser, 'XML_RPC_cd');
5041-
5042- $hdrfnd = 0;
5043- if ($this->debug) {
5044- print "<PRE>---GOT---\n";
5045- print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
5046- print "\n---END---\n</PRE>";
5047- }
5048-
5049- // see if we got an HTTP 200 OK, else bomb
5050- // but only do this if we're using the HTTP protocol.
5051- if (ereg('^HTTP', $data) &&
5052- !ereg('^HTTP/[0-9\.]+ 200 ', $data)) {
5053- $errstr = substr($data, 0, strpos($data, "\n") - 1);
5054- error_log('HTTP error, got response: ' . $errstr);
5055- $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'],
5056- $XML_RPC_str['http_error'] . ' (' .
5057- $errstr . ')');
5058- xml_parser_free($parser);
5059- return $r;
5060- }
5061- // gotta get rid of headers here
5062-
5063-
5064- if ((!$hdrfnd) && ($brpos = strpos($data,"\r\n\r\n"))) {
5065- $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
5066- $data = substr($data, $brpos + 4);
5067- $hdrfnd = 1;
5068- }
5069-
5070- /*
5071- * be tolerant of junk after methodResponse
5072- * (e.g. javascript automatically inserted by free hosts)
5073- * thanks to Luca Mariano <luca.mariano@email.it>
5074- */
5075- $data = substr($data, 0, strpos($data, "</methodResponse>") + 17);
5076-
5077- if (!xml_parse($parser, $data, sizeof($data))) {
5078- // thanks to Peter Kocks <peter.kocks@baygate.com>
5079- if ((xml_get_current_line_number($parser)) == 1) {
5080- $errstr = 'XML error at line 1, check URL';
5081- } else {
5082- $errstr = sprintf('XML error: %s at line %d',
5083- xml_error_string(xml_get_error_code($parser)),
5084- xml_get_current_line_number($parser));
5085- }
5086- error_log($errstr);
5087- $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
5088- $XML_RPC_str['invalid_return']);
5089- xml_parser_free($parser);
5090- return $r;
5091- }
5092- xml_parser_free($parser);
5093- if ($this->debug) {
5094- print '<PRE>---EVALING---[' .
5095- strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
5096- htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---</PRE>";
5097- }
5098- if (strlen($XML_RPC_xh[$parser]['st']) == 0) {
5099- // then something odd has happened
5100- // and it's time to generate a client side error
5101- // indicating something odd went on
5102- $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
5103- $XML_RPC_str['invalid_return']);
5104- } else {
5105- eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;');
5106- if ($XML_RPC_xh[$parser]['isf']) {
5107- $f = $v->structmem('faultCode');
5108- $fs = $v->structmem('faultString');
5109- $r = new XML_RPC_Response($v, $f->scalarval(),
5110- $fs->scalarval());
5111- } else {
5112- $r = new XML_RPC_Response($v);
5113- }
5114- }
5115- $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
5116- return $r;
5117- }
5118-}
5119-
5120-/**
5121- *
5122- *
5123- * @category Web Services
5124- * @package XML_RPC
5125- * @author Edd Dumbill <edd@usefulinc.com>
5126- * @author Stig Bakken <stig@php.net>
5127- * @author Martin Jansen <mj@php.net>
5128- * @copyright 1999-2001 Edd Dumbill
5129- * @version Release: 1.2.2
5130- * @link http://pear.php.net/package/XML_RPC
5131- */
5132-class XML_RPC_Value extends XML_RPC_Base
5133-{
5134- var $me = array();
5135- var $mytype = 0;
5136-
5137- /**
5138- * @return void
5139- */
5140- function XML_RPC_Value($val = -1, $type = '')
5141- {
5142- global $XML_RPC_Types;
5143- $this->me = array();
5144- $this->mytype = 0;
5145- if ($val != -1 || $type != '') {
5146- if ($type == '') {
5147- $type = 'string';
5148- }
5149- if (!array_key_exists($type, $XML_RPC_Types)) {
5150- // XXX
5151- // need some way to report this error
5152- } elseif ($XML_RPC_Types[$type] == 1) {
5153- $this->addScalar($val, $type);
5154- } elseif ($XML_RPC_Types[$type] == 2) {
5155- $this->addArray($val);
5156- } elseif ($XML_RPC_Types[$type] == 3) {
5157- $this->addStruct($val);
5158- }
5159- }
5160- }
5161-
5162- /**
5163- * @return int returns 1 if successful or 0 if there are problems
5164- */
5165- function addScalar($val, $type = 'string')
5166- {
5167- global $XML_RPC_Types, $XML_RPC_Boolean;
5168-
5169- if ($this->mytype == 1) {
5170- $this->raiseError('Scalar can have only one value',
5171- XML_RPC_ERROR_INVALID_TYPE);
5172- return 0;
5173- }
5174- $typeof = $XML_RPC_Types[$type];
5175- if ($typeof != 1) {
5176- $this->raiseError("Not a scalar type (${typeof})",
5177- XML_RPC_ERROR_INVALID_TYPE);
5178- return 0;
5179- }
5180-
5181- if ($type == $XML_RPC_Boolean) {
5182- if (strcasecmp($val, 'true') == 0
5183- || $val == 1
5184- || ($val == true && strcasecmp($val, 'false')))
5185- {
5186- $val = 1;
5187- } else {
5188- $val = 0;
5189- }
5190- }
5191-
5192- if ($this->mytype == 2) {
5193- // we're adding to an array here
5194- $ar = $this->me['array'];
5195- $ar[] = new XML_RPC_Value($val, $type);
5196- $this->me['array'] = $ar;
5197- } else {
5198- // a scalar, so set the value and remember we're scalar
5199- $this->me[$type] = $val;
5200- $this->mytype = $typeof;
5201- }
5202- return 1;
5203- }
5204-
5205- /**
5206- * @return int returns 1 if successful or 0 if there are problems
5207- */
5208- function addArray($vals)
5209- {
5210- global $XML_RPC_Types;
5211- if ($this->mytype != 0) {
5212- $this->raiseError(
5213- 'Already initialized as a [' . $this->kindOf() . ']',
5214- XML_RPC_ERROR_ALREADY_INITIALIZED);
5215- return 0;
5216- }
5217- $this->mytype = $XML_RPC_Types['array'];
5218- $this->me['array'] = $vals;
5219- return 1;
5220- }
5221-
5222- /**
5223- * @return int returns 1 if successful or 0 if there are problems
5224- */
5225- function addStruct($vals)
5226- {
5227- global $XML_RPC_Types;
5228- if ($this->mytype != 0) {
5229- $this->raiseError(
5230- 'Already initialized as a [' . $this->kindOf() . ']',
5231- XML_RPC_ERROR_ALREADY_INITIALIZED);
5232- return 0;
5233- }
5234- $this->mytype = $XML_RPC_Types['struct'];
5235- $this->me['struct'] = $vals;
5236- return 1;
5237- }
5238-
5239- /**
5240- * @return void
5241- */
5242- function dump($ar)
5243- {
5244- reset($ar);
5245- while (list($key, $val) = each($ar)) {
5246- echo "$key => $val<br>";
5247- if ($key == 'array') {
5248- while (list($key2, $val2) = each($val)) {
5249- echo "-- $key2 => $val2<br>";
5250- }
5251- }
5252- }
5253- }
5254-
5255- /**
5256- * @return string the data type of the current value
5257- */
5258- function kindOf()
5259- {
5260- switch ($this->mytype) {
5261- case 3:
5262- return 'struct';
5263-
5264- case 2:
5265- return 'array';
5266-
5267- case 1:
5268- return 'scalar';
5269-
5270- default:
5271- return 'undef';
5272- }
5273- }
5274-
5275- /**
5276- * @return string the data in XML format
5277- */
5278- function serializedata($typ, $val)
5279- {
5280- $rs = '';
5281- global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
5282- if (!array_key_exists($typ, $XML_RPC_Types)) {
5283- // XXX
5284- // need some way to report this error
5285- return;
5286- }
5287- switch ($XML_RPC_Types[$typ]) {
5288- case 3:
5289- // struct
5290- $rs .= "<struct>\n";
5291- reset($val);
5292- while (list($key2, $val2) = each($val)) {
5293- $rs .= "<member><name>${key2}</name>\n";
5294- $rs .= $this->serializeval($val2);
5295- $rs .= "</member>\n";
5296- }
5297- $rs .= '</struct>';
5298- break;
5299-
5300- case 2:
5301- // array
5302- $rs .= "<array>\n<data>\n";
5303- for ($i = 0; $i < sizeof($val); $i++) {
5304- $rs .= $this->serializeval($val[$i]);
5305- }
5306- $rs .= "</data>\n</array>";
5307- break;
5308-
5309- case 1:
5310- switch ($typ) {
5311- case $XML_RPC_Base64:
5312- $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
5313- break;
5314- case $XML_RPC_Boolean:
5315- $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
5316- break;
5317- case $XML_RPC_String:
5318- $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
5319- break;
5320- default:
5321- $rs .= "<${typ}>${val}</${typ}>";
5322- }
5323- }
5324- return $rs;
5325- }
5326-
5327- /**
5328- * @return string the data in XML format
5329- */
5330- function serialize()
5331- {
5332- return $this->serializeval($this);
5333- }
5334-
5335- /**
5336- * @return string the data in XML format
5337- */
5338- function serializeval($o)
5339- {
5340- $rs = '';
5341- $ar = $o->me;
5342- reset($ar);
5343- list($typ, $val) = each($ar);
5344- $rs .= '<value>';
5345- $rs .= $this->serializedata($typ, $val);
5346- $rs .= "</value>\n";
5347- return $rs;
5348- }
5349-
5350- /**
5351- * @return mixed the contents of the element requested
5352- */
5353- function structmem($m)
5354- {
5355- return $this->me['struct'][$m];
5356- }
5357-
5358- /**
5359- * @return void
5360- */
5361- function structreset()
5362- {
5363- reset($this->me['struct']);
5364- }
5365-
5366- /**
5367- * @return the key/value pair of the struct's current element
5368- */
5369- function structeach()
5370- {
5371- return each($this->me['struct']);
5372- }
5373-
5374- /**
5375- * @return mixed the current value
5376- */
5377- function getval() {
5378- // UNSTABLE
5379- global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
5380-
5381- reset($this->me);
5382- list($a, $b) = each($this->me);
5383-
5384- // contributed by I Sofer, 2001-03-24
5385- // add support for nested arrays to scalarval
5386- // i've created a new method here, so as to
5387- // preserve back compatibility
5388-
5389- if (is_array($b)) {
5390- foreach ($b as $id => $cont) {
5391- $b[$id] = $cont->scalarval();
5392- }
5393- }
5394-
5395- // add support for structures directly encoding php objects
5396- if (is_object($b)) {
5397- $t = get_object_vars($b);
5398- foreach ($t as $id => $cont) {
5399- $t[$id] = $cont->scalarval();
5400- }
5401- foreach ($t as $id => $cont) {
5402- eval('$b->'.$id.' = $cont;');
5403- }
5404- }
5405-
5406- // end contrib
5407- return $b;
5408- }
5409-
5410- /**
5411- * @return mixed
5412- */
5413- function scalarval()
5414- {
5415- global $XML_RPC_Boolean, $XML_RPC_Base64;
5416- reset($this->me);
5417- list($a, $b) = each($this->me);
5418- return $b;
5419- }
5420-
5421- /**
5422- * @return string
5423- */
5424- function scalartyp()
5425- {
5426- global $XML_RPC_I4, $XML_RPC_Int;
5427- reset($this->me);
5428- list($a, $b) = each($this->me);
5429- if ($a == $XML_RPC_I4) {
5430- $a = $XML_RPC_Int;
5431- }
5432- return $a;
5433- }
5434-
5435- /**
5436- * @return mixed the struct's current element
5437- */
5438- function arraymem($m)
5439- {
5440- return $this->me['array'][$m];
5441- }
5442-
5443- /**
5444- * @return int the number of elements in the array
5445- */
5446- function arraysize()
5447- {
5448- reset($this->me);
5449- list($a, $b) = each($this->me);
5450- return sizeof($b);
5451- }
5452-}
5453-
5454-/**
5455- * Return an ISO8601 encoded string
5456- *
5457- * While timezones ought to be supported, the XML-RPC spec says:
5458- *
5459- * "Don't assume a timezone. It should be specified by the server in its
5460- * documentation what assumptions it makes about timezones."
5461- *
5462- * This routine always assumes localtime unless $utc is set to 1, in which
5463- * case UTC is assumed and an adjustment for locale is made when encoding.
5464- *
5465- * @return string the formatted date
5466- */
5467-function XML_RPC_iso8601_encode($timet, $utc = 0) {
5468- if (!$utc) {
5469- $t = strftime('%Y%m%dT%H:%M:%S', $timet);
5470- } else {
5471- if (function_exists('gmstrftime')) {
5472- // gmstrftime doesn't exist in some versions
5473- // of PHP
5474- $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet);
5475- } else {
5476- $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z'));
5477- }
5478- }
5479- return $t;
5480-}
5481-
5482-/**
5483- * Convert a datetime string into a Unix timestamp
5484- *
5485- * While timezones ought to be supported, the XML-RPC spec says:
5486- *
5487- * "Don't assume a timezone. It should be specified by the server in its
5488- * documentation what assumptions it makes about timezones."
5489- *
5490- * This routine always assumes localtime unless $utc is set to 1, in which
5491- * case UTC is assumed and an adjustment for locale is made when encoding.
5492- *
5493- * @return int the unix timestamp of the date submitted
5494- */
5495-function XML_RPC_iso8601_decode($idate, $utc = 0) {
5496- $t = 0;
5497- if (ereg('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) {
5498- if ($utc) {
5499- $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
5500- } else {
5501- $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
5502- }
5503- }
5504- return $t;
5505-}
5506-
5507-/**
5508- * Takes a message in PHP XML_RPC object format and translates it into
5509- * native PHP types
5510- *
5511- * @return mixed
5512- *
5513- * @author Dan Libby <dan@libby.com>
5514- */
5515-function XML_RPC_decode($XML_RPC_val)
5516-{
5517- $kind = $XML_RPC_val->kindOf();
5518-
5519- if ($kind == 'scalar') {
5520- return $XML_RPC_val->scalarval();
5521-
5522- } elseif ($kind == 'array') {
5523- $size = $XML_RPC_val->arraysize();
5524- $arr = array();
5525- for ($i = 0; $i < $size; $i++) {
5526- $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i));
5527- }
5528- return $arr;
5529-
5530- } elseif ($kind == 'struct') {
5531- $XML_RPC_val->structreset();
5532- $arr = array();
5533- while (list($key, $value) = $XML_RPC_val->structeach()) {
5534- $arr[$key] = XML_RPC_decode($value);
5535- }
5536- return $arr;
5537- }
5538-}
5539-
5540-/**
5541- * Takes native php types and encodes them into XML_RPC PHP object format
5542- *
5543- * Feature creep -- could support more types via optional type argument.
5544- *
5545- * @return string
5546- *
5547- * @author Dan Libby <dan@libby.com>
5548- */
5549-function XML_RPC_encode($php_val) {
5550- global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double, $XML_RPC_String,
5551- $XML_RPC_Array, $XML_RPC_Struct;
5552-
5553- $type = gettype($php_val);
5554- $XML_RPC_val = new XML_RPC_Value;
5555-
5556- switch ($type) {
5557- case 'array':
5558- if (empty($php_val)) {
5559- $XML_RPC_val->addArray($php_val);
5560- break;
5561- }
5562- $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1));
5563- if (empty($tmp)) {
5564- $arr = array();
5565- foreach ($php_val as $k => $v) {
5566- $arr[$k] = XML_RPC_encode($v);
5567- }
5568- $XML_RPC_val->addArray($arr);
5569- break;
5570- }
5571- // fall though if it's not an enumerated array
5572-
5573- case 'object':
5574- $arr = array();
5575- foreach ($php_val as $k => $v) {
5576- $arr[$k] = XML_RPC_encode($v);
5577- }
5578- $XML_RPC_val->addStruct($arr);
5579- break;
5580-
5581- case 'integer':
5582- $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
5583- break;
5584-
5585- case 'double':
5586- $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
5587- break;
5588-
5589- case 'string':
5590- case 'NULL':
5591- $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
5592- break;
5593-
5594- case 'boolean':
5595- // Add support for encoding/decoding of booleans, since they
5596- // are supported in PHP
5597- // by <G_Giunta_2001-02-29>
5598- $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
5599- break;
5600-
5601- case 'unknown type':
5602- default:
5603- $XML_RPC_val = false;
5604- }
5605- return $XML_RPC_val;
5606-}
5607-
5608-/*
5609- * Local variables:
5610- * tab-width: 4
5611- * c-basic-offset: 4
5612- * c-hanging-comment-ender-p: nil
5613- * End:
5614- */
5615-
5616-?>
5617-XML_RPC-1.2.2/Server.php
5618-
5619-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5620-
5621-/**
5622- * PHP implementation of the XML-RPC protocol
5623- *
5624- * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
5625- * It has support for HTTP transport, proxies and authentication.
5626- *
5627- * PHP versions 4 and 5
5628- *
5629- * LICENSE: License is granted to use or modify this software
5630- * ("XML-RPC for PHP") for commercial or non-commercial use provided the
5631- * copyright of the author is preserved in any distributed or derivative work.
5632- *
5633- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
5634- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5635- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5636- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5637- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5638- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5639- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5640- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5641- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5642- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5643- *
5644- * @category Web Services
5645- * @package XML_RPC
5646- * @author Edd Dumbill <edd@usefulinc.com>
5647- * @author Stig Bakken <stig@php.net>
5648- * @author Martin Jansen <mj@php.net>
5649- * @copyright 1999-2001 Edd Dumbill
5650- * @version CVS: $Id: Server.php,v 1.17 2005/03/01 17:09:49 danielc Exp $
5651- * @link http://pear.php.net/package/XML_RPC
5652- */
5653-
5654-
5655-/**
5656- * Pull in the XML_RPC class
5657- */
5658-require_once 'XML/RPC.php';
5659-
5660-
5661-/**
5662- * listMethods: either a string, or nothing
5663- * @global array $GLOBALS['XML_RPC_Server_listMethods_sig']
5664- */
5665-$GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
5666- array($GLOBALS['XML_RPC_Array'],
5667- $GLOBALS['XML_RPC_String']
5668- ),
5669- array($GLOBALS['XML_RPC_Array'])
5670-);
5671-
5672-/**
5673- * @global string $GLOBALS['XML_RPC_Server_listMethods_doc']
5674- */
5675-$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the'
5676- . ' methods that the XML-RPC server knows how to dispatch';
5677-
5678-/**
5679- * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig']
5680- */
5681-$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
5682- array($GLOBALS['XML_RPC_Array'],
5683- $GLOBALS['XML_RPC_String']
5684- )
5685-);
5686-
5687-/**
5688- * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc']
5689- */
5690-$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
5691- . ' signatures (an array of arrays) for the method name passed. If'
5692- . ' no signatures are known, returns a none-array (test for type !='
5693- . ' array to detect missing signature)';
5694-
5695-/**
5696- * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig']
5697- */
5698-$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
5699- array($GLOBALS['XML_RPC_String'],
5700- $GLOBALS['XML_RPC_String']
5701- )
5702-);
5703-
5704-/**
5705- * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc']
5706- */
5707-$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined'
5708- . ' for the method passed, otherwise returns an empty string';
5709-
5710-/**
5711- * @global array $GLOBALS['XML_RPC_Server_dmap']
5712- */
5713-$GLOBALS['XML_RPC_Server_dmap'] = array(
5714- 'system.listMethods' => array(
5715- 'function' => 'XML_RPC_Server_listMethods',
5716- 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'],
5717- 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc']
5718- ),
5719- 'system.methodHelp' => array(
5720- 'function' => 'XML_RPC_Server_methodHelp',
5721- 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'],
5722- 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc']
5723- ),
5724- 'system.methodSignature' => array(
5725- 'function' => 'XML_RPC_Server_methodSignature',
5726- 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'],
5727- 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc']
5728- )
5729-);
5730-
5731-/**
5732- * @global string $GLOBALS['XML_RPC_Server_debuginfo']
5733- */
5734-$GLOBALS['XML_RPC_Server_debuginfo'] = '';
5735-
5736-
5737-/**
5738- * Lists all the methods that the XML-RPC server knows how to dispatch
5739- *
5740- * @return object a new XML_RPC_Response object
5741- */
5742-function XML_RPC_Server_listMethods($server, $m)
5743-{
5744- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
5745-
5746- $v = new XML_RPC_Value();
5747- $dmap = $server->dmap;
5748- $outAr = array();
5749- for (reset($dmap); list($key, $val) = each($dmap); ) {
5750- $outAr[] = new XML_RPC_Value($key, 'string');
5751- }
5752- $dmap = $XML_RPC_Server_dmap;
5753- for (reset($dmap); list($key, $val) = each($dmap); ) {
5754- $outAr[] = new XML_RPC_Value($key, 'string');
5755- }
5756- $v->addArray($outAr);
5757- return new XML_RPC_Response($v);
5758-}
5759-
5760-/**
5761- * Returns an array of known signatures (an array of arrays)
5762- * for the given method
5763- *
5764- * If no signatures are known, returns a none-array
5765- * (test for type != array to detect missing signature)
5766- *
5767- * @return object a new XML_RPC_Response object
5768- */
5769-function XML_RPC_Server_methodSignature($server, $m)
5770-{
5771- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
5772-
5773- $methName = $m->getParam(0);
5774- $methName = $methName->scalarval();
5775- if (strpos($methName, 'system.') === 0) {
5776- $dmap = $XML_RPC_Server_dmap;
5777- $sysCall = 1;
5778- } else {
5779- $dmap = $server->dmap;
5780- $sysCall = 0;
5781- }
5782- // print "<!-- ${methName} -->\n";
5783- if (isset($dmap[$methName])) {
5784- if ($dmap[$methName]['signature']) {
5785- $sigs = array();
5786- $thesigs = $dmap[$methName]['signature'];
5787- for ($i = 0; $i < sizeof($thesigs); $i++) {
5788- $cursig = array();
5789- $inSig = $thesigs[$i];
5790- for ($j = 0; $j < sizeof($inSig); $j++) {
5791- $cursig[] = new XML_RPC_Value($inSig[$j], 'string');
5792- }
5793- $sigs[] = new XML_RPC_Value($cursig, 'array');
5794- }
5795- $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array'));
5796- } else {
5797- $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string'));
5798- }
5799- } else {
5800- $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
5801- $XML_RPC_str['introspect_unknown']);
5802- }
5803- return $r;
5804-}
5805-
5806-/**
5807- * Returns help text if defined for the method passed, otherwise returns
5808- * an empty string
5809- *
5810- * @return object a new XML_RPC_Response object
5811- */
5812-function XML_RPC_Server_methodHelp($server, $m)
5813-{
5814- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
5815-
5816- $methName = $m->getParam(0);
5817- $methName = $methName->scalarval();
5818- if (strpos($methName, 'system.') === 0) {
5819- $dmap = $XML_RPC_Server_dmap;
5820- $sysCall = 1;
5821- } else {
5822- $dmap = $server->dmap;
5823- $sysCall = 0;
5824- }
5825- // print "<!-- ${methName} -->\n";
5826- if (isset($dmap[$methName])) {
5827- if ($dmap[$methName]['docstring']) {
5828- $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']),
5829- 'string');
5830- } else {
5831- $r = new XML_RPC_Response(new XML_RPC_Value('', 'string'));
5832- }
5833- } else {
5834- $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
5835- $XML_RPC_str['introspect_unknown']);
5836- }
5837- return $r;
5838-}
5839-
5840-/**
5841- * @return void
5842- */
5843-function XML_RPC_Server_debugmsg($m)
5844-{
5845- global $XML_RPC_Server_debuginfo;
5846- $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n";
5847-}
5848-
5849-
5850-/**
5851- *
5852- *
5853- * @category Web Services
5854- * @package XML_RPC
5855- * @author Edd Dumbill <edd@usefulinc.com>
5856- * @author Stig Bakken <stig@php.net>
5857- * @author Martin Jansen <mj@php.net>
5858- * @copyright 1999-2001 Edd Dumbill
5859- * @version Release: 1.2.2
5860- * @link http://pear.php.net/package/XML_RPC
5861- */
5862-class XML_RPC_Server
5863-{
5864- var $dmap = array();
5865- var $encoding = '';
5866- var $debug = 0;
5867-
5868- /**
5869- * @return void
5870- */
5871- function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0)
5872- {
5873- global $HTTP_RAW_POST_DATA;
5874-
5875- if ($debug) {
5876- $this->debug = 1;
5877- } else {
5878- $this->debug = 0;
5879- }
5880-
5881- // dispMap is a despatch array of methods
5882- // mapped to function names and signatures
5883- // if a method
5884- // doesn't appear in the map then an unknown
5885- // method error is generated
5886- $this->dmap = $dispMap;
5887- if ($serviceNow) {
5888- $this->service();
5889- }
5890- }
5891-
5892- /**
5893- * @return string the debug information if debug debug mode is on
5894- */
5895- function serializeDebug()
5896- {
5897- global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA;
5898-
5899- if ($this->debug) {
5900- XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n"
5901- . $HTTP_RAW_POST_DATA
5902- . "\n" . '^^^ END POST DATA ^^^');
5903- }
5904-
5905- if ($XML_RPC_Server_debuginfo != '') {
5906- return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n"
5907- . preg_replace('/-(?=-)/', '- ', $XML_RPC_Server_debuginfo)
5908- . "-->\n";
5909- } else {
5910- return '';
5911- }
5912- }
5913-
5914- /**
5915- * Print out the result
5916- *
5917- * The encoding and content-type are determined by
5918- * XML_RPC_Message::getEncoding()
5919- *
5920- * @return void
5921- *
5922- * @see XML_RPC_Message::getEncoding()
5923- */
5924- function service()
5925- {
5926- $r = $this->parseRequest();
5927- $payload = '<?xml version="1.0" encoding="'
5928- . $this->encoding . '"?>' . "\n"
5929- . $this->serializeDebug()
5930- . $r->serialize();
5931- header('Content-Length: ' . strlen($payload));
5932- header('Content-Type: text/xml; charset=' . $this->encoding);
5933- print $payload;
5934- }
5935-
5936- /**
5937- * @return array
5938- */
5939- function verifySignature($in, $sig)
5940- {
5941- for ($i = 0; $i < sizeof($sig); $i++) {
5942- // check each possible signature in turn
5943- $cursig = $sig[$i];
5944- if (sizeof($cursig) == $in->getNumParams() + 1) {
5945- $itsOK = 1;
5946- for ($n = 0; $n < $in->getNumParams(); $n++) {
5947- $p = $in->getParam($n);
5948- // print "<!-- $p -->\n";
5949- if ($p->kindOf() == 'scalar') {
5950- $pt = $p->scalartyp();
5951- } else {
5952- $pt = $p->kindOf();
5953- }
5954- // $n+1 as first type of sig is return type
5955- if ($pt != $cursig[$n+1]) {
5956- $itsOK = 0;
5957- $pno = $n+1;
5958- $wanted = $cursig[$n+1];
5959- $got = $pt;
5960- break;
5961- }
5962- }
5963- if ($itsOK) {
5964- return array(1);
5965- }
5966- }
5967- }
5968- return array(0, "Wanted ${wanted}, got ${got} at param ${pno})");
5969- }
5970-
5971- /**
5972- * @return object a new XML_RPC_Response object
5973- */
5974- function parseRequest($data = '')
5975- {
5976- global $XML_RPC_xh, $HTTP_RAW_POST_DATA,
5977- $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml,
5978- $XML_RPC_defencoding, $XML_RPC_Server_dmap;
5979-
5980- if ($data == '') {
5981- $data = $HTTP_RAW_POST_DATA;
5982- }
5983-
5984- $this->encoding = XML_RPC_Message::getEncoding($data);
5985- $parser = xml_parser_create($this->encoding);
5986-
5987- $XML_RPC_xh[$parser] = array();
5988- $XML_RPC_xh[$parser]['st'] = '';
5989- $XML_RPC_xh[$parser]['cm'] = 0;
5990- $XML_RPC_xh[$parser]['isf'] = 0;
5991- $XML_RPC_xh[$parser]['params'] = array();
5992- $XML_RPC_xh[$parser]['method'] = '';
5993-
5994- $plist = '';
5995-
5996- // decompose incoming XML into request structure
5997-
5998- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
5999- xml_set_element_handler($parser, 'XML_RPC_se', 'XML_RPC_ee');
6000- xml_set_character_data_handler($parser, 'XML_RPC_cd');
6001- if (!xml_parse($parser, $data, 1)) {
6002- // return XML error as a faultCode
6003- $r = new XML_RPC_Response(0,
6004- $XML_RPC_errxml+xml_get_error_code($parser),
6005- sprintf('XML error: %s at line %d',
6006- xml_error_string(xml_get_error_code($parser)),
6007- xml_get_current_line_number($parser)));
6008- xml_parser_free($parser);
6009- } else {
6010- xml_parser_free($parser);
6011- $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']);
6012- // now add parameters in
6013- for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) {
6014- // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n";
6015- $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n";
6016- eval('$m->addParam(' . $XML_RPC_xh[$parser]['params'][$i] . ');');
6017- }
6018- XML_RPC_Server_debugmsg($plist);
6019-
6020- // now to deal with the method
6021- $methName = $XML_RPC_xh[$parser]['method'];
6022- if (strpos($methName, 'system.') === 0) {
6023- $dmap = $XML_RPC_Server_dmap;
6024- $sysCall = 1;
6025- } else {
6026- $dmap = $this->dmap;
6027- $sysCall = 0;
6028- }
6029-
6030- if (isset($dmap[$methName]['function'])
6031- && is_string($dmap[$methName]['function'])
6032- && strpos($dmap[$methName]['function'], '::') !== false)
6033- {
6034- $dmap[$methName]['function'] =
6035- explode('::', $dmap[$methName]['function']);
6036- }
6037-
6038- if (isset($dmap[$methName]['function'])
6039- && is_callable($dmap[$methName]['function']))
6040- {
6041- // dispatch if exists
6042- if (isset($dmap[$methName]['signature'])) {
6043- $sr = $this->verifySignature($m,
6044- $dmap[$methName]['signature'] );
6045- }
6046- if ( (!isset($dmap[$methName]['signature'])) || $sr[0]) {
6047- // if no signature or correct signature
6048- if ($sysCall) {
6049- $r = call_user_func($dmap[$methName]['function'], $this, $m);
6050- } else {
6051- $r = call_user_func($dmap[$methName]['function'], $m);
6052- }
6053- } else {
6054- $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
6055- $XML_RPC_str['incorrect_params']
6056- . ': ' . $sr[1]);
6057- }
6058- } else {
6059- // else prepare error response
6060- $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'],
6061- $XML_RPC_str['unknown_method']);
6062- }
6063- }
6064- return $r;
6065- }
6066-
6067- /**
6068- * Echos back the input packet as a string value
6069- *
6070- * @return void
6071- *
6072- * Useful for debugging.
6073- */
6074- function echoInput() {
6075- global $HTTP_RAW_POST_DATA;
6076-
6077- $r = new XML_RPC_Response(0);
6078- $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string');
6079- print $r->serialize();
6080- }
6081-}
6082-
6083-/*
6084- * Local variables:
6085- * tab-width: 4
6086- * c-basic-offset: 4
6087- * c-hanging-comment-ender-p: nil
6088- * End:
6089- */
6090-
6091-?>
6092-
6093-<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
6094-<package version="1.0" packagerversion="1.4.0a1">
6095- <name>XML_RPC</name>
6096- <summary>PHP implementation of the XML-RPC protocol</summary>
6097- <description>A PEAR-ified version of Useful Inc's XML-RPC for PHP.
6098-
6099-It has support for HTTP/HTTPS transport, proxies and authentication.
6100- </description>
6101- <maintainers>
6102- <maintainer>
6103- <user>ssb</user>
6104- <name>Stig Bakken</name>
6105- <email>stig@php.net</email>
6106- <role>lead</role>
6107- </maintainer>
6108- <maintainer>
6109- <user>danielc</user>
6110- <name>Daniel Convissor</name>
6111- <email>danielc@php.net</email>
6112- <role>lead</role>
6113- </maintainer>
6114- </maintainers>
6115- <release>
6116- <version>1.2.2</version>
6117- <date>2005-03-07</date>
6118- <license>PHP License</license>
6119- <state>stable</state>
6120- <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.
6121- </notes>
6122- <filelist>
6123- <file role="php" baseinstalldir="XML" name="RPC.php">
6124- <replace from="@package_version@" to="version" type="package-info"/>
6125- </file>
6126- <file role="php" baseinstalldir="XML/RPC" name="Server.php">
6127- <replace from="@package_version@" to="version" type="package-info"/>
6128- </file>
6129- <file role="php" baseinstalldir="XML/RPC" name="Dump.php">
6130- <replace from="@package_version@" to="version" type="package-info"/>
6131- </file>
6132- <file role="test" name="tests/protoport.php">
6133- <replace from="@package_version@" to="version" type="package-info"/>
6134- </file>
6135- <file role="test" name="tests/test_Dump.php">
6136- <replace from="@package_version@" to="version" type="package-info"/>
6137- </file>
6138- </filelist>
6139- </release>
6140- <changelog>
6141- <release>
6142- <version>1.2.1</version>
6143- <date>2005-03-01</date>
6144- <state>stable</state>
6145- <notes>* Add isset() check before examining the dispatch map. Bug 3658.
6146- </notes>
6147- </release>
6148- <release>
6149- <version>1.2.0</version>
6150- <date>2005-02-27</date>
6151- <state>stable</state>
6152- <notes>* Provide the &quot;stable&quot; release.
6153-* Add package2.xml for compatibility with PEAR 1.4.0.
6154-* For changes since 1.1.0, see the changelogs for the various RC releases.
6155- </notes>
6156- </release>
6157- <release>
6158- <version>1.2.0RC7</version>
6159- <date>2005-02-22</date>
6160- <state>beta</state>
6161- <notes>* Add the setSendEncoding() method and $send_encoding
6162- property to XML_RPC_Message. Request 3537.
6163-* Allow class methods to be mapped using either syntax:
6164- 'function' =&gt; 'hello::sayHello',
6165- or
6166- 'function' =&gt; array('hello', 'sayhello'),
6167- Bug 3363.
6168-* Use 8192 instead of 32768 for bytes in fread()
6169- in parseResponseFile(). Bug 3340.
6170- </notes>
6171- </release>
6172- <release>
6173- <version>1.2.0RC6</version>
6174- <date>2005-01-25</date>
6175- <state>beta</state>
6176- <notes>* Don't put the protocol in the Host field of the POST data. (danielc)
6177- </notes>
6178- </release>
6179- <release>
6180- <version>1.2.0RC5</version>
6181- <date>2005-01-24</date>
6182- <state>beta</state>
6183- <notes>* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
6184- </notes>
6185- </release>
6186- <release>
6187- <version>1.2.0RC4</version>
6188- <date>2005-01-24</date>
6189- <state>beta</state>
6190- <notes>* When a connection attempt fails, have the method return 0. (danielc)
6191-* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
6192-* Add tests for setting the client properties. (danielc)
6193-* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc)
6194-* Bundle the tests with the package. (danielc)
6195- </notes>
6196- </release>
6197- <release>
6198- <version>1.2.0RC3</version>
6199- <date>2005-01-19</date>
6200- <state>beta</state>
6201- <notes>* ssl uses port 443, not 445.
6202- </notes>
6203- </release>
6204- <release>
6205- <version>1.2.0RC2</version>
6206- <date>2005-01-11</date>
6207- <state>beta</state>
6208- <notes>* Handle ssl:// in the $server string. (danielc)
6209-* Also default to port 445 for ssl:// requests as well. (danielc)
6210-* Enhance debugging in the server. (danielc)
6211- </notes>
6212- </release>
6213- <release>
6214- <version>1.2.0RC1</version>
6215- <date>2004-12-30</date>
6216- <state>beta</state>
6217- <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
6218-* Allow array function callbacks (Matt Kane)
6219-* Some minor speed-ups (Matt Kane)
6220-* Add Dump.php to the package (Christian Weiske)
6221-* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
6222-* Silence fsockopen() errors. Bug 1714. (danielc)
6223-* Encode empty arrays as an array. Bug 1493. (danielc)
6224-* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
6225-* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
6226-* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc)
6227-* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
6228-* Allow raiseError() to be called statically. (danielc)
6229-* Stop double escaping of character entities. Bug 987. (danielc)
6230- NOTICE: the following have been removed:
6231- * XML_RPC_dh()
6232- * $GLOBALS['XML_RPC_entities']
6233- * XML_RPC_entity_decode()
6234- * XML_RPC_lookup_entity()
6235-* Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)
6236- </notes>
6237- </release>
6238- <release>
6239- <version>1.1.0</version>
6240- <date>2004-03-15</date>
6241- <state>stable</state>
6242- <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
6243-* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
6244-* Remove &quot;require_once 'PEAR.php'&quot;, include only when needed to raise an error
6245-* Replace echo and error_log() with raiseError() (mroch)
6246-* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
6247-* be tolerant of junk after methodResponse (Luca Mariano, mroch)
6248-* Silent notice even in the error log (pierre)
6249-* fix include of shared xml extension on win32 (pierre)
6250- </notes>
6251- </release>
6252- <release>
6253- <version>1.0.4</version>
6254- <date>2002-10-02</date>
6255- <state>stable</state>
6256- <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)
6257- </notes>
6258- </release>
6259- <release>
6260- <version>1.0.3</version>
6261- <date>2002-05-19</date>
6262- <state>stable</state>
6263- <notes>* fix bug when parsing responses with boolean types
6264- </notes>
6265- </release>
6266- <release>
6267- <version>1.0.2</version>
6268- <date>2002-04-16</date>
6269- <state>stable</state>
6270- <notes>* E_ALL fixes
6271-* fix HTTP response header parsing
6272- </notes>
6273- </release>
6274- <release>
6275- <version>1.0.1</version>
6276- <date>2001-09-25</date>
6277- <state>stable</state>
6278- <notes>This is a PEAR-ified version of Useful Inc's 1.0.1 release.
6279-Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.
6280- </notes>
6281- </release>
6282- </changelog>
6283-</package>
6284-
6285\ Kein Zeilenumbruch am Dateiende.
6286diff -Naur php-4.3.11/pear/packages/XML_RPC-1.3.1.tar hardening-patch-4.3.11-0.3.2/pear/packages/XML_RPC-1.3.1.tar
6287--- php-4.3.11/pear/packages/XML_RPC-1.3.1.tar 1970-01-01 01:00:00.000000000 +0100
6288+++ hardening-patch-4.3.11-0.3.2/pear/packages/XML_RPC-1.3.1.tar 2005-07-09 08:53:02.503358096 +0200
6289@@ -0,0 +1,3733 @@
6290+package2.xml
6291+<package packagerversion="1.4.0a12" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
6292+ <name>XML_RPC</name>
6293+ <channel>pear.php.net</channel>
6294+ <summary>PHP implementation of the XML-RPC protocol</summary>
6295+ <description>A PEAR-ified version of Useful Inc&apos;s XML-RPC for PHP.
6296+
6297+It has support for HTTP/HTTPS transport, proxies and authentication.</description>
6298+ <lead>
6299+ <name>Stig Bakken</name>
6300+ <user>ssb</user>
6301+ <email>stig@php.net</email>
6302+ <active>no</active>
6303+ </lead>
6304+ <lead>
6305+ <name>Daniel Convissor</name>
6306+ <user>danielc</user>
6307+ <email>danielc@php.net</email>
6308+ <active>yes</active>
6309+ </lead>
6310+ <date>2005-06-29</date>
6311+ <time>15:09:18</time>
6312+ <version>
6313+ <release>1.3.1</release>
6314+ <api>1.3.0</api>
6315+ </version>
6316+ <stability>
6317+ <release>stable</release>
6318+ <api>stable</api>
6319+ </stability>
6320+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6321+ <notes>* Security fix. Update highly recommended!</notes>
6322+ <contents>
6323+ <dir name="/">
6324+ <file md5sum="9b06c053e8e534f8d731eb90de2d0681" name="tests/protoport.php" role="test">
6325+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6326+ </file>
6327+ <file md5sum="74d1c90ae551d28bd40030fcc0b0f38d" name="tests/test_Dump.php" role="test">
6328+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6329+ </file>
6330+ <file baseinstalldir="XML/RPC" md5sum="5e2dfc5771116965655e07b4665563ce" name="Dump.php" role="php">
6331+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6332+ </file>
6333+ <file baseinstalldir="XML" md5sum="1e79cf06ae3ada5a6603c003ac0521e3" name="RPC.php" role="php">
6334+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6335+ </file>
6336+ <file baseinstalldir="XML/RPC" md5sum="6a750e3517d25ca01e685e8afe3976d6" name="Server.php" role="php">
6337+ <tasks:replace from="@package_version@" to="version" type="package-info" />
6338+ </file>
6339+ </dir>
6340+ </contents>
6341+ <compatible>
6342+ <name>PEAR</name>
6343+ <channel>pear.php.net</channel>
6344+ <min>1.4.0a1</min>
6345+ <max>1.4.0a12</max>
6346+ </compatible>
6347+ <dependencies>
6348+ <required>
6349+ <php>
6350+ <min>4.2.0</min>
6351+ <max>6.0.0</max>
6352+ </php>
6353+ <pearinstaller>
6354+ <min>1.4.0a1</min>
6355+ </pearinstaller>
6356+ </required>
6357+ </dependencies>
6358+ <phprelease />
6359+ <changelog>
6360+ <release>
6361+ <version>
6362+ <release>1.3.0RC3</release>
6363+ <api>1.3.0</api>
6364+ </version>
6365+ <stability>
6366+ <release>beta</release>
6367+ <api>stable</api>
6368+ </stability>
6369+ <date>2005-05-10</date>
6370+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6371+ <notes>* When verifying requests against function signatures, if the number of parameters don&apos;t match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
6372+* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
6373+* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
6374+* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
6375+* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
6376+* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().</notes>
6377+ </release>
6378+ <release>
6379+ <version>
6380+ <release>1.3.0RC2</release>
6381+ <api>1.3.0</api>
6382+ </version>
6383+ <stability>
6384+ <release>beta</release>
6385+ <api>beta</api>
6386+ </stability>
6387+ <date>2005-05-05</date>
6388+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6389+ <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
6390+* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
6391+* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
6392+* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.</notes>
6393+ </release>
6394+ <release>
6395+ <version>
6396+ <release>1.3.0RC1</release>
6397+ <api>1.3.0</api>
6398+ </version>
6399+ <stability>
6400+ <release>beta</release>
6401+ <api>beta</api>
6402+ </stability>
6403+ <date>2005-04-07</date>
6404+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6405+ <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
6406+* Add Fault Code 6: &quot;The requested method didn&apos;t return an XML_RPC_Response object.&quot; Request 4032.
6407+* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
6408+* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
6409+* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
6410+* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.</notes>
6411+ </release>
6412+ <release>
6413+ <version>
6414+ <release>1.2.2</release>
6415+ <api>1.2.0</api>
6416+ </version>
6417+ <stability>
6418+ <release>stable</release>
6419+ <api>stable</api>
6420+ </stability>
6421+ <date>2005-03-07</date>
6422+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6423+ <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.</notes>
6424+ </release>
6425+ <release>
6426+ <version>
6427+ <release>1.2.1</release>
6428+ <api>1.2.0</api>
6429+ </version>
6430+ <stability>
6431+ <release>stable</release>
6432+ <api>stable</api>
6433+ </stability>
6434+ <date>2005-03-01</date>
6435+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6436+ <notes>* Add isset() check before examining the dispatch map. Bug 3658.</notes>
6437+ </release>
6438+ <release>
6439+ <version>
6440+ <release>1.2.0</release>
6441+ <api>1.2.0</api>
6442+ </version>
6443+ <stability>
6444+ <release>stable</release>
6445+ <api>stable</api>
6446+ </stability>
6447+ <date>2005-02-27</date>
6448+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6449+ <notes>* Provide the &quot;stable&quot; release.
6450+* Add package2.xml for compatibility with PEAR 1.4.0.
6451+* For changes since 1.1.0, see the changelogs for the various RC releases.</notes>
6452+ </release>
6453+ <release>
6454+ <version>
6455+ <release>1.2.0RC7</release>
6456+ <api>1.2.0RC7</api>
6457+ </version>
6458+ <stability>
6459+ <release>beta</release>
6460+ <api>beta</api>
6461+ </stability>
6462+ <date>2005-02-22</date>
6463+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6464+ <notes>* Add the setSendEncoding() method and $send_encoding
6465+ property to XML_RPC_Message. Request 3537.
6466+* Allow class methods to be mapped using either syntax:
6467+ &apos;function&apos; =&gt; &apos;hello::sayHello&apos;,
6468+ or
6469+ &apos;function&apos; =&gt; array(&apos;hello&apos;, &apos;sayhello&apos;),
6470+ Bug 3363.
6471+* Use 8192 instead of 32768 for bytes in fread()
6472+ in parseResponseFile(). Bug 3340.</notes>
6473+ </release>
6474+ <release>
6475+ <version>
6476+ <release>1.2.0RC6</release>
6477+ <api>1.2.0RC6</api>
6478+ </version>
6479+ <stability>
6480+ <release>beta</release>
6481+ <api>beta</api>
6482+ </stability>
6483+ <date>2005-01-25</date>
6484+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6485+ <notes>* Don&apos;t put the protocol in the Host field of the POST data. (danielc)</notes>
6486+ </release>
6487+ <release>
6488+ <version>
6489+ <release>1.2.0RC5</release>
6490+ <api>1.2.0RC5</api>
6491+ </version>
6492+ <stability>
6493+ <release>beta</release>
6494+ <api>beta</api>
6495+ </stability>
6496+ <date>2005-01-24</date>
6497+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6498+ <notes>* If $port is 443 but a protocol isn&apos;t specified in $server, assume ssl:// is the protocol.</notes>
6499+ </release>
6500+ <release>
6501+ <version>
6502+ <release>1.2.0RC4</release>
6503+ <api>1.2.0RC4</api>
6504+ </version>
6505+ <stability>
6506+ <release>beta</release>
6507+ <api>beta</api>
6508+ </stability>
6509+ <date>2005-01-24</date>
6510+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6511+ <notes>* When a connection attempt fails, have the method return 0. (danielc)
6512+* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
6513+* Add tests for setting the client properties. (danielc)
6514+* Remove $GLOBALS[&apos;XML_RPC_twoslash&apos;] since it&apos;s not used. (danielc)
6515+* Bundle the tests with the package. (danielc)</notes>
6516+ </release>
6517+ <release>
6518+ <version>
6519+ <release>1.2.0RC3</release>
6520+ <api>1.2.0RC3</api>
6521+ </version>
6522+ <stability>
6523+ <release>beta</release>
6524+ <api>beta</api>
6525+ </stability>
6526+ <date>2005-01-19</date>
6527+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6528+ <notes>* ssl uses port 443, not 445.</notes>
6529+ </release>
6530+ <release>
6531+ <version>
6532+ <release>1.2.0RC2</release>
6533+ <api>1.2.0RC2</api>
6534+ </version>
6535+ <stability>
6536+ <release>beta</release>
6537+ <api>beta</api>
6538+ </stability>
6539+ <date>2005-01-11</date>
6540+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6541+ <notes>* Handle ssl:// in the $server string. (danielc)
6542+* Also default to port 445 for ssl:// requests as well. (danielc)
6543+* Enhance debugging in the server. (danielc)</notes>
6544+ </release>
6545+ <release>
6546+ <version>
6547+ <release>1.2.0RC1</release>
6548+ <api>1.2.0RC1</api>
6549+ </version>
6550+ <stability>
6551+ <release>beta</release>
6552+ <api>beta</api>
6553+ </stability>
6554+ <date>2004-12-30</date>
6555+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6556+ <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
6557+* Allow array function callbacks (Matt Kane)
6558+* Some minor speed-ups (Matt Kane)
6559+* Add Dump.php to the package (Christian Weiske)
6560+* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
6561+* Silence fsockopen() errors. Bug 1714. (danielc)
6562+* Encode empty arrays as an array. Bug 1493. (danielc)
6563+* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
6564+* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
6565+* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()&apos;ing error messages. (danielc)
6566+* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
6567+* Allow raiseError() to be called statically. (danielc)
6568+* Stop double escaping of character entities. Bug 987. (danielc)
6569+ NOTICE: the following have been removed:
6570+ * XML_RPC_dh()
6571+ * $GLOBALS[&apos;XML_RPC_entities&apos;]
6572+ * XML_RPC_entity_decode()
6573+ * XML_RPC_lookup_entity()
6574+* Determine the XML&apos;s encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)</notes>
6575+ </release>
6576+ <release>
6577+ <version>
6578+ <release>1.1.0</release>
6579+ <api>1.1.0</api>
6580+ </version>
6581+ <stability>
6582+ <release>stable</release>
6583+ <api>stable</api>
6584+ </stability>
6585+ <date>2004-03-15</date>
6586+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6587+ <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
6588+* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
6589+* Remove &quot;require_once &apos;PEAR.php&apos;&quot;, include only when needed to raise an error
6590+* Replace echo and error_log() with raiseError() (mroch)
6591+* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
6592+* be tolerant of junk after methodResponse (Luca Mariano, mroch)
6593+* Silent notice even in the error log (pierre)
6594+* fix include of shared xml extension on win32 (pierre)</notes>
6595+ </release>
6596+ <release>
6597+ <version>
6598+ <release>1.0.4</release>
6599+ <api>1.0.4</api>
6600+ </version>
6601+ <stability>
6602+ <release>stable</release>
6603+ <api>stable</api>
6604+ </stability>
6605+ <date>2002-10-02</date>
6606+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6607+ <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)</notes>
6608+ </release>
6609+ <release>
6610+ <version>
6611+ <release>1.0.3</release>
6612+ <api>1.0.3</api>
6613+ </version>
6614+ <stability>
6615+ <release>stable</release>
6616+ <api>stable</api>
6617+ </stability>
6618+ <date>2002-05-19</date>
6619+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6620+ <notes>* fix bug when parsing responses with boolean types</notes>
6621+ </release>
6622+ <release>
6623+ <version>
6624+ <release>1.0.2</release>
6625+ <api>1.0.2</api>
6626+ </version>
6627+ <stability>
6628+ <release>stable</release>
6629+ <api>stable</api>
6630+ </stability>
6631+ <date>2002-04-16</date>
6632+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6633+ <notes>* E_ALL fixes
6634+* fix HTTP response header parsing</notes>
6635+ </release>
6636+ <release>
6637+ <version>
6638+ <release>1.0.1</release>
6639+ <api>1.0.1</api>
6640+ </version>
6641+ <stability>
6642+ <release>stable</release>
6643+ <api>stable</api>
6644+ </stability>
6645+ <date>2001-09-25</date>
6646+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
6647+ <notes>This is a PEAR-ified version of Useful Inc&apos;s 1.0.1 release.
6648+Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.</notes>
6649+ </release>
6650+ </changelog>
6651+</package>
6652+
6653+
6654+/**
6655+ * Tests that properties of XML_RPC_Client get properly set
6656+ *
6657+ * Any individual tests that fail will have their name, expected result
6658+ * and actual result printed out. So seeing no output when executing
6659+ * this file is a good thing.
6660+ *
6661+ * Can be run via CLI or a web server.
6662+ *
6663+ * PHP versions 4 and 5
6664+ *
6665+ * LICENSE: This source file is subject to version 3.0 of the PHP license
6666+ * that is available through the world-wide-web at the following URI:
6667+ * http://www.php.net/license/3_0.txt. If you did not receive a copy of
6668+ * the PHP License and are unable to obtain it through the web, please
6669+ * send a note to license@php.net so we can mail you a copy immediately.
6670+ *
6671+ * @category Web Services
6672+ * @package XML_RPC
6673+ * @author Daniel Convissor <danielc@php.net>
6674+ * @copyright 2005 The PHP Group
6675+ * @license http://www.php.net/license/3_0.txt PHP License
6676+ * @version CVS: $Id: protoport.php,v 1.4 2005/01/24 17:48:47 danielc Exp $
6677+ * @link http://pear.php.net/package/XML_RPC
6678+ * @since File available since Release 1.2
6679+ */
6680+
6681+/*
6682+ * If the package version number is found in the left hand
6683+ * portion of the if() expression below, that means this file has
6684+ * come from the PEAR installer. Therefore, let's test the
6685+ * installed version of XML_RPC which should be in the include path.
6686+ *
6687+ * If the version has not been substituted in the if() expression,
6688+ * this file has likely come from a CVS checkout or a .tar file.
6689+ * Therefore, we'll assume the tests should use the version of
6690+ * XML_RPC that has come from there as well.
6691+ */
6692+if ('1.3.1' != '@'.'package_version'.'@') {
6693+ /**
6694+ * Get the needed class from the PEAR installation
6695+ */
6696+ require_once 'XML/RPC.php';
6697+} else {
6698+ /**
6699+ * Get the needed class from the parent directory
6700+ */
6701+ require_once '../RPC.php';
6702+}
6703+
6704+/**
6705+ * Compare the test result to the expected result
6706+ *
6707+ * If the test fails, echo out the results.
6708+ *
6709+ * @param array $expect the array of object properties you expect
6710+ * from the test
6711+ * @param object $actual the object results from the test
6712+ * @param string $test_name the name of the test
6713+ *
6714+ * @return void
6715+ */
6716+function compare($expect, $actual, $test_name) {
6717+ $actual = get_object_vars($actual);
6718+ if (count(array_diff($actual, $expect))) {
6719+ echo "$test_name failed.\nExpect: ";
6720+ print_r($expect);
6721+ echo "Actual: ";
6722+ print_r($actual);
6723+ echo "\n";
6724+ }
6725+}
6726+
6727+if (php_sapi_name() != 'cli') {
6728+ echo "<pre>\n";
6729+}
6730+
6731+
6732+$x = array(
6733+ 'path' => 'thepath',
6734+ 'server' => 'theserver',
6735+ 'protocol' => 'http://',
6736+ 'port' => 80,
6737+ 'proxy' => '',
6738+ 'proxy_protocol' => 'http://',
6739+ 'proxy_port' => 8080,
6740+ 'proxy_user' => '',
6741+ 'proxy_pass' => '',
6742+ 'errno' => 0,
6743+ 'errstring' => '',
6744+ 'debug' => 0,
6745+ 'username' => '',
6746+ 'password' => '',
6747+);
6748+$c = new XML_RPC_Client('thepath', 'theserver');
6749+compare($x, $c, 'defaults');
6750+
6751+$x = array(
6752+ 'path' => 'thepath',
6753+ 'server' => 'theserver',
6754+ 'protocol' => 'http://',
6755+ 'port' => 80,
6756+ 'proxy' => '',
6757+ 'proxy_protocol' => 'http://',
6758+ 'proxy_port' => 8080,
6759+ 'proxy_user' => '',
6760+ 'proxy_pass' => '',
6761+ 'errno' => 0,
6762+ 'errstring' => '',
6763+ 'debug' => 0,
6764+ 'username' => '',
6765+ 'password' => '',
6766+);
6767+$c = new XML_RPC_Client('thepath', 'http://theserver');
6768+compare($x, $c, 'defaults with http');
6769+
6770+$x = array(
6771+ 'path' => 'thepath',
6772+ 'server' => 'theserver',
6773+ 'protocol' => 'ssl://',
6774+ 'port' => 443,
6775+ 'proxy' => '',
6776+ 'proxy_protocol' => 'http://',
6777+ 'proxy_port' => 8080,
6778+ 'proxy_user' => '',
6779+ 'proxy_pass' => '',
6780+ 'errno' => 0,
6781+ 'errstring' => '',
6782+ 'debug' => 0,
6783+ 'username' => '',
6784+ 'password' => '',
6785+);
6786+$c = new XML_RPC_Client('thepath', 'https://theserver');
6787+compare($x, $c, 'defaults with https');
6788+
6789+$x = array(
6790+ 'path' => 'thepath',
6791+ 'server' => 'theserver',
6792+ 'protocol' => 'ssl://',
6793+ 'port' => 443,
6794+ 'proxy' => '',
6795+ 'proxy_protocol' => 'http://',
6796+ 'proxy_port' => 8080,
6797+ 'proxy_user' => '',
6798+ 'proxy_pass' => '',
6799+ 'errno' => 0,
6800+ 'errstring' => '',
6801+ 'debug' => 0,
6802+ 'username' => '',
6803+ 'password' => '',
6804+);
6805+$c = new XML_RPC_Client('thepath', 'ssl://theserver');
6806+compare($x, $c, 'defaults with ssl');
6807+
6808+
6809+$x = array(
6810+ 'path' => 'thepath',
6811+ 'server' => 'theserver',
6812+ 'protocol' => 'http://',
6813+ 'port' => 65,
6814+ 'proxy' => '',
6815+ 'proxy_protocol' => 'http://',
6816+ 'proxy_port' => 8080,
6817+ 'proxy_user' => '',
6818+ 'proxy_pass' => '',
6819+ 'errno' => 0,
6820+ 'errstring' => '',
6821+ 'debug' => 0,
6822+ 'username' => '',
6823+ 'password' => '',
6824+);
6825+$c = new XML_RPC_Client('thepath', 'theserver', 65);
6826+compare($x, $c, 'port 65');
6827+
6828+$x = array(
6829+ 'path' => 'thepath',
6830+ 'server' => 'theserver',
6831+ 'protocol' => 'http://',
6832+ 'port' => 65,
6833+ 'proxy' => '',
6834+ 'proxy_protocol' => 'http://',
6835+ 'proxy_port' => 8080,
6836+ 'proxy_user' => '',
6837+ 'proxy_pass' => '',
6838+ 'errno' => 0,
6839+ 'errstring' => '',
6840+ 'debug' => 0,
6841+ 'username' => '',
6842+ 'password' => '',
6843+);
6844+$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
6845+compare($x, $c, 'port 65 with http');
6846+
6847+$x = array(
6848+ 'path' => 'thepath',
6849+ 'server' => 'theserver',
6850+ 'protocol' => 'ssl://',
6851+ 'port' => 65,
6852+ 'proxy' => '',
6853+ 'proxy_protocol' => 'http://',
6854+ 'proxy_port' => 8080,
6855+ 'proxy_user' => '',
6856+ 'proxy_pass' => '',
6857+ 'errno' => 0,
6858+ 'errstring' => '',
6859+ 'debug' => 0,
6860+ 'username' => '',
6861+ 'password' => '',
6862+);
6863+$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
6864+compare($x, $c, 'port 65 with https');
6865+
6866+$x = array(
6867+ 'path' => 'thepath',
6868+ 'server' => 'theserver',
6869+ 'protocol' => 'ssl://',
6870+ 'port' => 65,
6871+ 'proxy' => '',
6872+ 'proxy_protocol' => 'http://',
6873+ 'proxy_port' => 8080,
6874+ 'proxy_user' => '',
6875+ 'proxy_pass' => '',
6876+ 'errno' => 0,
6877+ 'errstring' => '',
6878+ 'debug' => 0,
6879+ 'username' => '',
6880+ 'password' => '',
6881+);
6882+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
6883+compare($x, $c, 'port 65 with ssl');
6884+
6885+
6886+$x = array(
6887+ 'path' => 'thepath',
6888+ 'server' => 'theserver',
6889+ 'protocol' => 'http://',
6890+ 'port' => 80,
6891+ 'proxy' => 'theproxy',
6892+ 'proxy_protocol' => 'http://',
6893+ 'proxy_port' => 8080,
6894+ 'proxy_user' => '',
6895+ 'proxy_pass' => '',
6896+ 'errno' => 0,
6897+ 'errstring' => '',
6898+ 'debug' => 0,
6899+ 'username' => '',
6900+ 'password' => '',
6901+);
6902+$c = new XML_RPC_Client('thepath', 'theserver', 0,
6903+ 'theproxy');
6904+compare($x, $c, 'defaults proxy');
6905+
6906+$x = array(
6907+ 'path' => 'thepath',
6908+ 'server' => 'theserver',
6909+ 'protocol' => 'http://',
6910+ 'port' => 80,
6911+ 'proxy' => 'theproxy',
6912+ 'proxy_protocol' => 'http://',
6913+ 'proxy_port' => 8080,
6914+ 'proxy_user' => '',
6915+ 'proxy_pass' => '',
6916+ 'errno' => 0,
6917+ 'errstring' => '',
6918+ 'debug' => 0,
6919+ 'username' => '',
6920+ 'password' => '',
6921+);
6922+$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
6923+ 'http://theproxy');
6924+compare($x, $c, 'defaults with http proxy');
6925+
6926+$x = array(
6927+ 'path' => 'thepath',
6928+ 'server' => 'theserver',
6929+ 'protocol' => 'ssl://',
6930+ 'port' => 443,
6931+ 'proxy' => 'theproxy',
6932+ 'proxy_protocol' => 'ssl://',
6933+ 'proxy_port' => 443,
6934+ 'proxy_user' => '',
6935+ 'proxy_pass' => '',
6936+ 'errno' => 0,
6937+ 'errstring' => '',
6938+ 'debug' => 0,
6939+ 'username' => '',
6940+ 'password' => '',
6941+);
6942+$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
6943+ 'https://theproxy');
6944+compare($x, $c, 'defaults with https proxy');
6945+
6946+$x = array(
6947+ 'path' => 'thepath',
6948+ 'server' => 'theserver',
6949+ 'protocol' => 'ssl://',
6950+ 'port' => 443,
6951+ 'proxy' => 'theproxy',
6952+ 'proxy_protocol' => 'ssl://',
6953+ 'proxy_port' => 443,
6954+ 'proxy_user' => '',
6955+ 'proxy_pass' => '',
6956+ 'errno' => 0,
6957+ 'errstring' => '',
6958+ 'debug' => 0,
6959+ 'username' => '',
6960+ 'password' => '',
6961+);
6962+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
6963+ 'ssl://theproxy');
6964+compare($x, $c, 'defaults with ssl proxy');
6965+
6966+
6967+$x = array(
6968+ 'path' => 'thepath',
6969+ 'server' => 'theserver',
6970+ 'protocol' => 'http://',
6971+ 'port' => 65,
6972+ 'proxy' => 'theproxy',
6973+ 'proxy_protocol' => 'http://',
6974+ 'proxy_port' => 6565,
6975+ 'proxy_user' => '',
6976+ 'proxy_pass' => '',
6977+ 'errno' => 0,
6978+ 'errstring' => '',
6979+ 'debug' => 0,
6980+ 'username' => '',
6981+ 'password' => '',
6982+);
6983+$c = new XML_RPC_Client('thepath', 'theserver', 65,
6984+ 'theproxy', 6565);
6985+compare($x, $c, 'port 65 proxy 6565');
6986+
6987+$x = array(
6988+ 'path' => 'thepath',
6989+ 'server' => 'theserver',
6990+ 'protocol' => 'http://',
6991+ 'port' => 65,
6992+ 'proxy' => 'theproxy',
6993+ 'proxy_protocol' => 'http://',
6994+ 'proxy_port' => 6565,
6995+ 'proxy_user' => '',
6996+ 'proxy_pass' => '',
6997+ 'errno' => 0,
6998+ 'errstring' => '',
6999+ 'debug' => 0,
7000+ 'username' => '',
7001+ 'password' => '',
7002+);
7003+$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
7004+ 'http://theproxy', 6565);
7005+compare($x, $c, 'port 65 with http proxy 6565');
7006+
7007+$x = array(
7008+ 'path' => 'thepath',
7009+ 'server' => 'theserver',
7010+ 'protocol' => 'ssl://',
7011+ 'port' => 65,
7012+ 'proxy' => 'theproxy',
7013+ 'proxy_protocol' => 'ssl://',
7014+ 'proxy_port' => 6565,
7015+ 'proxy_user' => '',
7016+ 'proxy_pass' => '',
7017+ 'errno' => 0,
7018+ 'errstring' => '',
7019+ 'debug' => 0,
7020+ 'username' => '',
7021+ 'password' => '',
7022+);
7023+$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
7024+ 'https://theproxy', 6565);
7025+compare($x, $c, 'port 65 with https proxy 6565');
7026+
7027+$x = array(
7028+ 'path' => 'thepath',
7029+ 'server' => 'theserver',
7030+ 'protocol' => 'ssl://',
7031+ 'port' => 65,
7032+ 'proxy' => 'theproxy',
7033+ 'proxy_protocol' => 'ssl://',
7034+ 'proxy_port' => 6565,
7035+ 'proxy_user' => '',
7036+ 'proxy_pass' => '',
7037+ 'errno' => 0,
7038+ 'errstring' => '',
7039+ 'debug' => 0,
7040+ 'username' => '',
7041+ 'password' => '',
7042+);
7043+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
7044+ 'ssl://theproxy', 6565);
7045+compare($x, $c, 'port 65 with ssl proxy 6565');
7046+
7047+
7048+$x = array(
7049+ 'path' => 'thepath',
7050+ 'server' => 'theserver',
7051+ 'protocol' => 'ssl://',
7052+ 'port' => 443,
7053+ 'proxy' => 'theproxy',
7054+ 'proxy_protocol' => 'ssl://',
7055+ 'proxy_port' => 443,
7056+ 'proxy_user' => '',
7057+ 'proxy_pass' => '',
7058+ 'errno' => 0,
7059+ 'errstring' => '',
7060+ 'debug' => 0,
7061+ 'username' => '',
7062+ 'password' => '',
7063+);
7064+$c = new XML_RPC_Client('thepath', 'theserver', 443,
7065+ 'theproxy', 443);
7066+compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
7067+
7068+$x = array(
7069+ 'path' => 'thepath',
7070+ 'server' => 'theserver',
7071+ 'protocol' => 'http://',
7072+ 'port' => 80,
7073+ 'proxy' => 'theproxy',
7074+ 'proxy_protocol' => 'ssl://',
7075+ 'proxy_port' => 6565,
7076+ 'proxy_user' => '',
7077+ 'proxy_pass' => '',
7078+ 'errno' => 0,
7079+ 'errstring' => '',
7080+ 'debug' => 0,
7081+ 'username' => '',
7082+ 'password' => '',
7083+);
7084+$c = new XML_RPC_Client('thepath', 'theserver', 0,
7085+ 'ssl://theproxy', 6565);
7086+compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
7087+
7088+
7089+/*
7090+ * If the package version number is found in the left hand
7091+ * portion of the if() expression below, that means this file has
7092+ * come from the PEAR installer. Therefore, let's test the
7093+ * installed version of XML_RPC which should be in the include path.
7094+ *
7095+ * If the version has not been substituted in the if() expression,
7096+ * this file has likely come from a CVS checkout or a .tar file.
7097+ * Therefore, we'll assume the tests should use the version of
7098+ * XML_RPC that has come from there as well.
7099+ */
7100+if ('1.3.1' != '@'.'package_version'.'@') {
7101+ /**
7102+ * Get the needed class from the PEAR installation
7103+ */
7104+ require_once 'XML/RPC/Dump.php';
7105+} else {
7106+ /**
7107+ * Get the needed class from the parent directory
7108+ */
7109+ require_once '../Dump.php';
7110+}
7111+
7112+$val = new XML_RPC_Value(array(
7113+ 'title' =>new XML_RPC_Value('das ist der Titel', 'string'),
7114+ 'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
7115+ 'endDate' =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
7116+ 'error' =>'string',
7117+ 'arkey' => new XML_RPC_Value( array(
7118+ new XML_RPC_Value('simple string'),
7119+ new XML_RPC_Value(12345, 'int')
7120+ ), 'array')
7121+ )
7122+ ,'struct');
7123+
7124+XML_RPC_Dump($val);
7125+
7126+echo '==============' . "\r\n";
7127+$val2 = new XML_RPC_Value(44353, 'int');
7128+XML_RPC_Dump($val2);
7129+
7130+echo '==============' . "\r\n";
7131+$val3 = new XML_RPC_Value('this should be a string', 'string');
7132+XML_RPC_Dump($val3);
7133+
7134+echo '==============' . "\r\n";
7135+$val4 = new XML_RPC_Value(true, 'boolean');
7136+XML_RPC_Dump($val4);
7137+
7138+
7139+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
7140+
7141+/**
7142+ * Function and class to dump XML_RPC_Value objects in a nice way
7143+ *
7144+ * Should be helpful as a normal var_dump(..) displays all internals which
7145+ * doesn't really give you an overview due to too much information.
7146+ *
7147+ * @category Web Services
7148+ * @package XML_RPC
7149+ * @author Christian Weiske <cweiske@php.net>
7150+ * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $
7151+ * @link http://pear.php.net/package/XML_RPC
7152+ */
7153+
7154+
7155+/**
7156+ * Pull in the XML_RPC class
7157+ */
7158+require_once 'XML/RPC.php';
7159+
7160+
7161+/**
7162+ * Generates the dump of the XML_RPC_Value and echoes it
7163+ *
7164+ * @param object $value the XML_RPC_Value object to dump
7165+ *
7166+ * @return void
7167+ */
7168+function XML_RPC_Dump($value)
7169+{
7170+ $dumper = new XML_RPC_Dump();
7171+ echo $dumper->generateDump($value);
7172+}
7173+
7174+
7175+/**
7176+ * Class which generates a dump of a XML_RPC_Value object
7177+ *
7178+ * @category Web Services
7179+ * @package XML_RPC
7180+ * @author Christian Weiske <cweiske@php.net>
7181+ * @version Release: 1.3.1
7182+ * @link http://pear.php.net/package/XML_RPC
7183+ */
7184+class XML_RPC_Dump
7185+{
7186+ /**
7187+ * The indentation array cache
7188+ * @var array
7189+ */
7190+ var $arIndent = array();
7191+
7192+ /**
7193+ * The spaces used for indenting the XML
7194+ * @var string
7195+ */
7196+ var $strBaseIndent = ' ';
7197+
7198+ /**
7199+ * Returns the dump in XML format without printing it out
7200+ *
7201+ * @param object $value the XML_RPC_Value object to dump
7202+ * @param int $nLevel the level of indentation
7203+ *
7204+ * @return string the dump
7205+ */
7206+ function generateDump($value, $nLevel = 0)
7207+ {
7208+ if (!is_object($value) && get_class($value) != 'xml_rpc_value') {
7209+ require_once 'PEAR.php';
7210+ PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n",
7211+ 0, PEAR_ERROR_PRINT);
7212+ if (is_object($value)) {
7213+ $strType = get_class($value);
7214+ } else {
7215+ $strType = gettype($value);
7216+ }
7217+ return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: '
7218+ . $strType . "\r\n";
7219+ }
7220+
7221+ switch ($value->kindOf()) {
7222+ case 'struct':
7223+ $ret = $this->genStruct($value, $nLevel);
7224+ break;
7225+ case 'array':
7226+ $ret = $this->genArray($value, $nLevel);
7227+ break;
7228+ case 'scalar':
7229+ $ret = $this->genScalar($value->scalarval(), $nLevel);
7230+ break;
7231+ default:
7232+ require_once 'PEAR.php';
7233+ PEAR::raiseError('Illegal type "' . $value->kindOf()
7234+ . '" in XML_RPC_Value' . "\r\n", 0,
7235+ PEAR_ERROR_PRINT);
7236+ }
7237+
7238+ return $ret;
7239+ }
7240+
7241+ /**
7242+ * Returns the scalar value dump
7243+ *
7244+ * @param object $value the scalar XML_RPC_Value object to dump
7245+ * @param int $nLevel the level of indentation
7246+ *
7247+ * @return string Dumped version of the scalar value
7248+ */
7249+ function genScalar($value, $nLevel)
7250+ {
7251+ if (gettype($value) == 'object') {
7252+ $strClass = ' ' . get_class($value);
7253+ } else {
7254+ $strClass = '';
7255+ }
7256+ return $this->getIndent($nLevel) . gettype($value) . $strClass
7257+ . ' ' . $value . "\r\n";
7258+ }
7259+
7260+ /**
7261+ * Returns the dump of a struct
7262+ *
7263+ * @param object $value the struct XML_RPC_Value object to dump
7264+ * @param int $nLevel the level of indentation
7265+ *
7266+ * @return string Dumped version of the scalar value
7267+ */
7268+ function genStruct($value, $nLevel)
7269+ {
7270+ $value->structreset();
7271+ $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n";
7272+ while (list($key, $keyval) = $value->structeach()) {
7273+ $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n";
7274+ $strOutput .= $this->generateDump($keyval, $nLevel + 2);
7275+ }
7276+ return $strOutput;
7277+ }
7278+
7279+ /**
7280+ * Returns the dump of an array
7281+ *
7282+ * @param object $value the array XML_RPC_Value object to dump
7283+ * @param int $nLevel the level of indentation
7284+ *
7285+ * @return string Dumped version of the scalar value
7286+ */
7287+ function genArray($value, $nLevel)
7288+ {
7289+ $nSize = $value->arraysize();
7290+ $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n";
7291+ for($nA = 0; $nA < $nSize; $nA++) {
7292+ $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n";
7293+ $strOutput .= $this->generateDump($value->arraymem($nA),
7294+ $nLevel + 2);
7295+ }
7296+ return $strOutput;
7297+ }
7298+
7299+ /**
7300+ * Returns the indent for a specific level and caches it for faster use
7301+ *
7302+ * @param int $nLevel the level
7303+ *
7304+ * @return string the indented string
7305+ */
7306+ function getIndent($nLevel)
7307+ {
7308+ if (!isset($this->arIndent[$nLevel])) {
7309+ $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel);
7310+ }
7311+ return $this->arIndent[$nLevel];
7312+ }
7313+}
7314+
7315+/*
7316+ * Local variables:
7317+ * tab-width: 4
7318+ * c-basic-offset: 4
7319+ * c-hanging-comment-ender-p: nil
7320+ * End:
7321+ */
7322+
7323+?>
7324+
7325+
7326+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
7327+
7328+/**
7329+ * PHP implementation of the XML-RPC protocol
7330+ *
7331+ * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
7332+ * It has support for HTTP transport, proxies and authentication.
7333+ *
7334+ * PHP versions 4 and 5
7335+ *
7336+ * LICENSE: License is granted to use or modify this software
7337+ * ("XML-RPC for PHP") for commercial or non-commercial use provided the
7338+ * copyright of the author is preserved in any distributed or derivative work.
7339+ *
7340+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
7341+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
7342+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
7343+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
7344+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
7345+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
7346+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7347+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7348+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
7349+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7350+ *
7351+ * @category Web Services
7352+ * @package XML_RPC
7353+ * @author Edd Dumbill <edd@usefulinc.com>
7354+ * @author Stig Bakken <stig@php.net>
7355+ * @author Martin Jansen <mj@php.net>
7356+ * @author Daniel Convissor <danielc@php.net>
7357+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7358+ * @version CVS: $Id: RPC.php,v 1.74 2005/05/09 20:51:54 danielc Exp $
7359+ * @link http://pear.php.net/package/XML_RPC
7360+ */
7361+
7362+
7363+if (!function_exists('xml_parser_create')) {
7364+ PEAR::loadExtension('xml');
7365+}
7366+
7367+/**#@+
7368+ * Error constants
7369+ */
7370+/**
7371+ * Parameter values don't match parameter types
7372+ */
7373+define('XML_RPC_ERROR_INVALID_TYPE', 101);
7374+/**
7375+ * Parameter declared to be numeric but the values are not
7376+ */
7377+define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
7378+/**
7379+ * Communication error
7380+ */
7381+define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
7382+/**
7383+ * The array or struct has already been started
7384+ */
7385+define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
7386+/**
7387+ * Incorrect parameters submitted
7388+ */
7389+define('XML_RPC_ERROR_INCORRECT_PARAMS', 105);
7390+/**
7391+ * Programming error by developer
7392+ */
7393+define('XML_RPC_ERROR_PROGRAMMING', 106);
7394+/**#@-*/
7395+
7396+
7397+/**
7398+ * Data types
7399+ * @global string $GLOBALS['XML_RPC_I4']
7400+ */
7401+$GLOBALS['XML_RPC_I4'] = 'i4';
7402+
7403+/**
7404+ * Data types
7405+ * @global string $GLOBALS['XML_RPC_Int']
7406+ */
7407+$GLOBALS['XML_RPC_Int'] = 'int';
7408+
7409+/**
7410+ * Data types
7411+ * @global string $GLOBALS['XML_RPC_Boolean']
7412+ */
7413+$GLOBALS['XML_RPC_Boolean'] = 'boolean';
7414+
7415+/**
7416+ * Data types
7417+ * @global string $GLOBALS['XML_RPC_Double']
7418+ */
7419+$GLOBALS['XML_RPC_Double'] = 'double';
7420+
7421+/**
7422+ * Data types
7423+ * @global string $GLOBALS['XML_RPC_String']
7424+ */
7425+$GLOBALS['XML_RPC_String'] = 'string';
7426+
7427+/**
7428+ * Data types
7429+ * @global string $GLOBALS['XML_RPC_DateTime']
7430+ */
7431+$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601';
7432+
7433+/**
7434+ * Data types
7435+ * @global string $GLOBALS['XML_RPC_Base64']
7436+ */
7437+$GLOBALS['XML_RPC_Base64'] = 'base64';
7438+
7439+/**
7440+ * Data types
7441+ * @global string $GLOBALS['XML_RPC_Array']
7442+ */
7443+$GLOBALS['XML_RPC_Array'] = 'array';
7444+
7445+/**
7446+ * Data types
7447+ * @global string $GLOBALS['XML_RPC_Struct']
7448+ */
7449+$GLOBALS['XML_RPC_Struct'] = 'struct';
7450+
7451+
7452+/**
7453+ * Data type meta-types
7454+ * @global array $GLOBALS['XML_RPC_Types']
7455+ */
7456+$GLOBALS['XML_RPC_Types'] = array(
7457+ $GLOBALS['XML_RPC_I4'] => 1,
7458+ $GLOBALS['XML_RPC_Int'] => 1,
7459+ $GLOBALS['XML_RPC_Boolean'] => 1,
7460+ $GLOBALS['XML_RPC_String'] => 1,
7461+ $GLOBALS['XML_RPC_Double'] => 1,
7462+ $GLOBALS['XML_RPC_DateTime'] => 1,
7463+ $GLOBALS['XML_RPC_Base64'] => 1,
7464+ $GLOBALS['XML_RPC_Array'] => 2,
7465+ $GLOBALS['XML_RPC_Struct'] => 3,
7466+);
7467+
7468+
7469+/**
7470+ * Error message numbers
7471+ * @global array $GLOBALS['XML_RPC_err']
7472+ */
7473+$GLOBALS['XML_RPC_err'] = array(
7474+ 'unknown_method' => 1,
7475+ 'invalid_return' => 2,
7476+ 'incorrect_params' => 3,
7477+ 'introspect_unknown' => 4,
7478+ 'http_error' => 5,
7479+ 'not_response_object' => 6,
7480+);
7481+
7482+/**
7483+ * Error message strings
7484+ * @global array $GLOBALS['XML_RPC_str']
7485+ */
7486+$GLOBALS['XML_RPC_str'] = array(
7487+ 'unknown_method' => 'Unknown method',
7488+ 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload',
7489+ 'incorrect_params' => 'Incorrect parameters passed to method',
7490+ 'introspect_unknown' => 'Can\'t introspect: method unknown',
7491+ 'http_error' => 'Didn\'t receive 200 OK from remote server.',
7492+ 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.',
7493+);
7494+
7495+
7496+/**
7497+ * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII)
7498+ * @global string $GLOBALS['XML_RPC_defencoding']
7499+ */
7500+$GLOBALS['XML_RPC_defencoding'] = 'UTF-8';
7501+
7502+/**
7503+ * User error codes start at 800
7504+ * @global int $GLOBALS['XML_RPC_erruser']
7505+ */
7506+$GLOBALS['XML_RPC_erruser'] = 800;
7507+
7508+/**
7509+ * XML parse error codes start at 100
7510+ * @global int $GLOBALS['XML_RPC_errxml']
7511+ */
7512+$GLOBALS['XML_RPC_errxml'] = 100;
7513+
7514+
7515+/**
7516+ * Compose backslashes for escaping regexp
7517+ * @global string $GLOBALS['XML_RPC_backslash']
7518+ */
7519+$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92);
7520+
7521+
7522+/**
7523+ * Stores state during parsing
7524+ *
7525+ * quick explanation of components:
7526+ * + st = builds up a string for evaluation
7527+ * + ac = accumulates values
7528+ * + qt = decides if quotes are needed for evaluation
7529+ * + cm = denotes struct or array (comma needed)
7530+ * + isf = indicates a fault
7531+ * + lv = indicates "looking for a value": implements the logic
7532+ * to allow values with no types to be strings
7533+ * + params = stores parameters in method calls
7534+ * + method = stores method name
7535+ *
7536+ * @global array $GLOBALS['XML_RPC_xh']
7537+ */
7538+$GLOBALS['XML_RPC_xh'] = array();
7539+
7540+
7541+/**
7542+ * Start element handler for the XML parser
7543+ *
7544+ * @return void
7545+ */
7546+function XML_RPC_se($parser_resource, $name, $attrs)
7547+{
7548+ global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String;
7549+ $parser = (int) $parser_resource;
7550+
7551+ switch ($name) {
7552+ case 'STRUCT':
7553+ case 'ARRAY':
7554+ $XML_RPC_xh[$parser]['st'] .= 'array(';
7555+ $XML_RPC_xh[$parser]['cm']++;
7556+ // this last line turns quoting off
7557+ // this means if we get an empty array we'll
7558+ // simply get a bit of whitespace in the eval
7559+ $XML_RPC_xh[$parser]['qt'] = 0;
7560+ break;
7561+
7562+ case 'NAME':
7563+ $XML_RPC_xh[$parser]['st'] .= '"';
7564+ $XML_RPC_xh[$parser]['ac'] = '';
7565+ break;
7566+
7567+ case 'FAULT':
7568+ $XML_RPC_xh[$parser]['isf'] = 1;
7569+ break;
7570+
7571+ case 'PARAM':
7572+ $XML_RPC_xh[$parser]['st'] = '';
7573+ break;
7574+
7575+ case 'VALUE':
7576+ $XML_RPC_xh[$parser]['st'] .= 'new XML_RPC_Value(';
7577+ $XML_RPC_xh[$parser]['lv'] = 1;
7578+ $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String;
7579+ $XML_RPC_xh[$parser]['ac'] = '';
7580+ $XML_RPC_xh[$parser]['qt'] = 0;
7581+ // look for a value: if this is still 1 by the
7582+ // time we reach the first data segment then the type is string
7583+ // by implication and we need to add in a quote
7584+ break;
7585+
7586+ case 'I4':
7587+ case 'INT':
7588+ case 'STRING':
7589+ case 'BOOLEAN':
7590+ case 'DOUBLE':
7591+ case 'DATETIME.ISO8601':
7592+ case 'BASE64':
7593+ $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator
7594+
7595+ if ($name == 'DATETIME.ISO8601' || $name == 'STRING') {
7596+ $XML_RPC_xh[$parser]['qt'] = 1;
7597+
7598+ if ($name == 'DATETIME.ISO8601') {
7599+ $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime;
7600+ }
7601+
7602+ } elseif ($name == 'BASE64') {
7603+ $XML_RPC_xh[$parser]['qt'] = 2;
7604+ } else {
7605+ // No quoting is required here -- but
7606+ // at the end of the element we must check
7607+ // for data format errors.
7608+ $XML_RPC_xh[$parser]['qt'] = 0;
7609+ }
7610+ break;
7611+
7612+ case 'MEMBER':
7613+ $XML_RPC_xh[$parser]['ac'] = '';
7614+ }
7615+
7616+ if ($name != 'VALUE') {
7617+ $XML_RPC_xh[$parser]['lv'] = 0;
7618+ }
7619+}
7620+
7621+/**
7622+ * End element handler for the XML parser
7623+ *
7624+ * @return void
7625+ */
7626+function XML_RPC_ee($parser_resource, $name)
7627+{
7628+ global $XML_RPC_xh, $XML_RPC_Types, $XML_RPC_String;
7629+ $parser = (int) $parser_resource;
7630+
7631+ switch ($name) {
7632+ case 'STRUCT':
7633+ case 'ARRAY':
7634+ if ($XML_RPC_xh[$parser]['cm']
7635+ && substr($XML_RPC_xh[$parser]['st'], -1) == ',')
7636+ {
7637+ $XML_RPC_xh[$parser]['st'] = substr($XML_RPC_xh[$parser]['st'], 0, -1);
7638+ }
7639+
7640+ $XML_RPC_xh[$parser]['st'] .= ')';
7641+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
7642+ $XML_RPC_xh[$parser]['cm']--;
7643+ break;
7644+
7645+ case 'NAME':
7646+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . '" => ';
7647+ break;
7648+
7649+ case 'BOOLEAN':
7650+ // special case here: we translate boolean 1 or 0 into PHP
7651+ // constants true or false
7652+ if ($XML_RPC_xh[$parser]['ac'] == '1') {
7653+ $XML_RPC_xh[$parser]['ac'] = 'true';
7654+ } else {
7655+ $XML_RPC_xh[$parser]['ac'] = 'false';
7656+ }
7657+
7658+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
7659+ // Drop through intentionally.
7660+
7661+ case 'I4':
7662+ case 'INT':
7663+ case 'STRING':
7664+ case 'DOUBLE':
7665+ case 'DATETIME.ISO8601':
7666+ case 'BASE64':
7667+ if ($XML_RPC_xh[$parser]['qt'] == 1) {
7668+ // we use double quotes rather than single so backslashification works OK
7669+ $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
7670+ } elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
7671+ $XML_RPC_xh[$parser]['st'] .= 'base64_decode("'
7672+ . $XML_RPC_xh[$parser]['ac'] . '")';
7673+ } elseif ($name == 'BOOLEAN') {
7674+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
7675+ } else {
7676+ // we have an I4, INT or a DOUBLE
7677+ // we must check that only 0123456789-.<space> are characters here
7678+ if (!ereg("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) {
7679+ XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE',
7680+ XML_RPC_ERROR_NON_NUMERIC_FOUND);
7681+ $XML_RPC_xh[$parser]['st'] .= 'XML_RPC_ERROR_NON_NUMERIC_FOUND';
7682+ } else {
7683+ // it's ok, add it on
7684+ $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
7685+ }
7686+ }
7687+
7688+ $XML_RPC_xh[$parser]['ac'] = '';
7689+ $XML_RPC_xh[$parser]['qt'] = 0;
7690+ $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value
7691+ break;
7692+
7693+ case 'VALUE':
7694+ // deal with a string value
7695+ if (strlen($XML_RPC_xh[$parser]['ac']) > 0 &&
7696+ $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) {
7697+
7698+ $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
7699+ }
7700+
7701+ // This if () detects if no scalar was inside <VALUE></VALUE>
7702+ // and pads an empty "".
7703+ if ($XML_RPC_xh[$parser]['st'][strlen($XML_RPC_xh[$parser]['st'])-1] == '(') {
7704+ $XML_RPC_xh[$parser]['st'] .= '""';
7705+ }
7706+ $XML_RPC_xh[$parser]['st'] .= ", '" . $XML_RPC_xh[$parser]['vt'] . "')";
7707+ if ($XML_RPC_xh[$parser]['cm']) {
7708+ $XML_RPC_xh[$parser]['st'] .= ',';
7709+ }
7710+ break;
7711+
7712+ case 'MEMBER':
7713+ $XML_RPC_xh[$parser]['ac'] = '';
7714+ $XML_RPC_xh[$parser]['qt'] = 0;
7715+ break;
7716+
7717+ case 'DATA':
7718+ $XML_RPC_xh[$parser]['ac'] = '';
7719+ $XML_RPC_xh[$parser]['qt'] = 0;
7720+ break;
7721+
7722+ case 'PARAM':
7723+ $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['st'];
7724+ break;
7725+
7726+ case 'METHODNAME':
7727+ case 'RPCMETHODNAME':
7728+ $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", '',
7729+ $XML_RPC_xh[$parser]['ac']);
7730+ break;
7731+ }
7732+
7733+ // if it's a valid type name, set the type
7734+ if (isset($XML_RPC_Types[strtolower($name)])) {
7735+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
7736+ }
7737+}
7738+
7739+/**
7740+ * Character data handler for the XML parser
7741+ *
7742+ * @return void
7743+ */
7744+function XML_RPC_cd($parser_resource, $data)
7745+{
7746+ global $XML_RPC_xh, $XML_RPC_backslash;
7747+ $parser = (int) $parser_resource;
7748+
7749+ if ($XML_RPC_xh[$parser]['lv'] != 3) {
7750+ // "lookforvalue==3" means that we've found an entire value
7751+ // and should discard any further character data
7752+
7753+ if ($XML_RPC_xh[$parser]['lv'] == 1) {
7754+ // if we've found text and we're just in a <value> then
7755+ // turn quoting on, as this will be a string
7756+ $XML_RPC_xh[$parser]['qt'] = 1;
7757+ // and say we've found a value
7758+ $XML_RPC_xh[$parser]['lv'] = 2;
7759+ }
7760+
7761+ // replace characters that eval would
7762+ // do special things with
7763+ if (!isset($XML_RPC_xh[$parser]['ac'])) {
7764+ $XML_RPC_xh[$parser]['ac'] = '';
7765+ }
7766+ $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$',
7767+ str_replace('"', '\"', str_replace(chr(92),
7768+ $XML_RPC_backslash, $data)));
7769+ }
7770+}
7771+
7772+/**
7773+ * The common methods and properties for all of the XML_RPC classes
7774+ *
7775+ * @category Web Services
7776+ * @package XML_RPC
7777+ * @author Edd Dumbill <edd@usefulinc.com>
7778+ * @author Stig Bakken <stig@php.net>
7779+ * @author Martin Jansen <mj@php.net>
7780+ * @author Daniel Convissor <danielc@php.net>
7781+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7782+ * @version Release: 1.3.1
7783+ * @link http://pear.php.net/package/XML_RPC
7784+ */
7785+class XML_RPC_Base {
7786+
7787+ /**
7788+ * PEAR Error handling
7789+ *
7790+ * @return object PEAR_Error object
7791+ */
7792+ function raiseError($msg, $code)
7793+ {
7794+ include_once 'PEAR.php';
7795+ if (is_object(@$this)) {
7796+ return PEAR::raiseError(get_class($this) . ': ' . $msg, $code);
7797+ } else {
7798+ return PEAR::raiseError('XML_RPC: ' . $msg, $code);
7799+ }
7800+ }
7801+
7802+ /**
7803+ * Tell whether something is a PEAR_Error object
7804+ *
7805+ * @param mixed $value the item to check
7806+ *
7807+ * @return bool whether $value is a PEAR_Error object or not
7808+ *
7809+ * @access public
7810+ */
7811+ function isError($value)
7812+ {
7813+ return is_a($value, 'PEAR_Error');
7814+ }
7815+}
7816+
7817+/**
7818+ * The methods and properties for submitting XML RPC requests
7819+ *
7820+ * @category Web Services
7821+ * @package XML_RPC
7822+ * @author Edd Dumbill <edd@usefulinc.com>
7823+ * @author Stig Bakken <stig@php.net>
7824+ * @author Martin Jansen <mj@php.net>
7825+ * @author Daniel Convissor <danielc@php.net>
7826+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7827+ * @version Release: 1.3.1
7828+ * @link http://pear.php.net/package/XML_RPC
7829+ */
7830+class XML_RPC_Client extends XML_RPC_Base {
7831+
7832+ /**
7833+ * The path and name of the RPC server script you want the request to go to
7834+ * @var string
7835+ */
7836+ var $path = '';
7837+
7838+ /**
7839+ * The name of the remote server to connect to
7840+ * @var string
7841+ */
7842+ var $server = '';
7843+
7844+ /**
7845+ * The protocol to use in contacting the remote server
7846+ * @var string
7847+ */
7848+ var $protocol = 'http://';
7849+
7850+ /**
7851+ * The port for connecting to the remote server
7852+ *
7853+ * The default is 80 for http:// connections
7854+ * and 443 for https:// and ssl:// connections.
7855+ *
7856+ * @var integer
7857+ */
7858+ var $port = 80;
7859+
7860+ /**
7861+ * A user name for accessing the RPC server
7862+ * @var string
7863+ * @see XML_RPC_Client::setCredentials()
7864+ */
7865+ var $username = '';
7866+
7867+ /**
7868+ * A password for accessing the RPC server
7869+ * @var string
7870+ * @see XML_RPC_Client::setCredentials()
7871+ */
7872+ var $password = '';
7873+
7874+ /**
7875+ * The name of the proxy server to use, if any
7876+ * @var string
7877+ */
7878+ var $proxy = '';
7879+
7880+ /**
7881+ * The protocol to use in contacting the proxy server, if any
7882+ * @var string
7883+ */
7884+ var $proxy_protocol = 'http://';
7885+
7886+ /**
7887+ * The port for connecting to the proxy server
7888+ *
7889+ * The default is 8080 for http:// connections
7890+ * and 443 for https:// and ssl:// connections.
7891+ *
7892+ * @var integer
7893+ */
7894+ var $proxy_port = 8080;
7895+
7896+ /**
7897+ * A user name for accessing the proxy server
7898+ * @var string
7899+ */
7900+ var $proxy_user = '';
7901+
7902+ /**
7903+ * A password for accessing the proxy server
7904+ * @var string
7905+ */
7906+ var $proxy_pass = '';
7907+
7908+ /**
7909+ * The error number, if any
7910+ * @var integer
7911+ */
7912+ var $errno = 0;
7913+
7914+ /**
7915+ * The error message, if any
7916+ * @var string
7917+ */
7918+ var $errstring = '';
7919+
7920+ /**
7921+ * The current debug mode (1 = on, 0 = off)
7922+ * @var integer
7923+ */
7924+ var $debug = 0;
7925+
7926+ /**
7927+ * The HTTP headers for the current request.
7928+ * @var string
7929+ */
7930+ var $headers = '';
7931+
7932+
7933+ /**
7934+ * Sets the object's properties
7935+ *
7936+ * @param string $path the path and name of the RPC server script
7937+ * you want the request to go to
7938+ * @param string $server the URL of the remote server to connect to.
7939+ * If this parameter doesn't specify a
7940+ * protocol and $port is 443, ssl:// is
7941+ * assumed.
7942+ * @param integer $port a port for connecting to the remote server.
7943+ * Defaults to 80 for http:// connections and
7944+ * 443 for https:// and ssl:// connections.
7945+ * @param string $proxy the URL of the proxy server to use, if any.
7946+ * If this parameter doesn't specify a
7947+ * protocol and $port is 443, ssl:// is
7948+ * assumed.
7949+ * @param integer $proxy_port a port for connecting to the remote server.
7950+ * Defaults to 8080 for http:// connections and
7951+ * 443 for https:// and ssl:// connections.
7952+ * @param string $proxy_user a user name for accessing the proxy server
7953+ * @param string $proxy_pass a password for accessing the proxy server
7954+ *
7955+ * @return void
7956+ */
7957+ function XML_RPC_Client($path, $server, $port = 0,
7958+ $proxy = '', $proxy_port = 0,
7959+ $proxy_user = '', $proxy_pass = '')
7960+ {
7961+ $this->path = $path;
7962+ $this->proxy_user = $proxy_user;
7963+ $this->proxy_pass = $proxy_pass;
7964+
7965+ preg_match('@^(http://|https://|ssl://)?(.*)$@', $server, $match);
7966+ if ($match[1] == '') {
7967+ if ($port == 443) {
7968+ $this->server = $match[2];
7969+ $this->protocol = 'ssl://';
7970+ $this->port = 443;
7971+ } else {
7972+ $this->server = $match[2];
7973+ if ($port) {
7974+ $this->port = $port;
7975+ }
7976+ }
7977+ } elseif ($match[1] == 'http://') {
7978+ $this->server = $match[2];
7979+ if ($port) {
7980+ $this->port = $port;
7981+ }
7982+ } else {
7983+ $this->server = $match[2];
7984+ $this->protocol = 'ssl://';
7985+ if ($port) {
7986+ $this->port = $port;
7987+ } else {
7988+ $this->port = 443;
7989+ }
7990+ }
7991+
7992+ if ($proxy) {
7993+ preg_match('@^(http://|https://|ssl://)?(.*)$@', $proxy, $match);
7994+ if ($match[1] == '') {
7995+ if ($proxy_port == 443) {
7996+ $this->proxy = $match[2];
7997+ $this->proxy_protocol = 'ssl://';
7998+ $this->proxy_port = 443;
7999+ } else {
8000+ $this->proxy = $match[2];
8001+ if ($proxy_port) {
8002+ $this->proxy_port = $proxy_port;
8003+ }
8004+ }
8005+ } elseif ($match[1] == 'http://') {
8006+ $this->proxy = $match[2];
8007+ if ($proxy_port) {
8008+ $this->proxy_port = $proxy_port;
8009+ }
8010+ } else {
8011+ $this->proxy = $match[2];
8012+ $this->proxy_protocol = 'ssl://';
8013+ if ($proxy_port) {
8014+ $this->proxy_port = $proxy_port;
8015+ } else {
8016+ $this->proxy_port = 443;
8017+ }
8018+ }
8019+ }
8020+ }
8021+
8022+ /**
8023+ * Change the current debug mode
8024+ *
8025+ * @param int $in where 1 = on, 0 = off
8026+ *
8027+ * @return void
8028+ */
8029+ function setDebug($in)
8030+ {
8031+ if ($in) {
8032+ $this->debug = 1;
8033+ } else {
8034+ $this->debug = 0;
8035+ }
8036+ }
8037+
8038+ /**
8039+ * Set username and password properties for connecting to the RPC server
8040+ *
8041+ * @param string $u the user name
8042+ * @param string $p the password
8043+ *
8044+ * @return void
8045+ *
8046+ * @see XML_RPC_Client::$username, XML_RPC_Client::$password
8047+ */
8048+ function setCredentials($u, $p)
8049+ {
8050+ $this->username = $u;
8051+ $this->password = $p;
8052+ }
8053+
8054+ /**
8055+ * Transmit the RPC request via HTTP 1.0 protocol
8056+ *
8057+ * @param object $msg the XML_RPC_Message object
8058+ * @param int $timeout how many seconds to wait for the request
8059+ *
8060+ * @return object an XML_RPC_Response object. 0 is returned if any
8061+ * problems happen.
8062+ *
8063+ * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(),
8064+ * XML_RPC_Client::setCredentials()
8065+ */
8066+ function send($msg, $timeout = 0)
8067+ {
8068+ if (strtolower(get_class($msg)) != 'xml_rpc_message') {
8069+ $this->errstr = 'send()\'s $msg parameter must be an'
8070+ . ' XML_RPC_Message object.';
8071+ $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING);
8072+ return 0;
8073+ }
8074+ $msg->debug = $this->debug;
8075+ return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
8076+ $timeout, $this->username,
8077+ $this->password);
8078+ }
8079+
8080+ /**
8081+ * Transmit the RPC request via HTTP 1.0 protocol
8082+ *
8083+ * Requests should be sent using XML_RPC_Client send() rather than
8084+ * calling this method directly.
8085+ *
8086+ * @param object $msg the XML_RPC_Message object
8087+ * @param string $server the server to send the request to
8088+ * @param int $port the server port send the request to
8089+ * @param int $timeout how many seconds to wait for the request
8090+ * before giving up
8091+ * @param string $username a user name for accessing the RPC server
8092+ * @param string $password a password for accessing the RPC server
8093+ *
8094+ * @return object an XML_RPC_Response object. 0 is returned if any
8095+ * problems happen.
8096+ *
8097+ * @access protected
8098+ * @see XML_RPC_Client::send()
8099+ */
8100+ function sendPayloadHTTP10($msg, $server, $port, $timeout = 0,
8101+ $username = '', $password = '')
8102+ {
8103+ /*
8104+ * If we're using a proxy open a socket to the proxy server
8105+ * instead to the xml-rpc server
8106+ */
8107+ if ($this->proxy) {
8108+ if ($this->proxy_protocol == 'http://') {
8109+ $protocol = '';
8110+ } else {
8111+ $protocol = $this->proxy_protocol;
8112+ }
8113+ if ($timeout > 0) {
8114+ $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
8115+ $this->errno, $this->errstr, $timeout);
8116+ } else {
8117+ $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
8118+ $this->errno, $this->errstr);
8119+ }
8120+ } else {
8121+ if ($this->protocol == 'http://') {
8122+ $protocol = '';
8123+ } else {
8124+ $protocol = $this->protocol;
8125+ }
8126+ if ($timeout > 0) {
8127+ $fp = @fsockopen($protocol . $server, $port,
8128+ $this->errno, $this->errstr, $timeout);
8129+ } else {
8130+ $fp = @fsockopen($protocol . $server, $port,
8131+ $this->errno, $this->errstr);
8132+ }
8133+ }
8134+
8135+ /*
8136+ * Just raising the error without returning it is strange,
8137+ * but keep it here for backwards compatibility.
8138+ */
8139+ if (!$fp && $this->proxy) {
8140+ $this->raiseError('Connection to proxy server '
8141+ . $this->proxy . ':' . $this->proxy_port
8142+ . ' failed. ' . $this->errstr,
8143+ XML_RPC_ERROR_CONNECTION_FAILED);
8144+ return 0;
8145+ } elseif (!$fp) {
8146+ $this->raiseError('Connection to RPC server '
8147+ . $server . ':' . $port
8148+ . ' failed. ' . $this->errstr,
8149+ XML_RPC_ERROR_CONNECTION_FAILED);
8150+ return 0;
8151+ }
8152+
8153+ if ($timeout) {
8154+ stream_set_timeout($fp, $timeout);
8155+ }
8156+
8157+ // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly
8158+ if ($username != $this->username) {
8159+ $this->setCredentials($username, $password);
8160+ }
8161+
8162+ // Only create the payload if it was not created previously
8163+ if (empty($msg->payload)) {
8164+ $msg->createPayload();
8165+ }
8166+ $this->createHeaders($msg);
8167+
8168+ $op = $this->headers . "\r\n\r\n";
8169+ $op .= $msg->payload;
8170+
8171+ if (!fputs($fp, $op, strlen($op))) {
8172+ $this->errstr = 'Write error';
8173+ return 0;
8174+ }
8175+ $resp = $msg->parseResponseFile($fp);
8176+
8177+ $meta = stream_get_meta_data($fp);
8178+ if ($meta['timed_out']) {
8179+ fclose($fp);
8180+ $this->errstr = 'RPC server did not send response before timeout.';
8181+ $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED);
8182+ return 0;
8183+ }
8184+
8185+ fclose($fp);
8186+ return $resp;
8187+ }
8188+
8189+ /**
8190+ * Determines the HTTP headers and puts it in the $headers property
8191+ *
8192+ * @param object $msg the XML_RPC_Message object
8193+ *
8194+ * @return boolean TRUE if okay, FALSE if the message payload isn't set.
8195+ *
8196+ * @access protected
8197+ */
8198+ function createHeaders($msg)
8199+ {
8200+ if (empty($msg->payload)) {
8201+ return false;
8202+ }
8203+ if ($this->proxy) {
8204+ $this->headers = 'POST ' . $this->protocol . $this->server;
8205+ if ($this->proxy_port) {
8206+ $this->headers .= ':' . $this->port;
8207+ }
8208+ } else {
8209+ $this->headers = 'POST ';
8210+ }
8211+ $this->headers .= $this->path. " HTTP/1.0\r\n";
8212+
8213+ $this->headers .= "User-Agent: PEAR XML_RPC\r\n";
8214+ $this->headers .= 'Host: ' . $this->server . "\r\n";
8215+
8216+ if ($this->proxy && $this->proxy_user) {
8217+ $this->headers .= 'Proxy-Authorization: Basic '
8218+ . base64_encode("$this->proxy_user:$this->proxy_pass")
8219+ . "\r\n";
8220+ }
8221+
8222+ // thanks to Grant Rauscher <grant7@firstworld.net> for this
8223+ if ($this->username) {
8224+ $this->headers .= 'Authorization: Basic '
8225+ . base64_encode("$this->username:$this->password")
8226+ . "\r\n";
8227+ }
8228+
8229+ $this->headers .= "Content-Type: text/xml\r\n";
8230+ $this->headers .= 'Content-Length: ' . strlen($msg->payload);
8231+ return true;
8232+ }
8233+}
8234+
8235+/**
8236+ * The methods and properties for interpreting responses to XML RPC requests
8237+ *
8238+ * @category Web Services
8239+ * @package XML_RPC
8240+ * @author Edd Dumbill <edd@usefulinc.com>
8241+ * @author Stig Bakken <stig@php.net>
8242+ * @author Martin Jansen <mj@php.net>
8243+ * @author Daniel Convissor <danielc@php.net>
8244+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
8245+ * @version Release: 1.3.1
8246+ * @link http://pear.php.net/package/XML_RPC
8247+ */
8248+class XML_RPC_Response extends XML_RPC_Base
8249+{
8250+ var $xv;
8251+ var $fn;
8252+ var $fs;
8253+ var $hdrs;
8254+
8255+ /**
8256+ * @return void
8257+ */
8258+ function XML_RPC_Response($val, $fcode = 0, $fstr = '')
8259+ {
8260+ if ($fcode != 0) {
8261+ $this->fn = $fcode;
8262+ $this->fs = htmlspecialchars($fstr);
8263+ } else {
8264+ $this->xv = $val;
8265+ }
8266+ }
8267+
8268+ /**
8269+ * @return int the error code
8270+ */
8271+ function faultCode()
8272+ {
8273+ if (isset($this->fn)) {
8274+ return $this->fn;
8275+ } else {
8276+ return 0;
8277+ }
8278+ }
8279+
8280+ /**
8281+ * @return string the error string
8282+ */
8283+ function faultString()
8284+ {
8285+ return $this->fs;
8286+ }
8287+
8288+ /**
8289+ * @return mixed the value
8290+ */
8291+ function value()
8292+ {
8293+ return $this->xv;
8294+ }
8295+
8296+ /**
8297+ * @return string the error message in XML format
8298+ */
8299+ function serialize()
8300+ {
8301+ $rs = "<methodResponse>\n";
8302+ if ($this->fn) {
8303+ $rs .= "<fault>
8304+ <value>
8305+ <struct>
8306+ <member>
8307+ <name>faultCode</name>
8308+ <value><int>" . $this->fn . "</int></value>
8309+ </member>
8310+ <member>
8311+ <name>faultString</name>
8312+ <value><string>" . $this->fs . "</string></value>
8313+ </member>
8314+ </struct>
8315+ </value>
8316+</fault>";
8317+ } else {
8318+ $rs .= "<params>\n<param>\n" . $this->xv->serialize() .
8319+ "</param>\n</params>";
8320+ }
8321+ $rs .= "\n</methodResponse>";
8322+ return $rs;
8323+ }
8324+}
8325+
8326+/**
8327+ * The methods and properties for composing XML RPC messages
8328+ *
8329+ * @category Web Services
8330+ * @package XML_RPC
8331+ * @author Edd Dumbill <edd@usefulinc.com>
8332+ * @author Stig Bakken <stig@php.net>
8333+ * @author Martin Jansen <mj@php.net>
8334+ * @author Daniel Convissor <danielc@php.net>
8335+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
8336+ * @version Release: 1.3.1
8337+ * @link http://pear.php.net/package/XML_RPC
8338+ */
8339+class XML_RPC_Message extends XML_RPC_Base
8340+{
8341+ /**
8342+ * The current debug mode (1 = on, 0 = off)
8343+ * @var integer
8344+ */
8345+ var $debug = 0;
8346+
8347+ /**
8348+ * The encoding to be used for outgoing messages
8349+ *
8350+ * Defaults to the value of <var>$GLOBALS['XML_RPC_defencoding']</var>
8351+ *
8352+ * @var string
8353+ * @see XML_RPC_Message::setSendEncoding(),
8354+ * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header()
8355+ */
8356+ var $send_encoding = '';
8357+
8358+ /**
8359+ * The method presently being evaluated
8360+ * @var string
8361+ */
8362+ var $methodname = '';
8363+
8364+ /**
8365+ * @var array
8366+ */
8367+ var $params = array();
8368+
8369+ /**
8370+ * The XML message being generated
8371+ * @var string
8372+ */
8373+ var $payload = '';
8374+
8375+ /**
8376+ * @return void
8377+ */
8378+ function XML_RPC_Message($meth, $pars = 0)
8379+ {
8380+ $this->methodname = $meth;
8381+ if (is_array($pars) && sizeof($pars) > 0) {
8382+ for ($i = 0; $i < sizeof($pars); $i++) {
8383+ $this->addParam($pars[$i]);
8384+ }
8385+ }
8386+ }
8387+
8388+ /**
8389+ * Produces the XML declaration including the encoding attribute
8390+ *
8391+ * The encoding is determined by this class' <var>$send_encoding</var>
8392+ * property. If the <var>$send_encoding</var> property is not set, use
8393+ * <var>$GLOBALS['XML_RPC_defencoding']</var>.
8394+ *
8395+ * @return string the XML declaration and <methodCall> element
8396+ *
8397+ * @see XML_RPC_Message::setSendEncoding(),
8398+ * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding']
8399+ */
8400+ function xml_header()
8401+ {
8402+ global $XML_RPC_defencoding;
8403+ if (!$this->send_encoding) {
8404+ $this->send_encoding = $XML_RPC_defencoding;
8405+ }
8406+ return '<?xml version="1.0" encoding="' . $this->send_encoding . '"?>'
8407+ . "\n<methodCall>\n";
8408+ }
8409+
8410+ /**
8411+ * @return string the closing </methodCall> tag
8412+ */
8413+ function xml_footer()
8414+ {
8415+ return "</methodCall>\n";
8416+ }
8417+
8418+ /**
8419+ * @return void
8420+ *
8421+ * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer()
8422+ */
8423+ function createPayload()
8424+ {
8425+ $this->payload = $this->xml_header();
8426+ $this->payload .= '<methodName>' . $this->methodname . "</methodName>\n";
8427+ $this->payload .= "<params>\n";
8428+ for ($i = 0; $i < sizeof($this->params); $i++) {
8429+ $p = $this->params[$i];
8430+ $this->payload .= "<param>\n" . $p->serialize() . "</param>\n";
8431+ }
8432+ $this->payload .= "</params>\n";
8433+ $this->payload .= $this->xml_footer();
8434+ $this->payload = ereg_replace("[\r\n]+", "\r\n", $this->payload);
8435+ }
8436+
8437+ /**
8438+ * @return string the name of the method
8439+ */
8440+ function method($meth = '')
8441+ {
8442+ if ($meth != '') {
8443+ $this->methodname = $meth;
8444+ }
8445+ return $this->methodname;
8446+ }
8447+
8448+ /**
8449+ * @return string the payload
8450+ */
8451+ function serialize()
8452+ {
8453+ $this->createPayload();
8454+ return $this->payload;
8455+ }
8456+
8457+ /**
8458+ * @return void
8459+ */
8460+ function addParam($par)
8461+ {
8462+ $this->params[] = $par;
8463+ }
8464+
8465+ /**
8466+ * Obtains an XML_RPC_Value object for the given parameter
8467+ *
8468+ * @param int $i the index number of the parameter to obtain
8469+ *
8470+ * @return object the XML_RPC_Value object.
8471+ * If the parameter doesn't exist, an XML_RPC_Response object.
8472+ *
8473+ * @since Returns XML_RPC_Response object on error since Release 1.3.0
8474+ */
8475+ function getParam($i)
8476+ {
8477+ global $XML_RPC_err, $XML_RPC_str;
8478+
8479+ if (isset($this->params[$i])) {
8480+ return $this->params[$i];
8481+ } else {
8482+ $this->raiseError('The submitted request did not contain this parameter',
8483+ XML_RPC_ERROR_INCORRECT_PARAMS);
8484+ return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
8485+ $XML_RPC_str['incorrect_params']);
8486+ }
8487+ }
8488+
8489+ /**
8490+ * @return int the number of parameters
8491+ */
8492+ function getNumParams()
8493+ {
8494+ return sizeof($this->params);
8495+ }
8496+
8497+ /**
8498+ * Sets the XML declaration's encoding attribute
8499+ *
8500+ * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII)
8501+ *
8502+ * @return void
8503+ *
8504+ * @see XML_RPC_Message::$send_encoding, XML_RPC_Message::xml_header()
8505+ * @since Method available since Release 1.2.0
8506+ */
8507+ function setSendEncoding($type)
8508+ {
8509+ $this->send_encoding = $type;
8510+ }
8511+
8512+ /**
8513+ * Determine the XML's encoding via the encoding attribute
8514+ * in the XML declaration
8515+ *
8516+ * If the encoding parameter is not set or is not ISO-8859-1, UTF-8
8517+ * or US-ASCII, $XML_RPC_defencoding will be returned.
8518+ *
8519+ * @param string $data the XML that will be parsed
8520+ *
8521+ * @return string the encoding to be used
8522+ *
8523+ * @link http://php.net/xml_parser_create
8524+ * @since Method available since Release 1.2.0
8525+ */
8526+ function getEncoding($data)
8527+ {
8528+ global $XML_RPC_defencoding;
8529+
8530+ if (preg_match('/<\?xml[^>]*\s*encoding\s*=\s*[\'"]([^"\']*)[\'"]/i',
8531+ $data, $match))
8532+ {
8533+ $match[1] = trim(strtoupper($match[1]));
8534+ switch ($match[1]) {
8535+ case 'ISO-8859-1':
8536+ case 'UTF-8':
8537+ case 'US-ASCII':
8538+ return $match[1];
8539+ break;
8540+
8541+ default:
8542+ return $XML_RPC_defencoding;
8543+ }
8544+ } else {
8545+ return $XML_RPC_defencoding;
8546+ }
8547+ }
8548+
8549+ /**
8550+ * @return object a new XML_RPC_Response object
8551+ */
8552+ function parseResponseFile($fp)
8553+ {
8554+ $ipd = '';
8555+ while ($data = @fread($fp, 8192)) {
8556+ $ipd .= $data;
8557+ }
8558+ return $this->parseResponse($ipd);
8559+ }
8560+
8561+ /**
8562+ * @return object a new XML_RPC_Response object
8563+ */
8564+ function parseResponse($data = '')
8565+ {
8566+ global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding;
8567+
8568+ $encoding = $this->getEncoding($data);
8569+ $parser_resource = xml_parser_create($encoding);
8570+ $parser = (int) $parser_resource;
8571+
8572+ $XML_RPC_xh[$parser] = array();
8573+
8574+ $XML_RPC_xh[$parser]['st'] = '';
8575+ $XML_RPC_xh[$parser]['cm'] = 0;
8576+ $XML_RPC_xh[$parser]['isf'] = 0;
8577+ $XML_RPC_xh[$parser]['ac'] = '';
8578+ $XML_RPC_xh[$parser]['qt'] = '';
8579+
8580+ xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
8581+ xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
8582+ xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
8583+
8584+ $hdrfnd = 0;
8585+ if ($this->debug) {
8586+ print "<PRE>---GOT---\n";
8587+ print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
8588+ print "\n---END---\n</PRE>";
8589+ }
8590+
8591+ // See if response is a 200 or a 100 then a 200, else raise error.
8592+ // But only do this if we're using the HTTP protocol.
8593+ if (ereg('^HTTP', $data) &&
8594+ !ereg('^HTTP/[0-9\.]+ 200 ', $data) &&
8595+ !preg_match('@^HTTP/[0-9\.]+ 10[0-9]([A-Za-z ]+)?[\r\n]+HTTP/[0-9\.]+ 200@', $data))
8596+ {
8597+ $errstr = substr($data, 0, strpos($data, "\n") - 1);
8598+ error_log('HTTP error, got response: ' . $errstr);
8599+ $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'],
8600+ $XML_RPC_str['http_error'] . ' (' .
8601+ $errstr . ')');
8602+ xml_parser_free($parser_resource);
8603+ return $r;
8604+ }
8605+ // gotta get rid of headers here
8606+
8607+
8608+ if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) {
8609+ $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
8610+ $data = substr($data, $brpos + 4);
8611+ $hdrfnd = 1;
8612+ }
8613+
8614+ /*
8615+ * be tolerant of junk after methodResponse
8616+ * (e.g. javascript automatically inserted by free hosts)
8617+ * thanks to Luca Mariano <luca.mariano@email.it>
8618+ */
8619+ $data = substr($data, 0, strpos($data, "</methodResponse>") + 17);
8620+
8621+ if (!xml_parse($parser_resource, $data, sizeof($data))) {
8622+ // thanks to Peter Kocks <peter.kocks@baygate.com>
8623+ if (xml_get_current_line_number($parser_resource) == 1) {
8624+ $errstr = 'XML error at line 1, check URL';
8625+ } else {
8626+ $errstr = sprintf('XML error: %s at line %d',
8627+ xml_error_string(xml_get_error_code($parser_resource)),
8628+ xml_get_current_line_number($parser_resource));
8629+ }
8630+ error_log($errstr);
8631+ $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
8632+ $XML_RPC_str['invalid_return']);
8633+ xml_parser_free($parser_resource);
8634+ return $r;
8635+ }
8636+ xml_parser_free($parser_resource);
8637+ if ($this->debug) {
8638+ print '<PRE>---EVALING---[' .
8639+ strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
8640+ htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---</PRE>";
8641+ }
8642+ if (strlen($XML_RPC_xh[$parser]['st']) == 0) {
8643+ // then something odd has happened
8644+ // and it's time to generate a client side error
8645+ // indicating something odd went on
8646+ $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
8647+ $XML_RPC_str['invalid_return']);
8648+ } else {
8649+ eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;');
8650+ if ($XML_RPC_xh[$parser]['isf']) {
8651+ $f = $v->structmem('faultCode');
8652+ $fs = $v->structmem('faultString');
8653+ $r = new XML_RPC_Response($v, $f->scalarval(),
8654+ $fs->scalarval());
8655+ } else {
8656+ $r = new XML_RPC_Response($v);
8657+ }
8658+ }
8659+ $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
8660+ return $r;
8661+ }
8662+}
8663+
8664+/**
8665+ * The methods and properties that represent data in XML RPC format
8666+ *
8667+ * @category Web Services
8668+ * @package XML_RPC
8669+ * @author Edd Dumbill <edd@usefulinc.com>
8670+ * @author Stig Bakken <stig@php.net>
8671+ * @author Martin Jansen <mj@php.net>
8672+ * @author Daniel Convissor <danielc@php.net>
8673+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
8674+ * @version Release: 1.3.1
8675+ * @link http://pear.php.net/package/XML_RPC
8676+ */
8677+class XML_RPC_Value extends XML_RPC_Base
8678+{
8679+ var $me = array();
8680+ var $mytype = 0;
8681+
8682+ /**
8683+ * @return void
8684+ */
8685+ function XML_RPC_Value($val = -1, $type = '')
8686+ {
8687+ global $XML_RPC_Types;
8688+ $this->me = array();
8689+ $this->mytype = 0;
8690+ if ($val != -1 || $type != '') {
8691+ if ($type == '') {
8692+ $type = 'string';
8693+ }
8694+ if (!array_key_exists($type, $XML_RPC_Types)) {
8695+ // XXX
8696+ // need some way to report this error
8697+ } elseif ($XML_RPC_Types[$type] == 1) {
8698+ $this->addScalar($val, $type);
8699+ } elseif ($XML_RPC_Types[$type] == 2) {
8700+ $this->addArray($val);
8701+ } elseif ($XML_RPC_Types[$type] == 3) {
8702+ $this->addStruct($val);
8703+ }
8704+ }
8705+ }
8706+
8707+ /**
8708+ * @return int returns 1 if successful or 0 if there are problems
8709+ */
8710+ function addScalar($val, $type = 'string')
8711+ {
8712+ global $XML_RPC_Types, $XML_RPC_Boolean;
8713+
8714+ if ($this->mytype == 1) {
8715+ $this->raiseError('Scalar can have only one value',
8716+ XML_RPC_ERROR_INVALID_TYPE);
8717+ return 0;
8718+ }
8719+ $typeof = $XML_RPC_Types[$type];
8720+ if ($typeof != 1) {
8721+ $this->raiseError("Not a scalar type (${typeof})",
8722+ XML_RPC_ERROR_INVALID_TYPE);
8723+ return 0;
8724+ }
8725+
8726+ if ($type == $XML_RPC_Boolean) {
8727+ if (strcasecmp($val, 'true') == 0
8728+ || $val == 1
8729+ || ($val == true && strcasecmp($val, 'false')))
8730+ {
8731+ $val = 1;
8732+ } else {
8733+ $val = 0;
8734+ }
8735+ }
8736+
8737+ if ($this->mytype == 2) {
8738+ // we're adding to an array here
8739+ $ar = $this->me['array'];
8740+ $ar[] = new XML_RPC_Value($val, $type);
8741+ $this->me['array'] = $ar;
8742+ } else {
8743+ // a scalar, so set the value and remember we're scalar
8744+ $this->me[$type] = $val;
8745+ $this->mytype = $typeof;
8746+ }
8747+ return 1;
8748+ }
8749+
8750+ /**
8751+ * @return int returns 1 if successful or 0 if there are problems
8752+ */
8753+ function addArray($vals)
8754+ {
8755+ global $XML_RPC_Types;
8756+ if ($this->mytype != 0) {
8757+ $this->raiseError(
8758+ 'Already initialized as a [' . $this->kindOf() . ']',
8759+ XML_RPC_ERROR_ALREADY_INITIALIZED);
8760+ return 0;
8761+ }
8762+ $this->mytype = $XML_RPC_Types['array'];
8763+ $this->me['array'] = $vals;
8764+ return 1;
8765+ }
8766+
8767+ /**
8768+ * @return int returns 1 if successful or 0 if there are problems
8769+ */
8770+ function addStruct($vals)
8771+ {
8772+ global $XML_RPC_Types;
8773+ if ($this->mytype != 0) {
8774+ $this->raiseError(
8775+ 'Already initialized as a [' . $this->kindOf() . ']',
8776+ XML_RPC_ERROR_ALREADY_INITIALIZED);
8777+ return 0;
8778+ }
8779+ $this->mytype = $XML_RPC_Types['struct'];
8780+ $this->me['struct'] = $vals;
8781+ return 1;
8782+ }
8783+
8784+ /**
8785+ * @return void
8786+ */
8787+ function dump($ar)
8788+ {
8789+ reset($ar);
8790+ foreach ($ar as $key => $val) {
8791+ echo "$key => $val<br />";
8792+ if ($key == 'array') {
8793+ foreach ($val as $key2 => $val2) {
8794+ echo "-- $key2 => $val2<br />";
8795+ }
8796+ }
8797+ }
8798+ }
8799+
8800+ /**
8801+ * @return string the data type of the current value
8802+ */
8803+ function kindOf()
8804+ {
8805+ switch ($this->mytype) {
8806+ case 3:
8807+ return 'struct';
8808+
8809+ case 2:
8810+ return 'array';
8811+
8812+ case 1:
8813+ return 'scalar';
8814+
8815+ default:
8816+ return 'undef';
8817+ }
8818+ }
8819+
8820+ /**
8821+ * @return string the data in XML format
8822+ */
8823+ function serializedata($typ, $val)
8824+ {
8825+ $rs = '';
8826+ global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
8827+ if (!array_key_exists($typ, $XML_RPC_Types)) {
8828+ // XXX
8829+ // need some way to report this error
8830+ return;
8831+ }
8832+ switch ($XML_RPC_Types[$typ]) {
8833+ case 3:
8834+ // struct
8835+ $rs .= "<struct>\n";
8836+ reset($val);
8837+ foreach ($val as $key2 => $val2) {
8838+ $rs .= "<member><name>${key2}</name>\n";
8839+ $rs .= $this->serializeval($val2);
8840+ $rs .= "</member>\n";
8841+ }
8842+ $rs .= '</struct>';
8843+ break;
8844+
8845+ case 2:
8846+ // array
8847+ $rs .= "<array>\n<data>\n";
8848+ for ($i = 0; $i < sizeof($val); $i++) {
8849+ $rs .= $this->serializeval($val[$i]);
8850+ }
8851+ $rs .= "</data>\n</array>";
8852+ break;
8853+
8854+ case 1:
8855+ switch ($typ) {
8856+ case $XML_RPC_Base64:
8857+ $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
8858+ break;
8859+ case $XML_RPC_Boolean:
8860+ $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
8861+ break;
8862+ case $XML_RPC_String:
8863+ $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
8864+ break;
8865+ default:
8866+ $rs .= "<${typ}>${val}</${typ}>";
8867+ }
8868+ }
8869+ return $rs;
8870+ }
8871+
8872+ /**
8873+ * @return string the data in XML format
8874+ */
8875+ function serialize()
8876+ {
8877+ return $this->serializeval($this);
8878+ }
8879+
8880+ /**
8881+ * @return string the data in XML format
8882+ */
8883+ function serializeval($o)
8884+ {
8885+ $rs = '';
8886+ $ar = $o->me;
8887+ reset($ar);
8888+ list($typ, $val) = each($ar);
8889+ $rs .= '<value>';
8890+ $rs .= $this->serializedata($typ, $val);
8891+ $rs .= "</value>\n";
8892+ return $rs;
8893+ }
8894+
8895+ /**
8896+ * @return mixed the contents of the element requested
8897+ */
8898+ function structmem($m)
8899+ {
8900+ return $this->me['struct'][$m];
8901+ }
8902+
8903+ /**
8904+ * @return void
8905+ */
8906+ function structreset()
8907+ {
8908+ reset($this->me['struct']);
8909+ }
8910+
8911+ /**
8912+ * @return the key/value pair of the struct's current element
8913+ */
8914+ function structeach()
8915+ {
8916+ return each($this->me['struct']);
8917+ }
8918+
8919+ /**
8920+ * @return mixed the current value
8921+ */
8922+ function getval()
8923+ {
8924+ // UNSTABLE
8925+ global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
8926+
8927+ reset($this->me);
8928+ $b = current($this->me);
8929+
8930+ // contributed by I Sofer, 2001-03-24
8931+ // add support for nested arrays to scalarval
8932+ // i've created a new method here, so as to
8933+ // preserve back compatibility
8934+
8935+ if (is_array($b)) {
8936+ foreach ($b as $id => $cont) {
8937+ $b[$id] = $cont->scalarval();
8938+ }
8939+ }
8940+
8941+ // add support for structures directly encoding php objects
8942+ if (is_object($b)) {
8943+ $t = get_object_vars($b);
8944+ foreach ($t as $id => $cont) {
8945+ $t[$id] = $cont->scalarval();
8946+ }
8947+ foreach ($t as $id => $cont) {
8948+ eval('$b->'.$id.' = $cont;');
8949+ }
8950+ }
8951+
8952+ // end contrib
8953+ return $b;
8954+ }
8955+
8956+ /**
8957+ * @return mixed
8958+ */
8959+ function scalarval()
8960+ {
8961+ global $XML_RPC_Boolean, $XML_RPC_Base64;
8962+ reset($this->me);
8963+ return current($this->me);
8964+ }
8965+
8966+ /**
8967+ * @return string
8968+ */
8969+ function scalartyp()
8970+ {
8971+ global $XML_RPC_I4, $XML_RPC_Int;
8972+ reset($this->me);
8973+ $a = key($this->me);
8974+ if ($a == $XML_RPC_I4) {
8975+ $a = $XML_RPC_Int;
8976+ }
8977+ return $a;
8978+ }
8979+
8980+ /**
8981+ * @return mixed the struct's current element
8982+ */
8983+ function arraymem($m)
8984+ {
8985+ return $this->me['array'][$m];
8986+ }
8987+
8988+ /**
8989+ * @return int the number of elements in the array
8990+ */
8991+ function arraysize()
8992+ {
8993+ reset($this->me);
8994+ list($a, $b) = each($this->me);
8995+ return sizeof($b);
8996+ }
8997+
8998+ /**
8999+ * Determines if the item submitted is an XML_RPC_Value object
9000+ *
9001+ * @param mixed $val the variable to be evaluated
9002+ *
9003+ * @return bool TRUE if the item is an XML_RPC_Value object
9004+ *
9005+ * @static
9006+ * @since Method available since Release 1.3.0
9007+ */
9008+ function isValue($val)
9009+ {
9010+ return (strtolower(get_class($val)) == 'xml_rpc_value');
9011+ }
9012+}
9013+
9014+/**
9015+ * Return an ISO8601 encoded string
9016+ *
9017+ * While timezones ought to be supported, the XML-RPC spec says:
9018+ *
9019+ * "Don't assume a timezone. It should be specified by the server in its
9020+ * documentation what assumptions it makes about timezones."
9021+ *
9022+ * This routine always assumes localtime unless $utc is set to 1, in which
9023+ * case UTC is assumed and an adjustment for locale is made when encoding.
9024+ *
9025+ * @return string the formatted date
9026+ */
9027+function XML_RPC_iso8601_encode($timet, $utc = 0)
9028+{
9029+ if (!$utc) {
9030+ $t = strftime('%Y%m%dT%H:%M:%S', $timet);
9031+ } else {
9032+ if (function_exists('gmstrftime')) {
9033+ // gmstrftime doesn't exist in some versions
9034+ // of PHP
9035+ $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet);
9036+ } else {
9037+ $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z'));
9038+ }
9039+ }
9040+ return $t;
9041+}
9042+
9043+/**
9044+ * Convert a datetime string into a Unix timestamp
9045+ *
9046+ * While timezones ought to be supported, the XML-RPC spec says:
9047+ *
9048+ * "Don't assume a timezone. It should be specified by the server in its
9049+ * documentation what assumptions it makes about timezones."
9050+ *
9051+ * This routine always assumes localtime unless $utc is set to 1, in which
9052+ * case UTC is assumed and an adjustment for locale is made when encoding.
9053+ *
9054+ * @return int the unix timestamp of the date submitted
9055+ */
9056+function XML_RPC_iso8601_decode($idate, $utc = 0)
9057+{
9058+ $t = 0;
9059+ if (ereg('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) {
9060+ if ($utc) {
9061+ $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
9062+ } else {
9063+ $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
9064+ }
9065+ }
9066+ return $t;
9067+}
9068+
9069+/**
9070+ * Converts an XML_RPC_Value object into native PHP types
9071+ *
9072+ * @param object $XML_RPC_val the XML_RPC_Value object to decode
9073+ *
9074+ * @return mixed the PHP values
9075+ */
9076+function XML_RPC_decode($XML_RPC_val)
9077+{
9078+ $kind = $XML_RPC_val->kindOf();
9079+
9080+ if ($kind == 'scalar') {
9081+ return $XML_RPC_val->scalarval();
9082+
9083+ } elseif ($kind == 'array') {
9084+ $size = $XML_RPC_val->arraysize();
9085+ $arr = array();
9086+ for ($i = 0; $i < $size; $i++) {
9087+ $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i));
9088+ }
9089+ return $arr;
9090+
9091+ } elseif ($kind == 'struct') {
9092+ $XML_RPC_val->structreset();
9093+ $arr = array();
9094+ while (list($key, $value) = $XML_RPC_val->structeach()) {
9095+ $arr[$key] = XML_RPC_decode($value);
9096+ }
9097+ return $arr;
9098+ }
9099+}
9100+
9101+/**
9102+ * Converts native PHP types into an XML_RPC_Value object
9103+ *
9104+ * @param mixed $php_val the PHP value or variable you want encoded
9105+ *
9106+ * @return object the XML_RPC_Value object
9107+ */
9108+function XML_RPC_encode($php_val)
9109+{
9110+ global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double, $XML_RPC_String,
9111+ $XML_RPC_Array, $XML_RPC_Struct;
9112+
9113+ $type = gettype($php_val);
9114+ $XML_RPC_val = new XML_RPC_Value;
9115+
9116+ switch ($type) {
9117+ case 'array':
9118+ if (empty($php_val)) {
9119+ $XML_RPC_val->addArray($php_val);
9120+ break;
9121+ }
9122+ $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1));
9123+ if (empty($tmp)) {
9124+ $arr = array();
9125+ foreach ($php_val as $k => $v) {
9126+ $arr[$k] = XML_RPC_encode($v);
9127+ }
9128+ $XML_RPC_val->addArray($arr);
9129+ break;
9130+ }
9131+ // fall though if it's not an enumerated array
9132+
9133+ case 'object':
9134+ $arr = array();
9135+ foreach ($php_val as $k => $v) {
9136+ $arr[$k] = XML_RPC_encode($v);
9137+ }
9138+ $XML_RPC_val->addStruct($arr);
9139+ break;
9140+
9141+ case 'integer':
9142+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
9143+ break;
9144+
9145+ case 'double':
9146+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
9147+ break;
9148+
9149+ case 'string':
9150+ case 'NULL':
9151+ $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
9152+ break;
9153+
9154+ case 'boolean':
9155+ // Add support for encoding/decoding of booleans, since they
9156+ // are supported in PHP
9157+ // by <G_Giunta_2001-02-29>
9158+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
9159+ break;
9160+
9161+ case 'unknown type':
9162+ default:
9163+ $XML_RPC_val = false;
9164+ }
9165+ return $XML_RPC_val;
9166+}
9167+
9168+/*
9169+ * Local variables:
9170+ * tab-width: 4
9171+ * c-basic-offset: 4
9172+ * c-hanging-comment-ender-p: nil
9173+ * End:
9174+ */
9175+
9176+?>
9177+
9178+
9179+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
9180+
9181+/**
9182+ * Server commands for our PHP implementation of the XML-RPC protocol
9183+ *
9184+ * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
9185+ * It has support for HTTP transport, proxies and authentication.
9186+ *
9187+ * PHP versions 4 and 5
9188+ *
9189+ * LICENSE: License is granted to use or modify this software
9190+ * ("XML-RPC for PHP") for commercial or non-commercial use provided the
9191+ * copyright of the author is preserved in any distributed or derivative work.
9192+ *
9193+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
9194+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
9195+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9196+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
9197+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
9198+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
9199+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9200+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9201+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
9202+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9203+ *
9204+ * @category Web Services
9205+ * @package XML_RPC
9206+ * @author Edd Dumbill <edd@usefulinc.com>
9207+ * @author Stig Bakken <stig@php.net>
9208+ * @author Martin Jansen <mj@php.net>
9209+ * @author Daniel Convissor <danielc@php.net>
9210+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
9211+ * @version CVS: $Id: Server.php,v 1.26 2005/05/09 21:39:47 danielc Exp $
9212+ * @link http://pear.php.net/package/XML_RPC
9213+ */
9214+
9215+
9216+/**
9217+ * Pull in the XML_RPC class
9218+ */
9219+require_once 'XML/RPC.php';
9220+
9221+
9222+/**
9223+ * signature for system.listMethods: return = array,
9224+ * parameters = a string or nothing
9225+ * @global array $GLOBALS['XML_RPC_Server_listMethods_sig']
9226+ */
9227+$GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
9228+ array($GLOBALS['XML_RPC_Array'],
9229+ $GLOBALS['XML_RPC_String']
9230+ ),
9231+ array($GLOBALS['XML_RPC_Array'])
9232+);
9233+
9234+/**
9235+ * docstring for system.listMethods
9236+ * @global string $GLOBALS['XML_RPC_Server_listMethods_doc']
9237+ */
9238+$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the'
9239+ . ' methods that the XML-RPC server knows how to dispatch';
9240+
9241+/**
9242+ * signature for system.methodSignature: return = array,
9243+ * parameters = string
9244+ * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig']
9245+ */
9246+$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
9247+ array($GLOBALS['XML_RPC_Array'],
9248+ $GLOBALS['XML_RPC_String']
9249+ )
9250+);
9251+
9252+/**
9253+ * docstring for system.methodSignature
9254+ * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc']
9255+ */
9256+$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
9257+ . ' signatures (an array of arrays) for the method name passed. If'
9258+ . ' no signatures are known, returns a none-array (test for type !='
9259+ . ' array to detect missing signature)';
9260+
9261+/**
9262+ * signature for system.methodHelp: return = string,
9263+ * parameters = string
9264+ * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig']
9265+ */
9266+$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
9267+ array($GLOBALS['XML_RPC_String'],
9268+ $GLOBALS['XML_RPC_String']
9269+ )
9270+);
9271+
9272+/**
9273+ * docstring for methodHelp
9274+ * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc']
9275+ */
9276+$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined'
9277+ . ' for the method passed, otherwise returns an empty string';
9278+
9279+/**
9280+ * dispatch map for the automatically declared XML-RPC methods.
9281+ * @global array $GLOBALS['XML_RPC_Server_dmap']
9282+ */
9283+$GLOBALS['XML_RPC_Server_dmap'] = array(
9284+ 'system.listMethods' => array(
9285+ 'function' => 'XML_RPC_Server_listMethods',
9286+ 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'],
9287+ 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc']
9288+ ),
9289+ 'system.methodHelp' => array(
9290+ 'function' => 'XML_RPC_Server_methodHelp',
9291+ 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'],
9292+ 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc']
9293+ ),
9294+ 'system.methodSignature' => array(
9295+ 'function' => 'XML_RPC_Server_methodSignature',
9296+ 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'],
9297+ 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc']
9298+ )
9299+);
9300+
9301+/**
9302+ * @global string $GLOBALS['XML_RPC_Server_debuginfo']
9303+ */
9304+$GLOBALS['XML_RPC_Server_debuginfo'] = '';
9305+
9306+
9307+/**
9308+ * Lists all the methods that the XML-RPC server knows how to dispatch
9309+ *
9310+ * @return object a new XML_RPC_Response object
9311+ */
9312+function XML_RPC_Server_listMethods($server, $m)
9313+{
9314+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
9315+
9316+ $v = new XML_RPC_Value();
9317+ $outAr = array();
9318+ foreach ($server->dmap as $key => $val) {
9319+ $outAr[] = new XML_RPC_Value($key, 'string');
9320+ }
9321+ foreach ($XML_RPC_Server_dmap as $key => $val) {
9322+ $outAr[] = new XML_RPC_Value($key, 'string');
9323+ }
9324+ $v->addArray($outAr);
9325+ return new XML_RPC_Response($v);
9326+}
9327+
9328+/**
9329+ * Returns an array of known signatures (an array of arrays)
9330+ * for the given method
9331+ *
9332+ * If no signatures are known, returns a none-array
9333+ * (test for type != array to detect missing signature)
9334+ *
9335+ * @return object a new XML_RPC_Response object
9336+ */
9337+function XML_RPC_Server_methodSignature($server, $m)
9338+{
9339+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
9340+
9341+ $methName = $m->getParam(0);
9342+ $methName = $methName->scalarval();
9343+ if (strpos($methName, 'system.') === 0) {
9344+ $dmap = $XML_RPC_Server_dmap;
9345+ $sysCall = 1;
9346+ } else {
9347+ $dmap = $server->dmap;
9348+ $sysCall = 0;
9349+ }
9350+ // print "<!-- ${methName} -->\n";
9351+ if (isset($dmap[$methName])) {
9352+ if ($dmap[$methName]['signature']) {
9353+ $sigs = array();
9354+ $thesigs = $dmap[$methName]['signature'];
9355+ for ($i = 0; $i < sizeof($thesigs); $i++) {
9356+ $cursig = array();
9357+ $inSig = $thesigs[$i];
9358+ for ($j = 0; $j < sizeof($inSig); $j++) {
9359+ $cursig[] = new XML_RPC_Value($inSig[$j], 'string');
9360+ }
9361+ $sigs[] = new XML_RPC_Value($cursig, 'array');
9362+ }
9363+ $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array'));
9364+ } else {
9365+ $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string'));
9366+ }
9367+ } else {
9368+ $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
9369+ $XML_RPC_str['introspect_unknown']);
9370+ }
9371+ return $r;
9372+}
9373+
9374+/**
9375+ * Returns help text if defined for the method passed, otherwise returns
9376+ * an empty string
9377+ *
9378+ * @return object a new XML_RPC_Response object
9379+ */
9380+function XML_RPC_Server_methodHelp($server, $m)
9381+{
9382+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
9383+
9384+ $methName = $m->getParam(0);
9385+ $methName = $methName->scalarval();
9386+ if (strpos($methName, 'system.') === 0) {
9387+ $dmap = $XML_RPC_Server_dmap;
9388+ $sysCall = 1;
9389+ } else {
9390+ $dmap = $server->dmap;
9391+ $sysCall = 0;
9392+ }
9393+ // print "<!-- ${methName} -->\n";
9394+ if (isset($dmap[$methName])) {
9395+ if ($dmap[$methName]['docstring']) {
9396+ $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']),
9397+ 'string');
9398+ } else {
9399+ $r = new XML_RPC_Response(new XML_RPC_Value('', 'string'));
9400+ }
9401+ } else {
9402+ $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
9403+ $XML_RPC_str['introspect_unknown']);
9404+ }
9405+ return $r;
9406+}
9407+
9408+/**
9409+ * @return void
9410+ */
9411+function XML_RPC_Server_debugmsg($m)
9412+{
9413+ global $XML_RPC_Server_debuginfo;
9414+ $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n";
9415+}
9416+
9417+
9418+/**
9419+ * A server for receiving and replying to XML RPC requests
9420+ *
9421+ * <code>
9422+ * $server = new XML_RPC_Server(
9423+ * array(
9424+ * 'isan8' =>
9425+ * array(
9426+ * 'function' => 'is_8',
9427+ * 'signature' =>
9428+ * array(
9429+ * array('boolean', 'int'),
9430+ * array('boolean', 'int', 'boolean'),
9431+ * array('boolean', 'string'),
9432+ * array('boolean', 'string', 'boolean'),
9433+ * ),
9434+ * 'docstring' => 'Is the value an 8?'
9435+ * ),
9436+ * ),
9437+ * 1,
9438+ * 0
9439+ * );
9440+ * </code>
9441+ *
9442+ * @category Web Services
9443+ * @package XML_RPC
9444+ * @author Edd Dumbill <edd@usefulinc.com>
9445+ * @author Stig Bakken <stig@php.net>
9446+ * @author Martin Jansen <mj@php.net>
9447+ * @author Daniel Convissor <danielc@php.net>
9448+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
9449+ * @version Release: 1.3.1
9450+ * @link http://pear.php.net/package/XML_RPC
9451+ */
9452+class XML_RPC_Server
9453+{
9454+ /**
9455+ * The dispatch map, listing the methods this server provides.
9456+ * @var array
9457+ */
9458+ var $dmap = array();
9459+
9460+ /**
9461+ * The present response's encoding
9462+ * @var string
9463+ * @see XML_RPC_Message::getEncoding()
9464+ */
9465+ var $encoding = '';
9466+
9467+ /**
9468+ * Debug mode (0 = off, 1 = on)
9469+ * @var integer
9470+ */
9471+ var $debug = 0;
9472+
9473+ /**
9474+ * The response's HTTP headers
9475+ * @var string
9476+ */
9477+ var $server_headers = '';
9478+
9479+ /**
9480+ * The response's XML payload
9481+ * @var string
9482+ */
9483+ var $server_payload = '';
9484+
9485+
9486+ /**
9487+ * Constructor for the XML_RPC_Server class
9488+ *
9489+ * @param array $dispMap the dispatch map. An associative array
9490+ * explaining each function. The keys of the main
9491+ * array are the procedure names used by the
9492+ * clients. The value is another associative array
9493+ * that contains up to three elements:
9494+ * + The 'function' element's value is the name
9495+ * of the function or method that gets called.
9496+ * To define a class' method: 'class::method'.
9497+ * + The 'signature' element (optional) is an
9498+ * array describing the return values and
9499+ * parameters
9500+ * + The 'docstring' element (optional) is a
9501+ * string describing what the method does
9502+ * @param int $serviceNow should the HTTP response be sent now?
9503+ * (1 = yes, 0 = no)
9504+ * @param int $debug should debug output be displayed?
9505+ * (1 = yes, 0 = no)
9506+ *
9507+ * @return void
9508+ */
9509+ function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0)
9510+ {
9511+ global $HTTP_RAW_POST_DATA;
9512+
9513+ if ($debug) {
9514+ $this->debug = 1;
9515+ } else {
9516+ $this->debug = 0;
9517+ }
9518+
9519+ $this->dmap = $dispMap;
9520+
9521+ if ($serviceNow) {
9522+ $this->service();
9523+ } else {
9524+ $this->createServerPayload();
9525+ $this->createServerHeaders();
9526+ }
9527+ }
9528+
9529+ /**
9530+ * @return string the debug information if debug debug mode is on
9531+ */
9532+ function serializeDebug()
9533+ {
9534+ global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA;
9535+
9536+ if ($this->debug) {
9537+ XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n"
9538+ . $HTTP_RAW_POST_DATA
9539+ . "\n" . '^^^ END POST DATA ^^^');
9540+ }
9541+
9542+ if ($XML_RPC_Server_debuginfo != '') {
9543+ return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n"
9544+ . preg_replace('/-(?=-)/', '- ', $XML_RPC_Server_debuginfo)
9545+ . "-->\n";
9546+ } else {
9547+ return '';
9548+ }
9549+ }
9550+
9551+ /**
9552+ * Sends the response
9553+ *
9554+ * The encoding and content-type are determined by
9555+ * XML_RPC_Message::getEncoding()
9556+ *
9557+ * @return void
9558+ *
9559+ * @uses XML_RPC_Server::createServerPayload(),
9560+ * XML_RPC_Server::createServerHeaders()
9561+ */
9562+ function service()
9563+ {
9564+ $this->createServerPayload();
9565+ $this->createServerHeaders();
9566+ header($this->server_headers);
9567+ print $this->server_payload;
9568+ }
9569+
9570+ /**
9571+ * Generates the payload and puts it in the $server_payload property
9572+ *
9573+ * @return void
9574+ *
9575+ * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding,
9576+ * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug()
9577+ */
9578+ function createServerPayload()
9579+ {
9580+ $r = $this->parseRequest();
9581+ $this->server_payload = '<?xml version="1.0" encoding="'
9582+ . $this->encoding . '"?>' . "\n"
9583+ . $this->serializeDebug()
9584+ . $r->serialize();
9585+ }
9586+
9587+ /**
9588+ * Determines the HTTP headers and puts them in the $server_headers
9589+ * property
9590+ *
9591+ * @return boolean TRUE if okay, FALSE if $server_payload isn't set.
9592+ *
9593+ * @uses XML_RPC_Server::createServerPayload(),
9594+ * XML_RPC_Server::$server_headers
9595+ */
9596+ function createServerHeaders()
9597+ {
9598+ if (!$this->server_payload) {
9599+ return false;
9600+ }
9601+ $this->server_headers = 'Content-Length: '
9602+ . strlen($this->server_payload) . "\r\n"
9603+ . 'Content-Type: text/xml;'
9604+ . ' charset=' . $this->encoding;
9605+ return true;
9606+ }
9607+
9608+ /**
9609+ * @return array
9610+ */
9611+ function verifySignature($in, $sig)
9612+ {
9613+ for ($i = 0; $i < sizeof($sig); $i++) {
9614+ // check each possible signature in turn
9615+ $cursig = $sig[$i];
9616+ if (sizeof($cursig) == $in->getNumParams() + 1) {
9617+ $itsOK = 1;
9618+ for ($n = 0; $n < $in->getNumParams(); $n++) {
9619+ $p = $in->getParam($n);
9620+ // print "<!-- $p -->\n";
9621+ if ($p->kindOf() == 'scalar') {
9622+ $pt = $p->scalartyp();
9623+ } else {
9624+ $pt = $p->kindOf();
9625+ }
9626+ // $n+1 as first type of sig is return type
9627+ if ($pt != $cursig[$n+1]) {
9628+ $itsOK = 0;
9629+ $pno = $n+1;
9630+ $wanted = $cursig[$n+1];
9631+ $got = $pt;
9632+ break;
9633+ }
9634+ }
9635+ if ($itsOK) {
9636+ return array(1);
9637+ }
9638+ }
9639+ }
9640+ if (isset($wanted)) {
9641+ return array(0, "Wanted ${wanted}, got ${got} at param ${pno}");
9642+ } else {
9643+ $allowed = array();
9644+ foreach ($sig as $val) {
9645+ end($val);
9646+ $allowed[] = key($val);
9647+ }
9648+ $allowed = array_unique($allowed);
9649+ $last = count($allowed) - 1;
9650+ if ($last > 0) {
9651+ $allowed[$last] = 'or ' . $allowed[$last];
9652+ }
9653+ return array(0,
9654+ 'Signature permits ' . implode(', ', $allowed)
9655+ . ' parameters but the request had '
9656+ . $in->getNumParams());
9657+ }
9658+ }
9659+
9660+ /**
9661+ * @return object a new XML_RPC_Response object
9662+ *
9663+ * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding
9664+ */
9665+ function parseRequest($data = '')
9666+ {
9667+ global $XML_RPC_xh, $HTTP_RAW_POST_DATA,
9668+ $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml,
9669+ $XML_RPC_defencoding, $XML_RPC_Server_dmap;
9670+
9671+ if ($data == '') {
9672+ $data = $HTTP_RAW_POST_DATA;
9673+ }
9674+
9675+ $this->encoding = XML_RPC_Message::getEncoding($data);
9676+ $parser_resource = xml_parser_create($this->encoding);
9677+ $parser = (int) $parser_resource;
9678+
9679+ $XML_RPC_xh[$parser] = array();
9680+ $XML_RPC_xh[$parser]['st'] = '';
9681+ $XML_RPC_xh[$parser]['cm'] = 0;
9682+ $XML_RPC_xh[$parser]['isf'] = 0;
9683+ $XML_RPC_xh[$parser]['params'] = array();
9684+ $XML_RPC_xh[$parser]['method'] = '';
9685+
9686+ $plist = '';
9687+
9688+ // decompose incoming XML into request structure
9689+
9690+ xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
9691+ xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
9692+ xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
9693+ if (!xml_parse($parser_resource, $data, 1)) {
9694+ // return XML error as a faultCode
9695+ $r = new XML_RPC_Response(0,
9696+ $XML_RPC_errxml+xml_get_error_code($parser_resource),
9697+ sprintf('XML error: %s at line %d',
9698+ xml_error_string(xml_get_error_code($parser_resource)),
9699+ xml_get_current_line_number($parser_resource)));
9700+ xml_parser_free($parser_resource);
9701+ } else {
9702+ xml_parser_free($parser_resource);
9703+ $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']);
9704+ // now add parameters in
9705+ for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) {
9706+ // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n";
9707+ $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n";
9708+ eval('$m->addParam(' . $XML_RPC_xh[$parser]['params'][$i] . ');');
9709+ }
9710+ XML_RPC_Server_debugmsg($plist);
9711+
9712+ // now to deal with the method
9713+ $methName = $XML_RPC_xh[$parser]['method'];
9714+ if (strpos($methName, 'system.') === 0) {
9715+ $dmap = $XML_RPC_Server_dmap;
9716+ $sysCall = 1;
9717+ } else {
9718+ $dmap = $this->dmap;
9719+ $sysCall = 0;
9720+ }
9721+
9722+ if (isset($dmap[$methName]['function'])
9723+ && is_string($dmap[$methName]['function'])
9724+ && strpos($dmap[$methName]['function'], '::') !== false)
9725+ {
9726+ $dmap[$methName]['function'] =
9727+ explode('::', $dmap[$methName]['function']);
9728+ }
9729+
9730+ if (isset($dmap[$methName]['function'])
9731+ && is_callable($dmap[$methName]['function']))
9732+ {
9733+ // dispatch if exists
9734+ if (isset($dmap[$methName]['signature'])) {
9735+ $sr = $this->verifySignature($m,
9736+ $dmap[$methName]['signature'] );
9737+ }
9738+ if (!isset($dmap[$methName]['signature']) || $sr[0]) {
9739+ // if no signature or correct signature
9740+ if ($sysCall) {
9741+ $r = call_user_func($dmap[$methName]['function'], $this, $m);
9742+ } else {
9743+ $r = call_user_func($dmap[$methName]['function'], $m);
9744+ }
9745+ if (!is_a($r, 'XML_RPC_Response')) {
9746+ $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'],
9747+ $XML_RPC_str['not_response_object']);
9748+ }
9749+ } else {
9750+ $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
9751+ $XML_RPC_str['incorrect_params']
9752+ . ': ' . $sr[1]);
9753+ }
9754+ } else {
9755+ // else prepare error response
9756+ $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'],
9757+ $XML_RPC_str['unknown_method']);
9758+ }
9759+ }
9760+ return $r;
9761+ }
9762+
9763+ /**
9764+ * Echos back the input packet as a string value
9765+ *
9766+ * @return void
9767+ *
9768+ * Useful for debugging.
9769+ */
9770+ function echoInput()
9771+ {
9772+ global $HTTP_RAW_POST_DATA;
9773+
9774+ $r = new XML_RPC_Response(0);
9775+ $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string');
9776+ print $r->serialize();
9777+ }
9778+}
9779+
9780+/*
9781+ * Local variables:
9782+ * tab-width: 4
9783+ * c-basic-offset: 4
9784+ * c-hanging-comment-ender-p: nil
9785+ * End:
9786+ */
9787+
9788+?>
9789+
9790+<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
9791+<package version="1.0" packagerversion="1.4.0a12">
9792+ <name>XML_RPC</name>
9793+ <summary>PHP implementation of the XML-RPC protocol</summary>
9794+ <description>A PEAR-ified version of Useful Inc's XML-RPC for PHP.
9795+
9796+It has support for HTTP/HTTPS transport, proxies and authentication.
9797+ </description>
9798+ <maintainers>
9799+ <maintainer>
9800+ <user>ssb</user>
9801+ <name>Stig Bakken</name>
9802+ <email>stig@php.net</email>
9803+ <role>lead</role>
9804+ </maintainer>
9805+ <maintainer>
9806+ <user>danielc</user>
9807+ <name>Daniel Convissor</name>
9808+ <email>danielc@php.net</email>
9809+ <role>lead</role>
9810+ </maintainer>
9811+ </maintainers>
9812+ <release>
9813+ <version>1.3.1</version>
9814+ <date>2005-06-29</date>
9815+ <license>PHP License</license>
9816+ <state>stable</state>
9817+ <notes>* Security fix. Update highly recommended!
9818+ </notes>
9819+ <filelist>
9820+ <file role="php" baseinstalldir="XML" name="RPC.php">
9821+ <replace from="@package_version@" to="version" type="package-info"/>
9822+ </file>
9823+ <file role="php" baseinstalldir="XML/RPC" name="Server.php">
9824+ <replace from="@package_version@" to="version" type="package-info"/>
9825+ </file>
9826+ <file role="php" baseinstalldir="XML/RPC" name="Dump.php">
9827+ <replace from="@package_version@" to="version" type="package-info"/>
9828+ </file>
9829+ <file role="test" name="tests/protoport.php">
9830+ <replace from="@package_version@" to="version" type="package-info"/>
9831+ </file>
9832+ <file role="test" name="tests/test_Dump.php">
9833+ <replace from="@package_version@" to="version" type="package-info"/>
9834+ </file>
9835+ </filelist>
9836+ </release>
9837+ <changelog>
9838+ <release>
9839+ <version>1.3.0RC3</version>
9840+ <date>2005-05-10</date>
9841+ <state>beta</state>
9842+ <notes>* When verifying requests against function signatures, if the number of parameters don't match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
9843+* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
9844+* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
9845+* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
9846+* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
9847+* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().
9848+ </notes>
9849+ </release>
9850+ <release>
9851+ <version>1.3.0RC2</version>
9852+ <date>2005-05-05</date>
9853+ <state>beta</state>
9854+ <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
9855+* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
9856+* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
9857+* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.
9858+ </notes>
9859+ </release>
9860+ <release>
9861+ <version>1.3.0RC1</version>
9862+ <date>2005-04-07</date>
9863+ <state>beta</state>
9864+ <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
9865+* Add Fault Code 6: &quot;The requested method didn't return an XML_RPC_Response object.&quot; Request 4032.
9866+* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
9867+* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
9868+* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
9869+* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.
9870+ </notes>
9871+ </release>
9872+ <release>
9873+ <version>1.2.2</version>
9874+ <date>2005-03-07</date>
9875+ <state>stable</state>
9876+ <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.
9877+ </notes>
9878+ </release>
9879+ <release>
9880+ <version>1.2.1</version>
9881+ <date>2005-03-01</date>
9882+ <state>stable</state>
9883+ <notes>* Add isset() check before examining the dispatch map. Bug 3658.
9884+ </notes>
9885+ </release>
9886+ <release>
9887+ <version>1.2.0</version>
9888+ <date>2005-02-27</date>
9889+ <state>stable</state>
9890+ <notes>* Provide the &quot;stable&quot; release.
9891+* Add package2.xml for compatibility with PEAR 1.4.0.
9892+* For changes since 1.1.0, see the changelogs for the various RC releases.
9893+ </notes>
9894+ </release>
9895+ <release>
9896+ <version>1.2.0RC7</version>
9897+ <date>2005-02-22</date>
9898+ <state>beta</state>
9899+ <notes>* Add the setSendEncoding() method and $send_encoding
9900+ property to XML_RPC_Message. Request 3537.
9901+* Allow class methods to be mapped using either syntax:
9902+ 'function' =&gt; 'hello::sayHello',
9903+ or
9904+ 'function' =&gt; array('hello', 'sayhello'),
9905+ Bug 3363.
9906+* Use 8192 instead of 32768 for bytes in fread()
9907+ in parseResponseFile(). Bug 3340.
9908+ </notes>
9909+ </release>
9910+ <release>
9911+ <version>1.2.0RC6</version>
9912+ <date>2005-01-25</date>
9913+ <state>beta</state>
9914+ <notes>* Don't put the protocol in the Host field of the POST data. (danielc)
9915+ </notes>
9916+ </release>
9917+ <release>
9918+ <version>1.2.0RC5</version>
9919+ <date>2005-01-24</date>
9920+ <state>beta</state>
9921+ <notes>* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
9922+ </notes>
9923+ </release>
9924+ <release>
9925+ <version>1.2.0RC4</version>
9926+ <date>2005-01-24</date>
9927+ <state>beta</state>
9928+ <notes>* When a connection attempt fails, have the method return 0. (danielc)
9929+* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
9930+* Add tests for setting the client properties. (danielc)
9931+* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc)
9932+* Bundle the tests with the package. (danielc)
9933+ </notes>
9934+ </release>
9935+ <release>
9936+ <version>1.2.0RC3</version>
9937+ <date>2005-01-19</date>
9938+ <state>beta</state>
9939+ <notes>* ssl uses port 443, not 445.
9940+ </notes>
9941+ </release>
9942+ <release>
9943+ <version>1.2.0RC2</version>
9944+ <date>2005-01-11</date>
9945+ <state>beta</state>
9946+ <notes>* Handle ssl:// in the $server string. (danielc)
9947+* Also default to port 445 for ssl:// requests as well. (danielc)
9948+* Enhance debugging in the server. (danielc)
9949+ </notes>
9950+ </release>
9951+ <release>
9952+ <version>1.2.0RC1</version>
9953+ <date>2004-12-30</date>
9954+ <state>beta</state>
9955+ <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
9956+* Allow array function callbacks (Matt Kane)
9957+* Some minor speed-ups (Matt Kane)
9958+* Add Dump.php to the package (Christian Weiske)
9959+* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
9960+* Silence fsockopen() errors. Bug 1714. (danielc)
9961+* Encode empty arrays as an array. Bug 1493. (danielc)
9962+* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
9963+* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
9964+* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc)
9965+* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
9966+* Allow raiseError() to be called statically. (danielc)
9967+* Stop double escaping of character entities. Bug 987. (danielc)
9968+ NOTICE: the following have been removed:
9969+ * XML_RPC_dh()
9970+ * $GLOBALS['XML_RPC_entities']
9971+ * XML_RPC_entity_decode()
9972+ * XML_RPC_lookup_entity()
9973+* Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)
9974+ </notes>
9975+ </release>
9976+ <release>
9977+ <version>1.1.0</version>
9978+ <date>2004-03-15</date>
9979+ <state>stable</state>
9980+ <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
9981+* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
9982+* Remove &quot;require_once 'PEAR.php'&quot;, include only when needed to raise an error
9983+* Replace echo and error_log() with raiseError() (mroch)
9984+* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
9985+* be tolerant of junk after methodResponse (Luca Mariano, mroch)
9986+* Silent notice even in the error log (pierre)
9987+* fix include of shared xml extension on win32 (pierre)
9988+ </notes>
9989+ </release>
9990+ <release>
9991+ <version>1.0.4</version>
9992+ <date>2002-10-02</date>
9993+ <state>stable</state>
9994+ <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)
9995+ </notes>
9996+ </release>
9997+ <release>
9998+ <version>1.0.3</version>
9999+ <date>2002-05-19</date>
10000+ <state>stable</state>
10001+ <notes>* fix bug when parsing responses with boolean types
10002+ </notes>
10003+ </release>
10004+ <release>
10005+ <version>1.0.2</version>
10006+ <date>2002-04-16</date>
10007+ <state>stable</state>
10008+ <notes>* E_ALL fixes
10009+* fix HTTP response header parsing
10010+ </notes>
10011+ </release>
10012+ <release>
10013+ <version>1.0.1</version>
10014+ <date>2001-09-25</date>
10015+ <state>stable</state>
10016+ <notes>This is a PEAR-ified version of Useful Inc's 1.0.1 release.
10017+Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.
10018+ </notes>
10019+ </release>
10020+ </changelog>
10021+</package>
10022+
10023\ Kein Zeilenumbruch am Dateiende.
10024diff -Naur php-4.3.11/php.ini-dist hardening-patch-4.3.11-0.3.2/php.ini-dist
10025--- php-4.3.11/php.ini-dist 2005-02-14 09:26:10.000000000 +0100
10026+++ hardening-patch-4.3.11-0.3.2/php.ini-dist 2005-07-09 08:53:02.504357944 +0200
10027@@ -1109,6 +1109,177 @@
10028 ;exif.decode_jis_motorola = JIS
10029 ;exif.decode_jis_intel = JIS
10030
10031+[hardening-patch]
10032+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10033+; Hardening-Patch's logging ;
10034+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10035+
10036+;
10037+; hphp.log.syslog - Configures level for alerts reported through syslog
10038+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
10039+; hphp.log.script - Configures level for alerts reported through external script
10040+;
10041+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
10042+; Or each number up to get desired Hardening-Patch's reporting level
10043+;
10044+; S_ALL - All alerts
10045+; S_MEMORY - All canary violations and the safe unlink protection use this class
10046+; S_VARS - All variable filters trigger this class
10047+; S_FILES - All violation of uploaded files filter use this class
10048+; S_INCLUDE - The protection against malicious include filenames use this class
10049+; S_SQL - Failed SQL queries in MySQL are logged with this class
10050+; S_EXECUTOR - The execution depth protection uses this logging class
10051+; S_MISC - All other log messages (f.e. format string protection) use this class
10052+;
10053+; Example:
10054+;
10055+; - Report all alerts (except memory alerts) to the SAPI errorlog,
10056+; memory alerts through syslog and SQL+Include alerts fo the script
10057+;
10058+;hphp.log.syslog = S_MEMORY
10059+;hphp.log.sapi = S_ALL & ~S_MEMORY
10060+;hphp.log.script = S_INCLUDE | S_SQL
10061+;
10062+; Syslog logging:
10063+;
10064+; - Facility configuration: one of the following facilities
10065+;
10066+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
10067+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
10068+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
10069+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
10070+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
10071+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
10072+; LOG_PERROR
10073+;
10074+; - Priority configuration: one of the followinf priorities
10075+;
10076+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
10077+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
10078+;
10079+hphp.log.syslog.priority = LOG_ALERT
10080+hphp.log.syslog.facility = LOG_USER
10081+;
10082+; Script logging:
10083+;
10084+;hphp.log.script.name = /home/hphp/log_script
10085+;
10086+; Alert configuration:
10087+;
10088+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
10089+;
10090+;hphp.log.use-x-forwarded-for = On
10091+;
10092+
10093+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10094+; Hardening-Patch's logging ;
10095+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10096+
10097+; Execution depth limit
10098+;hphp.executor.max_depth = 8000
10099+
10100+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10101+; Hardening-Patch's REQUEST variable filters ;
10102+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10103+
10104+; Limits the number of REQUEST variables
10105+hphp.request.max_vars = 200
10106+
10107+; Limits the length of variable names (without indices)
10108+hphp.request.max_varname_length = 64
10109+
10110+; Limits the length of complete variable names (with indices)
10111+hphp.request.max_totalname_length = 256
10112+
10113+; Limits the length of array indices
10114+hphp.request.max_array_index_length = 64
10115+
10116+; Limits the depth of arrays
10117+hphp.request.max_array_depth = 100
10118+
10119+; Limits the length of variable values
10120+hphp.request.max_value_length = 65000
10121+
10122+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10123+; Hardening-Patch's COOKIE variable filters ;
10124+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10125+
10126+; Limits the number of COOKIE variables
10127+hphp.cookie.max_vars = 100
10128+
10129+; Limits the length of variable names (without indices)
10130+hphp.cookie.max_name_length = 64
10131+
10132+; Limits the length of complete variable names (with indices)
10133+hphp.cookie.max_totalname_length = 256
10134+
10135+; Limits the length of array indices
10136+hphp.cookie.max_array_index_length = 64
10137+
10138+; Limits the depth of arrays
10139+hphp.cookie.max_array_depth = 100
10140+
10141+; Limits the length of variable values
10142+hphp.cookie.max_value_length = 10000
10143+
10144+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10145+; Hardening-Patch's GET variable filters ;
10146+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10147+
10148+; Limits the number of COOKIE variables
10149+hphp.get.max_vars = 100
10150+
10151+; Limits the length of variable names (without indices)
10152+hphp.get.max_name_length = 64
10153+
10154+; Limits the length of complete variable names (with indices)
10155+hphp.get.max_totalname_length = 256
10156+
10157+; Limits the length of array indices
10158+hphp.get.max_array_index_length = 64
10159+
10160+; Limits the depth of arrays
10161+hphp.get.max_array_depth = 50
10162+
10163+; Limits the length of variable values
10164+hphp.get.max_value_length = 512
10165+
10166+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10167+; Hardening-Patch's POST variable filters ;
10168+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10169+
10170+; Limits the number of POST variables
10171+hphp.post.max_vars = 200
10172+
10173+; Limits the length of variable names (without indices)
10174+hphp.post.max_name_length = 64
10175+
10176+; Limits the length of complete variable names (with indices)
10177+hphp.post.max_totalname_length = 256
10178+
10179+; Limits the length of array indices
10180+hphp.post.max_array_index_length = 64
10181+
10182+; Limits the depth of arrays
10183+hphp.post.max_array_depth = 100
10184+
10185+; Limits the length of variable values
10186+hphp.post.max_value_length = 65000
10187+
10188+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10189+; Hardening-Patch's fileupload variable filters ;
10190+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10191+
10192+; Limits the number of uploadable files
10193+hphp.upload.max_uploads = 25
10194+
10195+; Filter out the upload of ELF executables
10196+hphp.upload.disallow_elf_files = On
10197+
10198+; External filterscript for upload verification
10199+;hphp.upload.verification_script = /home/hphp/verify_script
10200+
10201+
10202 ; Local Variables:
10203 ; tab-width: 4
10204 ; End:
10205diff -Naur php-4.3.11/php.ini-recommended hardening-patch-4.3.11-0.3.2/php.ini-recommended
10206--- php-4.3.11/php.ini-recommended 2005-02-14 09:26:10.000000000 +0100
10207+++ hardening-patch-4.3.11-0.3.2/php.ini-recommended 2005-07-09 08:53:02.505357792 +0200
10208@@ -1107,6 +1107,177 @@
10209 ;exif.decode_jis_motorola = JIS
10210 ;exif.decode_jis_intel = JIS
10211
10212+[hardening-patch]
10213+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10214+; Hardening-Patch's logging ;
10215+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10216+
10217+;
10218+; hphp.log.syslog - Configures level for alerts reported through syslog
10219+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
10220+; hphp.log.script - Configures level for alerts reported through external script
10221+;
10222+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
10223+; Or each number up to get desired Hardening-Patch's reporting level
10224+;
10225+; S_ALL - All alerts
10226+; S_MEMORY - All canary violations and the safe unlink protection use this class
10227+; S_VARS - All variable filters trigger this class
10228+; S_FILES - All violation of uploaded files filter use this class
10229+; S_INCLUDE - The protection against malicious include filenames use this class
10230+; S_SQL - Failed SQL queries in MySQL are logged with this class
10231+; S_EXECUTOR - The execution depth protection uses this logging class
10232+; S_MISC - All other log messages (f.e. format string protection) use this class
10233+;
10234+; Example:
10235+;
10236+; - Report all alerts (except memory alerts) to the SAPI errorlog,
10237+; memory alerts through syslog and SQL+Include alerts fo the script
10238+;
10239+;hphp.log.syslog = S_MEMORY
10240+;hphp.log.sapi = S_ALL & ~S_MEMORY
10241+;hphp.log.script = S_INCLUDE | S_SQL
10242+;
10243+; Syslog logging:
10244+;
10245+; - Facility configuration: one of the following facilities
10246+;
10247+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
10248+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
10249+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
10250+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
10251+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
10252+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
10253+; LOG_PERROR
10254+;
10255+; - Priority configuration: one of the followinf priorities
10256+;
10257+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
10258+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
10259+;
10260+hphp.log.syslog.priority = LOG_ALERT
10261+hphp.log.syslog.facility = LOG_USER
10262+;
10263+; Script logging:
10264+;
10265+;hphp.log.script.name = /home/hphp/log_script
10266+;
10267+; Alert configuration:
10268+;
10269+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
10270+;
10271+;hphp.log.use-x-forwarded-for = On
10272+;
10273+
10274+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10275+; Hardening-Patch's logging ;
10276+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10277+
10278+; Execution depth limit
10279+;hphp.executor.max_depth = 8000
10280+
10281+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10282+; Hardening-Patch's REQUEST variable filters ;
10283+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10284+
10285+; Limits the number of REQUEST variables
10286+hphp.request.max_vars = 200
10287+
10288+; Limits the length of variable names (without indices)
10289+hphp.request.max_varname_length = 64
10290+
10291+; Limits the length of complete variable names (with indices)
10292+hphp.request.max_totalname_length = 256
10293+
10294+; Limits the length of array indices
10295+hphp.request.max_array_index_length = 64
10296+
10297+; Limits the depth of arrays
10298+hphp.request.max_array_depth = 100
10299+
10300+; Limits the length of variable values
10301+hphp.request.max_value_length = 65000
10302+
10303+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10304+; Hardening-Patch's COOKIE variable filters ;
10305+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10306+
10307+; Limits the number of COOKIE variables
10308+hphp.cookie.max_vars = 100
10309+
10310+; Limits the length of variable names (without indices)
10311+hphp.cookie.max_name_length = 64
10312+
10313+; Limits the length of complete variable names (with indices)
10314+hphp.cookie.max_totalname_length = 256
10315+
10316+; Limits the length of array indices
10317+hphp.cookie.max_array_index_length = 64
10318+
10319+; Limits the depth of arrays
10320+hphp.cookie.max_array_depth = 100
10321+
10322+; Limits the length of variable values
10323+hphp.cookie.max_value_length = 10000
10324+
10325+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10326+; Hardening-Patch's GET variable filters ;
10327+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10328+
10329+; Limits the number of COOKIE variables
10330+hphp.get.max_vars = 100
10331+
10332+; Limits the length of variable names (without indices)
10333+hphp.get.max_name_length = 64
10334+
10335+; Limits the length of complete variable names (with indices)
10336+hphp.get.max_totalname_length = 256
10337+
10338+; Limits the length of array indices
10339+hphp.get.max_array_index_length = 64
10340+
10341+; Limits the depth of arrays
10342+hphp.get.max_array_depth = 50
10343+
10344+; Limits the length of variable values
10345+hphp.get.max_value_length = 512
10346+
10347+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10348+; Hardening-Patch's POST variable filters ;
10349+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10350+
10351+; Limits the number of POST variables
10352+hphp.post.max_vars = 200
10353+
10354+; Limits the length of variable names (without indices)
10355+hphp.post.max_name_length = 64
10356+
10357+; Limits the length of complete variable names (with indices)
10358+hphp.post.max_totalname_length = 256
10359+
10360+; Limits the length of array indices
10361+hphp.post.max_array_index_length = 64
10362+
10363+; Limits the depth of arrays
10364+hphp.post.max_array_depth = 100
10365+
10366+; Limits the length of variable values
10367+hphp.post.max_value_length = 65000
10368+
10369+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10370+; Hardening-Patch's fileupload variable filters ;
10371+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10372+
10373+; Limits the number of uploadable files
10374+hphp.upload.max_uploads = 25
10375+
10376+; Filter out the upload of ELF executables
10377+hphp.upload.disallow_elf_files = On
10378+
10379+; External filterscript for upload verification
10380+;hphp.upload.verification_script = /home/hphp/verify_script
10381+
10382+
10383 ; Local Variables:
10384 ; tab-width: 4
10385 ; End:
10386diff -Naur php-4.3.11/README.input_filter hardening-patch-4.3.11-0.3.2/README.input_filter
10387--- php-4.3.11/README.input_filter 1970-01-01 01:00:00.000000000 +0100
10388+++ hardening-patch-4.3.11-0.3.2/README.input_filter 2005-07-09 08:53:02.506357640 +0200
10389@@ -0,0 +1,193 @@
10390+Input Filter Support ported from PHP 5
10391+--------------------------------------
10392+
10393+XSS (Cross Site Scripting) hacks are becoming more and more prevalent,
10394+and can be quite difficult to prevent. Whenever you accept user data
10395+and somehow display this data back to users, you are likely vulnerable
10396+to XSS hacks.
10397+
10398+The Input Filter support in PHP 5 is aimed at providing the framework
10399+through which a company-wide or site-wide security policy can be
10400+enforced. It is implemented as a SAPI hook and is called from the
10401+treat_data and post handler functions. To implement your own security
10402+policy you will need to write a standard PHP extension.
10403+
10404+A simple implementation might look like the following. This stores the
10405+original raw user data and adds a my_get_raw() function while the normal
10406+$_POST, $_GET and $_COOKIE arrays are only populated with stripped
10407+data. In this simple example all I am doing is calling strip_tags() on
10408+the data. If register_globals is turned on, the default globals that
10409+are created will be stripped ($foo) while a $RAW_foo is created with the
10410+original user input.
10411+
10412+ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
10413+ zval *post_array;
10414+ zval *get_array;
10415+ zval *cookie_array;
10416+ZEND_END_MODULE_GLOBALS(my_input_filter)
10417+
10418+#ifdef ZTS
10419+#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
10420+#else
10421+#define IF_G(v) (my_input_filter_globals.v)
10422+#endif
10423+
10424+ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)
10425+
10426+function_entry my_input_filter_functions[] = {
10427+ PHP_FE(my_get_raw, NULL)
10428+ {NULL, NULL, NULL}
10429+};
10430+
10431+zend_module_entry my_input_filter_module_entry = {
10432+ STANDARD_MODULE_HEADER,
10433+ "my_input_filter",
10434+ my_input_filter_functions,
10435+ PHP_MINIT(my_input_filter),
10436+ PHP_MSHUTDOWN(my_input_filter),
10437+ NULL,
10438+ PHP_RSHUTDOWN(my_input_filter),
10439+ PHP_MINFO(my_input_filter),
10440+ "0.1",
10441+ STANDARD_MODULE_PROPERTIES
10442+};
10443+
10444+PHP_MINIT_FUNCTION(my_input_filter)
10445+{
10446+ ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);
10447+
10448+ REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
10449+ REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
10450+ REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
10451+
10452+ sapi_register_input_filter(my_sapi_input_filter);
10453+ return SUCCESS;
10454+}
10455+
10456+PHP_RSHUTDOWN_FUNCTION(my_input_filter)
10457+{
10458+ if(IF_G(get_array)) {
10459+ zval_ptr_dtor(&IF_G(get_array));
10460+ IF_G(get_array) = NULL;
10461+ }
10462+ if(IF_G(post_array)) {
10463+ zval_ptr_dtor(&IF_G(post_array));
10464+ IF_G(post_array) = NULL;
10465+ }
10466+ if(IF_G(cookie_array)) {
10467+ zval_ptr_dtor(&IF_G(cookie_array));
10468+ IF_G(cookie_array) = NULL;
10469+ }
10470+ return SUCCESS;
10471+}
10472+
10473+PHP_MINFO_FUNCTION(my_input_filter)
10474+{
10475+ php_info_print_table_start();
10476+ php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
10477+ php_info_print_table_row( 2, "Revision", "$Revision: 1.1 $");
10478+ php_info_print_table_end();
10479+}
10480+
10481+/* The filter handler. If you return 1 from it, then PHP also registers the
10482+ * (modified) variable. Returning 0 prevents PHP from registering the variable;
10483+ * you can use this if your filter already registers the variable under a
10484+ * different name, or if you just don't want the variable registered at all. */
10485+SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter)
10486+{
10487+ zval new_var;
10488+ zval *array_ptr = NULL;
10489+ char *raw_var;
10490+ int var_len;
10491+
10492+ assert(*val != NULL);
10493+
10494+ switch(arg) {
10495+ case PARSE_GET:
10496+ if(!IF_G(get_array)) {
10497+ ALLOC_ZVAL(array_ptr);
10498+ array_init(array_ptr);
10499+ INIT_PZVAL(array_ptr);
10500+ }
10501+ IF_G(get_array) = array_ptr;
10502+ break;
10503+ case PARSE_POST:
10504+ if(!IF_G(post_array)) {
10505+ ALLOC_ZVAL(array_ptr);
10506+ array_init(array_ptr);
10507+ INIT_PZVAL(array_ptr);
10508+ }
10509+ IF_G(post_array) = array_ptr;
10510+ break;
10511+ case PARSE_COOKIE:
10512+ if(!IF_G(cookie_array)) {
10513+ ALLOC_ZVAL(array_ptr);
10514+ array_init(array_ptr);
10515+ INIT_PZVAL(array_ptr);
10516+ }
10517+ IF_G(cookie_array) = array_ptr;
10518+ break;
10519+ }
10520+ Z_STRLEN(new_var) = val_len;
10521+ Z_STRVAL(new_var) = estrndup(*val, val_len);
10522+ Z_TYPE(new_var) = IS_STRING;
10523+
10524+ var_len = strlen(var);
10525+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
10526+ strcpy(raw_var, "RAW_");
10527+ strlcat(raw_var,var,var_len+5);
10528+
10529+ php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);
10530+
10531+ php_strip_tags(*val, val_len, NULL, NULL, 0);
10532+
10533+ *new_val_len = strlen(*val);
10534+ return 1;
10535+}
10536+
10537+PHP_FUNCTION(my_get_raw)
10538+{
10539+ long arg;
10540+ char *var;
10541+ int var_len;
10542+ zval **tmp;
10543+ zval *array_ptr = NULL;
10544+ HashTable *hash_ptr;
10545+ char *raw_var;
10546+
10547+ if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
10548+ return;
10549+ }
10550+
10551+ switch(arg) {
10552+ case PARSE_GET:
10553+ array_ptr = IF_G(get_array);
10554+ break;
10555+ case PARSE_POST:
10556+ array_ptr = IF_G(post_array);
10557+ break;
10558+ case PARSE_COOKIE:
10559+ array_ptr = IF_G(post_array);
10560+ break;
10561+ }
10562+
10563+ if(!array_ptr) RETURN_FALSE;
10564+
10565+ /*
10566+ * I'm changing the variable name here because when running with register_globals on,
10567+ * the variable will end up in the global symbol table
10568+ */
10569+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
10570+ strcpy(raw_var, "RAW_");
10571+ strlcat(raw_var,var,var_len+5);
10572+ hash_ptr = HASH_OF(array_ptr);
10573+
10574+ if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
10575+ *return_value = **tmp;
10576+ zval_copy_ctor(return_value);
10577+ } else {
10578+ RETVAL_FALSE;
10579+ }
10580+ efree(raw_var);
10581+}
10582+
10583diff -Naur php-4.3.11/sapi/apache/mod_php4.c hardening-patch-4.3.11-0.3.2/sapi/apache/mod_php4.c
10584--- php-4.3.11/sapi/apache/mod_php4.c 2004-07-21 18:25:28.000000000 +0200
10585+++ hardening-patch-4.3.11-0.3.2/sapi/apache/mod_php4.c 2005-07-09 08:53:02.507357488 +0200
10586@@ -446,7 +446,7 @@
10587 sapi_apache_get_fd,
10588 sapi_apache_force_http_10,
10589 sapi_apache_get_target_uid,
10590- sapi_apache_get_target_gid
10591+ sapi_apache_get_target_gid,
10592 };
10593 /* }}} */
10594
10595@@ -892,7 +892,11 @@
10596 {
10597 TSRMLS_FETCH();
10598 if (PG(expose_php)) {
10599+#if HARDENING_PATCH
10600+ ap_add_version_component("PHP/" PHP_VERSION " with Hardening-Patch");
10601+#else
10602 ap_add_version_component("PHP/" PHP_VERSION);
10603+#endif
10604 }
10605 }
10606 #endif
10607diff -Naur php-4.3.11/sapi/apache2filter/sapi_apache2.c hardening-patch-4.3.11-0.3.2/sapi/apache2filter/sapi_apache2.c
10608--- php-4.3.11/sapi/apache2filter/sapi_apache2.c 2005-01-07 07:28:36.000000000 +0100
10609+++ hardening-patch-4.3.11-0.3.2/sapi/apache2filter/sapi_apache2.c 2005-07-09 08:53:02.507357488 +0200
10610@@ -563,7 +563,11 @@
10611 {
10612 TSRMLS_FETCH();
10613 if (PG(expose_php)) {
10614+#if HARDENING_PATCH
10615+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
10616+#else
10617 ap_add_version_component(p, "PHP/" PHP_VERSION);
10618+#endif
10619 }
10620 }
10621
10622diff -Naur php-4.3.11/sapi/apache2handler/sapi_apache2.c hardening-patch-4.3.11-0.3.2/sapi/apache2handler/sapi_apache2.c
10623--- php-4.3.11/sapi/apache2handler/sapi_apache2.c 2005-03-10 12:39:04.000000000 +0100
10624+++ hardening-patch-4.3.11-0.3.2/sapi/apache2handler/sapi_apache2.c 2005-07-09 08:53:02.508357336 +0200
10625@@ -345,7 +345,11 @@
10626 {
10627 TSRMLS_FETCH();
10628 if (PG(expose_php)) {
10629+#if HARDENING_PATCH
10630+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
10631+#else
10632 ap_add_version_component(p, "PHP/" PHP_VERSION);
10633+#endif
10634 }
10635 }
10636
10637diff -Naur php-4.3.11/sapi/cgi/cgi_main.c hardening-patch-4.3.11-0.3.2/sapi/cgi/cgi_main.c
10638--- php-4.3.11/sapi/cgi/cgi_main.c 2005-02-11 03:12:30.000000000 +0100
10639+++ hardening-patch-4.3.11-0.3.2/sapi/cgi/cgi_main.c 2005-07-09 08:53:02.509357184 +0200
10640@@ -1435,11 +1435,19 @@
10641 SG(headers_sent) = 1;
10642 SG(request_info).no_headers = 1;
10643 }
10644+#if HARDENING_PATCH
10645+#if ZEND_DEBUG
10646+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10647+#else
10648+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10649+#endif
10650+#else
10651 #if ZEND_DEBUG
10652 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10653 #else
10654 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10655 #endif
10656+#endif
10657 php_end_ob_buffers(1 TSRMLS_CC);
10658 exit(1);
10659 break;
10660diff -Naur php-4.3.11/sapi/cli/php_cli.c hardening-patch-4.3.11-0.3.2/sapi/cli/php_cli.c
10661--- php-4.3.11/sapi/cli/php_cli.c 2005-03-22 16:09:36.000000000 +0100
10662+++ hardening-patch-4.3.11-0.3.2/sapi/cli/php_cli.c 2005-07-09 08:53:02.510357032 +0200
10663@@ -652,11 +652,19 @@
10664 if (php_request_startup(TSRMLS_C)==FAILURE) {
10665 goto err;
10666 }
10667+#if HARDENING_PATCH
10668+#if ZEND_DEBUG
10669+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10670+#else
10671+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10672+#endif
10673+#else
10674 #if ZEND_DEBUG
10675 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10676 #else
10677 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
10678 #endif
10679+#endif
10680 php_end_ob_buffers(1 TSRMLS_CC);
10681 exit_status=1;
10682 goto out;
10683diff -Naur php-4.3.11/TSRM/TSRM.h hardening-patch-4.3.11-0.3.2/TSRM/TSRM.h
10684--- php-4.3.11/TSRM/TSRM.h 2005-02-11 04:34:04.000000000 +0100
10685+++ hardening-patch-4.3.11-0.3.2/TSRM/TSRM.h 2005-07-09 08:53:02.510357032 +0200
10686@@ -33,6 +33,13 @@
10687 # define TSRM_API
10688 #endif
10689
10690+#if HARDENING_PATCH
10691+# if HAVE_REALPATH
10692+# undef realpath
10693+# define realpath php_realpath
10694+# endif
10695+#endif
10696+
10697 /* Only compile multi-threading functions if we're in ZTS mode */
10698 #ifdef ZTS
10699
10700@@ -90,6 +97,7 @@
10701
10702 #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
10703
10704+
10705 #ifdef __cplusplus
10706 extern "C" {
10707 #endif
10708diff -Naur php-4.3.11/TSRM/tsrm_virtual_cwd.c hardening-patch-4.3.11-0.3.2/TSRM/tsrm_virtual_cwd.c
10709--- php-4.3.11/TSRM/tsrm_virtual_cwd.c 2005-02-11 04:34:04.000000000 +0100
10710+++ hardening-patch-4.3.11-0.3.2/TSRM/tsrm_virtual_cwd.c 2005-07-09 08:53:02.511356880 +0200
10711@@ -192,6 +192,165 @@
10712 return p;
10713 }
10714
10715+#if HARDENING_PATCH
10716+CWD_API char *php_realpath(const char *path, char *resolved)
10717+{
10718+ struct stat sb;
10719+ char *p, *q, *s;
10720+ size_t left_len, resolved_len;
10721+ unsigned symlinks;
10722+ int serrno, slen;
10723+ int is_dir = 1;
10724+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
10725+
10726+ serrno = errno;
10727+ symlinks = 0;
10728+ if (path[0] == '/') {
10729+ resolved[0] = '/';
10730+ resolved[1] = '\0';
10731+ if (path[1] == '\0')
10732+ return (resolved);
10733+ resolved_len = 1;
10734+ left_len = strlcpy(left, path + 1, sizeof(left));
10735+ } else {
10736+ if (getcwd(resolved, PATH_MAX) == NULL) {
10737+ strlcpy(resolved, ".", PATH_MAX);
10738+ return (NULL);
10739+ }
10740+ resolved_len = strlen(resolved);
10741+ left_len = strlcpy(left, path, sizeof(left));
10742+ }
10743+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
10744+ errno = ENAMETOOLONG;
10745+ return (NULL);
10746+ }
10747+
10748+ /*
10749+ * Iterate over path components in `left'.
10750+ */
10751+ while (left_len != 0) {
10752+ /*
10753+ * Extract the next path component and adjust `left'
10754+ * and its length.
10755+ */
10756+ p = strchr(left, '/');
10757+ s = p ? p : left + left_len;
10758+ if (s - left >= sizeof(next_token)) {
10759+ errno = ENAMETOOLONG;
10760+ return (NULL);
10761+ }
10762+ memcpy(next_token, left, s - left);
10763+ next_token[s - left] = '\0';
10764+ left_len -= s - left;
10765+ if (p != NULL)
10766+ memmove(left, s + 1, left_len + 1);
10767+ if (resolved[resolved_len - 1] != '/') {
10768+ if (resolved_len + 1 >= PATH_MAX) {
10769+ errno = ENAMETOOLONG;
10770+ return (NULL);
10771+ }
10772+ resolved[resolved_len++] = '/';
10773+ resolved[resolved_len] = '\0';
10774+ }
10775+ if (next_token[0] == '\0')
10776+ continue;
10777+ else if (strcmp(next_token, ".") == 0)
10778+ continue;
10779+ else if (strcmp(next_token, "..") == 0) {
10780+ /*
10781+ * Strip the last path component except when we have
10782+ * single "/"
10783+ */
10784+ if (!is_dir) {
10785+ errno = ENOENT;
10786+ return (NULL);
10787+ }
10788+ if (resolved_len > 1) {
10789+ resolved[resolved_len - 1] = '\0';
10790+ q = strrchr(resolved, '/');
10791+ *q = '\0';
10792+ resolved_len = q - resolved;
10793+ }
10794+ continue;
10795+ }
10796+
10797+ /*
10798+ * Append the next path component and lstat() it. If
10799+ * lstat() fails we still can return successfully if
10800+ * there are no more path components left.
10801+ */
10802+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
10803+ if (resolved_len >= PATH_MAX) {
10804+ errno = ENAMETOOLONG;
10805+ return (NULL);
10806+ }
10807+ if (lstat(resolved, &sb) != 0) {
10808+ if (errno == ENOENT && p == NULL) {
10809+ errno = serrno;
10810+ return (resolved);
10811+ }
10812+ return (NULL);
10813+ }
10814+ if (S_ISLNK(sb.st_mode)) {
10815+ if (symlinks++ > MAXSYMLINKS) {
10816+ errno = ELOOP;
10817+ return (NULL);
10818+ }
10819+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
10820+ if (slen < 0)
10821+ return (NULL);
10822+ symlink[slen] = '\0';
10823+ if (symlink[0] == '/') {
10824+ resolved[1] = 0;
10825+ resolved_len = 1;
10826+ } else if (resolved_len > 1) {
10827+ /* Strip the last path component. */
10828+ resolved[resolved_len - 1] = '\0';
10829+ q = strrchr(resolved, '/');
10830+ *q = '\0';
10831+ resolved_len = q - resolved;
10832+ }
10833+
10834+ /*
10835+ * If there are any path components left, then
10836+ * append them to symlink. The result is placed
10837+ * in `left'.
10838+ */
10839+ if (p != NULL) {
10840+ if (symlink[slen - 1] != '/') {
10841+ if (slen + 1 >= sizeof(symlink)) {
10842+ errno = ENAMETOOLONG;
10843+ return (NULL);
10844+ }
10845+ symlink[slen] = '/';
10846+ symlink[slen + 1] = 0;
10847+ }
10848+ left_len = strlcat(symlink, left, sizeof(left));
10849+ if (left_len >= sizeof(left)) {
10850+ errno = ENAMETOOLONG;
10851+ return (NULL);
10852+ }
10853+ }
10854+ left_len = strlcpy(left, symlink, sizeof(left));
10855+ } else {
10856+ if (S_ISDIR(sb.st_mode)) {
10857+ is_dir = 1;
10858+ } else {
10859+ is_dir = 0;
10860+ }
10861+ }
10862+ }
10863+
10864+ /*
10865+ * Remove trailing slash except when the resolved pathname
10866+ * is a single "/".
10867+ */
10868+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
10869+ resolved[resolved_len - 1] = '\0';
10870+ return (resolved);
10871+}
10872+#endif
10873+
10874 CWD_API void virtual_cwd_startup(void)
10875 {
10876 char cwd[MAXPATHLEN];
10877@@ -314,8 +473,7 @@
10878 path = resolved_path;
10879 path_length = strlen(path);
10880 } else {
10881- /* disable for now
10882- return 1; */
10883+ return 1;
10884 }
10885 }
10886 } else { /* Concat current directory with relative path and then run realpath() on it */
10887@@ -341,9 +499,8 @@
10888 path = resolved_path;
10889 path_length = strlen(path);
10890 } else {
10891- /* disable for now
10892 free(tmp);
10893- return 1; */
10894+ return 1;
10895 }
10896 }
10897 free(tmp);
10898diff -Naur php-4.3.11/TSRM/tsrm_virtual_cwd.h hardening-patch-4.3.11-0.3.2/TSRM/tsrm_virtual_cwd.h
10899--- php-4.3.11/TSRM/tsrm_virtual_cwd.h 2005-02-11 04:34:04.000000000 +0100
10900+++ hardening-patch-4.3.11-0.3.2/TSRM/tsrm_virtual_cwd.h 2005-07-09 08:53:02.511356880 +0200
10901@@ -128,6 +128,22 @@
10902
10903 typedef int (*verify_path_func)(const cwd_state *);
10904
10905+#ifndef HAVE_STRLCPY
10906+CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz);
10907+#undef strlcpy
10908+#define strlcpy php_strlcpy
10909+#endif
10910+
10911+#ifndef HAVE_STRLCAT
10912+CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz);
10913+#undef strlcat
10914+#define strlcat php_strlcat
10915+#endif
10916+
10917+
10918+#if HARDENING_PATCH
10919+CWD_API char *php_realpath(const char *path, char *resolved);
10920+#endif
10921 CWD_API void virtual_cwd_startup(void);
10922 CWD_API void virtual_cwd_shutdown(void);
10923 CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC);
10924diff -Naur php-4.3.11/Zend/zend_alloc.c hardening-patch-4.3.11-0.3.2/Zend/zend_alloc.c
10925--- php-4.3.11/Zend/zend_alloc.c 2004-08-27 18:51:25.000000000 +0200
10926+++ hardening-patch-4.3.11-0.3.2/Zend/zend_alloc.c 2005-07-09 08:53:02.512356728 +0200
10927@@ -56,6 +56,11 @@
10928 # define END_MAGIC_SIZE 0
10929 #endif
10930
10931+#if HARDENING_PATCH_MM_PROTECT
10932+# define CANARY_SIZE sizeof(unsigned int)
10933+#else
10934+# define CANARY_SIZE 0
10935+#endif
10936
10937 # if MEMORY_LIMIT
10938 # if ZEND_DEBUG
10939@@ -95,9 +100,17 @@
10940 if (p==AG(head)) { \
10941 AG(head) = p->pNext; \
10942 } else { \
10943+ if (p != p->pLast->pNext) { \
10944+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
10945+ exit(1); \
10946+ } \
10947 p->pLast->pNext = p->pNext; \
10948 } \
10949 if (p->pNext) { \
10950+ if (p != p->pNext->pLast) { \
10951+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
10952+ exit(1); \
10953+ } \
10954 p->pNext->pLast = p->pLast; \
10955 }
10956
10957@@ -129,6 +142,12 @@
10958 DECLARE_CACHE_VARS();
10959 TSRMLS_FETCH();
10960
10961+#if HARDENING_PATCH_MM_PROTECT
10962+ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) {
10963+ zend_security_log(S_MEMORY, "emalloc() - requested size would result in integer overflow");
10964+ exit(1);
10965+ }
10966+#endif
10967 CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);
10968
10969 if (!ZEND_DISABLE_MEMORY_CACHE && (CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] > 0)) {
10970@@ -146,6 +165,10 @@
10971 AG(cache_stats)[CACHE_INDEX][1]++;
10972 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
10973 #endif
10974+#if HARDENING_PATCH_MM_PROTECT
10975+ p->canary = HG(canary_1);
10976+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
10977+#endif
10978 p->cached = 0;
10979 p->size = size;
10980 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
10981@@ -161,7 +184,7 @@
10982 AG(allocated_memory_peak) = AG(allocated_memory);
10983 }
10984 #endif
10985- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE);
10986+ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE);
10987 }
10988
10989 HANDLE_BLOCK_INTERRUPTIONS();
10990@@ -191,7 +214,10 @@
10991 # endif
10992 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
10993 #endif
10994-
10995+#if HARDENING_PATCH_MM_PROTECT
10996+ p->canary = HG(canary_1);
10997+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
10998+#endif
10999 HANDLE_UNBLOCK_INTERRUPTIONS();
11000 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
11001 }
11002@@ -218,17 +244,33 @@
11003 return emalloc_rel(lval + offset);
11004 }
11005 }
11006-
11007+
11008+#if HARDENING_PATCH
11009+ zend_security_log(S_MEMORY, "Possible integer overflow catched by safe_emalloc()");
11010+#endif
11011 zend_error(E_ERROR, "Possible integer overflow in memory allocation (%ld * %ld + %ld)", nmemb, size, offset);
11012 return 0;
11013 }
11014
11015 ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
11016 {
11017+#if HARDENING_PATCH_MM_PROTECT
11018+ unsigned int *canary_2;
11019+#endif
11020 zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING);
11021 DECLARE_CACHE_VARS();
11022 TSRMLS_FETCH();
11023
11024+#if HARDENING_PATCH_MM_PROTECT
11025+ canary_2 = (unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
11026+ if (p->canary != HG(canary_1) || *canary_2 != HG(canary_2)) {
11027+ zend_security_log(S_MEMORY, "canary mismatch on efree() - heap overflow or double efree detected");
11028+ exit(1);
11029+ }
11030+ /* to catch double efree()s */
11031+ *canary_2 = p->canary = 0;
11032+#endif
11033+
11034 #if defined(ZTS) && TSRM_DEBUG
11035 if (p->thread_id != tsrm_thread_id()) {
11036 tsrm_error(TSRM_ERROR_LEVEL_ERROR, "Memory block allocated at %s:(%d) on thread %x freed at %s:(%d) on thread %x, ignoring",
11037@@ -273,6 +315,9 @@
11038 size_t _size = nmemb * size;
11039
11040 if (nmemb && (_size/nmemb!=size)) {
11041+#if HARDENING_PATCH
11042+ zend_security_log(S_MEMORY, "Possible integer overflow catched by ecalloc()");
11043+#endif
11044 fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size);
11045 #if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID
11046 kill(getpid(), SIGSEGV);
11047@@ -292,6 +337,9 @@
11048
11049 ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
11050 {
11051+#if HARDENING_PATCH_MM_PROTECT
11052+ unsigned int canary_2;
11053+#endif
11054 zend_mem_header *p;
11055 zend_mem_header *orig;
11056 DECLARE_CACHE_VARS();
11057@@ -303,6 +351,14 @@
11058
11059 p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING);
11060
11061+#if HARDENING_PATCH_MM_PROTECT
11062+ canary_2 = *(unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
11063+ if (p->canary != HG(canary_1) || canary_2 != HG(canary_2)) {
11064+ zend_security_log(S_MEMORY, "canary mismatch on erealloc() - heap overflow detected");
11065+ exit(1);
11066+ }
11067+#endif
11068+
11069 #if defined(ZTS) && TSRM_DEBUG
11070 if (p->thread_id != tsrm_thread_id()) {
11071 void *new_p;
11072@@ -326,7 +382,7 @@
11073 }
11074 #endif
11075 REMOVE_POINTER_FROM_LIST(p);
11076- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE);
11077+ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE);
11078 if (!p) {
11079 if (!allow_failure) {
11080 fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size);
11081@@ -348,6 +404,9 @@
11082 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
11083 #endif
11084
11085+#if HARDENING_PATCH_MM_PROTECT
11086+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
11087+#endif
11088 p->size = size;
11089
11090 HANDLE_UNBLOCK_INTERRUPTIONS();
11091@@ -423,6 +482,10 @@
11092 {
11093 AG(head) = NULL;
11094
11095+#if HARDENING_PATCH_MM_PROTECT
11096+ HG(canary_1) = zend_canary();
11097+ HG(canary_2) = zend_canary();
11098+#endif
11099 #if MEMORY_LIMIT
11100 AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */
11101 AG(allocated_memory) = 0;
11102diff -Naur php-4.3.11/Zend/zend_alloc.h hardening-patch-4.3.11-0.3.2/Zend/zend_alloc.h
11103--- php-4.3.11/Zend/zend_alloc.h 2004-08-11 08:10:46.000000000 +0200
11104+++ hardening-patch-4.3.11-0.3.2/Zend/zend_alloc.h 2005-07-09 08:53:02.513356576 +0200
11105@@ -32,6 +32,9 @@
11106 #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL
11107
11108 typedef struct _zend_mem_header {
11109+#if HARDENING_PATCH_MM_PROTECT
11110+ unsigned int canary;
11111+#endif
11112 #if ZEND_DEBUG
11113 long magic;
11114 char *filename;
11115diff -Naur php-4.3.11/Zend/zend_builtin_functions.c hardening-patch-4.3.11-0.3.2/Zend/zend_builtin_functions.c
11116--- php-4.3.11/Zend/zend_builtin_functions.c 2004-12-27 20:28:35.000000000 +0100
11117+++ hardening-patch-4.3.11-0.3.2/Zend/zend_builtin_functions.c 2005-07-09 08:53:02.514356424 +0200
11118@@ -49,6 +49,9 @@
11119 static ZEND_FUNCTION(crash);
11120 #endif
11121 #endif
11122+#if HARDENING_PATCH_MM_PROTECT_DEBUG
11123+static ZEND_FUNCTION(heap_overflow);
11124+#endif
11125 static ZEND_FUNCTION(get_included_files);
11126 static ZEND_FUNCTION(is_subclass_of);
11127 static ZEND_FUNCTION(is_a);
11128@@ -101,6 +104,9 @@
11129 ZEND_FE(crash, NULL)
11130 #endif
11131 #endif
11132+#if HARDENING_PATCH_MM_PROTECT_DEBUG
11133+ ZEND_FE(heap_overflow, NULL)
11134+#endif
11135 ZEND_FE(get_included_files, NULL)
11136 ZEND_FALIAS(get_required_files, get_included_files, NULL)
11137 ZEND_FE(is_subclass_of, NULL)
11138@@ -805,6 +811,19 @@
11139
11140 #endif /* ZEND_DEBUG */
11141
11142+
11143+#if HARDENING_PATCH_MM_PROTECT_DEBUG
11144+ZEND_FUNCTION(heap_overflow)
11145+{
11146+ char *nowhere = emalloc(10);
11147+
11148+ memcpy(nowhere, "something1234567890", sizeof("something1234567890"));
11149+
11150+ efree(nowhere);
11151+}
11152+#endif
11153+
11154+
11155 /* {{{ proto array get_included_files(void)
11156 Returns an array with the file names that were include_once()'d */
11157 ZEND_FUNCTION(get_included_files)
11158diff -Naur php-4.3.11/Zend/zend.c hardening-patch-4.3.11-0.3.2/Zend/zend.c
11159--- php-4.3.11/Zend/zend.c 2005-01-22 21:36:34.000000000 +0100
11160+++ hardening-patch-4.3.11-0.3.2/Zend/zend.c 2005-07-09 08:53:02.514356424 +0200
11161@@ -53,6 +53,12 @@
11162 ZEND_API void (*zend_unblock_interruptions)(void);
11163 ZEND_API void (*zend_ticks_function)(int ticks);
11164 ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
11165+#if HARDENING_PATCH
11166+ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
11167+#endif
11168+#if HARDENING_PATCH_INC_PROTECT
11169+ZEND_API int (*zend_is_valid_include)(zval *z);
11170+#endif
11171
11172 void (*zend_on_timeout)(int seconds TSRMLS_DC);
11173
11174@@ -70,9 +76,80 @@
11175 return SUCCESS;
11176 }
11177
11178+#if HARDENING_PATCH
11179+static ZEND_INI_MH(OnUpdateHPHP_log_syslog)
11180+{
11181+ if (!new_value) {
11182+ EG(hphp_log_syslog) = S_ALL & ~S_SQL | S_MEMORY;
11183+ } else {
11184+ EG(hphp_log_syslog) = atoi(new_value) | S_MEMORY;
11185+ }
11186+ return SUCCESS;
11187+}
11188+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_facility)
11189+{
11190+ if (!new_value) {
11191+ EG(hphp_log_syslog_facility) = LOG_USER;
11192+ } else {
11193+ EG(hphp_log_syslog_facility) = atoi(new_value);
11194+ }
11195+ return SUCCESS;
11196+}
11197+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_priority)
11198+{
11199+ if (!new_value) {
11200+ EG(hphp_log_syslog_priority) = LOG_ALERT;
11201+ } else {
11202+ EG(hphp_log_syslog_priority) = atoi(new_value);
11203+ }
11204+ return SUCCESS;
11205+}
11206+static ZEND_INI_MH(OnUpdateHPHP_log_sapi)
11207+{
11208+ if (!new_value) {
11209+ EG(hphp_log_sapi) = S_ALL & ~S_SQL;
11210+ } else {
11211+ EG(hphp_log_sapi) = atoi(new_value);
11212+ }
11213+ return SUCCESS;
11214+}
11215+static ZEND_INI_MH(OnUpdateHPHP_log_script)
11216+{
11217+ if (!new_value) {
11218+ EG(hphp_log_script) = S_ALL & ~S_MEMORY;
11219+ } else {
11220+ EG(hphp_log_script) = atoi(new_value) & ~S_MEMORY;
11221+ }
11222+ return SUCCESS;
11223+}
11224+static ZEND_INI_MH(OnUpdateHPHP_log_scriptname)
11225+{
11226+ if (!new_value) {
11227+ EG(hphp_log_scriptname) = NULL;
11228+ } else {
11229+ if (EG(hphp_log_scriptname)) {
11230+ pefree(EG(hphp_log_scriptname),1);
11231+ }
11232+ EG(hphp_log_scriptname) = pestrdup(new_value,1);
11233+ }
11234+ return SUCCESS;
11235+}
11236+#endif
11237
11238 ZEND_INI_BEGIN()
11239 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
11240+#if HARDENING_PATCH
11241+ ZEND_INI_ENTRY("hphp.log.syslog", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog)
11242+ ZEND_INI_ENTRY("hphp.log.syslog.facility", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_facility)
11243+ ZEND_INI_ENTRY("hphp.log.syslog.priority", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_priority)
11244+ ZEND_INI_ENTRY("hphp.log.sapi", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_sapi)
11245+ ZEND_INI_ENTRY("hphp.log.script", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_script)
11246+ ZEND_INI_ENTRY("hphp.log.script.name", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_scriptname)
11247+ STD_ZEND_INI_BOOLEAN("hphp.log.use-x-forwarded-for", "0", ZEND_INI_SYSTEM, OnUpdateBool, hphp_log_use_x_forwarded_for, zend_executor_globals, executor_globals)
11248+ STD_ZEND_INI_ENTRY("hphp.executor.max_depth", "0", ZEND_INI_PERDIR, OnUpdateLong, hphp_executor_max_depth, zend_executor_globals, executor_globals)
11249+ STD_ZEND_INI_BOOLEAN("hphp.sql.bailout_on_error", "0", ZEND_INI_PERDIR, OnUpdateBool, hphp_sql_bailout_on_error, hardened_globals_struct, hardened_globals)
11250+ STD_ZEND_INI_BOOLEAN("hphp.multiheader", "0", ZEND_INI_PERDIR, OnUpdateBool, hphp_multiheader, hardened_globals_struct, hardened_globals)
11251+#endif
11252 ZEND_INI_END()
11253
11254
11255@@ -354,6 +431,7 @@
11256 zend_init_rsrc_plist(TSRMLS_C);
11257 EG(lambda_count)=0;
11258 EG(user_error_handler) = NULL;
11259+ EG(in_code_type) = 0;
11260 EG(in_execution) = 0;
11261 EG(current_execute_data) = NULL;
11262 }
11263@@ -420,6 +498,14 @@
11264 extern zend_scanner_globals language_scanner_globals;
11265 #endif
11266
11267+ /* Set up Hardening-Patch utility functions first */
11268+#if HARDENING_PATCH
11269+ zend_security_log = utility_functions->security_log_function;
11270+#endif
11271+#if HARDENING_PATCH_INC_PROTECT
11272+ zend_is_valid_include = utility_functions->is_valid_include;
11273+#endif
11274+
11275 #ifdef ZTS
11276 ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
11277 #else
11278@@ -623,6 +709,7 @@
11279 }
11280 CG(unclean_shutdown) = 1;
11281 CG(in_compilation) = EG(in_execution) = 0;
11282+ EG(in_code_type) = 0;
11283 EG(current_execute_data) = NULL;
11284 longjmp(EG(bailout), FAILURE);
11285 }
11286diff -Naur php-4.3.11/Zend/zend_canary.c hardening-patch-4.3.11-0.3.2/Zend/zend_canary.c
11287--- php-4.3.11/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
11288+++ hardening-patch-4.3.11-0.3.2/Zend/zend_canary.c 2005-07-09 08:53:02.515356272 +0200
11289@@ -0,0 +1,58 @@
11290+/*
11291+ +----------------------------------------------------------------------+
11292+ | Hardening-Patch for PHP |
11293+ +----------------------------------------------------------------------+
11294+ | Copyright (c) 2004-2005 Stefan Esser |
11295+ +----------------------------------------------------------------------+
11296+ | This source file is subject to version 2.02 of the PHP license, |
11297+ | that is bundled with this package in the file LICENSE, and is |
11298+ | available at through the world-wide-web at |
11299+ | http://www.php.net/license/2_02.txt. |
11300+ | If you did not receive a copy of the PHP license and are unable to |
11301+ | obtain it through the world-wide-web, please send a note to |
11302+ | license@php.net so we can mail you a copy immediately. |
11303+ +----------------------------------------------------------------------+
11304+ | Author: Stefan Esser <sesser@hardened-php.net> |
11305+ +----------------------------------------------------------------------+
11306+ */
11307+/* $Id: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */
11308+
11309+#include "zend.h"
11310+
11311+#include <stdio.h>
11312+#include <stdlib.h>
11313+
11314+
11315+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
11316+
11317+/* will be replaced later with more compatible method */
11318+ZEND_API unsigned int zend_canary()
11319+{
11320+ time_t t;
11321+ unsigned int canary;
11322+ int fd;
11323+
11324+ fd = open("/dev/urandom", 0);
11325+ if (fd != -1) {
11326+ int r = read(fd, &canary, sizeof(canary));
11327+ close(fd);
11328+ if (r == sizeof(canary)) {
11329+ return (canary);
11330+ }
11331+ }
11332+ /* not good but we never want to do this */
11333+ time(&t);
11334+ canary = *(unsigned int *)&t + getpid() << 16;
11335+ return (canary);
11336+}
11337+#endif
11338+
11339+
11340+/*
11341+ * Local variables:
11342+ * tab-width: 4
11343+ * c-basic-offset: 4
11344+ * End:
11345+ * vim600: sw=4 ts=4 fdm=marker
11346+ * vim<600: sw=4 ts=4
11347+ */
11348diff -Naur php-4.3.11/Zend/zend_compile.h hardening-patch-4.3.11-0.3.2/Zend/zend_compile.h
11349--- php-4.3.11/Zend/zend_compile.h 2004-09-24 15:15:14.000000000 +0200
11350+++ hardening-patch-4.3.11-0.3.2/Zend/zend_compile.h 2005-07-09 08:53:02.515356272 +0200
11351@@ -546,6 +546,7 @@
11352 #define ZEND_USER_FUNCTION 2
11353 #define ZEND_OVERLOADED_FUNCTION 3
11354 #define ZEND_EVAL_CODE 4
11355+#define ZEND_SANDBOX_CODE 6
11356
11357 #define ZEND_INTERNAL_CLASS 1
11358 #define ZEND_USER_CLASS 2
11359diff -Naur php-4.3.11/Zend/zend_constants.c hardening-patch-4.3.11-0.3.2/Zend/zend_constants.c
11360--- php-4.3.11/Zend/zend_constants.c 2004-07-13 21:29:45.000000000 +0200
11361+++ hardening-patch-4.3.11-0.3.2/Zend/zend_constants.c 2005-07-09 08:53:02.516356120 +0200
11362@@ -111,6 +111,72 @@
11363 REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
11364
11365 REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
11366+#if HARDENING_PATCH
11367+ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
11368+ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
11369+ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_VARS, CONST_PERSISTENT | CONST_CS);
11370+ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
11371+ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
11372+ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
11373+ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
11374+ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
11375+
11376+ /* error levels */
11377+ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
11378+ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
11379+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
11380+ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
11381+ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
11382+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
11383+ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
11384+ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
11385+ /* facility: type of program logging the message */
11386+ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
11387+ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
11388+ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
11389+ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
11390+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
11391+ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
11392+ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
11393+#ifdef LOG_NEWS
11394+ /* No LOG_NEWS on HP-UX */
11395+ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
11396+#endif
11397+#ifdef LOG_UUCP
11398+ /* No LOG_UUCP on HP-UX */
11399+ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
11400+#endif
11401+#ifdef LOG_CRON
11402+ /* apparently some systems don't have this one */
11403+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
11404+#endif
11405+#ifdef LOG_AUTHPRIV
11406+ /* AIX doesn't have LOG_AUTHPRIV */
11407+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
11408+#endif
11409+#if !defined(PHP_WIN32) && !defined(NETWARE)
11410+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
11411+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
11412+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
11413+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
11414+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
11415+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
11416+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
11417+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
11418+#endif
11419+ /* options */
11420+ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
11421+ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
11422+ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
11423+ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
11424+#ifdef LOG_NOWAIT
11425+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
11426+#endif
11427+#ifdef LOG_PERROR
11428+ /* AIX doesn't have LOG_PERROR */
11429+ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
11430+#endif
11431+#endif
11432
11433 /* true/false constants */
11434 {
11435diff -Naur php-4.3.11/Zend/zend_errors.h hardening-patch-4.3.11-0.3.2/Zend/zend_errors.h
11436--- php-4.3.11/Zend/zend_errors.h 2002-12-31 17:22:59.000000000 +0100
11437+++ hardening-patch-4.3.11-0.3.2/Zend/zend_errors.h 2005-07-09 08:53:02.516356120 +0200
11438@@ -36,5 +36,16 @@
11439 #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE)
11440 #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
11441
11442+#if HARDENING_PATCH
11443+#define S_MEMORY (1<<0L)
11444+#define S_VARS (1<<1L)
11445+#define S_FILES (1<<2L)
11446+#define S_INCLUDE (1<<3L)
11447+#define S_SQL (1<<4L)
11448+#define S_EXECUTOR (1<<5L)
11449+#define S_MISC (1<<30L)
11450+#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MISC | S_SQL | S_EXECUTOR)
11451+#endif
11452+
11453 #endif /* ZEND_ERRORS_H */
11454
11455diff -Naur php-4.3.11/Zend/zend_execute_API.c hardening-patch-4.3.11-0.3.2/Zend/zend_execute_API.c
11456--- php-4.3.11/Zend/zend_execute_API.c 2004-11-04 00:15:05.000000000 +0100
11457+++ hardening-patch-4.3.11-0.3.2/Zend/zend_execute_API.c 2005-07-09 08:53:02.517355968 +0200
11458@@ -142,6 +142,7 @@
11459 EG(class_table) = CG(class_table);
11460
11461 EG(in_execution) = 0;
11462+ EG(in_code_type) = 0;
11463
11464 zend_ptr_stack_init(&EG(argument_stack));
11465
11466@@ -431,12 +432,14 @@
11467 zend_execute_data execute_data;
11468
11469 /* Initialize execute_data */
11470+ memset(&execute_data, 0, sizeof(execute_data));
11471 EX(fbc) = NULL;
11472 EX(object).ptr = NULL;
11473 EX(ce) = NULL;
11474 EX(Ts) = NULL;
11475 EX(op_array) = NULL;
11476 EX(opline) = NULL;
11477+ EX(execute_depth) = 0;
11478
11479 *retval_ptr_ptr = NULL;
11480
11481@@ -601,8 +604,7 @@
11482 return SUCCESS;
11483 }
11484
11485-
11486-ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
11487+ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int type TSRMLS_DC)
11488 {
11489 zval pv;
11490 zend_op_array *new_op_array;
11491@@ -635,6 +637,7 @@
11492 zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
11493 zend_op **original_opline_ptr = EG(opline_ptr);
11494
11495+ new_op_array->type = type;
11496 EG(return_value_ptr_ptr) = &local_retval_ptr;
11497 EG(active_op_array) = new_op_array;
11498 EG(no_extensions)=1;
11499@@ -668,6 +671,10 @@
11500 return retval;
11501 }
11502
11503+ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
11504+{
11505+ return (zend_eval_string_ex(str, retval_ptr, string_name, ZEND_EVAL_CODE TSRMLS_CC));
11506+}
11507
11508 void execute_new_code(TSRMLS_D)
11509 {
11510diff -Naur php-4.3.11/Zend/zend_execute.c hardening-patch-4.3.11-0.3.2/Zend/zend_execute.c
11511--- php-4.3.11/Zend/zend_execute.c 2005-02-21 13:38:54.000000000 +0100
11512+++ hardening-patch-4.3.11-0.3.2/Zend/zend_execute.c 2005-07-09 08:53:02.519355664 +0200
11513@@ -1042,6 +1042,7 @@
11514 zend_execute_data execute_data;
11515
11516 /* Initialize execute_data */
11517+ memset(&execute_data, 0, sizeof(execute_data));
11518 EX(fbc) = NULL;
11519 EX(ce) = NULL;
11520 EX(object).ptr = NULL;
11521@@ -1053,9 +1054,21 @@
11522 }
11523 EX(prev_execute_data) = EG(current_execute_data);
11524 EX(original_in_execution)=EG(in_execution);
11525+ EX(original_in_code_type)=EG(in_code_type);
11526
11527 EG(current_execute_data) = &execute_data;
11528
11529+#if HARDENING_PATCH
11530+ EX(execute_depth) = 0;
11531+
11532+ if (op_array->type == ZEND_EVAL_CODE && EG(in_code_type) != ZEND_SANDBOX_CODE) {
11533+ EG(in_code_type) = ZEND_EVAL_CODE;
11534+ } else if (op_array->type == ZEND_SANDBOX_CODE) {
11535+ EG(in_code_type) = ZEND_SANDBOX_CODE;
11536+ op_array->type = ZEND_EVAL_CODE;
11537+ }
11538+#endif
11539+
11540 EG(in_execution) = 1;
11541 if (op_array->start_op) {
11542 EX(opline) = op_array->start_op;
11543@@ -1087,6 +1100,19 @@
11544 }
11545 }
11546
11547+#if HARDENING_PATCH
11548+ if (EX(prev_execute_data) == NULL) {
11549+ EX(execute_depth) = 0;
11550+ } else {
11551+ EX(execute_depth) = EX(prev_execute_data)->execute_depth + 1;
11552+ }
11553+
11554+ if (EG(hphp_executor_max_depth) > 0 && EX(execute_depth) > EG(hphp_executor_max_depth)) {
11555+ zend_security_log(S_EXECUTOR, "Maximum execution depth of %u violated", EG(hphp_executor_max_depth));
11556+ zend_bailout();
11557+ }
11558+#endif
11559+
11560 while (1) {
11561 #ifdef ZEND_WIN32
11562 if (EG(timed_out)) {
11563@@ -1782,6 +1808,7 @@
11564 efree(EX(Ts));
11565 }
11566 EG(in_execution) = EX(original_in_execution);
11567+ EG(in_code_type) = EX(original_in_code_type);
11568 EG(current_execute_data) = EX(prev_execute_data);
11569 return;
11570 }
11571@@ -2161,7 +2188,12 @@
11572 int dummy = 1;
11573 zend_file_handle file_handle = {0};
11574
11575+#if HARDENING_PATCH_INC_PROTECT
11576+ if (zend_is_valid_include(inc_filename)
11577+ && zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
11578+#else
11579 if (zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
11580+#endif
11581 && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
11582
11583 file_handle.filename = inc_filename->value.str.val;
11584@@ -2190,6 +2222,11 @@
11585 break;
11586 case ZEND_INCLUDE:
11587 case ZEND_REQUIRE:
11588+#if HARDENING_PATCH_INC_PROTECT
11589+ if (!zend_is_valid_include(inc_filename)) {
11590+ break;
11591+ }
11592+#endif
11593 new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
11594 break;
11595 case ZEND_EVAL: {
11596diff -Naur php-4.3.11/Zend/zend_execute_globals.h hardening-patch-4.3.11-0.3.2/Zend/zend_execute_globals.h
11597--- php-4.3.11/Zend/zend_execute_globals.h 2002-12-31 17:23:00.000000000 +0100
11598+++ hardening-patch-4.3.11-0.3.2/Zend/zend_execute_globals.h 2005-07-09 08:53:02.519355664 +0200
11599@@ -59,6 +59,8 @@
11600 object_info object;
11601 temp_variable *Ts;
11602 zend_bool original_in_execution;
11603+ zend_uint original_in_code_type;
11604+ zend_uint execute_depth;
11605 zend_op_array *op_array;
11606 struct _zend_execute_data *prev_execute_data;
11607 } zend_execute_data;
11608diff -Naur php-4.3.11/Zend/zend_extensions.h hardening-patch-4.3.11-0.3.2/Zend/zend_extensions.h
11609--- php-4.3.11/Zend/zend_extensions.h 2002-12-31 17:23:02.000000000 +0100
11610+++ hardening-patch-4.3.11-0.3.2/Zend/zend_extensions.h 2005-07-09 08:53:02.520355512 +0200
11611@@ -23,7 +23,9 @@
11612
11613 #include "zend_compile.h"
11614
11615-#define ZEND_EXTENSION_API_NO 20021010
11616+/* Create own API version number for Hardening-Patch */
11617+
11618+#define ZEND_EXTENSION_API_NO 1020050626
11619
11620 typedef struct _zend_extension_version_info {
11621 int zend_extension_api_no;
11622diff -Naur php-4.3.11/Zend/zend_globals.h hardening-patch-4.3.11-0.3.2/Zend/zend_globals.h
11623--- php-4.3.11/Zend/zend_globals.h 2004-11-04 00:15:05.000000000 +0100
11624+++ hardening-patch-4.3.11-0.3.2/Zend/zend_globals.h 2005-07-09 08:53:02.520355512 +0200
11625@@ -163,6 +163,16 @@
11626
11627 int error_reporting;
11628 int orig_error_reporting;
11629+#if HARDENING_PATCH
11630+ int hphp_log_syslog;
11631+ int hphp_log_syslog_facility;
11632+ int hphp_log_syslog_priority;
11633+ int hphp_log_sapi;
11634+ int hphp_log_script;
11635+ char *hphp_log_scriptname;
11636+ zend_bool hphp_log_use_x_forwarded_for;
11637+ long hphp_executor_max_depth;
11638+#endif
11639 int exit_status;
11640
11641 zend_op_array *active_op_array;
11642@@ -176,6 +186,7 @@
11643 int ticks_count;
11644
11645 zend_bool in_execution;
11646+ zend_uint in_code_type;
11647 zend_bool bailout_set;
11648 zend_bool full_tables_cleanup;
11649
11650diff -Naur php-4.3.11/Zend/zend.h hardening-patch-4.3.11-0.3.2/Zend/zend.h
11651--- php-4.3.11/Zend/zend.h 2005-01-25 14:08:41.000000000 +0100
11652+++ hardening-patch-4.3.11-0.3.2/Zend/zend.h 2005-07-09 08:53:02.521355360 +0200
11653@@ -275,9 +275,10 @@
11654 struct _zval_struct {
11655 /* Variable information */
11656 zvalue_value value; /* value */
11657+ zend_uint refcount;
11658+ zend_ushort flags;
11659 zend_uchar type; /* active type */
11660 zend_uchar is_ref;
11661- zend_ushort refcount;
11662 };
11663
11664
11665@@ -338,6 +339,12 @@
11666 void (*ticks_function)(int ticks);
11667 void (*on_timeout)(int seconds TSRMLS_DC);
11668 zend_bool (*open_function)(const char *filename, struct _zend_file_handle *);
11669+#if HARDENING_PATCH
11670+ void (*security_log_function)(int loglevel, char *fmt, ...);
11671+#endif
11672+#if HARDENING_PATCH_INC_PROTECT
11673+ int (*is_valid_include)(zval *z);
11674+#endif
11675 } zend_utility_functions;
11676
11677
11678@@ -469,7 +476,16 @@
11679 extern ZEND_API void (*zend_ticks_function)(int ticks);
11680 extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
11681 extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
11682+#if HARDENING_PATCH
11683+extern ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
11684+#endif
11685+#if HARDENING_PATCH_INC_PROTECT
11686+extern ZEND_API int (*zend_is_valid_include)(zval *z);
11687+#endif
11688
11689+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
11690+ZEND_API unsigned int zend_canary(void);
11691+#endif
11692
11693 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 2, 3);
11694
11695@@ -576,6 +592,11 @@
11696
11697 #define ZEND_MAX_RESERVED_RESOURCES 4
11698
11699+#if HARDENING_PATCH
11700+#include "hardened_globals.h"
11701+#include "php_syslog.h"
11702+#endif
11703+
11704 #endif /* ZEND_H */
11705
11706 /*
11707diff -Naur php-4.3.11/Zend/zend_hash.c hardening-patch-4.3.11-0.3.2/Zend/zend_hash.c
11708--- php-4.3.11/Zend/zend_hash.c 2004-07-12 23:26:46.000000000 +0200
11709+++ hardening-patch-4.3.11-0.3.2/Zend/zend_hash.c 2005-07-09 08:53:02.522355208 +0200
11710@@ -26,6 +26,17 @@
11711 # include <stdlib.h>
11712 #endif
11713
11714+#if HARDENING_PATCH_HASH_PROTECT
11715+ unsigned int zend_hash_canary = 0x1234567;
11716+ zend_bool zend_hash_canary_inited = 0;
11717+#endif
11718+
11719+#define CHECK_HASH_CANARY(hash) \
11720+ if (zend_hash_canary != (hash)->canary) { \
11721+ zend_security_log(S_MEMORY, "Zend HashTable canary was overwritten"); \
11722+ exit(1); \
11723+ }
11724+
11725 #define HANDLE_NUMERIC(key, length, func) { \
11726 register char *tmp=key; \
11727 \
11728@@ -175,6 +186,9 @@
11729 {
11730 uint i = 3;
11731 Bucket **tmp;
11732+#if HARDENING_PATCH_HASH_PROTECT
11733+ TSRMLS_FETCH();
11734+#endif
11735
11736 SET_INCONSISTENT(HT_OK);
11737
11738@@ -184,6 +198,13 @@
11739
11740 ht->nTableSize = 1 << i;
11741 ht->nTableMask = ht->nTableSize - 1;
11742+#if HARDENING_PATCH_HASH_PROTECT
11743+ if (zend_hash_canary_inited==0) {
11744+ zend_hash_canary = zend_canary();
11745+ zend_hash_canary_inited = 1;
11746+ }
11747+ ht->canary = zend_hash_canary;
11748+#endif
11749 ht->pDestructor = pDestructor;
11750 ht->pListHead = NULL;
11751 ht->pListTail = NULL;
11752@@ -259,6 +280,9 @@
11753 }
11754 #endif
11755 if (ht->pDestructor) {
11756+#if HARDENING_PATCH_HASH_PROTECT
11757+ CHECK_HASH_CANARY(ht);
11758+#endif
11759 ht->pDestructor(p->pData);
11760 }
11761 UPDATE_DATA(ht, p, pData, nDataSize);
11762@@ -327,6 +351,9 @@
11763 }
11764 #endif
11765 if (ht->pDestructor) {
11766+#if HARDENING_PATCH_HASH_PROTECT
11767+ CHECK_HASH_CANARY(ht);
11768+#endif
11769 ht->pDestructor(p->pData);
11770 }
11771 UPDATE_DATA(ht, p, pData, nDataSize);
11772@@ -402,6 +429,9 @@
11773 }
11774 #endif
11775 if (ht->pDestructor) {
11776+#if HARDENING_PATCH_HASH_PROTECT
11777+ CHECK_HASH_CANARY(ht);
11778+#endif
11779 ht->pDestructor(p->pData);
11780 }
11781 UPDATE_DATA(ht, p, pData, nDataSize);
11782@@ -450,7 +480,7 @@
11783 IS_CONSISTENT(ht);
11784
11785 if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */
11786- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
11787+ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
11788 if (t) {
11789 HANDLE_BLOCK_INTERRUPTIONS();
11790 ht->arBuckets = t;
11791@@ -460,6 +490,7 @@
11792 HANDLE_UNBLOCK_INTERRUPTIONS();
11793 return SUCCESS;
11794 }
11795+ zend_error(E_ERROR, "zend_hash_do_resize - out of memory");
11796 return FAILURE;
11797 }
11798 return SUCCESS;
11799@@ -524,6 +555,9 @@
11800 ht->pInternalPointer = p->pListNext;
11801 }
11802 if (ht->pDestructor) {
11803+#if HARDENING_PATCH_HASH_PROTECT
11804+ CHECK_HASH_CANARY(ht);
11805+#endif
11806 ht->pDestructor(p->pData);
11807 }
11808 if (!p->pDataPtr) {
11809@@ -553,6 +587,9 @@
11810 q = p;
11811 p = p->pListNext;
11812 if (ht->pDestructor) {
11813+#if HARDENING_PATCH_HASH_PROTECT
11814+ CHECK_HASH_CANARY(ht);
11815+#endif
11816 ht->pDestructor(q->pData);
11817 }
11818 if (!q->pDataPtr && q->pData) {
11819@@ -579,6 +616,9 @@
11820 q = p;
11821 p = p->pListNext;
11822 if (ht->pDestructor) {
11823+#if HARDENING_PATCH_HASH_PROTECT
11824+ CHECK_HASH_CANARY(ht);
11825+#endif
11826 ht->pDestructor(q->pData);
11827 }
11828 if (!q->pDataPtr && q->pData) {
11829@@ -608,6 +648,9 @@
11830 HANDLE_BLOCK_INTERRUPTIONS();
11831
11832 if (ht->pDestructor) {
11833+#if HARDENING_PATCH_HASH_PROTECT
11834+ CHECK_HASH_CANARY(ht);
11835+#endif
11836 ht->pDestructor(p->pData);
11837 }
11838 if (!p->pDataPtr) {
11839diff -Naur php-4.3.11/Zend/zend_hash.h hardening-patch-4.3.11-0.3.2/Zend/zend_hash.h
11840--- php-4.3.11/Zend/zend_hash.h 2002-12-31 17:23:03.000000000 +0100
11841+++ hardening-patch-4.3.11-0.3.2/Zend/zend_hash.h 2005-07-09 08:53:02.522355208 +0200
11842@@ -54,6 +54,9 @@
11843 } Bucket;
11844
11845 typedef struct _hashtable {
11846+#if HARDENING_PATCH_HASH_PROTECT
11847+ unsigned int canary;
11848+#endif
11849 uint nTableSize;
11850 uint nTableMask;
11851 uint nNumOfElements;
11852diff -Naur php-4.3.11/Zend/zend_ini.h hardening-patch-4.3.11-0.3.2/Zend/zend_ini.h
11853--- php-4.3.11/Zend/zend_ini.h 2005-01-09 18:00:16.000000000 +0100
11854+++ hardening-patch-4.3.11-0.3.2/Zend/zend_ini.h 2005-07-09 08:53:02.522355208 +0200
11855@@ -174,6 +174,7 @@
11856 /* Standard message handlers */
11857 BEGIN_EXTERN_C()
11858 ZEND_API ZEND_INI_MH(OnUpdateBool);
11859+#define OnUpdateLong OnUpdateInt
11860 ZEND_API ZEND_INI_MH(OnUpdateInt);
11861 ZEND_API ZEND_INI_MH(OnUpdateReal);
11862 ZEND_API ZEND_INI_MH(OnUpdateString);
11863diff -Naur php-4.3.11/Zend/zend_llist.c hardening-patch-4.3.11-0.3.2/Zend/zend_llist.c
11864--- php-4.3.11/Zend/zend_llist.c 2002-12-31 17:23:04.000000000 +0100
11865+++ hardening-patch-4.3.11-0.3.2/Zend/zend_llist.c 2005-07-09 08:53:02.523355056 +0200
11866@@ -21,9 +21,34 @@
11867 #include "zend.h"
11868 #include "zend_llist.h"
11869 #include "zend_qsort.h"
11870+#include "zend_globals.h"
11871+
11872+#define CHECK_LIST_CANARY(list) \
11873+ if (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t) { \
11874+ zend_security_log(S_MEMORY, "linked list canary was overwritten"); \
11875+ exit(1); \
11876+ }
11877+
11878+#define CHECK_LISTELEMENT_CANARY(elem) \
11879+ if (HG(canary_3) != (elem)->canary) { \
11880+ zend_security_log(S_MEMORY, "linked list element canary was overwritten"); \
11881+ exit(1); \
11882+ }
11883+
11884
11885 ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
11886 {
11887+#if HARDENING_PATCH_LL_PROTECT
11888+ TSRMLS_FETCH();
11889+
11890+ if (!HG(ll_canary_inited)) {
11891+ HG(canary_3) = zend_canary();
11892+ HG(canary_4) = zend_canary();
11893+ HG(ll_canary_inited) = 1;
11894+ }
11895+ l->canary_h = HG(canary_3);
11896+ l->canary_t = HG(canary_4);
11897+#endif
11898 l->head = NULL;
11899 l->tail = NULL;
11900 l->count = 0;
11901@@ -37,6 +62,11 @@
11902 {
11903 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
11904
11905+#if HARDENING_PATCH_LL_PROTECT
11906+ TSRMLS_FETCH();
11907+ CHECK_LIST_CANARY(l)
11908+ tmp->canary = HG(canary_3);
11909+#endif
11910 tmp->prev = l->tail;
11911 tmp->next = NULL;
11912 if (l->tail) {
11913@@ -55,6 +85,11 @@
11914 {
11915 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
11916
11917+#if HARDENING_PATCH_LL_PROTECT
11918+ TSRMLS_FETCH();
11919+ CHECK_LIST_CANARY(l)
11920+ tmp->canary = HG(canary_3);
11921+#endif
11922 tmp->next = l->head;
11923 tmp->prev = NULL;
11924 if (l->head) {
11925@@ -91,10 +126,20 @@
11926 zend_llist_element *current=l->head;
11927 zend_llist_element *next;
11928
11929+#if HARDENING_PATCH_LL_PROTECT
11930+ TSRMLS_FETCH();
11931+ CHECK_LIST_CANARY(l)
11932+#endif
11933 while (current) {
11934+#if HARDENING_PATCH_LL_PROTECT
11935+ CHECK_LISTELEMENT_CANARY(current)
11936+#endif
11937 next = current->next;
11938 if (compare(current->data, element)) {
11939 DEL_LLIST_ELEMENT(current, l);
11940+#if HARDENING_PATCH_LL_PROTECT
11941+ current->canary = 0;
11942+#endif
11943 break;
11944 }
11945 current = next;
11946@@ -106,7 +151,14 @@
11947 {
11948 zend_llist_element *current=l->head, *next;
11949
11950+#if HARDENING_PATCH_LL_PROTECT
11951+ TSRMLS_FETCH();
11952+ CHECK_LIST_CANARY(l)
11953+#endif
11954 while (current) {
11955+#if HARDENING_PATCH_LL_PROTECT
11956+ CHECK_LISTELEMENT_CANARY(current)
11957+#endif
11958 next = current->next;
11959 if (l->dtor) {
11960 l->dtor(current->data);
11961@@ -131,7 +183,14 @@
11962 zend_llist_element *old_tail;
11963 void *data;
11964
11965+#if HARDENING_PATCH_LL_PROTECT
11966+ TSRMLS_FETCH();
11967+ CHECK_LIST_CANARY(l)
11968+#endif
11969 if ((old_tail = l->tail)) {
11970+#if HARDENING_PATCH_LL_PROTECT
11971+ CHECK_LISTELEMENT_CANARY(old_tail)
11972+#endif
11973 if (l->tail->prev) {
11974 l->tail->prev->next = NULL;
11975 }
11976@@ -157,9 +216,16 @@
11977 {
11978 zend_llist_element *ptr;
11979
11980+#if HARDENING_PATCH_LL_PROTECT
11981+ TSRMLS_FETCH();
11982+ CHECK_LIST_CANARY(src)
11983+#endif
11984 zend_llist_init(dst, src->size, src->dtor, src->persistent);
11985 ptr = src->head;
11986 while (ptr) {
11987+#if HARDENING_PATCH_LL_PROTECT
11988+ CHECK_LISTELEMENT_CANARY(ptr)
11989+#endif
11990 zend_llist_add_element(dst, ptr->data);
11991 ptr = ptr->next;
11992 }
11993@@ -170,11 +236,21 @@
11994 {
11995 zend_llist_element *element, *next;
11996
11997+#if HARDENING_PATCH_LL_PROTECT
11998+ TSRMLS_FETCH();
11999+ CHECK_LIST_CANARY(l)
12000+#endif
12001 element=l->head;
12002 while (element) {
12003+#if HARDENING_PATCH_LL_PROTECT
12004+ CHECK_LISTELEMENT_CANARY(element)
12005+#endif
12006 next = element->next;
12007 if (func(element->data)) {
12008 DEL_LLIST_ELEMENT(element, l);
12009+#if HARDENING_PATCH_LL_PROTECT
12010+ element->canary = 0;
12011+#endif
12012 }
12013 element = next;
12014 }
12015@@ -185,7 +261,13 @@
12016 {
12017 zend_llist_element *element;
12018
12019+#if HARDENING_PATCH_LL_PROTECT
12020+ CHECK_LIST_CANARY(l)
12021+#endif
12022 for (element=l->head; element; element=element->next) {
12023+#if HARDENING_PATCH_LL_PROTECT
12024+ CHECK_LISTELEMENT_CANARY(element)
12025+#endif
12026 func(element->data TSRMLS_CC);
12027 }
12028 }
12029@@ -197,6 +279,9 @@
12030 zend_llist_element **elements;
12031 zend_llist_element *element, **ptr;
12032
12033+#if HARDENING_PATCH_LL_PROTECT
12034+ CHECK_LIST_CANARY(l)
12035+#endif
12036 if (l->count <= 0) {
12037 return;
12038 }
12039@@ -206,6 +291,9 @@
12040 ptr = &elements[0];
12041
12042 for (element=l->head; element; element=element->next) {
12043+#if HARDENING_PATCH_LL_PROTECT
12044+ CHECK_LISTELEMENT_CANARY(element)
12045+#endif
12046 *ptr++ = element;
12047 }
12048
12049@@ -228,7 +316,13 @@
12050 {
12051 zend_llist_element *element;
12052
12053+#if HARDENING_PATCH_LL_PROTECT
12054+ CHECK_LIST_CANARY(l)
12055+#endif
12056 for (element=l->head; element; element=element->next) {
12057+#if HARDENING_PATCH_LL_PROTECT
12058+ CHECK_LISTELEMENT_CANARY(element)
12059+#endif
12060 func(element->data, arg TSRMLS_CC);
12061 }
12062 }
12063@@ -239,8 +333,14 @@
12064 zend_llist_element *element;
12065 va_list args;
12066
12067+#if HARDENING_PATCH_LL_PROTECT
12068+ CHECK_LIST_CANARY(l)
12069+#endif
12070 va_start(args, num_args);
12071 for (element=l->head; element; element=element->next) {
12072+#if HARDENING_PATCH_LL_PROTECT
12073+ CHECK_LISTELEMENT_CANARY(element)
12074+#endif
12075 func(element->data, num_args, args TSRMLS_CC);
12076 }
12077 va_end(args);
12078@@ -249,6 +349,10 @@
12079
12080 ZEND_API int zend_llist_count(zend_llist *l)
12081 {
12082+#if HARDENING_PATCH_LL_PROTECT
12083+ TSRMLS_FETCH();
12084+ CHECK_LIST_CANARY(l)
12085+#endif
12086 return l->count;
12087 }
12088
12089@@ -256,8 +360,15 @@
12090 {
12091 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
12092
12093+#if HARDENING_PATCH_LL_PROTECT
12094+ TSRMLS_FETCH();
12095+ CHECK_LIST_CANARY(l)
12096+#endif
12097 *current = l->head;
12098 if (*current) {
12099+#if HARDENING_PATCH_LL_PROTECT
12100+ CHECK_LISTELEMENT_CANARY(*current)
12101+#endif
12102 return (*current)->data;
12103 } else {
12104 return NULL;
12105@@ -269,8 +380,15 @@
12106 {
12107 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
12108
12109+#if HARDENING_PATCH_LL_PROTECT
12110+ TSRMLS_FETCH();
12111+ CHECK_LIST_CANARY(l)
12112+#endif
12113 *current = l->tail;
12114 if (*current) {
12115+#if HARDENING_PATCH_LL_PROTECT
12116+ CHECK_LISTELEMENT_CANARY(*current)
12117+#endif
12118 return (*current)->data;
12119 } else {
12120 return NULL;
12121@@ -282,9 +400,19 @@
12122 {
12123 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
12124
12125+#if HARDENING_PATCH_LL_PROTECT
12126+ TSRMLS_FETCH();
12127+ CHECK_LIST_CANARY(l)
12128+#endif
12129 if (*current) {
12130+#if HARDENING_PATCH_LL_PROTECT
12131+ CHECK_LISTELEMENT_CANARY(*current)
12132+#endif
12133 *current = (*current)->next;
12134 if (*current) {
12135+#if HARDENING_PATCH_LL_PROTECT
12136+ CHECK_LISTELEMENT_CANARY(*current)
12137+#endif
12138 return (*current)->data;
12139 }
12140 }
12141@@ -296,9 +424,19 @@
12142 {
12143 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
12144
12145+#if HARDENING_PATCH_LL_PROTECT
12146+ TSRMLS_FETCH();
12147+ CHECK_LIST_CANARY(l)
12148+#endif
12149 if (*current) {
12150+#if HARDENING_PATCH_LL_PROTECT
12151+ CHECK_LISTELEMENT_CANARY(*current)
12152+#endif
12153 *current = (*current)->prev;
12154 if (*current) {
12155+#if HARDENING_PATCH_LL_PROTECT
12156+ CHECK_LISTELEMENT_CANARY(*current)
12157+#endif
12158 return (*current)->data;
12159 }
12160 }
12161diff -Naur php-4.3.11/Zend/zend_llist.h hardening-patch-4.3.11-0.3.2/Zend/zend_llist.h
12162--- php-4.3.11/Zend/zend_llist.h 2002-12-31 17:23:04.000000000 +0100
12163+++ hardening-patch-4.3.11-0.3.2/Zend/zend_llist.h 2005-07-09 08:53:02.524354904 +0200
12164@@ -24,6 +24,9 @@
12165 #include <stdlib.h>
12166
12167 typedef struct _zend_llist_element {
12168+#if HARDENING_PATCH_LL_PROTECT
12169+ unsigned int canary;
12170+#endif
12171 struct _zend_llist_element *next;
12172 struct _zend_llist_element *prev;
12173 char data[1]; /* Needs to always be last in the struct */
12174@@ -36,6 +39,9 @@
12175 typedef void (*llist_apply_func_t)(void * TSRMLS_DC);
12176
12177 typedef struct _zend_llist {
12178+#if HARDENING_PATCH_LL_PROTECT
12179+ unsigned int canary_h; /* head */
12180+#endif
12181 zend_llist_element *head;
12182 zend_llist_element *tail;
12183 size_t size;
12184@@ -43,6 +49,9 @@
12185 llist_dtor_func_t dtor;
12186 unsigned char persistent;
12187 zend_llist_element *traverse_ptr;
12188+#if HARDENING_PATCH_LL_PROTECT
12189+ unsigned int canary_t; /* tail */
12190+#endif
12191 } zend_llist;
12192
12193 typedef zend_llist_element* zend_llist_position;
12194diff -Naur php-4.3.11/Zend/zend_modules.h hardening-patch-4.3.11-0.3.2/Zend/zend_modules.h
12195--- php-4.3.11/Zend/zend_modules.h 2002-12-31 17:23:04.000000000 +0100
12196+++ hardening-patch-4.3.11-0.3.2/Zend/zend_modules.h 2005-07-09 08:53:02.524354904 +0200
12197@@ -34,7 +34,7 @@
12198 ZEND_API extern unsigned char second_arg_force_ref[];
12199 ZEND_API extern unsigned char third_arg_force_ref[];
12200
12201-#define ZEND_MODULE_API_NO 20020429
12202+#define ZEND_MODULE_API_NO 1020050626
12203 #ifdef ZTS
12204 #define USING_ZTS 1
12205 #else