PHP userland backwards compatibility layer that emulates PHP 5.5+ core functions.

⌈⌋ branch:  upgrade.php


Check-in [51e3884900]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:upgradephp-15
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 51e388490038df1cb5bc3ce7d0c98bb3888b4a53
User & Date: mario 2010-06-22 17:03:27
Context
2010-06-22
17:03
upgradephp-16 check-in: 02e65f8aad user: mario tags: trunk
17:03
upgradephp-15 check-in: 51e3884900 user: mario tags: trunk
17:03
upgradephp-14 check-in: 39c9fa23ab user: mario tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Deleted README.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488

PHP downwards compatibility functions

The "upgrade.php" package implements features and functions from
later PHP versions in pure PHP script and dynamically defines them
at runtime. The emulated functions use exactly the same names as
the originals, and cannot perturb if the native functions exist.

So this is really a drop-in replacement, and allows you to use all
PHP features regardless of the current PHP interpreter. If you just
include() this single script you are freed from wasting time with
backward compatibility problems or omitting certain more useful PHP
functions or retyping workarounds then. Your applications remain
"PHP 4.1+ COMPATIBLE" while you in fact use PHP5.2 features.


this is useful:

- for distribution (of e.g. open source projects)  
- if your own providers PHP version is immemorial
- you want to test new functions, but not install a new PHP ver
- usage of gettext/bcmath/ftp/... extension would be nice in your
  project, but may not be available on all target web servers
- if some other PHP project has a unmet dependency on your server
- you have a sourceforge.net project homepage ;-)

tt however cannot help:

- extended PHP5 object-orientation semantics can't be emulated
- function signatures in newer PHP versions also sometimes change,
  and these cannot be overriden or extended by upgradephp
- doesn't help against amateur providers safe_mode
- compatibility with below PHP 4.0 cannot be reached


other things to note:

- as already said, speed won't suffer on up-to-date servers, because
  functions are only emulated/deifned if they are missing
- some functions are just simple stubs
- emulated functions code is often slower than the native - but few
  significantly slow your scripts (SQL accesses do)
- not all PHP errors are exactly mimicked,
  upgradephp leaves this often to parent functions (e.g. fopen)
- memory shouldn't increase significantly, because if(func_exists)
  "interpretes away" most code 


Remember that native functions will be used whereever available,
this emulation just helps getting scripts run on aging PHP versions.



      PEAR::PHP_Compat
      
      Alternatively to the "upgradephp" package, you could also give
      the PEAR package "PHP_Compat" (by Aidan Lister & Co.) from
      [http://pear.php.net/] a try. It comes under the PHP license
      and contains cleaner code in some areas (exotic array funcs and
      PHP4.0 code for example).

      It is more thoroughly commented and emulates PHP error messages
      completely.  In some circumstances you could benefit from its
      divided function definitions (each in a separate file), while it
      is possible to reassamble everything into a single script.  You
      could even load it in conjunction with upgrade.php then.

      Note: no code from PHP_Compat has been reused here (this is more
      a license thing, than NIH syndrome).



Usage

Simply include("upgrade.php"); in any of your scripts, if you want
to rely on some PHP4.3 or PHP5.2 functions.

   include("upgrade.php");

You could additionally check the PHP_VERSION, and only include the
emulation wrapper if you depend on features from a certain PHP
interpreter release:

  <?example
     if (PHP_VERSION < "4.3.0") { include(".../upgrade.php"); }
  ?>

Currently following functions can be emulated:
 json_encode
 json_decode
 strptime
 gzdecode
 htmlspecialchars_decode
 fputcsv
 ob_get_headers
 xmlentities
 stripos
 strripos
 str_ireplace
 get_headers
 headers_list
 fprintf
 vfprintf
 str_split
 http_build_query
 convert_uuencode
 convert_uudecode
 scandir
 idate
 time_nanosleep
 strpbrk
 php_real_logo_guid
 php_egg_logo_guid
 get_declared_interfaces
 array_combine
 array_walk_recursive
 substr_compare
 spl_classes
 class_parents
 session_commit
 dns_check_record
 dns_get_mx
 setrawcookie
 file_put_contents
 count_recursive
 file_get_contents
 fnmatch
 glob
 array_key_exists
 array_intersect_assoc
 array_diff_assoc
 html_entity_decode
 str_word_count
 str_shuffle
 get_include_path
 set_include_path
 restore_include_path
 str_rot13
 array_change_key_case
 array_fill
 array_chunk
 md5_file
 is_a
 fmod
 floatval
 is_infinite
 is_nan
 is_finite
 var_export
 strcoll
 diskfreespace
 disktotalspace
 vprintf
 vsprintf
 import_request_variables
 hypot
 log1p
 expm1
 sinh
 cosh
 tanh
 asinh
 acosh
 atanh
 mhash
 mhash_count
 mhash_get_hash_name
 mhash_get_block_size
 array_udiff_uassoc
 array_udiff_assoc
 array_diff_uassoc
 array_udiff
 array_uintersect_uassoc
 array_uintersect_assoc
 array_uintersect
 array_intersect_uassoc
 dc___exec
 bcscale
 bcadd
 bcsub
 bcmul
 bcdiv
 bcmod
 bcpow
 bcpowmod
 bcsqrt
 bccomp
 bc___scaledown
 gettext
 gettext___plural_guess
 ngettext
 dngettext
 dcngettext
 dcgettext
 dgettext
 textdomain
 bindtextdomain
 gettext___load_mo
 gettext___load_po
 bind_textdomain_codeset
 _
 mime_content_type
 image_type_to_mime_type
 image_type_to_extension
 exif_imagetype
 array_filter
 array_map
 is_callable
 array_search
 array_reduce
 is_scalar
 localeconv
 call_user_func_array
 call_user_method_array
 array_sum
 constant
 is_null
 pathinfo
 escapeshellarg
 is_uploaded_file
 move_uploaded_file
 strncasecmp
 wordwrap
 php_uname
 php_sapi_name
 posix_mkfifo
 posix_getcwd
 posix_kill
 posix_uname
 ctype_alnum
 ctype_alpha
 ctype_digit
 ctype_xdigit
 ctype_cntrl
 ctype_space
 ctype_upper
 ctype_lower
 ctype_graph
 ctype_punct
 ctype_print
 odbc_connect
 odbc_pconnect
 odbc_close
 odbc_exec
 odbc_do
 odbc_prepare
 odbc_execute
 odbc_fetch_array
 odbc_fetch_row
 odbc_fetch_object
 odbc_fetch_into
 odbc_free_result
 odbc_next_result
 odbc_num_fields
 odbc_num_rows


Redistribution

You are encouraged to distribute "upgrade.php" together with
other / your projects. That's also why it was released as Public
Domain (=compatible to ALL open source licenses, including the
GNU GPL and LGPL).

You could load it automatically then using the PHP_VERSION check,
or simply leave this to your users if they use an older PHP version;
a note often suffices.

Of course you might want to distribute only "upgrade.php" and any
required ext/ module. Just purge the rest (dtools/ and contrib/ or
this README), because they probably make little sense distributed
alongside elsewhere.

It is also safe to extract a few function bodies/definitions out of
upgrade.php to make a shorter version (load only the needed funcs).
But you should keep the "if (function_exists(...))" wrapper code
preferrably.
PHP_Compat however might make a better source for such purposes.


Omissions

A few PHP features are specifically NOT implemented, and so still
had to be taken care of in your scripts:

 predefined STDIN, STDOUT and STDERR constants
 UPLOAD_ERR_* constants (introduced with 4.2, officially 4.3)
 ob_* (eventually possible)
 clone (PHP5 language feature, but workaround exists in PHP_Compat)
 ini_get_all (ingenious trick in PHP_Compat)

It may be possible that a script in ext/ later adds support. Often
PHP_Compat already provides loadable definitions of above features.


ext/

The ext/ subdirectory in here provides a few more or less useful
emulations for various PHP extensions or function groups.

 "ext/array" provides a few exotic array diff functions (for
  associative arrays and for using multiple callback functions)

 "ext/exotic" contains some rarely needed functions, which have
  been removed from the main file for that and other reasons

 "ext/bcmath" provides the mathematical functions with arbitrary
  precision on Unix systems, but emulation also works on top of
  GMP or big_int

 "ext/dba" allows you to use scripts written for the dba module,
  if your interpreter only has dbm_*() functions; but only provides
  the minimum functionality

 "ext/ftp" emulates the ftp extension using only the bare socket
  and networking functions (should work anywhere), even has some
  features not found in the original

 "ext/gettext" simulates most of what gettext/libintl provides, and
  seems to read .mo data files correctly - plural support is however
  weak. There is also support for .po files, but since the libintl
  and original gettext functions don't normally read this, that's a
  useless feature (just for fun). You save 2K by ripping it out.

 "ext/mime" simulates the mime_content_type() function, either by
  accessing PECL::fileinfo or reading and evaluating the magic.mime
  database itself (likely slower and a bit unclean of course)

Other snippets in ext/ are probably incomplete or just TODO stubs.


dtools/

Please run the "updoc" script once to update your PHP manual, if you
are planning to use the upgrade.php script. Create a symlink from your
installed multi-file PHP manual to ease using this and the "doctests"
utility:

 The "dtools/updoc" commandline script updates your local PHP
  documentation to carry hints about emulated functions. It'll simply
  add a small "EMU" on top of the supported functions` description
  pages (in the line typically listing the PHP versions).

 "ckavail.php" was used to check for added functions between
   different PHP interpreter versions, purely a development script.

 "dtools/doctests" greps your local PHP manual for function use
  examples, and executes them with the given PHP interpreter and
  the "upgrade.php" script loaded of course. This way you get live
  tests, but also see:

 "dtools/compact" creates a collapsed version of the upgrade.php
  script (saved into contrib/)



tests/

Contains stupidly short scripts, that have been used to compare
behaviour of the original functions to that of the emulated ones.

Use the "tests/_runparts" shell script (Linux) to get all tests run
automatically. You must specify the names of two different PHP
interpreter versions, whose output for each test will be shown side
by side. If you don't have two, then simply give the name of your
only PHP (-cgi) interpreter twice or simply use "false" or "cat" as
the second argument.



contrib/

Holds a few library scripts, which are believed to be of higher
quality than any of the PEAR counterparts. Probably inappropriate to
place it in this tarball, but they usefully take advantage of the
upgrade.php provided gzdecode(). (PEARs HTTP and XML-RPC classes
don't even know about content-coding, btw).

 "contrib/http" can be used to contact Web form scripts, or PHP
  code utilizing "ext/phprequest" more efficiently. It especially
  supports content-coding as per RFC2616 (HTTP standard) for saving
  a lot of bandwidth and getting answers faster.

 "contrib/xmlrpc" likewise can compress output and is used to
  access XML-RPC and IETF XML+RPC Web services. It takes advantage
  of supported XML and EPI-XML-RPC extensions, but runs gracefully
  (not 100% exact XML parser) without. It was also made to provide
  downwards compatibility. Currently you shouldn't run it against
  old and not-HTTP standards-compliant servers and clients (=avoid
  compression unless you use it also as server or client at the
  other side).

 "contrib/hiddenerrors" shows a nice way to hide all disturbing
  error messages from users, but keeping them available for
  development. It is especially useful, when premature _NOTICEs or
  _WARNINGs could garbage (XML or binary) output or if this could
  prevent sending any further/required HTTP headers().

 "contrib/fix.php" fights magic_quotes and register_globals
  (though here it's often better to let users of outdated PHP setups
  run into the open knife, or die() with an error message)

 "contrib/phprequest" enables your PHP interpreter to receive HTTP
  requests with "application/vnd.php.serialized" encoding (even
  compressed) instead of the older "multipart/form-data" and the
  more simple "application/x-www-form-urlencoded" var post formats;
  this is faster and type-safe if you control both ends of the wire;
  see "contrib/README.http" for hints about the upcoming "PHP-RPC"

 "contrib/exceptions" provide a scheme for PHP4-compatible
  exception management using simple wrapper calls and agreements

Please also have a peek into the README files accompaning the script
snippets distributed in this directory.



Other Notes

 This script doesn't reside in any CVS/SVN reposititory currently
  because it is considered a too minor and small project.

 The project homepage is <http://upgradephp.berlios.de/> but see
  also <http://freshmeat.net/p/upgradephp> for update notifications.



License

Everything in here is Public Domain. There are no restrictions on how
or where you could use it. You may redistribute it under any license
as you wish, and you don't need to tell anyone where you got it from.
It has absolutely no impact on the rest of YOUR project; you are free
to include it as if you had written it yourself.

You could prepend the license preamble (GNU GPL, LGPL, BSD, MPL, MSFT
EULA, PHP, CDDL, Artistic, ...) of your choice if you want to.



Author

The current maintainer can be contacted under <milky*userssfnet>

Please drop me a line, if you found something important missing, or
a really frustrating bug, and if you have feature wishes, or if you
can name one of the functions that the php developers were too lazy
to implement.



ChangeLog


v14
  - initial comment restructuring
  - added json_encode/decode functions, basic strptime parsing
  - php5.1 functions fputcsv, property_exists, ... and constants
  - added dtools/php-commandline/PhpFunctionCall console script

v13
  - bcmath functions changed to use faster /usr/bin/dc, wrappers for GMP
    fixed and php_big_int.so usage possible
  - gettext_plural0 merged into old code and speed improved

v12
  - strripos() handling of positive offsets was fixed
  - strpbrk() fixed to not return string, if nothing found
  - php_strip_whitespace() and php_check_syntax() moved into ext/exotic
  + ext/bcmath using /usr/bin/bc
  + initial mhash (HMAC) implementation with MD5 and SHA1
  + incomplete ext/odbc
  + ext/exceptions for PHP4
  + extremely fast but incomplete plural form handling in gettext module
  - core script rewritten with more exhaustive comments

v11
  - shortened (whitespace- and comment-free) script was added
  - first gettext emulation version

v10
  (unreleased)

...
  (visit the BerliOS download page and diff it yourself)

v1
  - initial release (non-public)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted contrib/exceptions.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
<?php
/*
   simplistic exception handling for PHP4
   --------------------------------------
   
   As you might know, PHP5 introduced exceptions, similiar to Javas. This
   feature of course cannot be used for PHP4-compatible scripts, and it can
   in no way be emulated by a functional API emulation like "upgrade.php".

   To use an exception-like scheme in PHP4 you'd have to agree on conventions
   - lots of. And exceptions won't look object-oriented anymore and not be
   compliant with the PHP5 scheme - the names are in fact held incompatible
   to avoid conflicts in the language semantics (reserved words).
   

   interfaces
   ----------
  
    - class Exception 
    - global variable $_EXCEPTION (- should better be a list of excptn objs?)
    - _try() function
    - _throw() function
    - _catch() function


   howto
   -----
   
    - prefix a block of commands with _try();
      this will initialize exception handling (evtl. resets internal vars)
    - errors are thrown, by calling _throw() with an Exception-class derived
      object instance as parameter, and returning immediately
    - exceptions are "catched" in if() statements, the _catch() function
      with a classname as parameter returns false or the $_EXCEPTION object
    - you shouldn't use set_exception_handler(), but $_EXCEPTION="funcname";

    #-- main code      
    _try();
    {
       sub_call();
    }
    if ($e = _catch("Special_Case")) {
       echo $e->broken_file();
    }
    if ($e = _catch("Exception")) {
       echo "Something broke, I'd say.";
    }
    
    #-- error-prone
    function sub_call() {
       // ...
       _throw(new Exception("error",255)); return();
    }

    
   note
   ----
   
   Please don't send hatemails only because you feel the syntax is too
   far away from PHP5s native exception handling and counter to that in
   other languages. And the underscores in this agreement are just to
   prevent conflicts with PHP5 constructs - this is not yet another case
   of PHP-underscoritis ;)
   
   -> there has been another PHP framework which implemented exceptions
      long before PHP5 came out; I just don't know anymore which it was
      //@TODO: build a search engine similiar to Google to find that out
*/


#-- base class for exceptions
if (!class_exists("exception")) {
   class Exception
   {
      #-- attributes
      var $message = "";
      var $code = 0;
      var $file = NULL;
      var $line = NULL;
      var $backtrace = NULL;
      
      #-- constructor
      function Exception($message="", $code=0) {
      
         #-- values
         $this->message = $message;
         $this->code = $code;
         
         #-- debugging
         $this->backtrace = debug_backtrace();
         array_shift($this->backtrace);
         $this->file = @$this->backtrace[0]["file"];
         $this->line = @$this->backtrace[0]["line"];
      }
      
      #-- get_ wrappers
      function getMessage() {
         return($this->message);
      }
      function getCode() {
         return($this->code);
      }
      function getFile() {
         return($this->file);
      }
      function getLine() {
         return($this->line);
      }
      function getTrace() {
         return($this->backtrace);
      }
      function getTraceAsString() {
         return(var_export($this->backtrace, TRUE));
      }
      
      #-- output
      function __toString() {
         return($this->message);
      }
   }
}



#-- initialize exception handling for next block
function _try()
{
   global $_EXCEPTION;

   #-- clean up
   if (!is_string($_EXCEPTION) || !function_exists($_EXCEPTION)) {
      $_EXCEPTION = new Object();
   }
}


#-- use for throwing errors
function _throw($obj) {
   global $_EXCEPTION;

   #-- quick
   if (is_string($_EXCEPTION) && function_exists($_EXCEPTION)) {
      $_EXCEPTION($obj);
   }

   #-- what do we do if there's already an exception?
   if ($_EXCEPTION) {
      // ???
      trigger_error("_throw: there is already an unhandled exception on the stack", E_USER_ERROR);
   }

   #-- generate object from error message
   if (!is_object($obj)) {
      $_EXCEPTION = new Exception("$obj");
   }

   #-- pass
   $_EXCEPTION = $obj;

   return(true);
   // break 5;  (after throwing an exception, you should
   //           exit from your current function quickly)
}


#-- check if exception thrown
function &_catch($classname="Exception") {
   global $_EXCEPTION;
   static $e;

   #-- checked for a specific error type / exception class
   if (is_object($_EXCEPTION) && (($classname == "*") || is_a($_EXCEPTION, $classname))) {
      $e = &$_EXCEPTION;   //@FIX: remove reference passing, seems unnecessary
      unset($_EXCEPTION);  // this doesn't clean the global var  [but _try() does]
   }
   else {
      $e = false;
   }

   #-- give out extracted exception   
   return $e;
}


#-- functional additions
if (!function_exists("debug_backtrace")) {
   function debug_backtrace() {
      return array();
   }
}


#-- sets global state
if (!function_exists("set_exception_handler")) {
   // quick hack, should use a different func name
   function set_exception_handler($func) {
      global $_EXCEPTION;
      $_EXCEPTION = $func;
   }
}


?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































































































































































































































































































































Deleted contrib/fix.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php
/*
  api: PHP
  type: intercept
  title: PHP fixes
  descriptions: removes bogus magic_quotes and left over superglobals
  priority: auto
  category: library
  conflicts: strike_register_globals, strip_wonderful_slashes

   Outdated and bogus PHP settings (register_globals and magic_quotes) are
   defended by this script, so code cannot be negatively impacted. It can
   always be loaded as it doesn't cause problems or speed disadvantages on
   correctly configured servers. THE "PHP.INI" SHOULD BE FIXED PREFERABLY.
*/

 #-- strike register_globals (injected variables)
 if (ini_get("register_globals") == "1") {
    ewiki_recursive_unset($GLOBALS, $_REQUEST);
    ini_set("register_globals", 0);
 }

 #-- strip any \'s if magic_quotes (variable garbaging) is still enabled
 if (ini_get("magic_quotes_gpc") && get_magic_quotes_gpc()) {
    ewiki_recursive_stripslashes($_REQUEST);
    ewiki_recursive_stripslashes($_GET);
    ewiki_recursive_stripslashes($_POST);
    ewiki_recursive_stripslashes($_COOKIE);
    ewiki_recursive_stripslashes($_ENV);
    ewiki_recursive_stripslashes($_SERVER);
    ini_set("magic_quotes_gpc", 0);
 }

 #-- now that one is really dumb
 set_magic_quotes_runtime(0);


 #-- implementation
 function ewiki_recursive_unset(&$TO, $FROM) {
    foreach ($FROM as $var=>$value) {
       if (isset($TO[$var]) && ($TO[$var]==$FROM[$var])) {
          unset($TO[$var]);
          unset($TO[$var]);   // double unset to work around ZE-num/assoc-hashcode bug
       }
    }
 }
 function ewiki_recursive_stripslashes(&$var) {
    if (is_array($var)) {
       foreach ($var as $key=>$item) {
          ewiki_recursive_stripslashes($var[$key]);
       }
    }
    else {
       $var = stripslashes($var);
    }
 }

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































Deleted contrib/hiddenerrors.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
/*
   The error handler provided here will feed all errors and warnings
   into HTTP headers of the form "X-Error-NNNNN: ...", so they can't
   disturb page output or make XML documents invalid. This allows to
   turn on complete error_reporting() without any functionality loss
   due to premature output.
   You of course need a good Web browser that can easily display all
   response headers then for developing.
*/

set_error_handler("ewiki_http_header_errors");
ini_set("html_errors", 0);

function ewiki_http_header_errors($errno, $msg, $file, $line, $lvars) {

   static $error_types = array(
      E_PARSE => "PARSE ERROR",
      E_ERROR => "ERROR",
      E_WARNING => "WARNING",
      E_NOTICE => "NOTICE",
      E_STRICT => "STRICT",
      E_USER_ERROR => "USER ERROR",
      E_USER_WARNING => "USER WARNING",
      E_USER_NOTICE => "USER NOTICE",
   );
   ($errtype = $error_types[$errno]) or ($errtype = "UNDEF ERROR");
   
   #-- check for @ and disabled errors
   $emask = get_cfg_var("error_reporting");
   if (! ($emask & $errno)) {
      return;
   }

   #-- output
   $msg = strtr($msg, "\r\n\t\f", "    ");
   $msg = "$errtype: $msg in $file, line #$line";
   if (headers_sent()) {
      print "\n<!--<div class=\"php-error\">$msg</div>-->\n";
   }
   else {
      $no = crc32($msg);
      $no = ($no & 0xFFFF) ^ ($no >> 16);
      header("X-Error-$no: $msg");
      if ($errno == E_FATAL) { header("Status: 500 Something bad happened"); }
   }
}

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































Deleted contrib/http.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
<?php
/*
  api: PHP
  type: functions
  category: library
  priority: optional
  provides: http-request
  title: HTTP requests
  description: implements HTTP protocol, various request methods supported
  url: http://freshmeat.net/p/upgradephp
  version: 11.3

   This snippet implements HTTP queries, and allows for most request
   methods, content types and encodings. It is useful for contacting
   scripts made to serve HTML forms.
    - does neither depend upon wget or curl, nor any other extension
    - you can add ->$params (form variables) on the fly, it's a hash
    - if the initial URL contains a query string, the vars will be
      extracted first
    - set the ->$enc very carefully, because many CGI apps and HTTP
      servers can't deal with it (else "gzip" and "deflate" are nice)
    - there are abbreviations for the content ->$type values (namely
      "form" , "url" and "php")
    - user:password@ pairs may be included in the initially given URL
    - headers always get normalized to "Studly-Caps"
    - won't support keep-alive connections
    - for PUT and other methods, the ->$params var may just hold the
      request body
    - files can be added to the ->params array as hash with specially
      named fields: "content"/"data", and "filename"/"name" , "type"
    - you can add authentication information using the standard notation
      "http://user:passw@www.example.com/..." for ->$url and ->$proxy

   A response object will have a ->$content field, ->$headers[] and
   ->len, ->type attributes as well. You could also ->decode() the
   body, if it is app/vnd.php.serialized or app/x-www-form-urlencoded.
   
   Public Domain (use freely, transform into any other license, like
   LGPL, BSD, MPL, ...; but if you change this into GPL please be so
   kind and leave your users a hint where to find the free version).
*/


#-- request objects
class http_request {

   var $method = "GET";
   var $proto = "HTTP/1.1";
   var $url = "";
   var $params = array();   // URL/form post vars, or single request body str
   var $headers = array();
   var $cookies = array();
   var $type = "url";       // content-type, abbrv. for x-www-form-...
   var $enc = false;        // "gzip" or "deflate"
   var $error="", $io_err=0, $io_err_s="";
   var $active_client = 1;  // enables redirect-following
   var $redirects = 3;
   var $proxy = false;      // set to "http://host:NN/"
   var $timeout = 15;


   #-- constructor
   function http_request($method="GET", $url="", $params=NULL) {
      $this->headers["User-Agent"] = "http_query/17.2 {$GLOBALS[ewiki_config][ua]}";
      $this->headers["Accept"] = "text/html, application/xml;q=0.9, text/xml;q=0.7, xml/*;q=0.6, text/plain;q=0.5, text/*;q=0.1, image/png;q=0.8, image/*;q=0.4, */*+xml;q=0.3; application/x-msword;q=0.001, */*;q=0.075";
      $this->headers["Accept-Language"] = "en, eo, es;q=0.2, fr;q=0.1, nl;q=0.1, de;q=0.1";
      $this->headers["Accept-Charset"] = "iso-8859-1, utf-8";
      $this->headers["Accept-Feature"] = "textonly, tables, !tcpa, !javascript, !activex, !graphic";
      $this->headers["Accept-Encoding"] = "deflate, gzip, compress, x-gzip, x-bzip2";
      //$this->headers["Referer"] = '$google';
      $this->headers["TE"] = "identity, chunked, binary, base64";
      $this->headers["Connection"] = "close";
      //$this->headers["Content-Type"] = & $this->type;
      if (isset($params)) {
         $this->params = $params;
      }
      if (strpos($method, "://")) {
         $url = $method;  # glue for incompat PEAR::Http_Request
         $method = "GET";
      }
      $this->method($method);
      $this->setURL($url);
   }


   #-- sets request method
   function method($str = "GET") {
      $this->method = $str;
   }

   #-- special headers
   function setcookie($str="name=value", $add="") {
      $this->cookies[strtok($str,"=")] = strtok("\000").$add;
   }


   #-- deciphers URL into server+path and query string
   function setURL($url) {
      if ($this->method == "GET") {
         $this->url = strtok($url, "?");
         if ($uu = strtok("\000")) {
            $this->setQueryString($uu);
         }
      }
      else {
         $this->url = $url;
      }
   }
   
   
   #-- decodes a query strings vars into the $params hash
   function setQueryString($qs) {
      $qs = ltrim($qs, "?");
      parse_str($qs, $this->params);
   }


   #-- returns params as querystring for GET requests
   function getQueryString() {
      $qs = "";
      if (function_exists("http_build_query")) {
         $qs = http_build_query($this->params);
      }
      else {
         foreach ($this->params as $n=>$v) {
            $qs .= "&" . urlencode($n) . "=" . urlencode($v);
         }
         $qs = substr($qs, 1);
      }
      return($qs);
   }


   #-- transforms $params into request body
   function pack(&$path) {
      $m = strtoupper($this->method);

      #-- GET, HEAD
      if (($m == "GET") || ($m == "HEAD")) {
         $BODY = "";
         $path .= (strpos($path, "?") ? "&" : "?") . $this->getQueryString();
      }

      #-- POST
      elseif (($m == "POST") && is_array($this->params)) {

         #-- known encoding types
         $type = $this->type($this->type, 0);
         if ($type == "url") {
            $BODY = $this->getQueryString($prep="");
         }
         elseif ($type == "php") {
            $BODY = serialize($this->params);
         }
         elseif ($type == "form") {
            // boundary doesn't need checking, unique enough
            $bnd = "snip-".dechex(time())."-".md5(serialize($this->params))
                 . "-".dechex(rand())."-snap";
            $BODY = "";
            foreach ($this->params as $i=>$v) {
               $ct = "text/plain";
               $inj = "";
               if (is_array($v)) {
                  ($ct = $v["ct"].$v["type"].$v["content-type"]) || ($ct = "application/octet-stream");
                  $inj = ' filename="' . urlencode($v["name"].$v["file"].$v["filename"]) . '"';
                  $v = $v["data"].$v["content"].$v["body"];
               }
               $BODY .= "--$bnd\015\012"
                     . "Content-Disposition: form-data; name=\"".urlencode($i)."\"$inj\015\012"
                     . "Content-Type: $ct\015\012"
                     . "Content-Length: " . strlen($v) . "\015\012"
                     . "\015\012$v\015\012";
            }
            $BODY .= "--$bnd--\015\012";
            $ct = $this->type("form") . "; boundary=$bnd";
         }
         #-- ignore
         else {
            $this->error = "unsupported POST encoding";
          // return(false);
            $BODY = & $this->params;
         }

         $this->headers["Content-Type"] = isset($ct) ? $ct : $this->type($type, 1);
      }

      #-- PUT, POST, PUSH, P*
      elseif ($m[0] == "P") {
         $BODY = & $this->$params;
      }

      #-- ERROR (but don't complain)
      else {
         $this->error = "unsupported request method '{$this->method}'";
       //  return(false);
         $BODY = & $this->params;
      }

      return($BODY);
   }


   #-- converts content-type strings from/to shortened nick
   function type($str, $long=1) {
      $trans = array(
         "form" => "multipart/form-data",
         "url" => "application/x-www-form-urlencoded",
         "php" => "application/vnd.php.serialized",
      );
      $trans["multi"] = &$trans["form"];
      if ($long) {
         $new = $trans[$str];
      }
      else {
         $new = array_search($str, $trans);
      }
      return( $new ? $new : $str );
   }


   #-- initiate the configured HTTP request ------------------------------
   function go($force=0, $asis=0) {

      #-- prepare parts
      $url = $this->prepare_url();
      if (!$url && !$force) { return; }
      $BODY = $this->body($url);
      if (($BODY===false) && !$force) { return; }
      $HEAD = $this->head($url);

      #-- open socket
      if (!$this->connect($url)) {
         return;
      }

      #-- send request data
      fwrite($this->socket, $HEAD);
      fwrite($this->socket, $BODY);
      $HEAD = false;
      $BODY = false;

      #-- read response, end connection
      while (!feof($this->socket) && (strlen($DATA) <= 1<<22)) {
         $DATA .= fread($this->socket, 32<<10);
#echo "fread(".strlen($DATA).") ";
      }
      fclose($this->socket);
      unset($this->socket);

      #-- for raw http pings
      if ($asis) { 
         return($DATA);
      }

      #-- decode response
      $r = new http_response();
      $r->from($DATA);        // should auto-unset $DATA

      #-- handle redirects
      if ($this->active_client) {
         $this->auto_actions($r);
      }

      #-- fin      
      return($r);
   }

   #-- alias
   function start($a=0, $b=0) { 
      return $this->go($a, $b);
   }
   
   
   #-- creates socket connection
   function connect(&$url) {
      if ((isset($this->socket) and !feof($this->socket))
      or ($this->socket = fsockopen($url["host"], $url["port"], $this->io_err, $this->io_err_s, $this->timeout))) {
         socket_set_blocking($this->socket, true);
         socket_set_timeout($this->socket, $this->timeout, 555);
         return(true);
      }
      else {
         $this->error = "no socket/connection";
         return(false);
      }
   }


   #-- separate URL into pieces, prepare special headers
   function prepare_url() {
      $this->setURL($this->url);
      if (!$this->proxy) {
         $url = parse_url($this->url);
         if (strtolower($url["scheme"]) != "http") {
            $this->error = "unsupported protocol/scheme";
            return(false);
         }
         if (!$url["host"]) { return; }
         if (!$url["port"]) { $url["port"] = 80; }
         if (!$url["path"]) { $url["path"] = "/"; }
         if ($url["query"]) { $url["path"] .= "?" . $url["query"]; }
         $proxy = "";
      }
      else {
         $url = parse_url($this->proxy);
         $url["path"] = $this->url;
         $proxy = "Proxy-";
         $this->headers["Proxy-Connection"] = $this->headers["Connection"];
      }

      #-- inj auth headers
      if ($url["user"] || $url["pass"]) {
         $this->headers[$proxy."Authorization"] = "Basic " . base64_encode("$url[user]:$url[pass]");
      }
      
      return($url);
   }


   #-- generates request body (if any), must be called before ->head()
   function body(&$url) {

      #-- encoding of variable $params as request body (according to reqmethod)
      $BODY = $this->pack($url["path"]);
      if ($BODY === false) {
         return false;
      }
      elseif ($len = strlen($BODY)) {
         $this->headers["Content-Length"] = $len;
      }
      $enc_funcs = array("gzip"=>"gzencode", "deflate"=>"gzinflate", "bzip2"=>"bzcompress", "x-bzip2"=>"bzcompress", "compress"=>"gzcompress");
      if ((strlen($BODY) >= 1024) && ($f = $enc_funcs[$this->enc]) && function_exists($f)) {
         $BODY = $f($BODY);
         $this->headers["Content-Encoding"] = $this->enc;
         $this->headers["Content-Length"] = strlen($BODY);
      }
      return($BODY);
   }


   #-- generates request head part
   function head(&$url) {
   
      #-- inject cookie header (if any)
      if ($this->cookies) {
         $c = "";
         foreach ($this->cookies as $i=>$v) {
            $c .= "; " . urlencode($i) . "=" . urlencode($v);
         }
         $this->headers["Cookie"] = substr($c, 2);
         $this->headers["Cookie2"] = '$Version="1"';
      }
      
      #-- request head
      $CRLF = "\015\012";
      $HEAD  = "{$this->method} {$url[path]} {$this->proto}$CRLF";
      $HEAD .= "Host: {$url[host]}$CRLF";
      foreach ($this->headers as $h=>$v) {
         $HEAD .= trim($h) . ": " . strtr(trim($v), "\n", " ") . $CRLF;
      }
      $HEAD .= $CRLF;
      return($HEAD);
   }

   #-- perform some things automatically (redirects)
   function auto_actions(&$r) {

      #-- behaviour table
      static $bhv = array(
         "failure" => "204,300,304,305,306",
         "clean_::POST" => "300,301,302,303,307",
         "clean_::PUT" => "300,301,302,303,307",
         "clean_::GET" => "300",  // $params:=undef
         "GET_::POST" => "303",
         "GET_::PUT" => "303",    // downgrade $method:=GET
      );
   
      #-- failure
      if (strstr($this->behaviour_table["failure"], $r->status)) {
         return;
      }

      #-- HTTP redirects
      if (($pri_url=$r->headers["Location"]) || ($pri_url=$r->headers["Uri"])) {

         if ((($this->redirects--) >= 0) && ($r->status >= 300) && ($r->status < 400)) {
            $m = strtoupper($this->method);
            if (strstr($this->behaviour_table["clean_::$m"], $r->status)) {
               unset($this->params);
            }
            if (strstr($this->behaviour_table["GET_::$m"], $r->status)) {
               $this->method("GET");
            }
            $this->setURL($pri_url);
            $this->go();
         }
      }
   }
   
   #-- aliases for compatiblity to PEAR::HTTP_Request
   function sendRequest() {
      return $this->go();
   }
   function setBasicAuth($user, $pw) {
      $this->url = preg_replace("#//(.+?@)?#", "//$user@$pw", $this->url);
   }
   function setMethod($m) {
      $this->method($m);
   }
   function setProxy($host, $port=8080, $user="", $pw="") {
      $auth = ($pw ? "$user:$pw@" : ($user ? "$user@" : ""));
      $this->proxy = "http://$auth$server:$port";
   }
   function addHeader($h, $v) {
      $this->headers[$h] = $v;
   }
   function getResponseStatus() {
      $this->headers[$h] = $v;
   }
}
class http_query extends http_request {
   /* this is just an alias */
}




#-- every query result will be encoded in such an object --------------------
class http_response {

   var $status = 520;
   var $status_str = "";
   var $headers_str = "";
   var $headers = array();
   var $len = 0;
   var $type = "message/x-raw";
   var $content = "";
   
   
   function http_response() {
   }
   

   #-- fill object from given HTTP response BLOB   
   function from(&$SRC) {
      $this->breakHeaders($SRC);  // split data into body + headers
      $SRC = false;
      $this->decodeHeaders();     // normalize header names
      $this->headerMeta();
      $this->decodeTransferEncodings();    // chunked
      $this->decodeContentEncodings();     // gzip, deflate
      $this->len = strlen($this->content);
   }


   #-- separates headers block from response body part
   function breakHeaders(&$DATA) {
      $l = strpos($DATA, "\012\015\012"); $skip = 3;
      $r = strpos($DATA, "\012\012");
      if ($r && ($r<$l)) { $l = $r; $skip = 2; }
      if (!$l) { $l = strlen($DATA); }
      $this->headers_str = rtrim(substr($DATA, 0, $l), "\015");
      $this->content = substr($DATA, $l + $skip);
      $this->body = & $this->content;
      $this->data = & $this->content;  // aliases
      $this->ct = & $this->type;
   }


   #-- splits up the $headers_str into an array and normalizes header names
   function decodeHeaders() {

      #-- normalize linebreaks
      $str = & $this->headers_str;
//      $str = str_replace("\n ", " ", $str);
      $str = str_replace("\r", "", $str);
      
      #-- strip headline
      $nl = strpos($str, "\n") + 1;
      $this->proto = strtok(substr($str, 0, $nl), " ");
      $this->status = (int) strtok(" ");
      $this->status_str = strtok("\000\r\n");
      if ($this->status == 100) {
         $this->full_duplex = 1;
      }

      #-- go through lines, split name:value pairs
      foreach (explode("\n", substr($str, $nl)) as $line) {

         $i = trim(strtok($line, ":"));
         $v = trim(strtok("\000"));

         #-- normalize name look&feel
         $i = strtr(ucwords(strtolower(strtr($i, "-", " "))), " ", "-");

         #-- add to, if key exists
         if (!empty($this->headers[$i])) {
            $this->headers[$i] .= ", ".$v;
         }
         else {
            $this->headers[$i] = $v;
         }

      }
   }


   #-- extract interesting values
   function headerMeta() {
      $this->len = strlen($this->content);
      $this->type = trim(strtok(strtolower($this->headers["Content-Type"]), ";"));
   }
   

   #-- strip any content transformation
   function decodeTransferEncodings() {
      $enc = trim(strtok(strtolower($this->headers["Transfer-Encoding"]), ",;"));
      if ($enc) {
         switch ($enc) {
#echo "ENC($enc) ";
            case "chunked":
               $this->decodeChunkedEncoding();
               break;
            case "base64":
               $this->content = base64_decode($this->content);
               $this->len = strlen($this->content);
               break;
            case "identity": case "binary":
            case "7bit": case "8bit":
               break;
            default:
               trigger_error("http_response::decodeTransferEncodings: unkown TE of '$enc'\n", E_WARNING);
         }
      }
   }


   #-- scripts on HTTP/1.1 servers may send fragmented response
   function decodeChunkedEncoding() {

      $data = "";	# decoded data
      $p = 0;		# current string position
#file_put_contents("/tmp/1", $this->content);

      while ($p < strlen($this->content)) {
         #-- read len token
         $n = strtok(substr($this->content, $p, 20), "\n");
#echo "CHUNK($p,$n) ";
         $p += strlen($n)+1;
#echo "CHUNK2($p,$n) ";

         #-- make integer
         $n = hexdec(trim($n));
         if ($n===0) {
            break;
         }
         elseif (!$n) {
            break; //WARN
         }
         $n += 1;

         #-- read data
         $data .= substr($this->content, $p, $n);
         $p += $n + 1;
#echo "CHUNK3($p,$n) ";
      }

      $this->content = $data;
      unset($data);
      $this->len = strlen($this->content);
   }


   #-- uncompress response body
   function decodeContentEncodings() {
      $enc = trim(strtok(strtolower($this->headers["Content-Encoding"]), ";,"));
      $dat = &$this->content;
      if ($enc == "deflate") {
         $dat = gzinflate($dat);
      }
      elseif (($enc == "gzip") || ($enc == "x-gzip")) {
         if (function_exists("gzdecode")) {
            $dat = gzdecode($dat);
         }
         else {
            $dat = gzinflate(substr($dat, 10, strlen($dat)-18));
         }
      }
      elseif ($enc == "compress") {
         $dat = gzuncompress($dat);
      }
      elseif (($enc == "x-bzip2") || ($enc == "bzip2")) {
         if (function_exists("bzdecompress")) {
            $dat = bzdecompress($dat);
         }
         else trigger_error("http_response::decodeContentEncoding: bzip2 decoding isn't supported with this PHP interpreter version", E_WARNING);
      }
      $this->len = strlen($this->content);
   }


   #-- can handle special content-types (multipart, serialized, form-data)
   function decode() {
      $t = http_request::type($this->type, 0);
      if ($t == "php") {
         return(unserialize($this->content));
      }
      elseif ($t == "url") {
         parse_str($this->content, $r);
         return($r);
      }
      elseif ($t == "form") {
         // oh, not yet exactly
      }
   }

   #-- aliases for compatiblity to PEAR::HTTP_Request
   function getResponseBody() {
      return $this->content;
   }
   function getResponseStatus() {
      return $this->status;
   }
   function getResponseCode() {
      return $this->status;
   }
   function getResponseHeader($i=NULL) {
      if (!isset($i)) {
         return $this->headers;
      }
      $i = strtolower($i);
      foreach ($this->headers as $h=>$v) {
         if (strtolower($h)==$i) {
            return $v;
         }
      }
   }
}



?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted contrib/http.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

Note: This class and file will be renamed into "xhttp..." in the near
feature, to prevent clashes with the old PEAR class.

http.php

This script provides the easy to use "http_request" class ("http_query"
is an alias). You can contact forms or simply retrieve files with it.
Unlike fopen_wrappers, you get the response headers alongside and the
received file will be decompressed on-the-fly (it should also be faster
due to more supported compression methods).

There are some options, you can set before starting the request. Most
important aspect is, that you can add form ->params[] one after the
other for GET and POST requests. You can also use a proxy or include
authentication passwords in the initially given url, and of course
inject or override a few ->headers[] when it makes sense.



usage

It is really easy, you only must take care to always give the method
parameter before the URL ("GET" or "POST" in most cases), look at
the following:

  <?example

      #-- prepare
      $query = new http_request("GET", "http://example.com/form.php");
      $query->params["q"] = "search-this-...";

      #-- do request
      $result = $query->go();

      #-- use result
      if ($result && ($result->status == 200)) {
         echo $result->content;
      }
  ?>

Note, that we could have included the "q" parameter simply appended to
the URL in such simple cases ("http://example.com/form.php?q=search-...").

You can also do "POST" requests (normal for forms), but that you than
must decide about the encoding format. There are two for POST requests,
the default is always urlencoding (like with GET requests) with
  <?example 
      $query->type = "url";    // corresponds to "app/x-www-form-urlencoded"
  ?>
but many bigger forms however require the MIME type for form-data:
  <?example 
      $query->type = "form";    // translates to "multipart/form-data"
  ?>
You see, there are easy to remember abbreviations for this.

The form variables you want to transport are simply appended to the URL
for GETs or "url"-coded requests, but you could use the $query->params[]
array also here.

If you do a "POST" request, you do likewise; or you could also just assign
the $query->params a string blob to transfer as content (if the remote app
can deal with it or expects that, or you already have encoded eveything
into a valid form request).
If you just want to add upload-files to a "POST" request, then do this as
follows:
  <?example
      $query->params["fileformname"] = array(
         "filename" => "original-name.zip",
         "type" => "application/octet-stream",
         "content" => "$READ_FROM_FILE_DATA...",
      );
  // or
      $query->params["2nd_file"] = array(
         "ct" => "x.ml/my-format",
         "name" => "../../where/is/it/from.txt",
         "data" => file_get_contents(".../from.txt"),
      );
  ?>
"body" is a third alias for the "content" field here. If you don't set
the "type" or "ct" flag it will get "application/octet-stream" per default
(this is a good default). You could simply load the "ext/mime" script to
have the best possible MIME type here.



     start an request
     
     Use the ->go() method to start a prepared HTTP request. The only
     alias existing today is ->start(); simply derive or edit this class
     to add your preferred name for this likewise (->do() cannot be used
     as it is a PHP reserved word, sorry ;)

     There are two options to ->go(), the first $force will override a few
     problems, and with the second ($asis) set to 1 or true, you won't get
     a result object, but the plain HTTP response blob (headers and response
     body as one large string variable).



     authentication
     
     If the remote site requires authentification, you would simply give
     this within the URL:
      <?example
         $query = new http_request("GET", "http://user:passw@example.com/...");
           // or later:
         $query->setURL("http://username:pw2@server.../")
           // or even:
         $query->url = "http://name:password@localhost/form.php";
      ?>



     proxy
     
     You can also acccess a form or remote file using a proxy server easily,
     just follow this:
      <?example
         $query = new http_request("PUT", "...");
         $query->proxy = "http://servername.proxy.org:3219/";
           // ...
         $result = $query->go();
      ?>
     You could also give a password or username for your proxy server, if
     you need it (works the same as for above).




reponses

The $result value from the above examples should normally be an object,
it will be a scalar (false) only if something went really wrong.

It will have at least a ->status field, which is typically 200 for
succeeded requests. Everything above 500 means an server error, values
above 400 a transport and request error (= we did something wrong) and
a 300 response status means a redirection was issued.

For fulfilled requests you can access the returned file/data simply as
"$result->content" or "$result->body" or even "$result->data" (two aliases
again).

You will also have a "$result->headers[]" array, which will hold all
response HTTP headers in normalized form. Typically this means:
  <?example
      echo $result->headers["Content-Type"] . "\n";
      echo $result->headers["Date"] . "\n";
      echo $result->headers["Last-Modified"] . "\n";
      echo $result->headers["Content-Length"] . "\n";
      echo $result->headers["Etag"] . "\n";    // (beware of the lcased "t" !)
      echo $result->headers["Content-Encoding"] . "\n";
      ...
      print_r($result->headers);  // much better here ;)
  ?>
[[ Elsewhere the field names would be completely lowercased or fully
uppercase, we have CamelCase here, with the hyphens still in of course. ]]

Please note, that a known "Content-Encoding" was already removed from the
received ->content. And there is also a more correct "$result->len" and a
"$result->type" shorthand.

A few response types are understand as application data, and in this case
you can call the $result->decode() function and get a PHP variable/array
from the body.



     redirects
     
     If you expect HTTP redirects (->status codes from 300 till 375), then
     the default settings are ok for you, many will automatically be catched
     and the form data or file request will succeed at the replied URL.

     To tack/catch these cases yourself, simply disable that behaviour with:
      <?example
         $query->active_client = 0;
      ?>



PHP-RPC

Not yet!  But this is probably what it will look like:

  If you control both ends of the Wire, you shouldn't use the slow and
  buggy (not everything works with everything else) XML-RPC protocol for
  calling remote functions, but instead use the high speed PHP serialize
  encoding to transfer data.

  The "http_request" class can natively encode values as such. The MIME
  type "application/vnd.php.serialized" has been registered explicitely
  for this purpose (as alternative to "multipart/form-data" encoding,
  and it is type-safe as opposed to the "/x-www-form-urlencoded" format).
  Perl and JS implementations exist (probably also one for Python), so
  plattform-independence should be given.

  PHP-RPC shall inherit (not yet negotiated) some structure from the old
  XML-RPC protocol. That is, a few names are identical. If you start an
  request you would therefore do following:

<?php

    function phprpc($server, $function, $args=array()) {

       #-- init
       $query = new http_request("POST", $server);

       #-- set content
       $query->type = "php";  // here corresponds to "app/vnd.php.serialized"
       $query->params
         = array(
              "method" => $function,
              "params" => $args,
           );

       #-- start
       $result = $query->go();
       if ($result && ($result->status == 200)) {

          $r = $result->decode();
          if ($good = $r["result"]) {
             return($good);
          }
          return($r);
       }
    }
?>

  You of course need a server part to make use of this. Simply try the
  "ext/phprequest", in which case you would do the following:

<?php

   include("ext/phprequest.php")
   if (count($_POST) && ($method = $_POST["method"])
   and ($params = $_POST["params"]))
   {
      #-- call known/registered functions
      $method = strtolower($method);
      if ($method == "my.func") {
         $r = call_user_func_array("my_func", $params);
      }
      elseif ($method == "system.time") {
         $r = time();
      }
      elseif ($method == "sytem.listmethods") {
         $r = get_defined_functions();
         $r = $r["user"];
      }

      #-- if succeeded
      if ($r) { 
         header("Content-Type: application/vnd.php.serialized");
         header("Content-Encoding: deflate");
         $r = array("result" => $r);
         die(gzdeflate(serialize($r));
      }
   }

   #-- your normal script can go on here
   //...
?>

  You can inject this into anywhere as it only engages, if a PHP-RPC
  request was detected. 



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































































































































































































































































































































































































































































Deleted contrib/phprequest.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
/*
   Allows http "POST" and "PUSH" requests with a Content-Type of
   "application/vnd.php.serialized". This isn't used in the wild.
*/

if (empty($_POST)
and (strtoupper($_SERVER["REQUEST_METHOD"][0]) == "P")
and (strtolower(trim(strtok($_SERVER["CONTENT_TYPE"], ";,(")))
     == "application/vnd.php.serialized"))   
{
   #-- search for bare request body
   if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
      $_POST = $GLOBALS["HTTP_RAW_POST_DATA"];
   }
   else {
      $f = fopen("php://input", "rb");
      $_POST = fread($f, 1<<22);
      fclose($f);
   }

   #-- uncompress and decode, if something found
   if ($_POST) {

      #-- strip known/supported encodings
      $enc = trim(strtok(strtolower($_SERVER["HTTP_CONTENT_ENCODING"]), ",;"));
      if ($enc == "deflate") {
         $_POST = gzinflate($_POST);
      }
      elseif ($enc == "compress") {
         $_POST = gzuncompress($_POST);
      }
      elseif ($enc == "gzip") {
         $_POST = function_exists("gzdecode") ? gzdecode($_POST) : gzinflate(substr($_POST, 10, strlen($_POST) - 18));
      }
      elseif (($enc == "x-bzip2") or ($enc == "bzip2")) {
         $_POST = function_exists("bzdecompress") ? bzdecompress($_POST) : NULL;
      }

      #-- decipher
      if ($_POST) {
         $_POST = unserialize($_POST);
      }
      #-- merge
      if ($_POST) {
         $_REQUEST = array_merge($_REQUEST, $_POST);
      }

   }
}

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































Deleted contrib/xmlrpc.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
<?php define("XMLRPC_VERSION", "0.3.10");
# api: PHP
# type: api
# provides: rpc, xml-rpc
# version: 0.3.10
# category: library
# priority: optional
# title: XML-RPC client and server
# description: serves remote procedure calls
# homepage: http://freshmeat.net/p/upgradephp
#
#  Supports XML-RPC (text/xml) and XML+RPC (application/rpc+xml) compressed,
#  and can be used as client or server interface. Works without XMLRPC and
#  XML extensions, but utilizes them for optimal speed whenever available.
#
#   XXXX   XXXX MMM     MMM LLL              RRRRRRR   PPPPPPP    CCCCCCC
#    XXXX XXXX  MMMM   MMMM LLL      +++     RRRRRRRR  PPPPPPPP  CCCCCCCCC
#     XXXXXXX   MMMMM MMMMM LLL      +++     RRR   RRR PPP   PPP CCC    CCC
#      XXXXX    MMMMMMMMMMM LLL  +++++++++++ RRR   RRR PPP   PPP CCC
#       XXX     MMM MMM MMM LLL  +++++++++++ RRRRRRRR  PPPPPPPP  CCC
#      XXXXX    MMM  M  MMM LLL      +++     RRRRRRR   PPPPPPP   CCC
#     XXXXXXX   MMM     MMM LLL      +++     RRR  RRR  PPP       CCC    CCC
#    XXXX XXXX  MMM     MMM LLLLLLL          RRR   RRR PPP       CCCCCCCCC
#   XXXX   XXXX MMM     MMM LLLLLLL          RRR   RRR PPP        CCCCCCC
#
#  This is Public Domain. (c) 2004 WhoEver wants to. [milky*erphesfurtde]


#-- config
define("XMLRPC_PLUS", 0);        # use XML+RPC per default
define("XMLRPC_AUTO_TYPES", 0);  # detect base64+datetime strings and automatically generate the according xmlrpc object representations then
define("XMLRPC_AUTO_UTF8", 1);   # de/convert anything from and to UTF-8 automatically - if yourscripts use Latin1 natively, but the RPC server expects/sends UTF-8
define("XMLRPC_CHARSET", "utf-8");  # used in responses and requests
define("XMLRPC_AUTODISCOVERY", 0);  # "connections" automatically create methods
define("XMLRPC_FAST", 1);        # use PHPs XML-RPC extension where possible
define("XMLRPC_OO", 1);          # return XML-RPC/HTTP errors as objects
define("XMLRPC_DEBUG", 0);       # output error hints, write /tmp dumps - set this to 1, 2 or 3

#-- _server() settings
define("XMLRPC_LOG", "/tmp/xmlrpc.".@$_SERVER["SERVER_NAME"].".log");

#-- general data
#  (don't change the following, most are auto-configured values)
define("XMLRPC_UA", "xml+rpc/".XMLRPC_VERSION." (PHP/".PHP_VERSION."; ".PHP_OS.")");
define("XMLRPC_MIME_NEW", "application/rpc+xml");
define("XMLRPC_MIME_OLD", "text/xml");
define("XMLRPC_MIME", XMLRPC_MIME_OLD);
define("XMLRPC_ACCEPT", XMLRPC_MIME_NEW.", ".XMLRPC_MIME_OLD."; q=0.5");
define("XMLRPC_EPI", function_exists("xmlrpc_decode_request"));

#-- init
error_reporting(0);
if (isset($_SERVER["HTTP_CONTENT_TYPE"]) && empty($_SERVER["CONTENT_TYPE"])) {
   $_SERVER["CONTENT_TYPE"] = $_SERVER["HTTP_CONTENT_TYPE"];   // older CGI implementations
}




############################################################################
#                                                                          #
#  client part                                                             #
#                                                                          #
############################################################################


#-- Issue a request, call can take any number of arguments.
#     $result = xmlrpc("http://example.com/RPC2/", "method1", $arg1 ...);
#     $result = xmlrpc("xml+rpc://here.org/RPC3/", "ns.function", ...);
#   Results automatically have <datetime> values converted into Unix
#   timestamps and <base64> unpacked into strings.
#
function xmlrpc($server, $method=NULL /*, ... */) {
   if ($method) {
      $params = func_get_args();
      shift($params); shift($params);
      return
        xmlrpc_request($server, $method, $params);
   }
   else {
      return
        new xmlrpc_connection($server);
   }
}



#--  Generate and send request, decode response.
function xmlrpc_request($url, $method, $params=array(), $plus=XMLRPC_PLUS, $gzip=0) {
   global $xmlrpc_response_headers, $xmlrpc_error;
   
   #-- init whole lib for request (we are not-OO here)
   $xmlrpc_error = false;
   $xmlrpc_response_headers = array();
   
   #-- encapsulate req, transmit it
   $socket = xmlrpc_request_send($url, $method, $params, $plus, $gzip);
   if (!$socket) {
      return xmlrpc_error(-32768, "no connection", 0, "GLOBALVARS");
   }

   #-- wait for, read response
   $response = "";
   while (!feof($socket) && (strlen($DATA) <= 768<<10)) {
      $response .= fread($socket, 4<<10);
   }
   fclose($socket);
   if (XMLRPC_DEBUG >= 3) {
      echo "<code>$response</code>";
   }

   #-- decode answer and give results
   return xmlrpc_response_decode($response);
}


#-- an alias
function xmlrpc_call($url, $method, $params=array(), $plus=XMLRPC_PLUS, $gzip=0) {
   return xmlrpc_request($url, $method, $params, $plus, $gzip);
}



#-- marshall request parameters into array, hash, xml string
function xmlrpc_request_send($url, $method, &$params, $plus, $gzip, $blocking=true) {

   #-- get connection data
   $c = parse_url($url);
   ($host = $c["host"]);
   ($port = @$c["port"]) or ($port = 80);
   ($path = $c["path"]) or ($path = "/");
   if (strpos($c["scheme"], "+")) {
      $plus++;
   }
   if (strpos($c["scheme"], "gzip")) {
      $gzip++;
   }
   if (!$host) { return(NULL); }
   $inj = "";
   if ($str = $c["user"]) {
      if ($c["pass"]) { $str .= ":" . $c["pass"]; }
      $inj = "Authorization: Basic " . base64_encode($str) . "\n";
   }
   
   #-- mk request HTTP+XML block from params
   $request = xmlrpc_request_marshall($method, $params);
   $request = xmlrpc_request_http($request, $path, $host, $plus, $gzip, $inj);

   #-- connect, send request
   if ($socket = fsockopen($host, $port, $io_err, $io_err_s, 30)) {
      socket_set_blocking($socket, $blocking);
      socket_set_timeout($socket, 17, 555);
   }
   else {
      echo "Could not connect to '<b>$host</b>:$port$path' - error $io_err: $io_err_s.<br>\n";
      return(NULL);
   }
   fputs($socket, $request);

   #-- done here
   return($socket);
}


#-- marshall function call into XML+HTTP string
function xmlrpc_request_marshall($method, &$params) {

   #-- use xmlrpc-epi
   if (XMLRPC_FAST && XMLRPC_EPI) {
      $query = xmlrpc_encode_request($method, $params);
      return($query);
   }

   #-- build query
   $query = array(
      "methodCall" => array(
         "methodName" => array( ",0"=>$method ),
         "params" => array()
      )
   );
   foreach ($params as $i=>$p) {
      $query["methodCall"]["params"]["param,$i"] = xmlrpc_compact_value($p);
   }
   $query = array2xml($query, 1, 'encoding="'.XMLRPC_CHARSET.'" ');

   #-- encode?
   if (XMLRPC_AUTO_UTF8) {
      $query = utf8_encode($query);
   }
   
   return($query);   
}


#-- enclose body into HTTP request string
function xmlrpc_request_http(&$query, $path, $host, $plus, $gzip, $inj_header="") {

   #-- build request
   $n = "\015\012";
   $request = "POST $path HTTP/1.0$n"
            . "Host: $host$n"
            . ($inj_header ? str_replace("\n", $n, $inj_header) : "")
            . "User-Agent: " . XMLRPC_UA . "$n"
            . "Accept: ".XMLRPC_ACCEPT."$n"
            . (!XMLRPC_DEBUG ? "Accept-Encoding: deflate$n" : "")
            . "Content-Type: ".($plus ? XMLRPC_MIME_NEW : XMLRPC_MIME_OLD)
                              ."; charset=".XMLRPC_CHARSET."$n";

   #-- compress?
   if ($gzip) {
      $query = gzdeflate($query);
      $request .= "Content-Encoding: deflate$n";
   }
   $request .= "Content-Length: " . strlen($query) . "$n" . "$n";
   $request .= $query . "$n";

   return($request);
}


#-- unpack response from HTTP and XML representation
function xmlrpc_response_decode(&$response) {
   global $xmlrpc_response_headers;

   #-- split into headers and content
   $l1 = strpos($response, "\n\n");
   $l2 = strpos($response, "\n\r\n");
   if ($l2 && (!$l1 || ($l2<$l1))) {
      $head = substr($response, 0, $l2);
      $response = substr($response, $l2+3);
   }
   else {
      $head = substr($response, 0, $l1);
      $response = substr($response, $l2+2);
   }

   #-- decode headers, decompress body
   foreach (explode("\n", $head) as $line) {
      $xmlrpc_response_headers[strtolower(trim(strtok($line, ":")))] = trim(strtok("\000"));
   }
   if ($enc = trim(@$xmlrpc_response_headers["content-encoding"])) {
      if (($enc == "gzip") || ($enc == "x-gzip")) {
         $response = gzinflate(substr($response, 10, strlen($response)-18));
      }
      elseif (($enc == "compress") || ($enc == "x-compress")) {
         $response = gzuncompress($response);
      }
      elseif (($enc == "deflate") || ($enc == "x-deflate")) {
         $response = gzinflate($response);
      }
   }

   $r = xmlrpc_response_unmarshall($response);
   if (XMLRPC_DEBUG) {var_dump($r);}
   return($r);
}


#-- decode XML-RPC from string into array and extract its actual meaning
function xmlrpc_response_unmarshall(&$response) {
   global $xmlrpc_response_headers;

   #-- strip encoding
   if (XMLRPC_AUTO_UTF8) {
      xmlrpc_decode_utf8xml($response, @$xmlrpc_response_headers["content-type"].@$xmlrpc_response_headers["content-charset"]);
   }

   if (XMLRPC_DEBUG >= 4) { fwrite(fopen("/tmp/xmlrpc:resp_in_xml","w"), $response); }
   
   #-- use xmlrpc-epi
   if (XMLRPC_FAST && XMLRPC_EPI) {
      $r = xmlrpc_decode_request($response, $uu);
      xmlrpc_epi_decode_xtypes($r);
      if (is_array($r) && (count($r)==2) && isset($r["faultCode"]) && isset($r["faultString"])) {
         return xmlrpc_error($r["faultCode"], $r["faultString"], 1, "GLOBALVARS");
      }
      else {
         return($r);
      }
   }


   #-- unmarshall XML
   $response = xml2array($response);

   #-- fetch content (one returned element)
   if ($r = @$response["methodResponse,0"]["params,0"]["param,0"]["value,0"]) {
      $r = xmlrpc_decode_value($r);
      return($r);
   }
  
   #-- error cases
   #  (we should rather return an error object here)
   if (($r = @$response["methodResponse,0"]["fault,0"]["value,0"]) && ($r = xmlrpc_decode_value($r))) { 
      return xmlrpc_error($r["faultCode"], $r["faultString"], 1, "GLOBALVARS");
   }
   else {
      return xmlrpc_error(-32600, "xml+rpc: invalid response", 0, "GLBLVRS");
   }
   return(NULL);
}



#-- Establish a virtual XML+RPC or XML-RPC server connection (a pseudo
#   handshake is used to determine supported protocol / extensions).
class xmlrpc_connection {

   #-- init
   function xmlrpc_connection($url, $autodiscovery=0) {
      global $xmlrpc_response_headers;
      $this->server = $url;
      $this->plus = 0;
      $this->gzip = 0;

      #-- handshake to check supported protocol
      $funcs = $this->call("system.getVersion");
      $this->plus = (strpos($xmlrpc_response_headers["accept"], XMLRPC_MIME_NEW) !== false);
      $this->gzip = (strpos($xmlrpc_response_headers["accept_encoding"], "deflate") !== false);
      
      #-- auto-discovery, create 'method' names
      if ($funcs && (XMLRPC_AUTODISCOVERY || $autodiscovery)) {
         foreach ($funcs as $fn) {
            $short = $fn;
            if ($l = strpos($fn, ".")) {
               $short = substr($fn, $l + 1);
               if (substr($fn, 0, $l) == "system") { continue; }
            }
            $this->short = create_function("", "return xmlrpc_request('{$this->server}','$fn',func_get_args(),{$this->plus},{$this->gzip});");
         }
      }
   }
   
   #-- generical call (needs func name)
   function call($method /*, ... */) {
      $params = func_get_args();
      shift($params);
      $r = xmlrpc_request($this->serverm, $method, $params, $this->plus, $this->gzip);
      return($r);
   }
}

#-- an alias
class xmlrpc extends xmlrpc_connection {
}




############################################################################
#                                                                          #
#  server implementation                                                   #
#                                                                          #
############################################################################


#-- Check request and execute function if registered in $xmlrpc_methods[]
#   array.
function xmlrpc_server() {

   global $xmlrpc_methods;

   #-- server is active
   define("XMLRPC_SERVER", getmypid());
   if (XMLRPC_DEBUG) { error_reporting(E_ALL^E_NOTICE); }
   ob_start();

   #-- standard reply headers
   header("Accept: ".XMLRPC_MIME_NEW.", ".XMLRPC_MIME_OLD."; q=0.5");
   header("Accept-Encoding: deflate");
   header("X-Server: " . XMLRPC_UA);
   header("Connection: close");
   header("Cache-Control: private");

   #-- fixes for PHP/Apache
   if (function_exists("getallheaders")) {
      foreach (getallheaders() as $i=>$v) {
         $_SERVER[strtoupper(strtr("HTTP_$i", "-", "_"))] = $v;
      }
   }

   #-- check and get call
   $allowed = array(
      "REQUEST_METHOD" => array("POST", "PUT", "CALL"),
      "CONTENT_TYPE" => array(XMLRPC_MIME_NEW, XMLRPC_MIME_OLD),
   );
   foreach ($allowed as $WHAT=>$WHICH) {
      if (!in_array(trim(strtok($WRONG=$_SERVER[$WHAT], ";,(")), $WHICH)) {
         header("Status: 400 Go Away, Stupid!");
         if (!$WRONG) {
            $WRONG = "undefined";
         }
         die("<h2>Error</h2>Your request was bogus, <b>$WHAT</b> must be <i>"
             . implode("</i> or <i>", $WHICH) . "</i>, but yours was '<tt>$WRONG</tt>'.\n");
      }
   }
   if (!($xml_request = xmlrpc_fetch_post_chunk())) {
      header("Status: 500 How Sad");
      die("<h2>Error</h2>Could not fetch POST data.\n");
   }

   #-- decipher incoming XML request string
   $method = "";
   if (XMLRPC_FAST && XMLRPC_EPI) {
      $params = xmlrpc_decode_request($xml_request, $method);
      xmlrpc_epi_decode_xtypes($params);
   }
   else {
      $params = xmlrpc_request_unmarshall($xml_request, $method);
   }

   
   #-- add the few system.methods()
   //if (empty($xmlrpc_methods)) {
   //   $xmlrpc_methods = get_defined_functions();
   //}
   $xmlrpc_methods["system"] = "xmlrpc_system_methods";   # a class

   #-- call
   $result = xmlrpc_exec_method($method, $params);

   #-- send back result
   if (isset($result)) {
      if (isset($result)) {
         $resp["methodResponse"]["params"]["param"] = xmlrpc_compact_value($result);
      }
      else {
         $resp["methodResponse"]["params"] = array();
      }

      xmlrpc_send_response($resp);
   }
   else {
      $result = xmlrpc_error(0, "No Result");
      xmlrpc_send_response($result);
   }
}



#-- decode <methodCall> XML string into understandable chunks,
#   gives $params as return value and $method name via pass-by-ref
function xmlrpc_request_unmarshall(&$xml_request, &$method) {

   #-- mangle charset
   if (XMLRPC_AUTO_UTF8) {
      xmlrpc_decode_utf8xml($xml_request, $_SERVER["CONTENT_TYPE"].$_SERVER["HTTP_CONTENT_CHARSET"]);
   }

   #-- decode XML string into PHP arrays
   $call = xml2array($xml_request, 1);
   $xml_request = NULL;

   $call = $call["methodCall,0"];
   if (!$call) {
      xmlrpc_send_response(xmlrpc_error(-32600, "Bad Request, <methodCall> missing"));
   }
   $method = $call["methodName,0"][",0"];
   if (!$method) {
      xmlrpc_send_response(xmlrpc_error(-32600, "Bad Request, <methodName> missing"));
   } 

   $params = array();
   foreach ($call["params,1"] as $uu => $param) {
      $params[] = xmlrpc_decode_value($param["value,0"]);
   }

   return($params);
}



#-- Call the requested method (using the XML-method to PHP-function mapping
#   table and hints).
function xmlrpc_exec_method($method, $params) {

   global $xmlrpc_methods;
   if (XMLRPC_DEBUG >= 2) { error_reporting(E_ALL^E_NOTICE); }

   #-- check if allowed call
   $rf = strtr($method, ".", "_");
   $cl = strtok($method, ".");
   if (!$xmlrpc_methods[$method] && !$xmlrpc_methods[$cl]
      && !in_array($method, $xmlrpc_methods)
      && !in_array($rf, $xmlrpc_methods) && !in_array($cl, $xmlrpc_methods) )
   {
      xmlrpc_send_response(xmlrpc_error(-32601));
   }

   #-- real function call
   if ($php_func_name = $xmlrpc_methods[$method]) {
      $rf = $method = $php_func_name;
   }
   if (function_exists($rf)) {
      $result = call_user_func_array($rf, $params);
      if (XMLRPC_DEBUG >= 4) { fwrite(fopen("/tmp/xmlrpc:func_call_res","w"),serialize(array($rf,$result,$params))); }
      return($result);
   }
   #-- PHP object method calls
   else {
      $class = strtok($method, ".");
      $method = strtok("\000");
      if ($uu = $xmlrpc_methods[$class]) {
         $class = $uu;
      }
      if ($class && class_exists($class) && $method) {
         $obj = new $class;
         if (method_exists($obj, $method)) {
            $result = call_user_method_array($method, $obj, $params);  //<DEPRECATED>
            return($result);
         }
      }
   }

   #-- else error
   xmlrpc_send_response(xmlrpc_error(-32601));
}



#-- Get POST data from PHP (if it gives it to us).
function xmlrpc_fetch_post_chunk() {
   global $HTTP_RAW_POST_DATA;

   $data = false;
   if ($f = fopen("php://input", "rb")) {
      $data = fread($f, 0x0100000);
      fclose($f);
   }
   if (empty($data)) {
      ini_set("always_populate_raw_post_data", "true");  // well, maybe(!?)
      $data = $HTTP_RAW_POST_DATA;
      $HTTP_RAW_POST_DATA = "";
   }
   $enc = trim(strtolower($_SERVER["HTTP_CONTENT_ENCODING"]));
   $funcs = array("deflate"=>"gzinflate", "gzip"=>"gzdecode", "compress"=>"gzuncompress", "x-gzip"=>"gzdecode", "x-bzip2"=>"bzuncompress");
   if ($enc && ($pf = $funcs[$enc]) && function_exists($pf)) {
      $data = $pf($data);
   }
   return($data);
}


#-- converts UTF-8 documents into Latin-1 ones
function xmlrpc_decode_utf8xml(&$xml, $ct) {
   if (strpos(strtolower($ct), "utf-8") or preg_match('/<\?xml[^>]+encoding=["\']utf-8/i', $xml)) {
      $xml = utf8_decode($xml);
      $xml = preg_replace('/(<\?xml[^>]+encoding=["\'])utf-8(["\'])/i', '$1iso-8859-1$2', $xml, 1);
   }
}



#-- Creates an error object.
function xmlrpc_error($no=-32500, $str="", $type=1, $into_vars=0) {
   global $xmlrpc_error, $xmlrpc_errorcode;
   $errors = array(
           0 => "No Result",
      -32300 => "Transport error",
      -32400 => "Internal Server Error",
      -32500 => "Application error",
      -32600 => "Invalid message format / Bad request",
      -32601 => "Method does not exist",
      -32602 => "Parameter type mismatch",
      -32603 => "Internal XML-RPC error",
      -32604 => "Too many parameters",
      -32700 => "Not well-formed XML",
      -32701 => "Unsupported encoding - only ISO-8859-1 and UTF-8 capable",
      -32702 => "Invalid characters, encoding mismatch",
   );
   #-- build response xml/array
   if (!($str) && !($str = $errors[$no])) {
      $str = "Unknown Error";
   }
   if ($into_vars && !XMLRPC_OO) {
      $xmlrpc_error = $str;
      $xmlrpc_errorcode = $no;
      return(NULL);
   }
   else {
      return new xmlrpc_error($no, $str, $type);
   }
}


#-- error object
class xmlrpc_error {

   var $type = 1;   // else an HTTP error
   var $no;
   var $str;
   
   function xmlrpc_error($no, $str, $type=1) {
      $this->type = $type;
      $this->no = $no;
      $this->str = $str;
   }
   
   function send() {
      $error = xmlrpc_compact_value(array(
         "faultCode" => $no,
         "faultString" => $str,
      ));
      $resp = array(
         "methodResponse" => array(
            "fault" => $error
         )
      );
      xmlrpc_send_response($resp);
   }
}


#-- Sends a response.
function xmlrpc_send_response($r) {

   #-- error objects send itself (by calling _send_response() again ;-)
   if (is_object($r)) {
      $r->send();
   }

   #-- answer XML-RPC and XML+RPC requests
   $ct = trim(strtok(strtolower($_SERVER["CONTENT_TYPE"]), ";,("));  // from original request
   $cs = XMLRPC_CHARSET;
   header("Content-Type: $ct; charset=\"$cs\"");
   
   #-- make XML document from it
   if (is_array($r)) {
      $r = array2xml($r, 1, 'encoding="'.$cs.'" ');
   }

   #-- compress answer?
   if (!headers_sent()) {
      $enc = trim(strtolower($_SERVER["HTTP_ACCEPT_ENCODING"]));
      $funcs = array("deflate"=>"gzdeflate", "gzip"=>"gzencode", "compress"=>"gzcompress", "x-gzip"=>"gzencode", "x-bzip2"=>"bzcompress");
      if ($enc && ($pf = $funcs[$enc]) && function_exists($pf)) {
         header("Content-Encoding: $enc");
         $r = $pf($r);
      }
   }

   #-- send
   if (ob_get_level()) {
      #-- this prevents that PHP errors appear as garbage in our response
      $add .= "<!--\n" . ob_get_contents() . "\n-->";
      ob_end_clean();
   }
   header("Content-Length: " . strlen($r));
   print $r . $add;
   die;
}



#-- Provides "system.*" method namespace.
class xmlrpc_system_methods {

   function listMethods() {
      global $xmlrpc_methods;
      $r = array();
      foreach ($xmlrpc_methods as $i=>$i2) {
         $real = is_int($i) ? $i2 : $i;
         if (class_exists($real) && ($i2=$real) || class_exists($i2)) {
            foreach (get_class_methods($i2) as $add) {
               $r[] = $real.".".$add;
            }
         }
         else {
            $r[] = $real;
         }
      }
      return($r);
   }

   function time() {
      return new xmlrpc_datetime(time());
   }
}


############################################################################
#                                                                          #
#  misc functions                                                          #
#                                                                          #
############################################################################


function xmlrpc_log($message) {
}

function xmlrpc_die($error="", $str="") {
}



############################################################################
#                                                                          #
#  data representation mangling                                            #
#                                                                          #
############################################################################


#-- Makes compact-array2xml datavar from a PHP variable.
function xmlrpc_compact_value($var, $n=0) {

   #-- create compact-array2xml tree
   $root = array(
      "value,$n" => array(),
   );
   $r = &$root["value,$n"];

   #-- detect PHP values to be complex types in XML-RPC
   if (XMLRPC_AUTO_TYPES && is_string($var)) {
      if ((strlen($var) >= 64) && preg_match('/^[\w]+=*$/', $var)) {
         $var = new xmlrpc_base64($var);
      }
      elseif ((strlen($var)==17) && ($var[8]=="T") && preg_match('/^\d{8}T\d\d:\d\d:\d\d$/', $var)) {
         $var = new xmlrpc_datetime($var);
      }
   }

   #-- complex types
   if (is_object($var)) {
      $r = $var->out();
   }
   #-- arrays and hashes(structs)
   elseif (is_array($var)) {
      if (isset($var[0]) || empty($var)) {
         $r = array("array,$n" => array("data,0" => array()));
         $r = &$r["array,$n"]["data,0"];
         foreach ($var as $n=>$val) {
            $r = array_merge($r, xmlrpc_compact_value($val, $n));
         }
      }
      else {
         $r = array("struct,$n"=>array());
         $r = &$r["struct,$n"];
         $n = 0;
         foreach ($var as $i=>$val) {
            $r["member,$n"] = array_merge(array(
               "name,0" => array(",0" => "$i"),
            ), xmlrpc_compact_value($val, 1));
            $n++;
         }
      }
   }
   #-- simple types
   elseif (is_bool($var)) {
      $r = array(
         "boolean,$n" => array(",0" => ($var?1:0)),
      );
   }
   elseif (is_int($var)) {
      $r = array(
         "int,$n" => array(",0" => $var),
      );
   }
   elseif (is_float($var)) {
      $r = array(
         "double,$n" => array(",0" => $var),
      );
   }
   elseif (is_string($var)) {
      $r = array(
         "string,$n" => array(",0" => $var),
      );
   }
   return($root);
}


#-- Makes a PHP array from a compact-xml2array representation. $value must
#   always be the xml2array elements _below_ the ["value,0"] or ["data,0"]
#   or ["member,N"] entry.
function xmlrpc_decode_value($value) {
   $val = NULL;
   foreach ($value as $i=>$d) {

      #-- use single (text) content xml2array entry as actual $d var
      if (is_array($d) && isset($d[",0"])) {
         $d = $d[",0"];
      }

      #-- convert into PHP var based on type
      $type = strtok($i, ",");
      switch ($type) {

         case "array":
            $val = array();
            foreach ($d["data,0"] as $i=>$value) {
               $val[] = xmlrpc_decode_value($value);
            }
            break;

         case "struct":
            $val = array();
            foreach ($d as $uu=>$d2) {
               if (($in=$d2["name,0"][",0"]) && ($pos2=1) || ($in=$d2["name,1"][",0"]) && ($pos2=0)) {
                  $val[$in] = xmlrpc_decode_value($d2["value,$pos2"]);
               }
            }
            break;

         case "":    # handles also '<value>s</value>' instead
         case "0":   # of '<value><string>s</string></value>'
         case "string":
            $val =  is_array($d) ? "" : (string)$d;
            break;

         case "base64":
            $val = (XMLRPC_AUTO_TYPES>=2) ? base64_decode($d) : (string)$d;
            if ((XMLRPC_AUTO_UTF8 >= 2) && ($uu = utf8_decode($val))) {
               $val = $uu;
            }
            break;
            
      // case "real":  case "float":   // neither is allowed
         case "double":
            $val = (double)$d;
            break;
         case "i4":
         case "int":
            $val = (int)$d;
            break;

         case "boolean":
            $val = (boolean)$d;
            break;

         case "dateTime.iso8601":
            $val = xmlrpc_strtotime($d);
            break;

         default:
            if (defined("XMLRPC_SERVER")) {
               xmlrpc_send_response(xmlrpc_error(-32600, "Unknown data type '$type'"));
            }
            else {
               echo $xmlrpc_error = "UNKNOWN XML-RPC DATA TYPE '$type'<br>\n";
               $xmlrpc_errorcode = -32207;
            }
#           echo "<!-- UNKNOWN TYPE $type -->\n";
#           xmlrpc_log("bad data type '$type' enountered");
      }
   }
   return($val);
}


#-- More complex XML-RPC data types need object representation to
#   distinguish them from ordinary string and integer vars.
class xmlrpc_xtype {
   var $scalar = "";
   var $xmlrpc_type = "string";
   var $tag = "string";
   function xmlrpc_type($str) {
      $this->data = $str;
   }
   function out() {
      return array($this->tag.",0" => array(",0"=>$this->scalar));
   }
}
class xmlrpc_base64 extends xmlrpc_xtype {
   function xmlrpc_base64($str) {
      $this->tag = "base64";
      $this->xmlrpc_type = "base64";
      if (XMLRPC_AUTO_UTF8 >= 2) {
         $str = utf8_encode($str);
      }
      if (!preg_match("/^[=\w\s]+$/", $str)) {
         $this->encode=1;
      }
      $this->scalar = $str;
   }
   function out() {
      if (isset($this->encode)) {
         $this->scalar = chunk_split(base64_encode($this->scalar), 74, "\n");
      }
      return xmlrpc_xtype::out();
   }
}
class xmlrpc_datetime extends xmlrpc_xtype {
   function xmlrpc_datetime($t) {
      $this->tag = "dateTime.iso8601";
      $this->xmlrpc_type = "datetime";
      if (($t > 0) && ($t[8] != "T")) {
         $this->timestamp = $t;
         $t = xmlrpc_timetostr($t);
      }
      $this->scalar = $t;
   }
}

#-- Further simplify use of the above ones.
function xmlrpc_base64($string) {
   return(new xmlrpc_base64($string));
}
function xmlrpc_datetime($timestr) {
   return(new xmlrpc_datetime($timestr));
}


#-- Deciphers ISO datetime string into UNIX timestamp.
function xmlrpc_strtotime($str) {
   $tm = explode(":", substr($str, 9));
   $t = mktime($tm[0], $tm[1], $tm[2], substr($str, 4, 2), substr($str, 6, 2), substr($str, 0, 4));
   return($t);
}
function xmlrpc_timetostr($time) {
   return(gmstrftime("%Y%m%dT%T", $time));
}


#-- helping hand for the xmlrpc-epi extension of php
function xmlrpc_epi_decode_xtypes(&$r) {
   if (is_object($r) && isset($r->xmlrpc_type)) {
      if (isset($r->timestamp)) {
         $r = $r->timestamp;
      }
      else {
         $r = $r->scalar;
      }
   }
   elseif (is_array($r)) {
      foreach ($r as $i=>$v) {
         xmlrpc_epi_decode_xtypes($r[$i]);
      }
   }
}




############################################################################
#                                                                          #
#  simplified XML parser                                                   #
#                                                                          #
############################################################################


#-- Encode the two chars & and < into htmlentities (there is nothing said
#   about the possible other entities in the XML-RPC spec).
function xml_entities($str) {
   $e = array(
      "&" => "&amp;",
      "<" => "&lt;",
//      ">" => "&gt;",
   );
   return(strtr($str, $e));
}
function xml_decode_entities($str) {
   $e = array(
      "&lt;" => "<",
      "&gt;" => ">",
      "&apos;" => "'",
      "&quot;" => '"',
      "&amp;" => "&",
   );
   if (strpos($e, "&#") !== false) {
      $e = preg_replace('/&#(\d+);/e', 'chr($1)', $e);
      $e = preg_replace('/&#x([\da-fA-F]+);/e', 'chr(hexdec("$1"))', $e);
   }
   return(strtr($str, $e));
}


#-- Can split simplified XML into a PHP array structure. The now used
#   'compact' format will yield tag sub arrays with an "*,0" index and
#   just [",0"] for text nodes.
function xml2array($xml, $compact="ALWAYS") {
   $r = array();
   if (function_exists("xml_parser_create") && (strlen($xml) >= 512)) {
      $r = xml2array_php($xml);
   }
   else {
      xml2array_parse($xml, $r, $compact);
   }
   return($r);
}


#-- Recursively builds an array of the chunks fetched via strtok() from
#   the original XML input string.
function xml2array_parse(&$string, &$r, $compact=1) {
   $n = 0;
   do {
      #-- split chunks
      $l = strpos($string, "<");
      $p = strpos($string, ">", $l);
      $text = $attr=$close = $tag = false;
      if ($l === false) {
         $text = $string;
         $string = false;
      }
      else {
         $tag = strtok(substr($string, $l+1, $p-$l-1), " ");
         if ((strncmp($tag, "![CDATA[", 8)==0) && ($p = strpos($string, "]]>", $l))) {
            $text = substr($string, $l+9, $p-$l-9);
         }
         else {
            if ($l) {
               $text = xml_decode_entities(substr($string, 0, $l));
            }
            $attr = strtok("\000");
            $close = $attr && ($attr[strlen($attr)-1]=="/");
            $string = substr($string, $p+1);
         }
      }
      #-- insert text/body content into array
      if (trim($text)) {
#         if ($compact) {
             $r[",$n"] = $text;
#         }
#         else {
#            $r[] = $text;
#         }
         $n++;
      }
      #-- recurse for tags
      if ($tag && ($tag[0] >= 'A')) {    #-- don't read <? <! </ pseudo-tags
#         if ($compact) {
             $r["$tag,$n"] = array();
             $new = &$r["$tag,$n"];
#         } else {
#            $r[] = array($tag => array());
#            $new = &$r[count($r)-1][$tag];
#         }
         if (!$close) {
            xml2array_parse($string, $new, $compact);
         }
         $n++;
      }
      #-- stop if no more tags or content
      if (empty($tag) && empty($text) || empty($string)) {
         $tag = "/";
      }
   } while ($tag[0] != "/");
}


#-- Uses the XML extension of PHP to convert an XML stream into the
#   compact array representation.
function xml2array_php(&$xml, $compact=1) {

   $p = xml_parser_create(xml_which_charset($xml));
   xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, false);
   xml_parser_set_option($p, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");

   xml_parse_into_struct($p, $xml, $struct);

   $a = array();  // will hold all tag nodes
   $tree = array(&$a);  // stack of pointers to last node of any tree level
   $in = &$a;           // pointer to last created node

   foreach ($struct as $t) {
      unset($value);
      extract($t);

      $depth = count($tree) - 1;
      $in = &$tree[$depth];
      $tag .= "," . count($in);
//echo "#$depth, TAG=\"$tag\", TYP=$type, LEV=$level, VAL=$value\n";

      switch ($type[1]) {

         #--  OpEN
         case "p":
            $in[$tag] = array();
            if ($type=="open") {
               $tree[] = &$in[$tag];
            }
            if (isset($value) && trim($value)) {
               $in[$tag][",0"] = $value;
            }
            break;

         #--  CoMPLETE
         case "o":
            $in[$tag] = array();
            if (isset($value) && trim($value)) {
               $in[$tag][",0"] = $value;
            }
            break;

         #--  ClOSE
         case "l":
            array_pop($tree);
            break;

         #--  CdATA - usually just whitespace
         case "d":
            if (isset($value) && trim($value)) {
               $in[",".count($in)] = $value;
            }
            break;
         
         default:
            // case "attribute":
            // and anything else we do not want
      }
      
   }
   
   return($a);
}



function xml_which_charset(&$xml) {
   return( strpos(strtok($xml, "\n"), '-8859-1"') ? "iso-8859-1" : "utf-8" );
}



############################################################################
#                                                                          #
#  simplified XML creator                                                  #
#                                                                          #
############################################################################


#-- This is the opposite of the above xml2array, and can also work with the
#   so called $compact format.
function array2xml($r, $compact=1, $ins="") {
   $string = "<?xml version=\"1.0\" $ins?>";
   array2xml_push($string, $r, $compact);
   return($string);
}


#-- Recursively throws out the XMLified tree generated by the xml2array()
#   'parser' function.
function array2xml_push(&$string, &$r, $compact, $ind=-1) {
   $old_ind = ++$ind - 1;
   if ($old_ind < 0) { $old_ind = 0; }
   foreach ($r as $i=>$d) {
      $d = &$r[$i];
      if (is_scalar($d)) {
         $string .= xml_entities($d);
      }
      elseif (is_array($d)) {
         if ($compact) {
            $i = strtok($i, ","); 
         }
         $ls = str_repeat(" ", $ind);
         $string .= "\n$ls<$i>";
         $string .=  array2xml_push($string, $d, $compact, $ind);
         $ls = str_repeat(" ", $old_ind);
         $string .= "</$i>\n$ls";
      }
   }
}




?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted contrib/xmlrpc.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

XML-RPC is a "standard" (well, not yet exactly) for accessing remotely
provided 'Web services'. More exactly it is just a complicated encoding
standard for calling functions and procedures on a remote Web server
(and getting its calculation or data request results of course).

It is still in wide use for many interesting features like accessing
database content, searching, data conversion, and so on. It started as
a lightweight alternative to SOAP, which currently is more on the rise.
While SOAP is much more bloated, also XML-RPC is not the quickest RPC
format available, is not really standards-compliant (bogus specs over
the time), and so has probably only a limited lifetime now.
Therefore you should try to provide your services and access others`
via vanilla HTTP requests (form or url encoding), when possible; use
the "http.php" class for this.

(There is also a faster PHP-RPC standard on the rise, which provides
type-safe data transport over compressed and fast connections, without
the encoding overhead and charset issues when using XML-RPC.)



xmlrpc.php

The 'xmlrpc.php' script implements the XML-RPC spec., but adds a few
extensions, namely use of the (yet unregistered) "application/rpc+xml"
MIME type and compressed HTTP transportation. It uses a builtin stupid
XML parser (for the highly simplified XML-RPC message content) and thus
is totally independent of any PHP extensions. It of course takes
advantage of the XML extension where present (a lot faster), and it even
can make use of Epinions XML-RPC extension for PHP (really fast than).

It is mostly not object-oriented, but extremely easy to use for building
XML-RPC servers or calling remote procedures.


configuration

There are a few constants and variables that the 'xmlrpc.php' script
respects.

XMLRPC_PLUS
   If set to 1 enables use of the "application/rpc+xml" MIME type and
   request compression per default (for server and client). In 2004
   still not the recommended setting.

XMLRPC_AUTO_TYPES
   Allows the request encoder to automatically determine the <base64>
   and <dateTime.iso8061> types, even if you just used them as scalar PHP
   values. Otherwise you had to use 'new xmlrpc_base64("STrinG==")' and
   'new xmlrpc_datetime("20001020T00:00:00")' to prepare such values.

XMLRPC_AUTO_UTF8
   Takes care of transforming the complete RPC messages into/from UTF-8,
   what is useful if your scripts deal only with Latin1 and always expect
   this. <base64> are also de/encoded if you set this constant to 2.

XMLRPC_CHARSET
   The whole script is currently optimized to produce UTF-8 and decode
   requests from/into Latin-1 for your scripts.

XMLRPC_FAST
   Enables use of Epinions XML-RPC extension module for PHP automatically
   where available. You only want to disable this for debugging purposes.

XMLRPC_OO
   Engages error result objects, else you had to use the two global vars
   "$xmlrpc_error" and "$xmlrpc_errorstr" to detect such cases. If you
   enable it you must however compare all xmlrpc_request() result values
   against being an object (what does not happen for succeeded XML-RPC
   requests).

XMLRPC_AUTODISCOVERY
   If you create a "xmlrpc" or "xmlrpc_connection" object and this is
   enabled, you would get the object with function names of the
   automatically instantiated methods of the remotely provided service
   wrapped into one object (not yet), much like in the Python library
   for xmlrpc.

XMLRPC_LOG
   Creates a log file for incoming requests to the _server() part of xmlrpc
   (whenerver you activate it with the _server() call).


There are also a few automatically defined values, which you shouldn't
care about:

XMLRPC_MIME
   Contains the currently selected default MIME type for transport.
XMLRPC_MIME_NEW
   Contains the newer MIME type value. Do not change.
XMLRPC_MIME_OLD
   For compatibility with older XML-RPC clients and servers. Do not change.
XMLRPC_ACCEPT
   Again the MIME Types wrapped into a HTTP Accept: header for requests
   and responses.
XMLRPC_EPI
   Tells if the Epinions extension is available.


server configuration

$xmlrpc_methods[]
   Every accessible method (for remote calls) must be defined here, for
   use with the xmlrpc_server(). There is a separate section on this one.


making xmlrpc() requests

You can call a remote procedure by just using the short xmlrpc() call
syntax:

  $result = xmlrpc("http://example.com/rpc.php", "the.function", 1, 2, 3);

Where 1, 2 and 3 would be parameters to "the.function" on the remote server.
The number of parameters is not limited, and you do not need to give one at
all (if the remote procedure does not require them. The parameter values
are automatically encoded into XML-RPC representations except for <base64>
and <dateTime.iso8061> ones, for which you needed to create objects first.
The $result of course recieved in ordinary PHP representation of the remote
functions result value.


       xmlrpc_request()
       
       Is basically the same as calling the xmlrpc() function, but that
       all parameters given to the remote function are now to be passed
       as array in the third parameter:

         $params = array(  "param1", "param2", "param3"  );
         $r = xmlrpc_request("server.com:80", "remoteMethod", $params);

       Also a fourth parameter to xmlrpc_request (boolean) says if to
       use the old XML-RPC or the faster XML+RPC interface. But beware,
       that this could fail if you connect to an older server.


       xmlrpc_connection
       
       You can also establish a 'connection' (this is purely virtual) to
       a remote XML-RPC server, using a xmlrpc_connection object as follows:

         $xc = new xmlrpc_connection("http://example.com/rpc.php");

       Then you could regularily call remote functions on that server:

         $result1 = $xc->call("function1");
         $result2 = $xc->call("function2", 2, $result1, 0x5F02);

       The xmlrpc_connection automatically chooses XML+RPC if available
       with the remote server.


       data types
       
       Unless XMLRPC_AUTO_TYPES was enabled (discouraged, because this is
       considered 'unreliable type guessing') you need to explicetely mark
       parameters passed to the xmlrpc() or xmlrpc_request() calls for
       their later XML-RPC type.

       To do so, you have the two class types 'xmlrpc_datetime' and
       'xmlrpc_base64' availabe. Use them as follows:

          $param1 = new xmlrpc_base64(  base64_encode($string1)  );
          $p2 = new xmlrpc_datetime(  time() + 60*60*24*7  );
          $r = xmlrpc("www.server.com/rpc/", "function1", $param1, $p2);

       Please note, that you needed to call base64_encode() yourself, and
       that the _datetime() can also use standard Unix timestamps as input.

       The XML-RPC <dateTime.iso8601> entites are, btw, automatically
       converted into Unix timestamps, if returned as result from xmlrpc()
       and xmlrpc_request() calls. This happens regardless of
       XMLRPC_AUTO_TYPES.

       If XMLRPC_AUTO_TYPES is set to 2, then even <base64> result values
       would be automatically converted into their plain (binary) string
       representation.


       "Bugs"
       
       pass-by-reference is not possible ;)



xmlrpc_server() use

To make a set of functions available for remote calls, you would create
an interface script and make its URL public. Assuming that you had a
subdirectory "./myrpc" on your server, you would likely want to create 
the file "./myrpc/index.php" with following content:

   <?php

      $xmlrpc_methods = array(
         "myFunction",
         "mySecondOne",
      );
 
      include("xmlrpc.php");
      xmlrpc_server();
   ?>

So, by calling the xmlrpc_server() you make all registered functions
($xmlrpc_methods) available with the URL "xml+rpc://example.com/myrpc/" for
remote calls.


       $xmlrpc_methods[]
       
       All function names you list in this array (before calling the
       xmlrpc_server() function) will be available for remote calls. The
       function names are mapped to remote method names by having the
       _ underscore as alias the the . dot, which is commonly used. So a
       function whose name was "tools_register" was available as remotely
       callable method "tools_register" or "tools.register".

       Also with xmlrpc_server() it is possible to register member methods
       of object classes as remotely callable methods. All you needed to
       do is list your class in $xmlrpc_methods[].

       You can also give aliases, both for function names and for object
       classes:

          $xmlrpc_methods["callable.methodname"] = "here_function_name";
          $xmlrpc_methods["section"] = "here_class_name";

       The member methods of a class cannot be aliased however.


       xmlrpc_server()
       
       Just fetches the current request, decodes it and executes the
       destination method (PHP function) if listed in the global
       $xmlrpc_methods[] variable.

       It automatically exits after sending the response or an error. So
       this is the last command in your xmlrpc wrapper script.


       xmlrpc_fetch_post_chunk()
       
       Begs PHP for the complete POST data stream. It only has two options
       to do so and may fail with some Webservers and earlier PHP versions.
       In either case try to set the "always_populate_raw_post_data" option
       in php.ini or from within a .htaccess file.

       To allow the server part to receive the XML-RPC message, you either
       need PHP 4.3 or later, or configure your PHP interpreter specifically
       to pass in the POSTed data stream. In you php.ini ([PHP] section) add:

         always_populate_raw_post_data = 1

       Or following in a .htaccess per-dir configuration
       file for Apache:

         php_option always_populate_raw_post_data=1


       xmlrpc_send_response()
       
       Is called from within xmlrpc_server() to send the response for the
       processed request (also sends error responses).


       xmlrpc_error()
       
       Creates a XML-RPC error result array.



---------------------------------------------------------------------------
internals
---------------------------------------------------------------------------
Unless you are interrested in an in-deep discussion of the "xmlrpc.php"
you should effectively stop reading here.


xmlrpc data representation encoders

This lib uses the simple xml2array() compact format to do the initial work
of converting a XML file into an array representation. Various design
restrictions of the XML-RPC message format then impose certain structures
inside of the xml2array-compact representation, what is taken adavantage of.

For example <struct> entries have in the compact representation sub-elements
like ["member,0"], ["member,1"], ["member,2"] and so on. Each of which then
has two sub elements: ["name,0"] and ["value,1"].

The XML-RPC <array> instead had one ["data,0"] with sub-arrays of
["value,0"], ["value,1"], ["value,2"] and so on, which would be recursively
feed through:


      xmlrpc_decode_value()
      
      Makes a PHP representation of a part (one must start it with the
      content of a ["value,0"]) from a xml2array()-compact representation
      made out of a XML-RPC message.


      xmlrpc_compact_value()
      
      Converts a PHP array or scalar variable into an array suitable for
      transformation into a XML-RPC message string using the array2xml()
      function then.



generic functions

The xml2array() and array2xml() functions are stupid XML parsers and
probably only suitable for XML-RPC messages.


       xml2array()
       
       Can decode a SimplifiedXML document into an array structure - and this
       in two formats. Internall xml+rpc uses only the so called "$compact
       format". If we had a XML document like the following:

       <xml>
         <more> <string> String </string>
         </more>
         <more> <string> String2 </string>
                <int>5</int>
         </more>
       </xml>

       It would return for the $compact=1 format, something like:

       array(
          "xml,0" => array(
             "more,0" => array(
                "string,0" = array(
                   ",0" => " String "
                )
             )
             "more,1" => array(
                "string,0" = array(
                   ",0" => " String2 "
                ),
                "int,1" = array(
                   ",0" => 5
                )
             )
          )
       );

       Where every tagname had a ","+NUMBER suffix, and text nodes would
       start with the comma. The numbers are always counted up in each
       nesting level from 0, regardless if it counted text or tag nodes.

       The not-compact format would hold another subarray to denote a deeper
       level tag node, but leave the text nodes as entries into the ordering
       array level. This was more suitable for XML like files, where you had
       mixed text and tag nodes in a level. For example:

       <html>
          string1
          <b>string2</b>
       </html>

       Would become in the not-compact format:

       array(
          0 => array(
             "html" => array(
                0 => "\n   string1\n   "
                1 => array(
                   "b" => array(
                       0 => "string2",
                   )
             )
          )
       )


       array2xml()
       
       Regenerates a XML stream from an array structure like the one emitted
       by xml2array().


other functions

If you want a different behaviour, you might want to alter one of
the following functions.


      xmlrpc_method_call()
      
      Is responsible in the _server() part for invoking the requested
      function. It does so by using the $xmlrpc_methods[] array as mapping
      to the PHP functions to activate.

      If you would like to have a better mapping support, or even to add
      parameter type and number checking, then this is where you would
      want to start editing the code.


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































































































































































































































































































































































































































































































































































Added doc/README.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490

PHP downwards compatibility functions
-------------------------------------
The "upgrade.php" package implements features and functions from
later PHP versions in pure PHP script and dynamically defines them
at runtime. The emulated functions use exactly the same names as
the originals, and cannot perturb if the native functions exist.

So this is really a drop-in replacement, and allows you to use all
PHP features regardless of the current PHP interpreter. If you just
include() this single script you are freed from wasting time with
backward compatibility problems. Stop omitting certain more useful
PHP functions or retyping workarounds. Your applications remain
"PHP 4.1+ COMPATIBLE" while you in fact use PHP5.2 features.


this is useful:

- for open source distributions
- if your own providers PHP version is immemorial
- you want to test new functions, but not install a new PHP ver
- usage of gettext/bcmath/ftp/... extension would be nice in your
  project, but may not be available on all target web servers
- if some other PHP project has a unmet dependency on your server
- you have a sourceforge.net project homepage ;-)


when it cannot help:

- extended PHP5 object-orientation semantics can't be emulated
- function signatures in newer PHP versions also sometimes change,
  and these cannot be overriden or extended by upgradephp
- doesn't help against amateur providers safe_mode
- compatibility with PHP<4.0 cannot be reached


other things to note:

- as already said, speed won't suffer on up-to-date servers, because
  functions are only emulated/defined if they are missing
- some functions are just simple stubs
- emulated functions are mostly slower than the native would be,
  of course
- not all PHP errors are exactly mimicked,
  -> upgradephp leaves this often to parent functions (e.g. fopen)
  -> and you probably test for errors on the native PHP anyhow
     (no practical need to have that in emulation mode)
- memory shouldn't increase significantly, because if(func_exists)
  "interpretes away" most code 


Remember that native functions will be used whereever available,
this emulation just helps getting scripts run on aging PHP versions.



      PEAR::PHP_Compat
      ----------------
      Alternatively to the "upgradephp" package, you could also give
      the PEAR package "PHP_Compat" (by Aidan Lister & Co.) from
      [http://pear.php.net/] a try. It comes under the LGPL license
      and contains more PHP4.0 emulation (what's not targetted anymore
      in upgrade.php).
      You could even use it in conjunction with upgrade.php

      Note: no code from PHP_Compat has been reused here (this is more
      a license thing, than NIH syndrome).



Usage
-----
Simply include("upgrade.php"); in any of your scripts, if you want
to rely on some PHP4.3 or PHP5.2 functions.

   include("upgrade.php");

You could additionally check the PHP_VERSION, and only include the
emulation wrapper if you depend on features from a certain PHP
interpreter release:

  <?example
     if (PHP_VERSION < "4.4.0") { include(".../upgrade.php"); }
  ?>

Currently following functions can be emulated:
 json_encode
 json_decode
 strptime
 gzdecode
 htmlspecialchars_decode
 fputcsv
 ob_get_headers
 xmlentities
 stripos
 strripos
 str_ireplace
 get_headers
 headers_list
 fprintf
 vfprintf
 str_split
 http_build_query
 convert_uuencode
 convert_uudecode
 scandir
 idate
 time_nanosleep
 strpbrk
 php_real_logo_guid
 php_egg_logo_guid
 get_declared_interfaces
 array_combine
 array_walk_recursive
 substr_compare
 spl_classes
 class_parents
 session_commit
 dns_check_record
 dns_get_mx
 setrawcookie
 file_put_contents
 count_recursive
 file_get_contents
 fnmatch
 glob
 array_key_exists
 array_intersect_assoc
 array_diff_assoc
 html_entity_decode
 str_word_count
 str_shuffle
 get_include_path
 set_include_path
 restore_include_path
 str_rot13
 array_change_key_case
 array_fill
 array_chunk
 md5_file
 is_a
 fmod
 floatval
 is_infinite
 is_nan
 is_finite
 var_export
 strcoll
 diskfreespace
 disktotalspace
 vprintf
 vsprintf
 import_request_variables
 hypot
 log1p
 expm1
 sinh
 cosh
 tanh
 asinh
 acosh
 atanh
 mhash
 mhash_count
 mhash_get_hash_name
 mhash_get_block_size
 array_udiff_uassoc
 array_udiff_assoc
 array_diff_uassoc
 array_udiff
 array_uintersect_uassoc
 array_uintersect_assoc
 array_uintersect
 array_intersect_uassoc
 dc___exec
 bcscale
 bcadd
 bcsub
 bcmul
 bcdiv
 bcmod
 bcpow
 bcpowmod
 bcsqrt
 bccomp
 bc___scaledown
 gettext
 gettext___plural_guess
 ngettext
 dngettext
 dcngettext
 dcgettext
 dgettext
 textdomain
 bindtextdomain
 gettext___load_mo
 gettext___load_po
 bind_textdomain_codeset
 _
 mime_content_type
 image_type_to_mime_type
 image_type_to_extension
 exif_imagetype
 array_filter
 array_map
 is_callable
 array_search
 array_reduce
 is_scalar
 localeconv
 call_user_func_array
 call_user_method_array
 array_sum
 constant
 is_null
 pathinfo
 escapeshellarg
 is_uploaded_file
 move_uploaded_file
 strncasecmp
 wordwrap
 php_uname
 php_sapi_name
 posix_mkfifo
 posix_getcwd
 posix_kill
 posix_uname
 ctype_alnum
 ctype_alpha
 ctype_digit
 ctype_xdigit
 ctype_cntrl
 ctype_space
 ctype_upper
 ctype_lower
 ctype_graph
 ctype_punct
 ctype_print
 odbc_connect
 odbc_pconnect
 odbc_close
 odbc_exec
 odbc_do
 odbc_prepare
 odbc_execute
 odbc_fetch_array
 odbc_fetch_row
 odbc_fetch_object
 odbc_fetch_into
 odbc_free_result
 odbc_next_result
 odbc_num_fields
 odbc_num_rows


Redistribution
--------------
You are encouraged to distribute "upgrade.php" together with
other / your projects. That's also why it was released as Public
Domain (=compatible to ALL open source licenses, including the
GNU GPL and LGPL).

You could load it automatically then using the PHP_VERSION check.
Or simply leave this to your users if they use an older PHP version.
A note often suffices.

Of course you might want to distribute only "upgrade.php" and any
required ext/ module. Just purge the rest (dtools/ and contrib/ or
this README), because they probably make little sense distributed
alongside elsewhere.

It is also safe to extract a few function bodies/definitions out of
upgrade.php to make a shorter version (load only the needed funcs).
But you should keep the "if (function_exists(...))" wrapper code
preferrably.
PHP_Compat however might make a better source, if you seriously need
just one or two functions.


Omissions
---------
A few PHP features are specifically NOT implemented, and so still
had to be taken care of in your scripts:

 predefined STDIN, STDOUT and STDERR constants
 UPLOAD_ERR_* constants (introduced with 4.2, officially 4.3)
 ob_* (eventually possible)
 ini_get_all (ingenious trick in PHP_Compat)

Some of these functions and other esoteric code is implemented
in the ext/ scripts:


ext/
----
The ext/ subdirectory in here provides a few more or less useful
emulations for various PHP extensions or function groups.

 "ext/array" provides a few exotic array diff functions (for
  associative arrays and for using multiple callback functions)

 "ext/exotic" contains some rarely needed functions, which have
  been removed from the main file for that and other reasons

 "ext/bcmath" provides the mathematical functions with arbitrary
  precision on Unix systems, but emulation also works on top of
  GMP or big_int

 "ext/dba" allows you to use scripts written for the dba module,
  if your interpreter only has dbm_*() functions; but only provides
  the minimum functionality

 "ext/ftp" emulates the ftp extension using only the bare socket
  and networking functions (should work anywhere), even has some
  features not found in the original

 "ext/gettext" simulates most of what gettext/libintl provides, and
  seems to read .mo data files correctly - plural support is however
  weak. There is also support for .po files, but since the libintl
  and original gettext functions don't normally read this, that's a
  useless feature (just for fun). You save 2K by ripping it out.

 "ext/mime" simulates the mime_content_type() function, either by
  accessing PECL::fileinfo or reading and evaluating the magic.mime
  database itself (likely slower and a bit unclean of course)

Other snippets in ext/ are probably incomplete or just TODO stubs.


doc/devtools/
-------------
Please run the "updoc" script once to update your PHP manual, if you
are planning to use the upgrade.php script. Create a symlink from your
installed multi-file PHP manual to ease using this and the "doctests"
utility:

 The "dtools/updoc" commandline script updates your local PHP
  documentation to carry hints about emulated functions. It'll simply
  add a small "EMU" on top of the supported functions` description
  pages (in the line typically listing the PHP versions).

 "ckavail.php" was used to check for added functions between
   different PHP interpreter versions, purely a development script.

 "dtools/doctests" greps your local PHP manual for function use
  examples, and executes them with the given PHP interpreter and
  the "upgrade.php" script loaded of course. This way you get live
  tests, but also see:

 "dtools/compact" creates a collapsed version of the upgrade.php
  script (saved into contrib/)



doc/tests*
----------
Contains stupidly short scripts, that have been used to compare
behaviour of the original functions to that of the emulated ones.

The tests now can be run using PEARs RunTest class. (But not all
have been updated or proof-checked.)



ext/contrib/
------------
Holds a few library scripts, that will later be reworked to mimick
other new PHP extensions.

 "contrib/http" can be used to contact Web form scripts, or PHP
  code utilizing "ext/phprequest" more efficiently. It especially
  supports content-coding as per RFC2616 (HTTP standard) for saving
  a lot of bandwidth and getting answers faster.

 "contrib/xmlrpc" likewise can compress output and is used to
  access XML-RPC and IETF XML+RPC Web services. It takes advantage
  of supported XML and EPI-XML-RPC extensions, but runs gracefully
  (not 100% exact XML parser) without. It was also made to provide
  downwards compatibility. Currently you shouldn't run it against
  old and not-HTTP standards-compliant servers and clients (=avoid
  compression unless you use it also as server or client at the
  other side).

 "contrib/hiddenerrors" shows a nice way to hide all disturbing
  error messages from users, but keeping them available for
  development. It is especially useful, when premature _NOTICEs or
  _WARNINGs could garbage (XML or binary) output or if this could
  prevent sending any further/required HTTP headers().

 "contrib/fix.php" fights magic_quotes and register_globals
  (though here it's often better to let users of outdated PHP setups
  run into the open knife, or die() with an error message)

 "contrib/phprequest" enables your PHP interpreter to receive HTTP
  requests with "application/vnd.php.serialized" encoding (even
  compressed) instead of the older "multipart/form-data" and the
  more simple "application/x-www-form-urlencoded" var post formats;
  this is faster and type-safe if you control both ends of the wire;
  see "contrib/README.http" for hints about the upcoming "PHP-RPC"

 "contrib/exceptions" provide a scheme for PHP4-compatible
  exception management using simple wrapper calls and agreements

Please also have a peek into the README files accompaning the script
snippets distributed in this directory.



Other Notes
-----------
 This script doesn't reside in any CVS/SVN reposititory currently
  because it is considered a too minor and small project.

 The project homepage is <http://upgradephp.berlios.de/> but see
  also <http://freshmeat.net/p/upgradephp> for update notifications.



License
-------
Almost all in here is Public Domain. There are no restrictions on how
or where you could use it. You may redistribute it under any license
as you wish, and you don't need to tell anyone where you got it from.
It has absolutely no impact on the rest of YOUR project; you are free
to include it as if you had written it yourself.

You could prepend the license preamble (GNU GPL, LGPL, BSD, MPL, MSFT
EULA, PHP, CDDL, Artistic, ...) of your choice if you want to.

Exceptions are the doc/tests* and doc/runtest scripts. Those are under
the PHP license, taken from PEAR, PECL or PHP.

The "ext/pdo.php" class is from Andrea Giammarchi and under the PHP
License as well. Also check out http://xpdo.org/ - slightly related.


Author
------
The current maintainer can be contacted under <milky*userssfnet>

Please drop me a line, regarding omissions, bugs, contributing a few
bytes...



ChangeLog
---------

v15
  - moved to phpDoc comment style,
    but not all emulated functions carry @param lists
  - tarball directories restructured
  - ext/filter ...
  - json_decode now decodes \uXXXX unicode references
  - include the PDO emulation classes of Andrea Giammarchi (under PHP License)

v14
  - initial comment restructuring
  - added json_encode/decode functions, basic strptime parsing
  - php5.1 functions fputcsv, property_exists, ... and constants
  - added dtools/php-commandline/PhpFunctionCall console script

v13
  - bcmath functions changed to use faster /usr/bin/dc, wrappers for GMP
    fixed and php_big_int.so usage possible
  - gettext_plural0 merged into old code and speed improved

v12
  - strripos() handling of positive offsets was fixed
  - strpbrk() fixed to not return string, if nothing found
  - php_strip_whitespace() and php_check_syntax() moved into ext/exotic
  + ext/bcmath using /usr/bin/bc
  + initial mhash (HMAC) implementation with MD5 and SHA1
  + incomplete ext/odbc
  + ext/exceptions for PHP4
  + extremely fast but incomplete plural form handling in gettext module
  - core script rewritten with more exhaustive comments

v11
  - shortened (whitespace- and comment-free) script was added
  - first gettext emulation version

v10
  (unreleased)

...
  (visit the BerliOS download page and diff it yourself)

v1
  - initial release (non-public)

Added doc/devtools/_dt.

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
#!/bin/sh
# runs the `doctests` utility for a given (param) function,
# simply has some custom pathnames built-in
MAN=/usr/local/doc/php5-doc/
PHP=php412

DIR=$(dirname $(dirname $(realpath $0)))
$DIR/dtools/doctests $PHP $MAN $@

Added doc/devtools/_notdefined.







>
>
>
1
2
3
#!/usr/bin/perl -p

s/^(\s*)(define\("(.+?)".+\);)/$1if (!defined("$3")) { $2 }/;

Added doc/devtools/ckavail.php.













































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?php
/*
   Run this first with an older PHP interpreter, and then with a newer
   version. This way you get a list (once) of added functions (the func
   list is stored in a temporary file).
*/
$DATA_FILE = "/tmp/ckavail.lst";

#-- load previous list
if ($f = @fopen($DATA_FILE, "rb")) {
   $oldl = unserialize(fread($f, 1<<20));
   fclose($f);
}
//echo "OLD=";print_r($oldl);

#-- current func list
$newl = get_defined_stuff();
//echo "NEW=";print_r($newl);

#-- save this one
if ($f = fopen($DATA_FILE, "wb")) {
   fwrite($f, serialize($newl));
   fclose($f);
}
else {
   echo "ERROR(could not save current list)\n";
}

#-- comparison of  current / last run
echo "old(".count($oldl["functions"])."), new(".count($newl["functions"]).")\n";
if ($oldl) {

   #-- funcs
   $new = array_diff($newl["functions"], $oldl["functions"]);
   echo "New functions added between PHP $oldl[version] and current $newl[version] interpreter:\n";
   print_r($new);

   #-- constants
   $new = array_diff(array_keys($newl["constants"]), array_keys($oldl["constants"]));
   echo "\nNewly added constants:\n";
   print_r($new);

   #-- classes
   $new = array_diff($newl["classes"], $oldl["classes"]);
   echo "\nAnd classes:\n";
   print_r($new);

}
else {
   echo "Now start this script a 2nd time with the newer interpreter version.\n";
}


function get_defined_stuff() {
   $rl = array();
   $f = get_defined_functions();
   while ($f["internal"]) {
      $f = $f["internal"];
   }
   $rl["functions"] = $f;
   $c = get_defined_constants();
   $rl["constants"] = $c;
   $c = get_declared_classes();
   $rl["classes"] = $c;
   $rl["version"] = PHP_VERSION;
   return($rl);
}


?>

Added doc/devtools/compact.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh

#
#  creates comment+whitespace free version of upgrade.php script
#

cd `dirname $0`
cd ../..

php -q -w upgrade.php | perl -pe 's/\s*([{}()\[\]=\-\/\$<>+*",;!&|])\s*|\n/$1/gmis;' > upgrade.php.shortened

ls -l upgrade.php*

Added doc/devtools/convertoldtest.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/php
<?php


$fn = $_SERVER["argv"][1];

$src = file_get_contents($fn);
$src = preg_replace("/\s+include\(.+?\);/ims", "", $src);
$src = trim($src);
file_put_contents($fn, $src);

$expect = `php -qC $fn`;
$src = "--TEST--\n$fn\n--FILE--\n$src\n--EXPECT--\n$expect";
file_put_contents("$fn.phpt", $src);


?>

Added doc/devtools/crw.













































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/usr/bin/php -qC
<?php
/**
 *
 * converts hash-style function comments into phpDoc-style blocks,
 * adds guessed @param list on the way
 * 
 *
 */

 

  $txt = file_get_contents("/dev/stdin");
//  $txt = addslashes($txt);
  $txt = preg_replace(
     "_^#--\s*(.+?\n(^#.+?\n)*)(.+?function\s+\w+\((.*?)\))?_imse",
     "'/**\n' . stripslashes(newcmt('$1')) . paramdesc('$4') . ' */\n' . stripslashes('$3')",
     $txt
  );
//  $txt = stripslashes($txt);
  print $txt;


function newcmt($c) {
   return preg_replace("_^[*/# ]*_ims", " * ", $c);
}

function paramdesc($f) {
   if (!$f || !$_SERVER["argv"][1]) {
     return " * \n";
   }
   $c = "";
   $retype = "mixed";
   preg_match_all("/([$]\w+)(=[^),]+)?/ims", $f, $uu);
   foreach ($uu[1] as $i=>$var) {
      $opt = stripslashes(substr($uu[2][$i],1));
      $type = vartype($var, $opt);
      $c .= " * @param  $type $var  "
          . ($opt ? "(optional) $opt" : "")
          . "\n";
      if ($i==0) { $retype = $type; }
   }
   return $c ? " *\n$c" . " * @return $retype\n" : "";
}

function vartype($name, $defval="") {
   $deftype = array(
      "/^[\"\']/" => "string",
      "/array\(/" => "array",
      "/^\d+$/" => "integer",
   );
   foreach ($deftype as $rx=>$t) if (preg_match($rx, $defval)) {
      return $t;
   }
   $typenames = array(
      "/int|num|size|count|index|time|offs|len|flags/i" => "integer",
      "/bool|option/i" => "boolean",
      "/str|needle|name|char|form|call|func/i" => "string",
      "/obj|class/i" => "object",
      "/hash|list|keys|values|search|arr/i" => "array",
      "/data|var/i" => "mixed",
      "/asc|desc/i" => "boolean",
   );
   foreach ($typenames as $rx=>$t) if (preg_match($rx, $name)) {
      return $t;
   }
   return "mixed";
}

?>

Added doc/devtools/doctests.

































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/usr/local/bin/php -qC
<?php
/*
   Makes small test scripts, which get extracted from the PHP manual
   on the fly (but not every function has one there, suddenly).
*/

#-- config
$PAUSE = 1;   // (use 3) break between tests; you should use `|less` instead
$CLEAN = 0;   // remove test scripts after use
$MANY = 1;    // create one testing script per function


#-- help
if (count($_SERVER["argv"]) < 3) {
   echo<<<END

Usage: doctest  [php-interpreter]  [/path/to/your/php/manual/]

   Runs the examples from your locally installed PHP manual (any language
   will work, but get the latest!) with the given PHP interpreter version
   (use an older version to really test the emulated functions). You need
   lynx or w3m installed also. Use only under U*ix/Linux.

   Pipe the output through |less, |more or |most, there are built-in
   delays. Rarely example scripts may not run (they are examples only).

END;
}

#-- proceed
else {

   #-- args
   $php = $_SERVER["argv"][1];
   $php = trim(`which $php`);
   if (!$php) {
      die(__FILE__.": Given PHP interpreter not in your %PATH!\n");
   }
   $dir = $_SERVER["argv"][2];
   if (!is_dir($dir) || !file_exists("$dir/function.print.html")) {
      die(__FILE__.": PHP manual does not live under '$dir'.\n");
   }
   ($html = `which w3m`) or ($html = `which lynx`);
   if (!($html = trim($html))) {
      die(__FILE__.": lynx or w3m required.\n");
   }
   $tmp = "/tmp/upgrade.php.doctest.tmp";
   $tmpdir = $tmp;
   if ($MANY) { @unlink($tmpdir); @mkdir($tmpdir); }

   #-- load emulation script
   $emu = realpath(dirname(__FILE__) . "/../upgrade.php");
   $emu2 = dirname($emu)."/ext/array.php";
   $emu3 = dirname($emu)."/ext/mime.php";
   require($emu);

   #-- get function names
   $text = file_get_contents($emu);
   preg_match_all("/function[ ]+([_\w\d]+)\s*\(/", $text, $uu);
   $funcs = $uu[1];
   #-- or use user-specified list
   if (count($_SERVER["argv"]) >= 4) {
      $funcs = array_slice($_SERVER["argv"], 3);
   }

   #-- generate list of really emulated functions
   $simulated = `echo '<?php echo serialize(get_defined_functions()); ?>' | $php -q`;
   $simulated = unserialize($simulated);
   $simulated = $simulated["internal"];

   #-- all
   foreach ($funcs as $func) {
      if (file_exists($fn = "$dir/function.".strtr($func, "_", "-").".html")) {
         echo "checking function '\033[31m$func\033[37m'... ";

         #-- only run over emulated stuff
         if (in_array($func, $simulated)) {
            echo "NOT EMULATED (with your PHP version)... ";
            // continue;
         }

         #-- grep example scripts
         $text = `$html -dump $fn`;
         preg_match_all("/<\?php(.+?)\?".">/ms", $text, $uu);

         #-- exec each
         if ($n = count($uu[1])) {

            #-- note
            echo "$n examples:\n\n";

            #-- multiple scripts to run
            foreach ($uu[1] as $i=>$scr) {

               #-- fix output-less scripts: find last assigned-to variable name
               if (!strpos($scr, "echo") && !strpos($scr, "print")) {
                  if (preg_match('/^.+(\$[_\w\d\[\"\'\]]+)\s*=/s', $scr, $uu)) {
                     $scr .= "\n\n#-- auto-added\nprint_r($uu[1]);\n";
                  }
                  else {
                     $scr .= "\n\n#-- this script gives no useful output, or does it?";
                  }
               }

               #-- fix compatibility to older PHP versions
               $scr = preg_replace('/(\s)private(\s\$)/', '$1var$2', $scr);

               #-- output sample script text from doc
               if ($i) {
                  echo "\n++++++++++++++++++++++++++++\n\n";
                  sleep($PAUSE);
               }
               echo "\033[1;30m<?php $scr\n?".">\033[0;37m\n";

               #-- create temp script, run it
               if ($MANY) {
                  $tmp = "$tmpdir/$func#$i.php";
               }
               $scr = ltrim($scr);
               file_put_contents(
                  $tmp,
                  "<?php\n\n".
                  "#-- a test script for emulated function '$func'\n".
                  "if (function_exists('$func')) { echo \"ATTENTION: the native '$func' function will engage for this test\\n\"; }\n".
                  "include('$emu');\n".
                  "include('$emu2');\n".
                  "include('$emu3');\n".
                  "error_reporting(E_ALL);\n\n".
                  "#-- example[$i] as taken from PHP manual page '$fn'\n".
                  "$scr\n".
                  "\n?".">"
               );
               echo "==>\033[32m\n";
               passthru("$php $tmp");
               echo "\033[0;37m\n\n";
            }

            #-- pause before next func/script
            sleep($PAUSE);
            echo "\n-------------------------------------------------------------------\n\n";
         }

         else {
            echo "NO EXAMPLES found in doc, skipping";
         }
         echo "\n";
      }
   }

   #-- clean up
   if ($CLEAN) {
      unlink($tmp);
   }
}

#-- even more clean
if ($MANY && CLEAN) { @rmdir($tmpdir); }

?>

Added doc/devtools/listemu.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/local/bin/php -qC
<?php
/*
   Prints the list of emulated functions.
*/

#-- basedir
$dir = realpath(dirname(__FILE__) . "/../");

#-- grep for function definitions
$text = "";
$text .= implode("", file("$dir/upgrade.php"));
$text .= implode("", file("$dir/ext/array.php"));
$text .= implode("", file("$dir/ext/bcmath.php"));
$text .= implode("", file("$dir/ext/gettext.php"));
$text .= implode("", file("$dir/ext/mime.php"));
$text .= implode("", file("$dir/ext/old.php"));
$text .= implode("", file("$dir/ext/posix.php"));
$text .= implode("", file("$dir/ext/ctype.php"));
$text .= implode("", file("$dir/ext/odbc.php"));
if (preg_match_all("/function[ ]+([_\w\d]+)\s*\(/", $text, $uu)) {
   $list = array_unique($uu[1]);
}

#-- print
echo "Following functions can be emulated currently:\n";
foreach ($list as $func) {
   echo " $func\n";
}

?>

Added doc/devtools/php-commandline/PhpFunctionCall.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/php -qC
<?php

   #-- function name
   $func = $_SERVER["argv"][0];
   $func = substr($func, strrpos($func, "/") + 1);

   #-- args
   $args = $_SERVER["argv"];
   array_shift($args);

   #-- stdin as arg
   if (!count($args)) {
      if (($f = fopen("php://stdin", "rb"))
      and ($input = fread($f, 1<<22))) {
         array_unshift($args, $input);
         fclose($f);
      }
   }

   #-- do
   $output = call_user_func_array($func, $args);
   echo $output;

?>

Added doc/devtools/php-commandline/README.































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47


  BEWARE: GIMMICK!!

  If you run Linux and work on the console occasionally, you probably love
  commandline tools. If you further develop PHP scripts, then you probably
  sometimes wish to test PHP functions on the fly and more easily (without
  typing yet another test script).

  If that's the case, here is a simple script to simplify this. To install
  follow these steps:


  1. Create a $HOME/bin/php directory
     (and add ~/bin/php/ to your shell PATH, of course)

  2. Move the contents of this ./ dir into ~/bin/php/

  3. Run "./make_symlinks" in this directory.

  4. Eventually adapt the interpreter shebang #! in the PhpFuncCall script.


  This will create a lot of symlinks to the "PhpFunctionCall" script. You
  then can run PHP functions on the terminal like:


   localhost:~$   base64_encode  AbcDef_1234


  Of course this is not useful for all PHP functions, because some must be
  used in conjunction or do not return displayable results. And some have
  already been removed from the list. You can of course create special PHP
  scripts, like the example 'phpecho' that call other PHP code or function
  groups, of course.

  If you run an older PHP version, then -sure-, you might want to include
  upgrade.php from within 'PhpFunctionCall'.
  


  WINDOWS

  No. Using that under Windows with its frustrating commandline window makes
  little sense.


Added doc/devtools/php-commandline/make_symlinks.





























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/bin/sh

SCRIPT=PhpFunctionCall
FUNCS="json_encode json_decode inet_ntop inet_pton error_get_last strptime
htmlspecialchars_decode zend_version strlen strcmp strncmp strcasecmp
strncasecmp each error_reporting define defined get_parent_class
method_exists class_exists interface_exists function_exists
get_included_files get_required_files is_subclass_of is_a get_class_vars
get_object_vars get_class_methods trigger_error user_error set_error_handler
restore_error_handler set_exception_handler restore_exception_handler
get_declared_classes get_declared_interfaces get_defined_functions
get_defined_vars create_function get_resource_type get_loaded_extensions
extension_loaded get_extension_funcs get_defined_constants debug_backtrace
debug_print_backtrace xmlrpc_encode xmlrpc_decode xmlrpc_decode_request
xmlrpc_encode_request xmlrpc_get_type xmlrpc_set_type xmlrpc_is_fault
utf8_encode utf8_decode token_get_all token_name constant bin2hex sleep
usleep time_nanosleep time mktime gmmktime strftime gmstrftime strtotime
date idate gmdate getdate localtime checkdate flush wordwrap
htmlspecialchars htmlentities html_entity_decode get_html_translation_table
sha1 sha1_file md5 md5_file crc32 iptcparse iptcembed getimagesize
image_type_to_mime_type phpinfo phpversion phpcredits php_logo_guid
php_real_logo_guid php_egg_logo_guid zend_logo_guid php_sapi_name php_uname
php_ini_scanned_files strnatcmp strnatcasecmp substr_count strspn strcspn
strtok strtoupper strtolower strpos stripos strrpos strripos strrev hebrev
hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr
stristr strrchr str_shuffle str_word_count str_split strpbrk substr_compare
strcoll money_format substr substr_replace quotemeta ucfirst ucwords strtr
addslashes addcslashes rtrim str_replace str_ireplace str_repeat count_chars
chunk_split trim ltrim strip_tags similar_text explode implode setlocale
localeconv nl_langinfo soundex levenshtein chr ord parse_str str_pad chop
strchr sprintf printf vprintf vsprintf fprintf vfprintf sscanf fscanf
parse_url urlencode urldecode rawurlencode rawurldecode http_build_query
readlink linkinfo symlink link unlink exec system escapeshellcmd
escapeshellarg passthru shell_exec proc_open proc_close proc_terminate
proc_get_status proc_nice rand srand getrandmax mt_rand mt_srand
mt_getrandmax getservbyname getservbyport getprotobyname getprotobynumber
getmyuid getmygid getmypid getmyinode getlastmod base64_decode base64_encode
convert_uuencode convert_uudecode abs ceil floor round sin cos tan asin acos
atan atan2 sinh cosh tanh asinh acosh atanh expm1 log1p pi is_finite is_nan
is_infinite pow exp log log10 sqrt hypot deg2rad rad2deg bindec hexdec
octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip
getenv putenv getopt microtime gettimeofday getrusage uniqid
quoted_printable_decode convert_cyr_string get_current_user set_time_limit
get_cfg_var get_magic_quotes_gpc get_magic_quotes_runtime
import_request_variables error_log call_user_func call_user_func_array
call_user_method call_user_method_array serialize unserialize var_dump
var_export debug_zval_dump print_r unregister_tick_function highlight_file
show_source highlight_string php_strip_whitespace php_check_syntax ini_get
ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path
restore_include_path setcookie setrawcookie header headers_sent headers_list
connection_aborted connection_status ignore_user_abort parse_ini_file
is_uploaded_file move_uploaded_file gethostbyaddr gethostbyname
gethostbynamel dns_check_record checkdnsrr dns_get_mx getmxrr dns_get_record
intval floatval doubleval strval gettype settype is_null is_resource is_bool
is_long is_float is_int is_integer is_double is_real is_numeric is_string
is_array is_object is_scalar is_callable ereg ereg_replace eregi
eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind
rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate
fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file
file_get_contents file_put_contents fgetcsv flock get_meta_tags
set_file_buffer get_headers realpath fnmatch fsockopen pfsockopen pack
unpack get_browser crypt opendir closedir chdir chroot getcwd rewinddir
readdir dir scandir glob fileatime filectime filegroup fileinode filemtime
fileowner fileperms filesize filetype file_exists is_writable is_writeable
is_readable is_executable is_file is_dir is_link stat lstat chown chgrp
chmod touch clearstatcache disk_total_space disk_free_space diskfreespace
mail ezmlm_hash openlog syslog closelog define_syslog_variables lcg_value
metaphone ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush
ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents
ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort
arsort sort rsort usort uasort uksort shuffle array_walk
array_walk_recursive count end prev next reset current key min max in_array
array_search extract compact array_fill range array_multisort array_push
array_pop array_shift array_unshift array_splice array_slice array_merge
array_merge_recursive array_keys array_values array_count_values
array_reverse array_reduce array_pad array_flip array_change_key_case
array_rand array_unique array_intersect array_uintersect
array_intersect_assoc array_uintersect_assoc array_intersect_uassoc
array_uintersect_uassoc array_diff array_udiff array_diff_assoc
array_udiff_assoc array_diff_uassoc array_udiff_uassoc array_sum
array_filter array_map array_chunk array_combine array_key_exists pos sizeof
key_exists assert assert_options version_compare ftok str_rot13
stream_get_filters output_add_rewrite_var output_reset_rewrite_vars
date_sunrise date_sunset spl_classes class_parents class_implements
use_soap_error_handler is_soap_fault simplexml_load_file
simplexml_load_string simplexml_import_dom session_name session_module_name
session_save_path session_id session_regenerate_id session_decode
session_register session_unregister session_is_registered session_encode
session_start session_destroy session_unset session_set_save_handler
session_cache_limiter session_cache_expire session_set_cookie_params
session_get_cookie_params session_write_close session_commit posix_kill
posix_getpid posix_getppid posix_getuid posix_setuid posix_geteuid
posix_seteuid posix_getgid posix_setgid posix_getegid posix_setegid
posix_getgroups posix_getlogin posix_getpgrp posix_setsid posix_setpgid
posix_getpgid posix_getsid posix_uname posix_times posix_ctermid
posix_ttyname posix_isatty posix_getcwd posix_mkfifo posix_getgrnam
posix_getgrgid posix_getpwnam posix_getpwuid posix_getrlimit
posix_get_last_error posix_errno posix_strerror preg_match preg_match_all
preg_replace preg_replace_callback preg_split preg_quote preg_grep
pcntl_fork pcntl_waitpid pcntl_wait pcntl_signal pcntl_wifexited
pcntl_wifstopped pcntl_wifsignaled pcntl_wexitstatus pcntl_wtermsig
pcntl_wstopsig pcntl_exec pcntl_alarm pcntl_getpriority pcntl_setpriority
mime_content_type iconv ob_iconv_handler iconv_get_encoding
iconv_set_encoding iconv_strlen iconv_substr iconv_strpos iconv_strrpos
iconv_mime_encode iconv_mime_decode iconv_mime_decode_headers gd_info
imagetypes jpeg2wbmp png2wbmp image2wbmp imagelayereffect imagecolormatch
imagefilter dom_import_simplexml ctype_alnum ctype_alpha ctype_cntrl
ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space
ctype_upper ctype_xdigit readgzfile gzrewind gzclose gzeof gzgetc gzgets
gzgetss gzread gzopen gzpassthru gzseek gztell gzwrite gzputs gzfile
gzcompress gzuncompress gzdeflate gzinflate gzencode ob_gzhandler
zlib_get_coding_type"


# start
if [ -e $SCRIPT ]
then

   for F in $FUNCS
   do

      ln -s $SCRIPT $F

   done

fi

Added doc/devtools/php-commandline/phpecho.







>
>
>
1
2
3
#!/bin/sh

echo "<?php print_r($1); ?>" | php

Added doc/gettext.txt.



















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

PHP-only gettext emulation
--------------------------

The "gettext.php" include script tries to reimplement GNU gettext in
pure PHP. It is incomplete and divergent in many ways, but seems to
work well in its goal to be a quick drop-in replacement.

You load the script, like you'd include the "upgrade.php" script, and
then have the family of gettext functions always available - if they
are compiled in into your PHP binary or not. This way you can freely
use standardized i18n features safely on any web server and with all
your applications.

There are however a few minor obstacles and differences in between
the original and the emulation which you have to take care of. Most
of the incompatibilites descend from lousily documented behaviour of
the original and from lack of extensqive testing of the emulated
versions.

 - You should use setlocale() before any bindtextdomain(), because
   this emulation does load the .mo/.po data files only once.

 - The emulation only ever loads one translation file (it never
   retrieves translation strings from different localizations,
   so it is less useful in conjunction with Accept-Language header
   settings - where multiple languages could be given).
   [Original gettext may or may not load from multiple files??]

 - To be compliant with the native implementation, you have to make
   sure, that the .mo files are built from the *.po source files.
   (The emulation tries to work on both, but it really shouldn't do
   that.)

 - Order of environment variable precedence is:
     1. LANGUAGE
     2. LC_ALL
     3. LC_MESSAGE
     4. LANG                    (multiple langs)
     5. setlocale()
     6. HTTP_ACCEPT_LANGUAGE    (incompliant with GNU gettext)

 - There is a second variant of the script, which tries to handle
   plural forms. This has multiple limitations:
     - does not employ a full Plural-Forms parser (a C expression
       which must be interpreted at runtime)
     - matches and works only with a few built-in language plural
       form syntaxes and orderings
     - and it's fully untested as of yet

 - It constructs a global $_GETTEXT[] variable which contains all
   messages and translations at runtime in-memory. That means, it
   is far more memory-hungry and less scalable than the original
   GNU libintl in C.



Added doc/runtest.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
#!/usr/bin/php -qC
<?php
#
# doesn't yet run a choosen PHP interpreter,
# and auto_prepend_file doesn't seem to work either
#


#-- Use the emulation, Luke.
$T = new PEAR_RunTest();
$T->ini_overwrites[] = "auto_prepend_file=".dirname(dirname(__FILE__))."/upgrade.php";
// $T->_php = "php412";


#-- *.phpt file list
$files = $_SERVER["argv"];
unset($files[0]);

#-- exec all
foreach ($files as $i => $fn) {
   $T->run($fn, array(), $i);
}




/**
 * PEAR_RunTest
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   pear
 * @package    PEAR
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2006 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id: RunTest.php,v 1.45 2007/06/19 03:10:49 cellog Exp $
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 1.3.3
 */

/**
 * for error handling
 */
require_once 'PEAR.php';
require_once 'PEAR/Config.php';

define('DETAILED', 1);
putenv("PHP_PEAR_RUNTESTS=1");

/**
 * Simplified version of PHP's test suite
 *
 * Try it with:
 *
 * $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
 *
 *
 * @category   pear
 * @package    PEAR
 * @author     Tomas V.V.Cox <cox@idecnet.com>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2006 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: 1.6.1
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since Release 1.3.3
 */
class PEAR_RunTest
{
    var $_headers = array();
    var $_logger;
    var $_options;
    var $_php;
    var $test_count;
    var $xdebug_loaded;
    var $ini_overwrites = array(
        'output_handler=',
        'open_basedir=',
        'safe_mode=0',
        'disable_functions=',
        'output_buffering=Off',
        'display_errors=1',
        'log_errors=0',
        'html_errors=0',
        'track_errors=1',
        'report_memleaks=0',
        'report_zend_debug=0',
        'docref_root=',
        'docref_ext=.html',
        'error_prepend_string=',
        'error_append_string=',
#        'auto_prepend_file=',
        'auto_append_file=',
        'magic_quotes_runtime=0',
        'xdebug.default_enable=0',
        'allow_url_fopen=1',
    );

    /**
     * An object that supports the PEAR_Common->log() signature, or null
     * @param PEAR_Common|null
     */
    function PEAR_RunTest($logger = null, $options = array())
    {
        $this->ini_overwrites[] = 'error_reporting=' . E_ALL;
        if (is_null($logger)) {
            require_once 'PEAR/Common.php';
            $logger = new PEAR_Common;
        }
        $this->_logger  = $logger;
        $this->_options = $options;
        
        $conf = &PEAR_Config::singleton();
        $this->_php = $conf->get('php_bin');
    }

    /**
     * Taken from php-src/run-tests.php
     *
     * @param string $commandline command name
     * @param array $env
     * @param string $stdin standard input to pass to the command
     * @return unknown
     */
    function system_with_timeout($commandline, $env = null, $stdin = null)
    {
        $data = '';
        if (version_compare(phpversion(), '5.0.0', '<')) {
            $proc = proc_open($commandline, array(
                0 => array('pipe', 'r'),
                1 => array('pipe', 'w'),
                2 => array('pipe', 'w')
                ), $pipes);
        } else {
            $proc = proc_open($commandline, array(
                0 => array('pipe', 'r'),
                1 => array('pipe', 'w'),
                2 => array('pipe', 'w')
                ), $pipes, null, $env, array('suppress_errors' => true));
        }
    
        if (!$proc) {
            return false;
        }
    
        if (is_string($stdin)) {
            fwrite($pipes[0], $stdin);
        }
        fclose($pipes[0]);
    
        while (true) {
            /* hide errors from interrupted syscalls */
            $r = $pipes;
            $e = $w = null;
            $n = @stream_select($r, $w, $e, 60);
    
            if ($n === 0) {
                /* timed out */
                $data .= "\n ** ERROR: process timed out **\n";
                proc_terminate($proc);
                return array(1234567890, $data);
            } else if ($n > 0) {
                $line = fread($pipes[1], 8192);
                if (strlen($line) == 0) {
                    /* EOF */
                    break;
                }
                $data .= $line;
            }
        }
        if (function_exists('proc_get_status')) {
            $stat = proc_get_status($proc);
            if ($stat['signaled']) {
                $data .= "\nTermsig=".$stat['stopsig'];
            }
        }
        $code = proc_close($proc);
        if (function_exists('proc_get_status')) {
            $code = $stat['exitcode'];
        }
        return array($code, $data);
    }

    function settings2array($settings, $ini_settings)
    {
        foreach ($settings as $setting) {
            if (strpos($setting, '=')!== false) {
                $setting = explode('=', $setting, 2);
                $name  = trim(strtolower($setting[0]));
                $value = trim($setting[1]);
                $ini_settings[$name] = $value;
            }
        }
        return $ini_settings;
    }
    
    function settings2params($ini_settings)
    {
        $settings = '';
        foreach ($ini_settings as $name => $value) {
            $value = addslashes($value);
            $settings .= " -d \"$name=$value\"";
        }
        return $settings;
    }

    function runPHPUnit($file, $ini_settings = '')
    {
        $cmd = "$this->_php$ini_settings -f $file";
        if (isset($this->_logger)) {
            $this->_logger->log(2, 'Running command "' . $cmd . '"');
        }
    
        $savedir = getcwd(); // in case the test moves us around
        chdir(dirname($file));
        echo `$cmd`;
        chdir($savedir);
        return 'PASSED'; // we have no way of knowing this information so assume passing
    }

    //
    //  Run an individual test case.
    //

    function run($file, $ini_settings = '', $test_number)
    {
        if (empty($this->_options['cgi'])) {
            // try to see if php-cgi is in the path
            if (false !== $this->system_with_timeout('php-cgi -v')) {
                $this->_options['cgi'] = 'php-cgi';
            }
        }
        if (1 < $len = strlen($this->tests_count)) {
            $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT);
            $test_nr = "[$test_number/$this->tests_count] ";
        } else {
            $test_nr = '';
        }

        $file = realpath($file);
        $section_text = $this->_readFile($file);
        if (PEAR::isError($section_text)) {
            return $section_text;
        }

        if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
            return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
        }

        $cwd = getcwd();
        
        $pass_options = '';
        if (!empty($this->_options['ini'])) {
            $pass_options = $this->_options['ini'];
        }

        $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
        if ($section_text['INI']) {
            if (strpos($section_text['INI'], '{PWD}') !== false) {
                $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
            }
            $ini = preg_split( "/[\n\r]+/", $section_text['INI']);
            $ini_settings = $this->settings2array($ini, $ini_settings);
        }
        $ini_settings = $this->settings2params($ini_settings);
        $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);

        $tested = trim($section_text['TEST']);
        $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' ';

        if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) ||
              !empty($section_text['UPLOAD']) || !empty($section_text['GET']) ||
              !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) {
            if (empty($this->_options['cgi'])) {
                if (!isset($this->_options['quiet'])) {
                    $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
                }
                if (isset($this->_options['tapoutput'])) {
                    return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
                }
                return 'SKIPPED';
            }
            $this->_php = $this->_options['cgi'];
        }

        $temp_dir = realpath(dirname($file));
    	$main_file_name = basename($file, 'phpt');
    	$diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
    	$log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
    	$exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
    	$output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
    	$memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
    	$temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
    	$temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
    	$temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
    	$tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');

    	// unlink old test results
        $this->_cleanupOldFiles($file);

        // Check if test should be skipped.
        $res  = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings);
        if (count($res) != 2) {
            return $res;
        }
        $info = $res['info'];
        $warn = $res['warn'];

        // We've satisfied the preconditions - run the test!
        if (isset($this->_options['coverage']) && $this->xdebug_loaded) {
            $len_f = 5;
            if (substr($section_text['FILE'], 0, 5) != '<?php'
                && substr($section_text['FILE'], 0, 2) == '<?') {
                $len_f = 2;
            }

            $text = '<?php' . "\n" . 'xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);' . "\n";
            $new = substr($section_text['FILE'], $len_f, strlen($section_text['FILE']));
            $text.= substr($new, 0, strrpos($new, '?>'));
            $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug';
            $text.= "\n" . 
                   "\n" . '$xdebug = var_export(xdebug_get_code_coverage(), true);' . 
                   "\n" . 'file_put_contents(\'' . $xdebug_file . '\', $xdebug);' . 
                   "\n" . 'xdebug_stop_code_coverage();' . "\n" . '?>';

            $this->save_text($temp_file, $text);
        } else {
            $this->save_text($temp_file, $section_text['FILE']);
        }

        $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
        $cmd = "$this->_php$ini_settings \"$temp_file\" $args 2>&1";
        if (isset($this->_logger)) {
            $this->_logger->log(2, 'Running command "' . $cmd . '"');
        }

        // Reset environment from any previous test.
        $env = $this->_resetEnv($section_text, $temp_file);

        $section_text = $this->_processUpload($section_text, $file);
        if (PEAR::isError($section_text)) {
            return $section_text;
        }

        if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
            $post = trim($section_text['POST_RAW']);
            $raw_lines = explode("\n", $post);
    
            $request = '';
            $started = false;
            foreach ($raw_lines as $i => $line) {
                if (empty($env['CONTENT_TYPE']) &&
                    preg_match('/^Content-Type:(.*)/i', $line, $res)) {
                    $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
                    continue;
                }
                if ($started) {
                    $request .= "\n";
                }
                $started = true;
                $request .= $line;
            }
    
            $env['CONTENT_LENGTH'] = strlen($request);
            $env['REQUEST_METHOD'] = 'POST';

            $this->save_text($tmp_post, $request);
            $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
        } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
            $post = trim($section_text['POST']);
            $this->save_text($tmp_post, $post);
            $content_length = strlen($post);
    
            $env['REQUEST_METHOD'] = 'POST';
            $env['CONTENT_TYPE']   = 'application/x-www-form-urlencoded';
            $env['CONTENT_LENGTH'] = $content_length;
    
            $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
        } else {
            $env['REQUEST_METHOD'] = 'GET';
            $env['CONTENT_TYPE']   = '';
            $env['CONTENT_LENGTH'] = '';
        }

        if (OS_WINDOWS && isset($section_text['RETURNS'])) {
            ob_start();
            system($cmd, $return_value);
            $out = ob_get_contents();
            ob_end_clean();
            $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
            $returnfail = ($return_value != $section_text['RETURNS']);
        } else {
            $returnfail = false;
            $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null;
            $out = $this->system_with_timeout($cmd, $env, $stdin);
            $return_value = $out[0];
            $out = $out[1];
        }

        $output = preg_replace('/\r\n/', "\n", trim($out));

        if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) {
            @unlink(realpath($tmp_post));
        }
        chdir($cwd); // in case the test moves us around

        $this->_testCleanup($section_text, $temp_clean);

        /* when using CGI, strip the headers from the output */
        $output = $this->_stripHeadersCGI($output);

        if (isset($section_text['EXPECTHEADERS'])) {
            $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']);
            $missing = array_diff_assoc($testheaders, $this->_headers);
            $changed = '';
            foreach ($missing as $header => $value) {
                if (isset($this->_headers[$header])) {
                    $changed .= "-$header: $value\n+$header: ";
                    $changed .= $this->_headers[$header];
                } else {
                    $changed .= "-$header: $value\n";
                }
            }
            if ($missing) {
                // tack on failed headers to output:
                $output .= "\n====EXPECTHEADERS FAILURE====:\n$changed";
            }
        }
        // Does the output match what is expected?
        do {
            if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
                if (isset($section_text['EXPECTF'])) {
                    $wanted = trim($section_text['EXPECTF']);
                } else {
                    $wanted = trim($section_text['EXPECTREGEX']);
                }
                $wanted_re = preg_replace('/\r\n/', "\n", $wanted);
                if (isset($section_text['EXPECTF'])) {
                    $wanted_re = preg_quote($wanted_re, '/');
                    // Stick to basics
                    $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
                    $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
                    $wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
                    $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
                    $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
                    $wanted_re = str_replace("%c", ".", $wanted_re);
                    // %f allows two points "-.0.0" but that is the best *simple* expression
                }
    /* DEBUG YOUR REGEX HERE
            var_dump($wanted_re);
            print(str_repeat('=', 80) . "\n");
            var_dump($output);
    */
                if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
                    if (file_exists($temp_file)) {
                        unlink($temp_file);
                    }
                    if (array_key_exists('FAIL', $section_text)) {
                        break;
                    }
                    if (!isset($this->_options['quiet'])) {
                        $this->_logger->log(0, "PASS $test_nr$tested$info");
                    }
                    if (isset($this->_options['tapoutput'])) {
                        return array('ok', ' - ' . $tested);
                    }
                    return 'PASSED';
                }
            } else {
                if (isset($section_text['EXPECTFILE'])) {
                    $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']);
                    if (!($fp = @fopen($f, 'rb'))) {
                        return PEAR::raiseError('--EXPECTFILE-- section file ' .
                            $f . ' not found');
                    }
                    fclose($fp);
                    $section_text['EXPECT'] = file_get_contents($f);
                }
                $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT']));
                // compare and leave on success
                if (!$returnfail && 0 == strcmp($output, $wanted)) {
                    if (file_exists($temp_file)) {
                        unlink($temp_file);
                    }
                    if (array_key_exists('FAIL', $section_text)) {
                        break;
                    }
                    if (!isset($this->_options['quiet'])) {
                        $this->_logger->log(0, "PASS $test_nr$tested$info");
                    }
                    if (isset($this->_options['tapoutput'])) {
                        return array('ok', ' - ' . $tested);
                    }
                    return 'PASSED';
                }
            }
        } while (false);

        if (array_key_exists('FAIL', $section_text)) {
            // we expect a particular failure
            // this is only used for testing PEAR_RunTest
            $expectf  = isset($section_text['EXPECTF']) ? $wanted_re : null;
            $faildiff = $this->generate_diff($wanted, $output, null, $expectf);
            $faildiff = preg_replace('/\r/', '', $faildiff);
            $wanted   = preg_replace('/\r/', '', trim($section_text['FAIL']));
            if ($faildiff == $wanted) {
                if (!isset($this->_options['quiet'])) {
                    $this->_logger->log(0, "PASS $test_nr$tested$info");
                }
                if (isset($this->_options['tapoutput'])) {
                    return array('ok', ' - ' . $tested);
                }
                return 'PASSED';
            }
            unset($section_text['EXPECTF']);
            $output = $faildiff;
            if (isset($section_text['RETURNS'])) {
                return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' .
                    $file);
            }
        }

        // Test failed so we need to report details.
        $txt = $warn ? 'WARN ' : 'FAIL ';
        $this->_logger->log(0, $txt . $test_nr . $tested . $info);

        // write .exp
        $res = $this->_writeLog($exp_filename, $wanted);
        if (PEAR::isError($res)) {
            return $res;
        }

        // write .out
        $res = $this->_writeLog($output_filename, $output);
        if (PEAR::isError($res)) {
            return $res;
        }

        // write .diff
        $returns = isset($section_text['RETURNS']) ?
                        array(trim($section_text['RETURNS']), $return_value) : null;
        $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
        $data = $this->generate_diff($wanted, $output, $returns, $expectf);
        $res  = $this->_writeLog($diff_filename, $data);
        if (PEAR::isError($res)) {
            return $res;
        }

        // write .log
        $data = "
---- EXPECTED OUTPUT
$wanted
---- ACTUAL OUTPUT
$output
---- FAILED
";

        if ($returnfail) {
            $data .= "
---- EXPECTED RETURN
$section_text[RETURNS]
---- ACTUAL RETURN
$return_value
";
        }

        $res = $this->_writeLog($log_filename, $data);
        if (PEAR::isError($res)) {
            return $res;
        }

        if (isset($this->_options['tapoutput'])) {
            $wanted = explode("\n", $wanted);
            $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted);
            $output = explode("\n", $output);
            $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output);
            return array($wanted . $output . 'not ok', ' - ' . $tested);
        }
        return $warn ? 'WARNED' : 'FAILED';
    }

    function generate_diff($wanted, $output, $rvalue, $wanted_re)
    {
        $w  = explode("\n", $wanted);
        $o  = explode("\n", $output);
        $wr = explode("\n", $wanted_re);
        $w1 = array_diff_assoc($w, $o);
        $o1 = array_diff_assoc($o, $w);
        $o2 = $w2 = array();
        foreach ($w1 as $idx => $val) {
            if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
                  !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) {
                $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
            }
        }
        foreach ($o1 as $idx => $val) {
            if (!$wanted_re || !isset($wr[$idx]) ||
                  !preg_match('/^' . $wr[$idx] . '\\z/', $val)) {
                $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
            }
        }
        $diff = array_merge($w2, $o2);
        ksort($diff);
        $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : '';
        return implode("\r\n", $diff) . $extra;
    }

    //  Write the given text to a temporary file, and return the filename.
    function save_text($filename, $text)
    {
        if (!$fp = fopen($filename, 'w')) {
            return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
        }
        fwrite($fp, $text);
        fclose($fp);
    if (1 < DETAILED) echo "
FILE $filename {{{
$text
}}}
";
    }
    
    function _cleanupOldFiles($file)
    {
        $temp_dir = realpath(dirname($file));
        $mainFileName = basename($file, 'phpt');
    	$diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff';
    	$log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log';
    	$exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp';
    	$output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out';
    	$memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem';
    	$temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php';
    	$temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php';
    	$temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php';
    	$tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');

    	// unlink old test results
    	@unlink($diff_filename);
    	@unlink($log_filename);
    	@unlink($exp_filename);
    	@unlink($output_filename);
    	@unlink($memcheck_filename);
    	@unlink($temp_file);
    	@unlink($temp_skipif);
    	@unlink($tmp_post);
    	@unlink($temp_clean);
    }
    
    function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings)
    {
        $info = '';
        $warn = false;
        if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) {
            $this->save_text($temp_skipif, $section_text['SKIPIF']);
            $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\"");
            $output = $output[1];
            $loutput = ltrim($output);
            unlink($temp_skipif);
            if (!strncasecmp('skip', $loutput, 4)) {
                $skipreason = "SKIP $tested";
                if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
                    $skipreason .= '(reason: ' . $m[1] . ')';
                }
                if (!isset($this->_options['quiet'])) {
                    $this->_logger->log(0, $skipreason);
                }
                if (isset($this->_options['tapoutput'])) {
                    return array('ok', ' # skip ' . $reason);
                }
                return 'SKIPPED';
            }

            if (!strncasecmp('info', $loutput, 4)
                && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
                $info = " (info: $m[1])";
            }

            if (!strncasecmp('warn', $loutput, 4)
                && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
                $warn = true; /* only if there is a reason */
                $info = " (warn: $m[1])";
            }
        }
        
        return array('warn' => $warn, 'info' => $info);
    }
    
    function _stripHeadersCGI($output)
    {
        $this->headers = array();
        if (!empty($this->_options['cgi']) &&
              $this->_php == $this->_options['cgi'] && 
              preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) {
            $output = isset($match[2]) ? trim($match[2]) : '';
            $this->_headers = $this->_processHeaders($match[1]);
        }
        
        return $output;
    }

    /**
     * Return an array that can be used with array_diff() to compare headers
     *
     * @param string $text
     */
    function _processHeaders($text)
    {
        $headers = array();
        $rh = preg_split("/[\n\r]+/", $text);
        foreach ($rh as $line) {
            if (strpos($line, ':')!== false) {
                $line = explode(':', $line, 2);
                $headers[trim($line[0])] = trim($line[1]);
            }
        }
        return $headers;
    }

    function _readFile($file)
    {
        // Load the sections of the test file.
        $section_text = array(
            'TEST'   => '(unnamed test)',
            'SKIPIF' => '',
            'GET'    => '',
            'COOKIE' => '',
            'POST'   => '',
            'ARGS'   => '',
            'INI'    => '',
            'CLEAN'  => '',
        );

        if (!is_file($file) || !$fp = fopen($file, "r")) {
            return PEAR::raiseError("Cannot open test file: $file");
        }

        $section = '';
        while (!feof($fp)) {
            $line = fgets($fp);

            // Match the beginning of a section.
            if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
                $section = $r[1];
                $section_text[$section] = '';
                continue;
            } elseif (empty($section)) {
                fclose($fp);
                return PEAR::raiseError("Invalid sections formats in test file: $file");
            }

            // Add to the section text.
            $section_text[$section] .= $line;
        }
        fclose($fp);
        
        return $section_text;
    }
    
    function _writeLog($logname, $data)
    {
        if (!$log = fopen($logname, 'w')) {
            return PEAR::raiseError("Cannot create test log - $logname");
        }
        fwrite($log, $data);
        fclose($log);
    }

    function _resetEnv($section_text, $temp_file)
    {
        $env = $_ENV;
        $env['REDIRECT_STATUS'] = '';
        $env['QUERY_STRING']    = '';
        $env['PATH_TRANSLATED'] = '';
        $env['SCRIPT_FILENAME'] = '';
        $env['REQUEST_METHOD']  = '';
        $env['CONTENT_TYPE']    = '';
        $env['CONTENT_LENGTH']  = '';
        if (!empty($section_text['ENV'])) {
            foreach (explode("\n", trim($section_text['ENV'])) as $e) {
                $e = explode('=', trim($e), 2);
                if (!empty($e[0]) && isset($e[1])) {
                    $env[$e[0]] = $e[1];
                }
            }
        }
        if (array_key_exists('GET', $section_text)) {
            $env['QUERY_STRING'] = trim($section_text['GET']);
        } else {
            $env['QUERY_STRING'] = '';
        }
        if (array_key_exists('COOKIE', $section_text)) {
            $env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
        } else {
            $env['HTTP_COOKIE'] = '';
        }
        $env['REDIRECT_STATUS'] = '1';
        $env['PATH_TRANSLATED'] = $temp_file;
        $env['SCRIPT_FILENAME'] = $temp_file;
        
        return $env;
    }
    
    function _processUpload($section_text, $file)
    {
        if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
            $upload_files = trim($section_text['UPLOAD']);
            $upload_files = explode("\n", $upload_files);

            $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
                       "-----------------------------20896060251896012921717172737\n";
            foreach ($upload_files as $fileinfo) {
                $fileinfo = explode('=', $fileinfo);
                if (count($fileinfo) != 2) {
                    return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
                }
                if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
                    return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
                        "in test file: $file");
                }
                $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
                $fileinfo[1] = basename($fileinfo[1]);
                $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
                $request .= "Content-Type: text/plain\n\n";
                $request .= $file_contents . "\n" .
                    "-----------------------------20896060251896012921717172737\n";
            }

            if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
                // encode POST raw
                $post = trim($section_text['POST']);
                $post = explode('&', $post);
                foreach ($post as $i => $post_info) {
                    $post_info = explode('=', $post_info);
                    if (count($post_info) != 2) {
                        return PEAR::raiseError("Invalid POST data in test file: $file");
                    }
                    $post_info[0] = rawurldecode($post_info[0]);
                    $post_info[1] = rawurldecode($post_info[1]);
                    $post[$i] = $post_info;
                }
                foreach ($post as $post_info) {
                    $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
                    $request .= $post_info[1] . "\n" .
                        "-----------------------------20896060251896012921717172737\n";
                }
                unset($section_text['POST']);
            }
            $section_text['POST_RAW'] = $request;
        }
        
        return $section_text;
    }
    
    function _testCleanup($section_text, $temp_clean)
    {
        if ($section_text['CLEAN']) {
            // perform test cleanup
            $this->save_text($temp_clean, $section_text['CLEAN']);
            $this->system_with_timeout("$this->_php $temp_clean");
            if (file_exists($temp_clean)) {
                unlink($temp_clean);
            }
        }
    }
}

Added doc/tests1all/array_change_key_case.phpt.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--TEST--
array_change_key_case
--FILE--
<?php

$a = array("low"=>32, "CamelCase"=>"Wiki");
print_r($a);
echo "\n";
$a = array_change_key_case($a, CASE_UPPER);
print_r($a);

?>
--EXPECT--
Array
(
    [low] => 32
    [CamelCase] => Wiki
)

Array
(
    [LOW] => 32
    [CAMELCASE] => Wiki
)

Added doc/tests1all/array_chunk.phpt.

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
--TEST--
array_chunk
--FILE--
<?php

$a = array("a", "b", "c", "d", "e");
$r = array_chunk($a, 2, 1);
echo 'array_chunk($a, 2, 1) = ';
print_r($r);

?>
--EXPECT--
array_chunk($a, 2, 1) = Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )

    [1] => Array
        (
            [2] => c
            [3] => d
        )

    [2] => Array
        (
            [4] => e
        )

)

Added doc/tests1all/array_combine.phpt.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
--TEST--
array_combine
--FILE--
<?php


?>
$a = array('green', 'red', 'yellow');
$b = array('avocado', 'apple', 'banana');
$c = array_combine($a, $b);

print_r($c);
<?php
$a = array('green', 'red', 'yellow');
$b = array('avocado', 'apple', 'banana');
$c = array_combine($a, $b);

print_r($c);
?>
--EXPECT--
$a = array('green', 'red', 'yellow');
$b = array('avocado', 'apple', 'banana');
$c = array_combine($a, $b);

print_r($c);
Array
(
    [green] => avocado
    [red] => apple
    [yellow] => banana
)

Added doc/tests1all/array_diff_assoc.phpt.



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
--TEST--
array_diff_assoc
--FILE--
<?php


?>
$a = array(5=>5, 14=>10000, "ccc"=>555, 555);
$b = array(5=>5, 13=>10000,         15=>555);
$res = array_diff_assoc($a, $b);

print_r($res);
<?php
$a = array(5=>5, 14=>10000, "ccc"=>555, 555);
$b = array(5=>5, 13=>10000,         15=>555);
$res = array_diff_assoc($a, $b);
print_r($res);
?>
--EXPECT--
$a = array(5=>5, 14=>10000, "ccc"=>555, 555);
$b = array(5=>5, 13=>10000,         15=>555);
$res = array_diff_assoc($a, $b);

print_r($res);
Array
(
    [14] => 10000
    [ccc] => 555
)

Added doc/tests1all/array_fill.phpt.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
--TEST--
array_fill
--FILE--
<?php

$a = 17;
$a = array_fill(1, 17, $a);
print_r($a);

?>
--EXPECT--
Array
(
    [1] => 17
    [2] => 17
    [3] => 17
    [4] => 17
    [5] => 17
    [6] => 17
    [7] => 17
    [8] => 17
    [9] => 17
    [10] => 17
    [11] => 17
    [12] => 17
    [13] => 17
    [14] => 17
    [15] => 17
    [16] => 17
    [17] => 17
)

Added doc/tests1all/array_intersect_assoc.phpt.























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
--TEST--
array_intersect_assoc
--FILE--
<?php

?>
$a = array(5=>5, 14=>10000, "ccc"=>555, 555);
$b = array(5=>5, 13=>10000, 555);
$res = array_intersect_assoc($a, $b);

print_r($res);
<?php
$a = array(5=>5, 14=>10000, "ccc"=>555, 555);
$b = array(5=>5, 13=>10000, 555);
$res = array_intersect_assoc($a, $b);
print_r($res);
?>
--EXPECT--
$a = array(5=>5, 14=>10000, "ccc"=>555, 555);
$b = array(5=>5, 13=>10000, 555);
$res = array_intersect_assoc($a, $b);

print_r($res);
Array
(
    [5] => 5
)

Added doc/tests1all/array_udiff_uassoc.phpt.

























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
--TEST--
array_udiff_uassoc
--FILE--
<?php

#-- from manual --

class cr {
    var $priv_member;
    function cr($val)
    {
        $this->priv_member = $val;
    }
}
    function comp_func_cr($a, $b)
    {
        if ($a->priv_member === $b->priv_member) return 0;
        return ($a->priv_member > $b->priv_member)? 1:-1;
    }
    
    function comp_func_key($a, $b)
    {
        if ($a === $b) return 0;
        return ($a > $b)? 1:-1;
    }


$a = array(
   "0.1" => new cr(9),
   "0.5" => new cr(12),
   0 => new cr(23),
   1=> new cr(4),
   2 => new cr(-15),
);
$b = array(
   "0.2" => new cr(9),
   "0.5" => new cr(22),
   0 => new cr(3),
   1=> new cr(4),
   2 => new cr(-15),
);

$result = array_udiff_uassoc($a, $b, "comp_func_cr", "comp_func_key");
$expected = array (
  '0.1' => new cr(9),
  '0.5' => new cr(12),
  0 => new cr(23),
);
print_r($result);

if ($result == $expected) {
   echo "\n--> works correctly\n";
}

?>
--EXPECT--
Array
(
    [0.1] => cr Object
        (
            [priv_member] => 9
        )

    [0.5] => cr Object
        (
            [priv_member] => 12
        )

    [0] => cr Object
        (
            [priv_member] => 23
        )

)

--> works correctly

Added doc/tests1all/array_walk_recursive.phpt.







































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
--TEST--
array_walk_recursive
--FILE--
<?php

$a = array(
  "x1",
  "x2\\",
  array(
     "x3aaa1",
     "x3a\\a2",
  ),
  "x4\+end",
);

echo "__start:\n";
array_walk_recursive($a, "outp");

function outp(&$a) {
   var_dump($a);
   $a = stripslashes($a);
}

echo "\n__result:\n";
var_dump($a);

?>
--EXPECT--
__start:
string(2) "x1"
string(3) "x2\"
string(6) "x3aaa1"
string(6) "x3a\a2"
string(7) "x4\+end"

__result:
array(4) {
  [0]=>
  string(2) "x1"
  [1]=>
  string(2) "x2"
  [2]=>
  &array(2) {
    [0]=>
    string(6) "x3aaa1"
    [1]=>
    string(5) "x3aa2"
  }
  [3]=>
  string(6) "x4+end"
}

Added doc/tests1all/base16.phpt.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--TEST--
base16
--FILE--
<?php
include "../../ext/nonstandard/base64.php";

echo base16_encode("123");
echo "\n";
echo base16_decode("313233");

?>
--EXPECT--
313233

123

Added doc/tests1all/bcmath.phpt.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
--TEST--
bcmath
--FILE--
<?php

bcscale(50);
echo "1/17=";
echo bcdiv("1", "17");
echo "\n";

echo "2^55%77777=";
echo bcpowmod(2, 55, 77777);
echo "\n";

?>
--EXPECT--
1/17=0.05882352941176470588235294117647058823529411764705
2^55%77777=0.00000000000000000000000000000000000000000000000000

Added doc/tests1all/class_parents.phpt.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--TEST--
class_parents
--FILE--
<?php

class a {}
class x extends a {}
class y extends x {}
class z extends a {}
class eve extends y {}

$y = new y;
$r = class_parents($y);
print_r($r);

?>
--EXPECT--
Array
(
    [x] => x
    [a] => a
)

Added doc/tests1all/file_put_contents.phpt.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--TEST--
file_put_contents
--FILE--
<?php

$FN = "/tmp/test_fpc";

echo 'file_put_contents("/tmp/test_fpc", "abc-test-text");'."\n";
file_put_contents($FN, "abc-test-text");

echo 'echo file_get_contents("/tmp/test_fpc");'."\n => ";
echo file_get_contents($FN);

unlink($FN);

?>
--EXPECT--
file_put_contents("/tmp/test_fpc", "abc-test-text");
echo file_get_contents("/tmp/test_fpc");
 => abc-test-text

Added doc/tests1all/floatval.phpt.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
--TEST--
floatval
--FILE--
floatval("1234.567abc") = <?php

$str = "1234.567abc";
echo floatval($str);

?>
--EXPECT--
floatval("1234.567abc") = 1234.567

Added doc/tests1all/fmod.phpt.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
--TEST--
fmod
--FILE--
<?php

$r = fmod(5.7, 1.3);
echo "fmod(5.7, 1.3) = $r\n";

?>
--EXPECT--
fmod(5.7, 1.3) = 0.5

Added doc/tests1all/fnmatch.phpt.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
--TEST--
fnmatch
--FILE--
<?php

$text = "Some text goes here...";
echo '$text = "Some text goes here...";';
echo "\nfnmatch('go*', $text) = ". (fnmatch('go*', $text) ?1:0);
echo "\nfnmatch('*go', $text) = ". (fnmatch('*go', $text) ?1:0);
echo "\nfnmatch('*go*', $text) = ". (fnmatch('*go*', $text) ?1:0);
echo "\nfnmatch('*te?x*', $text) = ". (fnmatch('*te?x*', $text) ?1:0);
echo "\nfnmatch('*te?t*', $text) = ". (fnmatch('*te?t*', $text) ?1:0);
echo "\nfnmatch('So?m*', $text) = ". (fnmatch('So?m*', $text) ?1:0);
echo "\nfnmatch('So*m*', $text) = ". (fnmatch('*So*m*', $text) ?1:0);

?>
--EXPECT--
$text = "Some text goes here...";
fnmatch('go*', Some text goes here...) = 0
fnmatch('*go', Some text goes here...) = 0
fnmatch('*go*', Some text goes here...) = 1
fnmatch('*te?x*', Some text goes here...) = 0
fnmatch('*te?t*', Some text goes here...) = 1
fnmatch('So?m*', Some text goes here...) = 0
fnmatch('So*m*', Some text goes here...) = 1

Added doc/tests1all/get_headers.phpt.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--TEST--
get_headers
--FILE--
<?php

$r = get_headers("http://localhost/");
print_r($r);

?>
--EXPECT--
Array
(
    [0] => HTTP/1.1 200 OK
    [1] => Date: Mon, 30 Jul 2007 04:38:37 GMT
    [2] => Server: aEGiS_nanoweb/2.2.8 (Linux; PHP/5.2.1)
    [3] => Content-Type: text/html
    [4] => Last-Modified: Fri, 01 Sep 2006 16:22:06 GMT
    [5] => ETag: "19e700:6r0x:44f85e2e:99d"
    [6] => Accept-Ranges: bytes
    [7] => Connection: close
    [8] => Content-Length: 2461
)

Added doc/tests1all/gettext.phpt.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
--TEST--
gettext
--FILE--
<?php

#-- load
echo "bindtextdomain(\"tar\");\n";
bindtextdomain("tar");
textdomain("tar");

#-- query
echo "_(\"stdin\") == \"";
echo _("stdin");
echo "\"\n";

?>
--EXPECT--
bindtextdomain("tar");

Warning: Wrong parameter count for bindtextdomain() in /home/mario/www/berli/upgradephp/doc/tests1all/gettext on line 5
_("stdin") == "stdin"

Added doc/tests1all/glob.phpt.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--TEST--
glob
--FILE--
<?php

echo 'glob("../tests/*m*") = ';
$r = glob("../tests/*m*");
print_r($r);


?>
--EXPECT--
glob("../tests/*m*") = Array
(
)

Added doc/tests1all/gzdecode.phpt.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--TEST--
gzdecode
--FILE--
<?php

$orig =
"ORIGINAL_TEXT.................................................................................................................................................................................................................................End";
$gz = gzencode($orig);
echo "strlen(\$orig) == ".strlen($orig)."\n";
echo "strlen(\$gz) == ".strlen($gz)."\n...\n";

$text = gzdecode($gz);
echo "gzdecode(\$gz) = \"$text\"\n\n";


?>
--EXPECT--
strlen($orig) == 241
strlen($gz) == 39
...
gzdecode($gz) = "ORIGINAL_TEXT.................................................................................................................................................................................................................................End"

Added doc/tests1all/headers_list.phpt.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
--TEST--
headers_list
--FILE--
<?php

header("Content-Type: text/x-display-on-console");
header("X-Server: upgradephp-test/2.75.01d");
echo "header(\"...\");\n\n";

echo "\$r = headers_list();\n\n";
error_reporting(E_ALL);
$r = headers_list();
print_r($r);

?>
--EXPECT--
header("...");

$r = headers_list();

Array
(
)

Added doc/tests1all/html_entity_decode.phpt.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
--TEST--
html_entity_decode
--FILE--
<?php

echo 'html_entity_decode("&lt;&amp;&gt;&auml;&szlig;") = ';
echo html_entity_decode("&lt;&amp;&gt;&auml;&szlig;");

?>
--EXPECT--
html_entity_decode("&lt;&amp;&gt;&auml;&szlig;") = <&>

Added doc/tests1all/http_build_query.phpt.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
--TEST--
http_build_query
--FILE--
<?php


?>
$data = array('foo', 'bar', "sub"=>array('b', 'c'), 'cow' => 'milk', 'php' =>'hypertext processor');
echo http_build_query($data, "num_");

<?php
$data = array('foo', 'bar', "sub"=>array('b', 'c'), 'cow' => 'milk', 'php' =>'hypertext processor');
echo http_build_query($data, "num_");
?>
--EXPECT--
$data = array('foo', 'bar', "sub"=>array('b', 'c'), 'cow' => 'milk', 'php' =>'hypertext processor');
echo http_build_query($data, "num_");

num_0=foo&num_1=bar&sub%5B0%5D=b&sub%5B1%5D=c&cow=milk&php=hypertext+processor

Added doc/tests1all/is_a.phpt.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
--TEST--
is_a
--FILE--
<?php

class y {}
class x extends y {}
$x = new x;

echo is_a($x, "x") ? "works" : "failed";
echo "\n";
echo is_a($x, "y") ? "works" : "failed";

?>
--EXPECT--
works
works

Added doc/tests1all/json.phpt.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
--TEST--
json
--FILE--
<?php

$a = array(
  "x" => "y",
  "text" => "Hallchen
",
  "abc" => TRUE,
  "int" => 512,
  "float" => 3.14159,
  "null" => NULL,
  "sub" => array(1,2,3),
  "sub2" => array(1,2,"a"=>3),
);

for ($n=0; $n<1000; $n++)
$js = json_encode($a);

echo "$js\n";

?>
--EXPECT--
{"x":"y","text":"Hall","abc":true,"int":512,"float":3.14159,"null":null,"sub":[1,2,3],"sub2":{"0":1,"1":2,"a":3}}

Added doc/tests1all/json2.phpt.





































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
--TEST--
json2
--FILE--
<?php
error_reporting(E_ALL);

$s = ' { "A" : [ 1 , 2 ] , "B" : [ 3.1 , 4.2e10 ]   } ';
$s =<<<END
{"menu": {
    "header": "SVG Viewer",
    "items": [
        {"id": "Open"},
        {"id": "OpenNew", "label": "Open New"},
        null,
        {"id": "ZoomIn", "label": "Zoom In"},
        {"id": "ZoomOut", "label": "Zoom Out"},
        {"id": "OriginalView", "label": "Original View"},
        null,
        {"id": "Quality"},
        {"id": "Pause"},
        {"id": "Mute"},
        null,
        {"id": "Find", "label": "Find..."},
        {"id": "FindAgain", "label": "Find Again"},
        {"id": "Copy"},
        {"id": "CopyAgain", "label": "Copy Again"},
        {"id": "CopySVG", "label": "Copy SVG"},
        {"id": "ViewSVG", "label": "View SVG"},
        {"id": "ViewSource", "label": "View Source"},
        {"id": "SaveAs", "label": "Save As"},
        null,
        {"id": "Help"},
        {"id": "About", "label": "About Adobe CVG Viewer..."}
    ]
}}
END;

for ($n=0;$n<1000;$n++) {
  $a = json_decode($s, 0);
}
print_r($a);

?>
--EXPECT--
stdClass Object
(
    [menu] => stdClass Object
        (
            [header] => SVG Viewer
            [items] => Array
                (
                    [0] => stdClass Object
                        (
                            [id] => Open
                        )

                    [1] => stdClass Object
                        (
                            [id] => OpenNew
                            [label] => Open New
                        )

                    [2] => 
                    [3] => stdClass Object
                        (
                            [id] => ZoomIn
                            [label] => Zoom In
                        )

                    [4] => stdClass Object
                        (
                            [id] => ZoomOut
                            [label] => Zoom Out
                        )

                    [5] => stdClass Object
                        (
                            [id] => OriginalView
                            [label] => Original View
                        )

                    [6] => 
                    [7] => stdClass Object
                        (
                            [id] => Quality
                        )

                    [8] => stdClass Object
                        (
                            [id] => Pause
                        )

                    [9] => stdClass Object
                        (
                            [id] => Mute
                        )

                    [10] => 
                    [11] => stdClass Object
                        (
                            [id] => Find
                            [label] => Find...
                        )

                    [12] => stdClass Object
                        (
                            [id] => FindAgain
                            [label] => Find Again
                        )

                    [13] => stdClass Object
                        (
                            [id] => Copy
                        )

                    [14] => stdClass Object
                        (
                            [id] => CopyAgain
                            [label] => Copy Again
                        )

                    [15] => stdClass Object
                        (
                            [id] => CopySVG
                            [label] => Copy SVG
                        )

                    [16] => stdClass Object
                        (
                            [id] => ViewSVG
                            [label] => View SVG
                        )

                    [17] => stdClass Object
                        (
                            [id] => ViewSource
                            [label] => View Source
                        )

                    [18] => stdClass Object
                        (
                            [id] => SaveAs
                            [label] => Save As
                        )

                    [19] => 
                    [20] => stdClass Object
                        (
                            [id] => Help
                        )

                    [21] => stdClass Object
                        (
                            [id] => About
                            [label] => About Adobe CVG Viewer...
                        )

                )

        )

)

Added doc/tests1all/md5_file.phpt.





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
--TEST--
md5_file
--FILE--
md5_file(__FILE__) = <?php

echo md5_file(__FILE__);

?>
--EXPECT--
md5_file(__FILE__) = 187c2e06df4fb02560064398685e5113

Added doc/tests1all/mhash.phpt.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
--TEST--
mhash
--FILE--
<?php

echo "HMAC-MD5 test cases (RFC2104/page 9):\n\n";

# 1
$k = str_pad("", 16, chr(0x0b));
$text = "Hi There";
$end = unpack("H32", mhash(MHASH_MD5, $text, $k));
echo "key =     0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\n";
echo "data =    \"$text\"\n";
echo "digest =  0x$end[1]\n";
echo "should =  0x9294727a3638bb1c13f48ef8158bfc9d\n\n";

# 2
$k = "Jefe";
$text = "what do ya want for nothing?";
$end = unpack("H32", mhash(MHASH_MD5, $text, $k));
echo "key =     \"$k\"\n";
echo "data =    \"$text\"\n";
echo "digest =  0x$end[1]\n";
echo "should =  0x750c783e6ab0b503eaa86e310a5db738\n\n";



?>
--EXPECT--
HMAC-MD5 test cases (RFC2104/page 9):


Fatal error: Call to undefined function mhash() in /home/mario/www/berli/upgradephp/doc/tests1all/mhash on line 8

Added doc/tests1all/mime_content_type.phpt.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
--TEST--
mime_content_type
--FILE--
<?php

$t = mime_content_type(__FILE__);
echo "mime_content_type(__FILE__) = $t\n\n";

?>
--EXPECT--
mime_content_type(__FILE__) = text/plain

Added doc/tests1all/scandir.phpt.























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
--TEST--
scandir
--FILE--
<?php

$r = scandir("..");
echo "..\n\n";
print_r($r);

?>
--EXPECT--
..

Array
(
    [0] => .
    [1] => ..
    [2] => README
    [3] => ctest
    [4] => devtools
    [5] => gettext.txt
    [6] => index.xhtml
    [7] => runtest
    [8] => tests0old
    [9] => tests1all
    [10] => tests2filter
)

Added doc/tests1all/spl_classes.phpt.























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
--TEST--
spl_classes
--FILE--
<?php

echo "print_r(spl_classes());\n\n";
$r=spl_classes();
print_r($r);

?>
--EXPECT--
print_r(spl_classes());

Array
(
    [AppendIterator] => AppendIterator
    [ArrayIterator] => ArrayIterator
    [ArrayObject] => ArrayObject
    [BadFunctionCallException] => BadFunctionCallException
    [BadMethodCallException] => BadMethodCallException
    [CachingIterator] => CachingIterator
    [Countable] => Countable
    [DirectoryIterator] => DirectoryIterator
    [DomainException] => DomainException
    [EmptyIterator] => EmptyIterator
    [FilterIterator] => FilterIterator
    [InfiniteIterator] => InfiniteIterator
    [InvalidArgumentException] => InvalidArgumentException
    [IteratorIterator] => IteratorIterator
    [LengthException] => LengthException
    [LimitIterator] => LimitIterator
    [LogicException] => LogicException
    [NoRewindIterator] => NoRewindIterator
    [OuterIterator] => OuterIterator
    [OutOfBoundsException] => OutOfBoundsException
    [OutOfRangeException] => OutOfRangeException
    [OverflowException] => OverflowException
    [ParentIterator] => ParentIterator
    [RangeException] => RangeException
    [RecursiveArrayIterator] => RecursiveArrayIterator
    [RecursiveCachingIterator] => RecursiveCachingIterator
    [RecursiveDirectoryIterator] => RecursiveDirectoryIterator
    [RecursiveFilterIterator] => RecursiveFilterIterator
    [RecursiveIterator] => RecursiveIterator
    [RecursiveIteratorIterator] => RecursiveIteratorIterator
    [RecursiveRegexIterator] => RecursiveRegexIterator
    [RegexIterator] => RegexIterator
    [RuntimeException] => RuntimeException
    [SeekableIterator] => SeekableIterator
    [SimpleXMLIterator] => SimpleXMLIterator
    [SplFileInfo] => SplFileInfo
    [SplFileObject] => SplFileObject
    [SplObjectStorage] => SplObjectStorage
    [SplObserver] => SplObserver
    [SplSubject] => SplSubject
    [SplTempFileObject] => SplTempFileObject
    [UnderflowException] => UnderflowException
    [UnexpectedValueException] => UnexpectedValueException
)

Added doc/tests1all/str_ireplace.phpt.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
--TEST--
str_ireplace
--FILE--
<?php

$text = "ABC_abc_DEF_def_AAaaAAaa_DDddEEee";
echo "\$text = \"$text\";\n";
echo 'str_ireplace("abc", "xxx", $text);'."\n\n";

$text = str_ireplace("abc", "xxx", $text);
echo "\$text = \"$text\";\n";

?>
--EXPECT--
$text = "ABC_abc_DEF_def_AAaaAAaa_DDddEEee";
str_ireplace("abc", "xxx", $text);

$text = "xxx_xxx_DEF_def_AAaaAAaa_DDddEEee";

Added doc/tests1all/str_rot13.phpt.





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
--TEST--
str_rot13
--FILE--
str_rot13('upgrade.php v4') = "<?php

echo str_rot13('upgrade.php v4');

?>"
--EXPECT--
str_rot13('upgrade.php v4') = "hctenqr.cuc i4"

Added doc/tests1all/str_shuffle.phpt.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
--TEST--
str_shuffle
--FILE--
str_shuffle("ABCDEF") == "<?php

srand(17);
echo str_shuffle("ABCDEF");

?>"
--EXPECT--
str_shuffle("ABCDEF") == "FBCEAD"

Added doc/tests1all/str_split.phpt.

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
--TEST--
str_split
--FILE--
<?php


?>
$str = "Hello Friend";
$r = str_split($str, 3);
print_r($r);

<?php
$str = "Hello_Friend";
$r = str_split($str, 3);
print_r($r);
?>
--EXPECT--
$str = "Hello Friend";
$r = str_split($str, 3);
print_r($r);

Array
(
    [0] => Hel
    [1] => lo_
    [2] => Fri
    [3] => end
)

Added doc/tests1all/str_word_count.phpt.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--TEST--
str_word_count
--FILE--
<?php


$r = str_word_count("This is-a sample string.", 2);
echo 'str_word_count("This is-a sample string.", 2) = ';
print_r($r);


?>
--EXPECT--
str_word_count("This is-a sample string.", 2) = Array
(
    [0] => This
    [5] => is-a
    [10] => sample
    [17] => string
)

Added doc/tests1all/strftime.phpt.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--TEST--
strftime
--FILE--
<?php


$format = "time=%T date=%D";
$str = strftime($format, time());

$r = strptime($str, $format);

echo "$str\n";
print_r($r);


?>
--EXPECT--
time=06:38:38 date=07/30/07
Array
(
    [tm_sec] => 38
    [tm_min] => 38
    [tm_hour] => 6
    [tm_mday] => 30
    [tm_mon] => 6
    [tm_year] => 107
    [tm_wday] => 1
    [tm_yday] => 210
    [unparsed] => 
)

Added doc/tests1all/stripos.phpt.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
--TEST--
stripos
--FILE--
<?php

$l = stripos("ABCDEFef", "e");
echo "stripos(\"ABCDEFef\", \"e\") == $l\n\n";

$r = strripos("ABCDefEF", "e");
echo "strripos(\"ABCDefEF\", \"e\") == $r\n\n";

?>
--EXPECT--
stripos("ABCDEFef", "e") == 4

strripos("ABCDefEF", "e") == 6

Added doc/tests1all/strpbrk.phpt.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
--TEST--
strpbrk
--FILE--
<?php

?>
$text = 'This is a Simple text.';

echo strpbrk($text, 'mi');
<?php
$text = 'This is a Simple text.';
echo strpbrk($text, 'mi')."\n\n";

echo 'echo strpbrk($text, "S");'."\n";
echo strpbrk($text, "S")."\n\n";
?>
--EXPECT--
$text = 'This is a Simple text.';

echo strpbrk($text, 'mi');
is is a Simple text.

echo strpbrk($text, "S");
Simple text.

Added doc/tests1all/strripos.phpt.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
--TEST--
strripos
--FILE--
<?php

echo 'strripos("aaaabc_DEFff_ABCccc", "a") == ';
echo strripos("aaaabc_DEFff_ABCccc", "a");

?>
--EXPECT--
strripos("aaaabc_DEFff_ABCccc", "a") == 13

Added doc/tests1all/substr_compare.phpt.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--TEST--
substr_compare
--FILE--
<?php


echo 'substr_compare("abcde", "bc", 1, 2) == '. substr_compare("abcde", "bc", 1, 2) . "   // 0\n";
echo 'substr_compare("abcde", "bcg", 1, 2) == '. substr_compare("abcde", "bcg", 1, 2). "   // 0\n"; 
echo 'substr_compare("abcde", "BC", 1, 2, true) == '. substr_compare("abcde", "BC", 1, 2, true) . "   // 0\n";
echo 'substr_compare("abcde", "bc", 1, 3) == '. substr_compare("abcde", "bc", 1, 3) ."   // 1\n";
echo 'substr_compare("abcde", "cd", 1, 2) == '. substr_compare("abcde", "cd", 1, 2) ."  // -1\n";
echo 'substr_compare("abcde", "abc", 5, 1) == '. substr_compare("abcde", "abc", 5, 1) . "   // warning\n";
?>
--EXPECT--
substr_compare("abcde", "bc", 1, 2) == 0   // 0
substr_compare("abcde", "bcg", 1, 2) == 0   // 0
substr_compare("abcde", "BC", 1, 2, true) == 0   // 0
substr_compare("abcde", "bc", 1, 3) == 1   // 1
substr_compare("abcde", "cd", 1, 2) == -1  // -1

Warning: substr_compare(): The length cannot exceed initial string length in /home/mario/www/berli/upgradephp/doc/tests1all/substr_compare.php on line 9
substr_compare("abcde", "abc", 5, 1) ==    // warning

Added doc/tests1all/uuencode.phpt.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
--TEST--
uuencode
--FILE--
<?php

$uu = convert_uuencode("ABCDEFGHIJ");
echo "\$uu = \"$uu\"\n\n";

$text = convert_uudecode($uu);
echo "\$text = \"$text\"\n\n";

?>
--EXPECT--
$uu = "*04)#1$5&1TA)2@``
`
"

$text = "ABCDEFGHIJ"

Added doc/tests1all/vprintf.phpt.





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
--TEST--
vprintf
--FILE--
<?php

vprintf("%d, %d\n", array(17, 5));

?>
--EXPECT--
17, 5

Added doc/tests2filter/001.phpt.

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
--TEST--
Simple GET test
--GET--
a=1
--FILE--
<?php echo $_GET['a']; ?>
--EXPECT--
1

Added doc/tests2filter/002.phpt.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
--TEST--
GET test with 2 values and an empty one
--GET--
a=1&b=&c=3
--FILE--
<?php echo $_GET['a'];
echo $_GET['b']; 
echo $_GET['c'];
?>
--EXPECT--
13

Added doc/tests2filter/003.phpt.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--TEST--
GET/POST/REQUEST Test
--POST--
d=4&e=5
--GET--
a=1&b=&c=3
--FILE--
<?php echo $_GET['a'];
echo $_GET['b']; 
echo $_GET['c'];
echo $_POST['d'];
echo $_POST['e'];
echo "\n";
echo $_REQUEST['a'];
echo $_REQUEST['b'];
echo $_REQUEST['c'];
echo $_REQUEST['d'];
echo $_REQUEST['e'];
?>
--EXPECT--
1345
1345

Added doc/tests2filter/004.phpt.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--TEST--
GET/POST/REQUEST Test with filtered data
--SKIPIF--
<?php
/* CGI doesn't read commandline options when it sees REQUES_METHOD */
die("skip");
die("not possible to set ini setting using -d and CGI");
?>
--INI--
filter.default=special_chars
--POST--
d="quotes"&e=\slash
--GET--
a=O'Henry&b=&c=<b>Bold</b>
--FILE--
<?php echo $_GET['a'];
echo $_GET['b']; 
echo $_GET['c'];
echo $_POST['d'];
echo $_POST['e'];
echo "\n";
echo $_REQUEST['a'];
echo $_REQUEST['b'];
echo $_REQUEST['c'];
echo $_REQUEST['d'];
echo $_REQUEST['e'];
?>
--EXPECT--
O&#39;HenryBold&quot;quotes&quot;\slash
O&#39;HenryBold&quot;quotes&quot;\slash

Added doc/tests2filter/005.phpt.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
--TEST--
GET/REQUEST Test with fifa example data
--INI--
filter.default=stripped
--GET--
id=f03_photos&pgurl=http%3A//fifaworldcup.yahoo.com/03/en/photozone/index.html
--FILE--
<?php 
echo $_GET['id'];
echo "\n";
echo $_GET['pgurl']; 
echo "\n";
echo $_REQUEST['id'];
echo "\n";
echo $_REQUEST['pgurl']; 
?>
--EXPECT--
f03_photos
http://fifaworldcup.yahoo.com/03/en/photozone/index.html
f03_photos
http://fifaworldcup.yahoo.com/03/en/photozone/index.html

Added doc/tests2filter/006.phpt.





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
--TEST--
filter() test
--POST--
foo=<b>abc</b>
--FILE--
<?php 
echo filter_input(INPUT_POST, 'foo', FILTER_SANITIZE_STRIPPED);
?>
--EXPECT--
abc

Added doc/tests2filter/007.phpt.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
--TEST--
input_has_variable()
--SKIPIF--
<?php
/* TODO: Check why we get warnings 2x */
die("skip");
die("error mode cannot be changed via -d");
?>
--GET--
a=qwe&abc=<a>href</a>
--POST--
b=qwe&bbc=<a>href</a>
--FILE--
<?php

var_dump(input_has_variable(INPUT_GET, "a"));
var_dump(input_has_variable(INPUT_GET, "abc"));
var_dump(input_has_variable(INPUT_GET, "nonex"));
var_dump(input_has_variable(INPUT_GET, " "));
var_dump(input_has_variable(INPUT_GET, ""));
var_dump(input_has_variable(INPUT_GET, array()));

var_dump(input_has_variable(INPUT_POST, "b"));
var_dump(input_has_variable(INPUT_POST, "bbc"));
var_dump(input_has_variable(INPUT_POST, "nonex"));
var_dump(input_has_variable(INPUT_POST, " "));
var_dump(input_has_variable(INPUT_POST, ""));
var_dump(input_has_variable(INPUT_POST, array()));

var_dump(input_has_variable(-1, ""));
var_dump(input_has_variable("", ""));
var_dump(input_has_variable(array(), array()));
var_dump(input_has_variable(array(), ""));
var_dump(input_has_variable("", array()));

echo "Done\n";
?>
--EXPECTF--	
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)

Warning: input_has_variable() expects parameter 2 to be string, array given in %s on line %d
NULL
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)

Warning: input_has_variable() expects parameter 2 to be string, array given in %s on line %d
NULL
bool(false)

Warning: input_has_variable() expects parameter 1 to be long, string given in %s on line %d
NULL

Warning: input_has_variable() expects parameter 1 to be long, array given in %s on line %d
NULL

Warning: input_has_variable() expects parameter 1 to be long, array given in %s on line %d
NULL

Warning: input_has_variable() expects parameter 1 to be long, string given in %s on line %d
NULL
Done

Added doc/tests2filter/008.phpt.











































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
--TEST--
filter_list()
--FILE--
<?php

var_dump(filter_list());
var_dump(filter_list(array()));

echo "Done\n";
?>
--EXPECTF--	
array(18) {
  [0]=>
  string(3) "int"
  [1]=>
  string(7) "boolean"
  [2]=>
  string(5) "float"
  [3]=>
  string(15) "validate_regexp"
  [4]=>
  string(12) "validate_url"
  [5]=>
  string(14) "validate_email"
  [6]=>
  string(11) "validate_ip"
  [7]=>
  string(6) "string"
  [8]=>
  string(8) "stripped"
  [9]=>
  string(7) "encoded"
  [10]=>
  string(13) "special_chars"
  [11]=>
  string(10) "unsafe_raw"
  [12]=>
  string(5) "email"
  [13]=>
  string(3) "url"
  [14]=>
  string(10) "number_int"
  [15]=>
  string(12) "number_float"
  [16]=>
  string(12) "magic_quotes"
  [17]=>
  string(8) "callback"
}

Warning: Wrong parameter count for filter_list() in %s008.php on line 4
NULL
Done

Added doc/tests2filter/009.phpt.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
--TEST--
filter_id()
--FILE--
<?php

var_dump(filter_id("stripped"));
var_dump(filter_id("string"));
var_dump(filter_id("url"));
var_dump(filter_id("int"));
var_dump(filter_id("none"));
var_dump(filter_id(array()));
var_dump(filter_id(-1));
var_dump(filter_id(0,0,0));

echo "Done\n";
?>
--EXPECTF--	
int(513)
int(513)
int(518)
int(257)
bool(false)

Warning: filter_id() expects parameter 1 to be string, array given in %s009.php on line %d
NULL
bool(false)

Warning: filter_id() expects exactly 1 parameter, 3 given in %s009.php on line %d
NULL
Done
--UEXPECTF--
int(513)
int(513)
int(518)
int(257)
bool(false)

Warning: filter_id() expects parameter 1 to be binary string, array given in %s009.php on line %d
NULL
bool(false)

Warning: filter_id() expects exactly 1 parameter, 3 given in %s009.php on line %d
NULL
Done

Added doc/tests2filter/010.phpt.

























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
--TEST--
filter_var()
--FILE--
<?php

var_dump(filter_var(array(1,"1","", "-23234", "text", "asdf234asdfgs", array()), FILTER_VALIDATE_INT, FILTER_REQUIRE_ARRAY));
var_dump(filter_var(array(1.2,"1.7","", "-23234.123", "text", "asdf234.2asdfgs", array()), FILTER_VALIDATE_FLOAT, FILTER_REQUIRE_ARRAY));
var_dump(filter_var(1, array()));
var_dump(filter_var(1, FILTER_SANITIZE_STRING, 1));
var_dump(filter_var(1, FILTER_SANITIZE_STRING, 0));
var_dump(filter_var(1, FILTER_SANITIZE_STRING, array()));
var_dump(filter_var(1, -1, array(123)));
var_dump(filter_var(1, 0, array()));

echo "Done\n";
?>
--EXPECTF--	
array(7) {
  [0]=>
  int(1)
  [1]=>
  int(1)
  [2]=>
  bool(false)
  [3]=>
  int(-23234)
  [4]=>
  bool(false)
  [5]=>
  bool(false)
  [6]=>
  array(0) {
  }
}
array(7) {
  [0]=>
  float(1.2)
  [1]=>
  float(1.7)
  [2]=>
  bool(false)
  [3]=>
  float(-23234.123)
  [4]=>
  bool(false)
  [5]=>
  bool(false)
  [6]=>
  array(0) {
  }
}

Warning: filter_var() expects parameter 2 to be long, array given in %s on line %d
NULL
string(1) "1"
string(1) "1"
string(1) "1"
string(1) "1"
string(1) "1"
Done

Added doc/tests2filter/011.phpt.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
--TEST--
input_get()
--SKIPIF--
<?php
/* TODO: Check why we get warnings 2x */
die("skip");
die("error mode cannot be changed via -d");
?>
--GET--
a=<b>test</b>&b=http://example.com
--POST--
c=<p>string</p>&d=12345.7
--FILE--
<?php
ini_set('html_errors', false);
var_dump(input_get(INPUT_GET, "a", FILTER_SANITIZE_STRIPPED));
var_dump(input_get(INPUT_GET, "b", FILTER_SANITIZE_URL));
var_dump(input_get(INPUT_GET, "a", FILTER_SANITIZE_SPECIAL_CHARS, array(1,2,3,4,5)));
var_dump(input_get(INPUT_GET, "b", FILTER_VALIDATE_FLOAT, new stdClass));
var_dump(input_get(INPUT_POST, "c", FILTER_SANITIZE_STRIPPED, array(5,6,7,8)));
var_dump(input_get(INPUT_POST, "d", FILTER_VALIDATE_FLOAT));
var_dump(input_get(INPUT_POST, "c", FILTER_SANITIZE_SPECIAL_CHARS));
var_dump(input_get(INPUT_POST, "d", FILTER_VALIDATE_INT));

var_dump(input_get(new stdClass, "d"));

var_dump(input_get(INPUT_POST, "c", "", ""));
var_dump(input_get("", "", "", "", ""));
var_dump(input_get(0, 0, 0, 0, 0));

echo "Done\n";
?>
--EXPECTF--	
string(4) "test"
string(18) "http://example.com"
string(27) "&#60;b&#62;test&#60;/b&#62;"
bool(false)
string(6) "string"
float(12345.7)
string(29) "&#60;p&#62;string&#60;/p&#62;"
bool(false)

Warning: input_get() expects parameter 1 to be long, object given in %s on line %d
NULL

Warning: input_get() expects parameter 3 to be long, string given in %s on line %d
NULL

Warning: input_get() expects parameter 1 to be long, string given in %s on line %d
NULL
NULL
Done

Added doc/tests2filter/012.phpt.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
--TEST--
filter_input()
--FILE--
<?php

var_dump(filter_input(INPUT_GET, "test"));
var_dump(filter_input(INPUT_POST, "test"));
var_dump(filter_input(INPUT_COOKIE, ""));

echo "Done\n";
?>
--EXPECT--	
NULL
NULL
NULL
Done

Added doc/tests2filter/013.phpt.

















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
--TEST--
filter_var() and flags
--FILE--
<?php
var_dump(filter_var("  234", FILTER_VALIDATE_INT));
var_dump(filter_var("234    ", FILTER_VALIDATE_INT));
var_dump(filter_var("  234  ", FILTER_VALIDATE_INT));
var_dump(filter_var("0xff", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("0Xff", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("0xFF", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("0XFF", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("07", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
var_dump(filter_var("0xff0000", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("0666", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
var_dump(filter_var("08", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
var_dump(filter_var("00", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
var_dump(filter_var("000", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));

var_dump(filter_var("-0xff", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("-0Xff", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("-0xFF", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("-0XFF", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("-07", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
var_dump(filter_var("-0xff0000", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
var_dump(filter_var("-0666", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));

var_dump(filter_var("6", FILTER_VALIDATE_INT, array("options" => array("min_range"=>1, "max_range"=>7))));
var_dump(filter_var("6", FILTER_VALIDATE_INT, array("options" => array("min_range"=>0, "max_range"=>5))));
var_dump(filter_var(-1, FILTER_VALIDATE_INT, array("options" => array("min_range"=>1, "max_range"=>7))));
var_dump(filter_var(-1, FILTER_VALIDATE_INT, array("options" => array("min_range"=>-4, "max_range"=>7))));

var_dump(filter_var("", FILTER_VALIDATE_INT, array("options" => array("min_range"=>-4, "max_range"=>7))));
var_dump(filter_var("", FILTER_VALIDATE_INT, array("options" => array("min_range"=>2, "max_range"=>7))));
var_dump(filter_var("", FILTER_VALIDATE_INT, array("options" => array("min_range"=>-5, "max_range"=>-3))));
var_dump(filter_var(345, FILTER_VALIDATE_INT, array("options" => array("min_range"=>500, "max_range"=>100))));
var_dump(filter_var("0ff", FILTER_VALIDATE_INT));
var_dump(filter_var("010", FILTER_VALIDATE_INT));

echo "Done\n";
?>
--EXPECT--	
int(234)
int(234)
int(234)
int(255)
int(255)
int(255)
int(255)
int(7)
int(16711680)
int(438)
bool(false)
int(0)
int(0)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
int(6)
bool(false)
bool(false)
int(-1)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
Done

Added doc/tests2filter/014.phpt.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
--TEST--
filter_var() and FILTER_VALIDATE_BOOLEAN
--FILE--
<?php

class test {

	function __toString() {
		return "blah";
	}
}

$t = new test;

var_dump(filter_var("no", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var(NULL, FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var($t, FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var(array(1,2,3,0,array("", "123")), FILTER_VALIDATE_BOOLEAN, FILTER_REQUIRE_ARRAY));
var_dump(filter_var("yes", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("true", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("false", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("off", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("on", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("0", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("1", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("NONE", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var(-1, FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("000000", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("111111", FILTER_VALIDATE_BOOLEAN));
	

echo "Done\n";
?>
--EXPECT--	
bool(false)
bool(false)
bool(false)
array(5) {
  [0]=>
  bool(true)
  [1]=>
  bool(false)
  [2]=>
  bool(false)
  [3]=>
  bool(false)
  [4]=>
  array(2) {
    [0]=>
    bool(false)
    [1]=>
    bool(false)
  }
}
bool(true)
bool(true)
bool(false)
bool(false)
bool(true)
bool(false)
bool(true)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
Done

Added doc/tests2filter/015.phpt.















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
--TEST--
filter_var() and FILTER_VALIDATE_URL
--FILE--
<?php

$values = Array(
'http://example.com/index.html',	
'http://www.example.com/index.php',	
'http://www.example/img/test.png',	
'http://www.example/img/dir/',	
'http://www.example/img/dir',	
'http//www.example/wrong/url/',	
'http:/www.example',	
'file:///tmp/test.c',	
'ftp://ftp.example.com/tmp/',	
'/tmp/test.c',	
'/',	
'http://',	
'http:/',	
'http:',	
'http',	
'',	
-1,	
array(),	
);
foreach ($values as $value) {
	var_dump(filter_var($value, FILTER_VALIDATE_URL));
}


var_dump(filter_var("qwe", FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var("http://qwe", FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var("http://", FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var("/tmp/test", FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var("http://www.example.com", FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var("http://www.example.com", FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var("http://www.example.com/path/at/the/server/", FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var("http://www.example.com/index.html", FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED));
var_dump(filter_var("http://www.example.com/index.php?a=b&c=d", FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED));

echo "Done\n";
?>
--EXPECT--	
string(29) "http://example.com/index.html"
string(32) "http://www.example.com/index.php"
string(31) "http://www.example/img/test.png"
string(27) "http://www.example/img/dir/"
string(26) "http://www.example/img/dir"
string(28) "http//www.example/wrong/url/"
string(17) "http:/www.example"
string(18) "file:///tmp/test.c"
string(26) "ftp://ftp.example.com/tmp/"
string(11) "/tmp/test.c"
string(1) "/"
bool(false)
string(6) "http:/"
string(5) "http:"
string(4) "http"
string(0) ""
string(2) "-1"
bool(false)
bool(false)
string(10) "http://qwe"
bool(false)
bool(false)
string(22) "http://www.example.com"
bool(false)
string(42) "http://www.example.com/path/at/the/server/"
bool(false)
string(40) "http://www.example.com/index.php?a=b&c=d"
Done

Added doc/tests2filter/016.phpt.

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
--TEST--
filter_var() and FILTER_VALIDATE_EMAIL
--FILE--
<?php
$values = Array(
'a@b.c',	
'abuse@example.com',	
'test!.!@#$%^&*@example.com',	
'test@@#$%^&*())).com',	
'test@.com',	
'test@com',	
'@',	
'[]()/@example.com',	
'QWERTYUIOPASDFGHJKLZXCVBNM@QWERTYUIOPASDFGHJKLZXCVBNM.NET',	
);
foreach ($values as $value) {
	var_dump(filter_var($value, FILTER_VALIDATE_EMAIL));
}

echo "Done\n";
?>
--EXPECT--	
string(5) "a@b.c"
string(17) "abuse@example.com"
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
string(57) "QWERTYUIOPASDFGHJKLZXCVBNM@QWERTYUIOPASDFGHJKLZXCVBNM.NET"
Done

Added doc/tests2filter/017.phpt.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--TEST--
filter_var() and FILTER_VALIDATE_REGEXP
--FILE--
<?php

var_dump(filter_var("data", FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/.*/'))));
var_dump(filter_var("data", FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/^b(.*)/'))));
var_dump(filter_var("data", FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/^d(.*)/'))));
var_dump(filter_var("data", FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/blah/'))));
var_dump(filter_var("data", FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/\[/'))));
var_dump(filter_var("data", FILTER_VALIDATE_REGEXP));

echo "Done\n";
?>
--EXPECTF--	
string(4) "data"
bool(false)
string(4) "data"
bool(false)
bool(false)

Warning: filter_var(): 'regexp' option missing in %s on line %d
bool(false)
Done

Added doc/tests2filter/018.phpt.





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
--TEST--
filter_var() and FILTER_VALIDATE_IP
--FILE--
<?php
var_dump(filter_var("192.168.0.1", FILTER_VALIDATE_IP));
var_dump(filter_var("192.168.0.1.1", FILTER_VALIDATE_IP));
var_dump(filter_var("::1", FILTER_VALIDATE_IP));
var_dump(filter_var("fe00::0", FILTER_VALIDATE_IP));
var_dump(filter_var("::123456", FILTER_VALIDATE_IP));
var_dump(filter_var("::1::b", FILTER_VALIDATE_IP));
var_dump(filter_var("127.0.0.1", FILTER_VALIDATE_IP));
var_dump(filter_var("192.168.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE));
var_dump(filter_var("192.0.34.166", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE));
var_dump(filter_var("127.0.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var("192.0.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var("192.0.34.166", FILTER_VALIDATE_IP));
var_dump(filter_var("256.1237.123.1", FILTER_VALIDATE_IP));
var_dump(filter_var("255.255.255.255", FILTER_VALIDATE_IP));
var_dump(filter_var("255.255.255.255", FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var("", FILTER_VALIDATE_IP));
var_dump(filter_var(-1, FILTER_VALIDATE_IP));
var_dump(filter_var("::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV4));
var_dump(filter_var("127.0.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
var_dump(filter_var("::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
var_dump(filter_var("127.0.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV4));
echo "Done\n";
?>
--EXPECT--	
string(11) "192.168.0.1"
bool(false)
string(3) "::1"
string(7) "fe00::0"
bool(false)
bool(false)
string(9) "127.0.0.1"
bool(false)
string(12) "192.0.34.166"
string(9) "127.0.0.1"
string(9) "192.0.0.1"
string(12) "192.0.34.166"
bool(false)
string(15) "255.255.255.255"
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
string(3) "::1"
string(9) "127.0.0.1"
Done

Added doc/tests2filter/019.phpt.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--TEST--
filter_var() & FILTER_VALIDATE_IP and weird data
--FILE--
<?php

var_dump(filter_var("....", FILTER_VALIDATE_IP));
var_dump(filter_var("...", FILTER_VALIDATE_IP));
var_dump(filter_var("..", FILTER_VALIDATE_IP));
var_dump(filter_var(".", FILTER_VALIDATE_IP));
var_dump(filter_var("1.1.1.1", FILTER_VALIDATE_IP));

echo "Done\n";
?>
--EXPECT--	
bool(false)
bool(false)
bool(false)
bool(false)
string(7) "1.1.1.1"
Done

Added doc/tests2filter/020.phpt.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
--TEST--
filter_var() and FILTER_SANITIZE_MAGIC_QUOTES
--FILE--
<?php

var_dump(filter_var("test'asd'asd'' asd\'\"asdfasdf", FILTER_SANITIZE_MAGIC_QUOTES));
var_dump(filter_var("'", FILTER_SANITIZE_MAGIC_QUOTES));
var_dump(filter_var("", FILTER_SANITIZE_MAGIC_QUOTES));
var_dump(filter_var(-1, FILTER_SANITIZE_MAGIC_QUOTES));

echo "Done\n";
?>
--EXPECT--	
string(36) "test\'asd\'asd\'\' asd\\\'\"asdfasdf"
string(2) "\'"
string(0) ""
string(2) "-1"
Done

Added doc/tests2filter/021.phpt.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
--TEST--
filter_var() and FILTER_SANITIZE_NUMBER_*
--FILE--
<?php

var_dump(filter_var("qwertyu123456dfghj", FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var("asd123123.asd123.23", FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var("123,23", FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var("", FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var("0", FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var("asd123.2asd", FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var("qwertyuiop", FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var("123.4", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
var_dump(filter_var("123,4", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
var_dump(filter_var("123.4", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND));
var_dump(filter_var("123,4", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND));
var_dump(filter_var("123.4e", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC));
var_dump(filter_var("123,4E", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC));
var_dump(filter_var("qwe123,4qwe", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
var_dump(filter_var("werty65456.34", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
var_dump(filter_var("234.56fsfd", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
var_dump(filter_var("", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));

echo "Done\n";
?>
--EXPECT--	
string(6) "123456"
string(11) "12312312323"
string(5) "12323"
string(0) ""
string(1) "0"
string(4) "1232"
string(0) ""
string(5) "123.4"
string(4) "1234"
string(4) "1234"
string(5) "123,4"
string(5) "1234e"
string(5) "1234E"
string(4) "1234"
string(8) "65456.34"
string(6) "234.56"
string(0) ""
Done

Added doc/tests2filter/022.phpt.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--TEST--
filter_var() and FILTER_SANITIZE_EMAIL
--FILE--
<?php

var_dump(filter_var("a@b.c", FILTER_SANITIZE_EMAIL));
var_dump(filter_var("a[!@#$%^&*()@a@#$%^&*(.com@#$%^&*(", FILTER_SANITIZE_EMAIL));
var_dump(filter_var("white space here \ \ \" som more", FILTER_SANITIZE_EMAIL));
var_dump(filter_var("", FILTER_SANITIZE_EMAIL));
var_dump(filter_var("123456789000000", FILTER_SANITIZE_EMAIL));
	
echo "Done\n";
?>
--EXPECTF--	
string(5) "a@b.c"
string(30) "a[!@#$%^&*@a@#$%^&*.com@#$%^&*"
string(21) "whitespaceheresommore"
string(0) ""
string(15) "123456789000000"
Done

Added doc/tests2filter/023.phpt.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--TEST--
filter_var() and FILTER_UNSAFE_RAW
--FILE--
<?php

var_dump(filter_var("}\"<p>test para</p>", FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_AMP));
var_dump(filter_var("a[!@#<b>$%^&*()@a@#$%^&*(.<br>com@#$%^&*(", FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_AMP));
var_dump(filter_var("white space here \ \ \" some more", FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_AMP));
var_dump(filter_var("", FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_AMP));
var_dump(filter_var("             123456789000000       <qwertyuiop> ", FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_AMP));
	
echo "Done\n";
?>
--EXPECT--	
string(18) "}"<p>test para</p>"
string(53) "a[!@#<b>$%^&#38;*()@a@#$%^&#38;*(.<br>com@#$%^&#38;*("
string(32) "white space here \ \ " some more"
string(0) ""
string(48) "             123456789000000       <qwertyuiop> "
Done

Added doc/tests2filter/024.phpt.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
--TEST--
filter_var() and FILTER_SANITIZE_ENCODED
--FILE--
<?php

var_dump(filter_var("\"<br>blah</ph>", FILTER_SANITIZE_ENCODED));
var_dump(filter_var("", FILTER_SANITIZE_ENCODED));
var_dump(filter_var("  text here  ", FILTER_SANITIZE_ENCODED));
var_dump(filter_var("!@#$%^&*()QWERTYUIOP{ASDFGHJKL:\"ZXCVBNM<>?", FILTER_SANITIZE_ENCODED));

echo "Done\n";
?>
--EXPECT--	
string(26) "%22%3Cbr%3Eblah%3C%2Fph%3E"
string(0) ""
string(23) "%20%20text%20here%20%20"
string(74) "%21%40%23%24%25%5E%26%2A%28%29QWERTYUIOP%7BASDFGHJKL%3A%22ZXCVBNM%3C%3E%3F"
Done

Added doc/tests2filter/025.phpt.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--TEST--
filter_var() and FILTER_SANITIZE_STRING
--FILE--
<?php

var_dump(filter_var("", FILTER_SANITIZE_STRING));
var_dump(filter_var("<>", FILTER_SANITIZE_STRING));
var_dump(filter_var("<>!@#$%^&*()'\"", FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES));
var_dump(filter_var("<>!@#$%^&*()'\"", FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_AMP));
var_dump(filter_var("<>`1234567890", FILTER_SANITIZE_STRING));
var_dump(filter_var("`123`", FILTER_SANITIZE_STRING));
var_dump(filter_var(".", FILTER_SANITIZE_STRING));

echo "Done\n";
?>
--EXPECT--	
string(0) ""
string(0) ""
string(12) "!@#$%^&*()'""
string(32) "!@#$%^&#38;*()&#38;#39;&#38;#34;"
string(11) "`1234567890"
string(5) "`123`"
string(1) "."
Done

Added doc/tests2filter/026.phpt.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--TEST--
filter_var() and FILTER_SANITIZE_STRIPPED
--FILE--
<?php

var_dump(filter_var("<p>Let me <font color=\"#000000\">see</font> you <br /><b>Stripped</b> down to the bone</p>", FILTER_SANITIZE_STRIPPED));
var_dump(filter_var("!@#$%^&*()><<>+_\"'<br><p /><li />", FILTER_SANITIZE_STRIPPED));
var_dump(filter_var("", FILTER_SANITIZE_STRIPPED));

var_dump(filter_var("<p>Let me <font color=\"#000000\">see</font> you <br /><b>Stripped</b> down to the bone</p>", FILTER_SANITIZE_STRIPPED, FILTER_FLAG_STRIP_LOW));
var_dump(filter_var("!@#$%^&*()><<>+_\"'<br><p /><li />", FILTER_SANITIZE_STRIPPED, FILTER_FLAG_STRIP_LOW));
var_dump(filter_var("", FILTER_SANITIZE_STRIPPED, FILTER_FLAG_STRIP_LOW));

var_dump(filter_var("<p>Let me <font color=\"#000000\">see</font> you <br /><b>Stripped</b> down to the bone</p>", FILTER_SANITIZE_STRIPPED, FILTER_FLAG_STRIP_HIGH));
var_dump(filter_var("!@#$%^&*()><<>+_\"'<br><p /><li />", FILTER_SANITIZE_STRIPPED, FILTER_FLAG_STRIP_HIGH));
var_dump(filter_var("", FILTER_SANITIZE_STRIPPED, FILTER_FLAG_STRIP_HIGH));

echo "Done\n";
?>
--EXPECTF--	
string(40) "Let me see you Stripped down to the bone"
string(11) "!@#$%^&*()>"
string(0) ""
string(40) "Let me see you Stripped down to the bone"
string(11) "!@#$%^&*()>"
string(0) ""
string(40) "Let me see you Stripped down to the bone"
string(11) "!@#$%^&*()>"
string(0) ""
Done

Added doc/tests2filter/027.phpt.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--TEST--
filter_var() and FILTER_SANITIZE_ENCODED
--FILE--
<?php

var_dump(filter_var("?><!@#$%^&*()}{~Qwertyuilfdsasdfgmnbvcxcvbn", FILTER_SANITIZE_ENCODED));
var_dump(filter_var("<data&sons>", FILTER_SANITIZE_ENCODED));
var_dump(filter_var("", FILTER_SANITIZE_ENCODED));

var_dump(filter_var("?><!@#$%^&*()}{~Qwertyuilfdsasdfgmnbvcxcvbn", FILTER_SANITIZE_ENCODED, FILTER_FLAG_ENCODE_LOW));
var_dump(filter_var("<data&sons>", FILTER_SANITIZE_ENCODED, FILTER_FLAG_ENCODE_LOW));
var_dump(filter_var("", FILTER_SANITIZE_ENCODED, FILTER_FLAG_ENCODE_LOW));

var_dump(filter_var("?><!@#$%^&*()}{~Qwertyuilfdsasdfgmnbvcxcvbn", FILTER_SANITIZE_ENCODED, FILTER_FLAG_ENCODE_HIGH));
var_dump(filter_var("<data&sons>", FILTER_SANITIZE_ENCODED, FILTER_FLAG_ENCODE_HIGH));
var_dump(filter_var("", FILTER_SANITIZE_ENCODED, FILTER_FLAG_ENCODE_HIGH));

echo "Done\n";
?>
--EXPECT--	
string(75) "%3F%3E%3C%21%40%23%24%25%5E%26%2A%28%29%7D%7B%7EQwertyuilfdsasdfgmnbvcxcvbn"
string(17) "%3Cdata%26sons%3E"
string(0) ""
string(75) "%3F%3E%3C%21%40%23%24%25%5E%26%2A%28%29%7D%7B%7EQwertyuilfdsasdfgmnbvcxcvbn"
string(17) "%3Cdata%26sons%3E"
string(0) ""
string(75) "%3F%3E%3C%21%40%23%24%25%5E%26%2A%28%29%7D%7B%7EQwertyuilfdsasdfgmnbvcxcvbn"
string(17) "%3Cdata%26sons%3E"
string(0) ""
Done

Added doc/tests2filter/028.phpt.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
--TEST--
filter_var() and FILTER_SANITIZE_SPECIAL_CHARS
--FILE--
<?php

var_dump(filter_var("?><!@#$%^&*()}{~Qwertyuilfdsasdfgmnbvcxcvbn", FILTER_SANITIZE_SPECIAL_CHARS));
var_dump(filter_var("<data&sons>", FILTER_SANITIZE_SPECIAL_CHARS));
var_dump(filter_var("", FILTER_SANITIZE_SPECIAL_CHARS));

var_dump(filter_var("?><!@#$%^&*()}{~Qwertyuilfdsasdfgmnbvcxcvbn", FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_LOW));
var_dump(filter_var("<data&sons>", FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_LOW));
var_dump(filter_var("", FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_LOW));

var_dump(filter_var("?><!@#$%^&*()}{~Qwertyuilfdsasdfgmnbvcxcvbn", FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_HIGH));
var_dump(filter_var("<data&sons>", FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_HIGH));
var_dump(filter_var("", FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_HIGH));

var_dump(filter_var("кириллица", FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_HIGH));
var_dump(filter_var("кириллица", FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_LOW));

echo "Done\n";
?>
--EXPECT--	
string(55) "?&#62;&#60;!@#$%^&#38;*()}{~Qwertyuilfdsasdfgmnbvcxcvbn"
string(23) "&#60;data&#38;sons&#62;"
string(0) ""
string(55) "?&#62;&#60;!@#$%^&#38;*()}{~Qwertyuilfdsasdfgmnbvcxcvbn"
string(23) "&#60;data&#38;sons&#62;"
string(0) ""
string(55) "?&#62;&#60;!@#$%^&#38;*()}{~Qwertyuilfdsasdfgmnbvcxcvbn"
string(23) "&#60;data&#38;sons&#62;"
string(0) ""
string(108) "&#208;&#186;&#208;&#184;&#209;&#128;&#208;&#184;&#208;&#187;&#208;&#187;&#208;&#184;&#209;&#134;&#208;&#176;"
string(18) "кириллица"
Done

Added doc/tests2filter/029.phpt.















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
--TEST--
filter_var() and FILTER_CALLBACK
--FILE--
<?php

/* Simple callback function */
function test($var) {
	return strtoupper($var);
}
	
var_dump(filter_var("data", FILTER_CALLBACK, array("options"=>"test")));
var_dump(filter_var("~!@#$%^&*()_QWERTYUIOPASDFGHJKLZXCVBNM<>>?\"}{:", FILTER_CALLBACK, array("options"=>"test")));
var_dump(filter_var("", FILTER_CALLBACK, array("options"=>"test")));
var_dump(filter_var("qwe", FILTER_CALLBACK, array("options"=>"no such func")));
var_dump(filter_var("qwe", FILTER_CALLBACK, array("options"=>"")));
var_dump(filter_var("qwe", FILTER_CALLBACK));

/* Simple class method callback */
class test_class {
	static function test ($var) {
		return strtolower($var);
	}
}

var_dump(filter_var("dAtA", FILTER_CALLBACK, array("options"=>array("test_class", "test"))));
var_dump(filter_var("~!@#$%^&*()_QWERTYUIOPASDFGHJKLZXCVBNM<>>?\"}{:", FILTER_CALLBACK, array("options"=>array("test_class","test"))));
var_dump(filter_var("", FILTER_CALLBACK, array("options"=>array("test_class","test"))));

/* empty function without return value */
function test1($var) {
}
	
var_dump(filter_var("data", FILTER_CALLBACK, array("options"=>"test1")));
var_dump(filter_var("~!@#$%^&*()_QWERTYUIOPASDFGHJKLZXCVBNM<>>?\"}{:", FILTER_CALLBACK, array("options"=>"test1")));
var_dump(filter_var("", FILTER_CALLBACK, array("options"=>"test1")));

/* attempting to change data by reference */
function test2(&$var) {
	$var = 1;
}
	
var_dump(filter_var("data", FILTER_CALLBACK, array("options"=>"test2")));
var_dump(filter_var("~!@#$%^&*()_QWERTYUIOPASDFGHJKLZXCVBNM<>>?\"}{:", FILTER_CALLBACK, array("options"=>"test2")));
var_dump(filter_var("", FILTER_CALLBACK, array("options"=>"test2")));

/* unsetting data */
function test3(&$var) {
	unset($var);
}
	
var_dump(filter_var("data", FILTER_CALLBACK, array("options"=>"test3")));
var_dump(filter_var("~!@#$%^&*()_QWERTYUIOPASDFGHJKLZXCVBNM<>>?\"}{:", FILTER_CALLBACK, array("options"=>"test3")));
var_dump(filter_var("", FILTER_CALLBACK, array("options"=>"test3")));

/* unset data and return value */
function test4(&$var) {
	unset($var);
	return 1;
}
	
var_dump(filter_var("data", FILTER_CALLBACK, array("options"=>"test4")));

/* thrown exception in the callback */
function test5(&$var) {
	throw new Exception("test");
}

try {
	var_dump(filter_var("data", FILTER_CALLBACK, array("options"=>"test5")));
} catch (Exception $e) {
	var_dump($e->getMessage());
}

echo "Done\n";
?>
--EXPECTF--	
string(4) "DATA"
string(46) "~!@#$%^&*()_QWERTYUIOPASDFGHJKLZXCVBNM<>>?"}{:"
string(0) ""

Warning: filter_var(): First argument is expected to be a valid callback in %s on line %d
NULL

Warning: filter_var(): First argument is expected to be a valid callback in %s on line %d
NULL

Warning: filter_var(): First argument is expected to be a valid callback in %s on line %d
NULL
string(4) "data"
string(46) "~!@#$%^&*()_qwertyuiopasdfghjklzxcvbnm<>>?"}{:"
string(0) ""
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
int(1)
string(4) "test"
Done

Added doc/tests2filter/030.phpt.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
--TEST--
filter_var() and IPv6 
--FILE--
<?php
$ipv6_test = array(
	"::127.0.0.1"				=> true,
	"FF01::101:127.0.1" 		=> false,
	"FF01:0:0:0:101:127.0.1.1"  => false,
	"FF01:0:0:0:237:101:127.0.1.1"  => true,
	"FF01::101"					=> true,
	"A1080::8:800:200C:417A"	=> false,
	"1080::8:Z00:200C:417A"		=> false,
	"FF01::101::1"				=> false,
	"1080::8:800:200C:417A"		=> true,
	"1080:0:0:0:8:800:200C:417A" => true,
	"2001:ec8:1:1:1:1:1:1"			=> true,
	"ffff::FFFF:129.144.52.38"		=> true,
	"::ffff:1.2.3.4"				=> true,
	"0:0:0:0:0:FFFF:129.144.52.38" => true,
	"0:0:0:0:0:0:13.1.68.3"		=> true,
	"::13.1.68.3"				=> true,
    "::FFFF:129.144.52.38"		=> true
);
foreach ($ipv6_test as $ip => $exp) {
	$out = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
	$out = (int) ($out === false ? 0 : 1);
	if ($exp != $out) {
		echo "$ip failed\n";
	}
}

echo "Ok\n";
?>
--EXPECT--	
Ok

Added doc/tests2filter/031.phpt.













































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
--TEST--
filter_var() and FLOAT
--FILE--
<?php

$floats = array(
'1.234   ',
'   1.234',
'1.234'	,
'1.2e3',
'7E3',
'7E3     ',
'  7E3     ',
'  7E-3     '
);

foreach ($floats as $float) {
	$out = filter_var($float, FILTER_VALIDATE_FLOAT);
	var_dump($out);
}

$floats = array(
'1.234   '	=> ',',
'1,234'		=> ',',
'   1.234'	=> '.',
'1.234'		=> '..',
'1.2e3'		=> ','
);

echo "\ncustom decimal:\n";
foreach ($floats as $float => $dec) {
	$out = filter_var($float, FILTER_VALIDATE_FLOAT, array("options"=>array('decimal' => $dec)));
	var_dump($out);
}

?>
--EXPECTF--
float(1.234)
float(1.234)
float(1.234)
float(1200)
float(7000)
float(7000)
float(7000)
float(0.007)

custom decimal:
bool(false)
float(1.234)
float(1.234)

Warning: filter_var(): decimal separator must be one char in %s on line %d
bool(false)
bool(false)

Added doc/tests2filter/032.phpt.















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
--TEST--
input_get_args()
--FILE--
<?php
$data = array(
    'product_id'    => 'libgd<script>',
    'component'     => '10dhsajkkdhk <do>',
    'versions'      => '2.0.33',
    'testscalar'    => array('2','23','10','12'),
    'testarray'     => '2',
);

$args = array(
    'product_id'    => FILTER_SANITIZE_ENCODED,
    'component'     => array(//'filter' => FILTER_VALIDATE_INT,
                             'flags'    => FILTER_FORCE_ARRAY,
                             'options'  => array("min_range"=>1, "max_range"=>10)
                        ),
    'versions'      => array(
                            'filter' => FILTER_SANITIZE_ENCODED,
                            'flags'  => FILTER_REQUIRE_SCALAR,
                            ),
    'doesnotexist'  => FILTER_VALIDATE_INT,
    'testscalar'    => FILTER_VALIDATE_INT,
    'testarray' => array(
                            'filter' => FILTER_VALIDATE_INT,
                            'flags'  => FILTER_FORCE_ARRAY,
                        )

);

$myinputs = filter_var_array($data, $args);
var_dump($myinputs);
?>
--EXPECT--
array(6) {
  ["product_id"]=>
  string(17) "libgd%3Cscript%3E"
  ["component"]=>
  array(1) {
    [0]=>
    string(17) "10dhsajkkdhk <do>"
  }
  ["versions"]=>
  string(6) "2.0.33"
  ["doesnotexist"]=>
  NULL
  ["testscalar"]=>
  bool(false)
  ["testarray"]=>
  array(1) {
    [0]=>
    int(2)
  }
}

Added doc/tests2filter/033.phpt.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
--TEST--
Test all filters returned by filter_list()
--FILE--
<?php
include dirname(__FILE__) . '/033_run.inc';
?>
--EXPECT--     
int                      1                                               123                                               
boolean                  1                                                                                                 
float                    1                                               123                                               
validate_regexp                                                                                   O'Henry                  
validate_url        PHP  1  foo@bar.com    http://a.b.c        1.2.3.4   123  123abc<>()          O'Henry        하퍼    
validate_email              foo@bar.com                                                                                    
validate_ip                                                    1.2.3.4                                                     
string              PHP  1  foo@bar.com    http://a.b.c        1.2.3.4   123  123abc()            O&#39;Henry    하퍼    
stripped            PHP  1  foo@bar.com    http://a.b.c        1.2.3.4   123  123abc()            O&#39;Henry    하퍼    
encoded             PHP  1  foo%40bar.com  http%3A%2F%2Fa.b.c  1.2.3.4   123  123abc%3C%3E%28%29  O%27Henry      %ED%95%98%ED%8D%BC
special_chars       PHP  1  foo@bar.com    http://a.b.c        1.2.3.4   123  123abc&#60;&#62;()  O&#39;Henry    하퍼    
unsafe_raw          PHP  1  foo@bar.com    http://a.b.c        1.2.3.4   123  123abc<>()          O'Henry        하퍼    
email               PHP  1  foo@bar.com    http//a.b.c         1.2.3.4   123  123abc              O'Henry                  
url                 PHP  1  foo@bar.com    http://a.b.c        1.2.3.4   123  123abc<>()          O'Henry                  
number_int               1                                     1234      123  123                                          
number_float             1                                     1234      123  123                                          
magic_quotes        PHP  1  foo@bar.com    http://a.b.c        1.2.3.4   123  123abc<>()          O\'Henry       하퍼    
callback            PHP  1  FOO@BAR.COM    HTTP://A.B.C        1.2.3.4   123  123ABC<>()          O'HENRY        하퍼  

Added doc/tests2filter/034.phpt.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
--TEST--
Logical filter: boolean
--FILE--
<?php
$booleans = array(
'1' => true,
'On' => true,
'Off' => true,
'True' => true,
'TrUe' => true,
'oN' => true,

'0' => false,
'Off' => false,
'False' => false,
'faLsE' => false,
'oFf' => false,

'' => false
);

foreach($booleans as $val=>$exp) {
    $res =filter_var($val, FILTER_VALIDATE_BOOLEAN);
	    if ($res !== $exp) {
        echo "$val failed,'$exp' expect, '$res' received.\n";
    }
}
echo "Ok.";
?>
--EXPECTF--	
Ok.

Added doc/tests2filter/035.phpt.









































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
--TEST--
GET/POST/REQUEST Test with input_filter 
--POST--
d=379
--GET--
ar[elm1]=1234&ar[elm2]=0660&a=0234
--FILE--
<?php
$ret = filter_input(INPUT_GET, 'a', FILTER_VALIDATE_INT);
var_dump($ret);

$ret = filter_input(INPUT_GET, 'a', FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL));
var_dump($ret);

$ret = filter_input(INPUT_GET, 'ar', FILTER_VALIDATE_INT, array('flags'=>FILTER_REQUIRE_ARRAY));
var_dump($ret);

$ret = filter_input(INPUT_GET, 'ar', FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL|FILTER_REQUIRE_ARRAY));
var_dump($ret);

?>
--EXPECT--
bool(false)
int(156)
array(2) {
  ["elm1"]=>
  int(1234)
  ["elm2"]=>
  bool(false)
}
array(2) {
  ["elm1"]=>
  int(1234)
  ["elm2"]=>
  int(432)
}

Added doc/tests2filter/036.phpt.















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
--TEST--
input_get_args() and references
--SKIPIF--
<?php if (!extension_loaded("filter")) print "skip"; ?>
--FILE--
<?php

$var = "1";

$data = array();
$data["test1"] = 1;
$data["test2"] = &$var;

$args = array();
$args["test1"] = FILTER_VALIDATE_INT;
$args["test2"] = FILTER_VALIDATE_INT;

$ret = filter_var_array($data, $args);
var_dump($ret);
var_dump($data); //should be separated, i.e. not reference anymore. looks like we can't change this, or it'd change the original zval instead..
var_dump($var); //should be still string(1) "1"

echo "Done\n";
?>
--EXPECTF--	
array(2) {
  ["test1"]=>
  int(1)
  ["test2"]=>
  int(1)
}
array(2) {
  ["test1"]=>
  int(1)
  ["test2"]=>
  &string(1) "1"
}
string(1) "1"
Done

Added doc/tests2filter/037.phpt.















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
--TEST--
GET and data callback tests
--GET--
a=1&b=2
--FILE--
<?php
function myfunc($val) {
	return $val . '_callback';
}
echo filter_input(INPUT_GET, 'a', FILTER_CALLBACK, array("options"=>'myfunc'));
echo "\n";
echo filter_input(INPUT_GET, 'b', FILTER_VALIDATE_INT);
echo "\n";
$data = "data";

echo filter_var($data, FILTER_CALLBACK, array("options"=>'myfunc'));
echo "\n";

$res = filter_input_array(INPUT_GET, array(
				'a' => array(
					'filter' => FILTER_CALLBACK,
					'options' => 'myfunc'
					),
				'b' => FILTER_VALIDATE_INT 
		)
	);

var_dump($res);
?>
--EXPECT--
1_callback
2
data_callback
array(2) {
  ["a"]=>
  string(10) "1_callback"
  ["b"]=>
  int(2)
}

Added doc/tests2filter/038.phpt.

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
--TEST--
Test scalar, array
--FILE--
<?php

$var = 12;
$res = filter_var($var, FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL));
var_dump($res);

$var = array(12);
$res = filter_var($var, FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL));
var_dump($res);

$var = 12;
$res = filter_var($var, FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL|FILTER_FORCE_ARRAY));
var_dump($res);



$var = 12;
$res = filter_var($var, FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL|FILTER_REQUIRE_ARRAY));
var_dump($res);

$var = array(12);
$res = filter_var($var, FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL|FILTER_REQUIRE_ARRAY));
var_dump($res);

$var = array(12);
$res = filter_var($var, FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL|FILTER_FORCE_ARRAY|FILTER_REQUIRE_ARRAY));
var_dump($res);

$var = array(12);
$res = filter_var($var, FILTER_VALIDATE_INT, array('flags'=>FILTER_FLAG_ALLOW_OCTAL|FILTER_FORCE_ARRAY));
var_dump($res);

?>
--EXPECT--
int(12)
bool(false)
array(1) {
  [0]=>
  int(12)
}
bool(false)
array(1) {
  [0]=>
  int(12)
}
array(1) {
  [0]=>
  int(12)
}
array(1) {
  [0]=>
  int(12)
}

Added doc/tests2filter/LICENSE.









>
>
>
>
1
2
3
4
Copyright (c) 1997-2006 The PHP Group
Rasmus Lerdorf, Derick Rethans, Pierre-Alain Joye, Ilia Alshanetsky
PHP license v3.01
http://www.php.net/license/3_01.txt

Added doc/tests2filter/bug7586.phpt.











































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
--TEST--
input_get_args() filter not reseted between elements
--FILE--
<?php
$data = array(
    'product_id'    => 'libgd<script>',
    'component'     => '10dhsajkkdhk <do>',
    'versions'      => '2.0.33',
    'testscalar'    => array('2','23','10','12'),
    'testarray'     => '2',
);

$args = array(
    'product_id'    => FILTER_SANITIZE_ENCODED,
    'component'     => array('flags'    => FILTER_FORCE_ARRAY,
                             'options'  => array("min_range"=>1, "max_range"=>10)
                        ),
    'versions'      => array(
                            'filter' => FILTER_SANITIZE_ENCODED,
                            'flags'  => FILTER_REQUIRE_SCALAR,
                            ),
    'doesnotexist'  => FILTER_VALIDATE_INT,
    'testscalar'    => FILTER_VALIDATE_INT,
    'testarray' => array(
                            'filter' => FILTER_VALIDATE_INT,
                            'flags'  => FILTER_FORCE_ARRAY,
                        )

);
$out = filter_var_array($data, $args);
var_dump($out);
?>
--EXPECTF--	
array(6) {
  ["product_id"]=>
  string(17) "libgd%3Cscript%3E"
  ["component"]=>
  array(1) {
    [0]=>
    string(17) "%s"
  }
  ["versions"]=>
  string(6) "2.0.33"
  ["doesnotexist"]=>
  NULL
  ["testscalar"]=>
  bool(false)
  ["testarray"]=>
  array(1) {
    [0]=>
    int(2)
  }
}

Added doc/tests2filter/bug7715.phpt.



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
--TEST--
bug 7715, floats value with integer or incomplete input
--FILE--
<?php
$data = array(
	'.23',
	'-42',
	'+42',
	'.4',
	'-.4',
	'1000000000000',
	'-1000000000000',
	'02.324'
);
foreach ($data as $val) {
	$res = filter_var($val, FILTER_VALIDATE_FLOAT);
	var_dump($res);
}
echo "\n";
?>
--EXPECTF--	
float(0.23)
float(-42)
float(42)
float(0.4)
float(-0.4)
float(1.0E+12)
float(-1.0E+12)
float(2.324)

Added doc/tests2filter/bug8315.phpt.



























>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
--TEST--
bug 8315, NULL values halt the validation 
--FILE--
<?php

$var="3".chr(0)."foo";
var_dump(filter_var($var, FILTER_VALIDATE_INT));
$var="3".chr(0)."foo";
var_dump(filter_var($var, FILTER_VALIDATE_FLOAT));
?>
--EXPECT--	
bool(false)
bool(false)

Added doc/tests2filter/callback_non_modified_var.phpt.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
--TEST--
callback function returns non modified value
--FILE--
<?php
function callback($var) {
	return $var;
}
$var = "test";
var_dump(filter_var($var, FILTER_CALLBACK, array('options'=>'callback')));
?>
--EXPECT--	
string(4) "test"

Added doc/updoc.















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/php -qC
<?php
/*
   Adds hints about emulation functions to your local PHP documentation.
*/

#-- help
if ($_SERVER["argc"] < 2) {

   echo<<<END

Usage: updoc [.../upgrade.php] /path/to/your/php-doc/directory/
 
   This script will update your PHP documentation, if you have the
   (DocBook-converted) multi-html-files version installed. The first
   parameter must be the filepath to the 'upgrade.php' script, so the
   names of the emulated functions are known.

   You will afterwards find the abbreviation "EMU" in the required-
   PHP-version line throughout the documentation, so you know which
   functions you could safely use from now on (= without backwards
   compatibility stomach aches).


END;

}

#-- run
else {
   error_reporting(0);

   #-- params
   $emu = $_SERVER["argv"][1];
   $dir = $_SERVER["argv"][2];
   if (!$dir) {
      $dir = $emu;
      $emu = dirname(__FILE__)."/../upgrade.php";
   }
   if (!is_dir($dir)) {
      die("The given 'PHP doc directory' of \"$dir\" isn't!\n");
   }
   if (!file_exists($emu)) {
      die("Couldn't find 'upgrade.php' script under the given name \"$emu\".\n");
   }
   include($emu);
   
   #-- grep for function definitions
   $text = file_get_contents($emu);
   if (preg_match_all("/function[ ]+([_\w\d]+)\s*\(/", $text, $uu)) {
      $list = $uu[1];
   }
   
   #-- go thru doc
   if ($list) {
      $chng = 0;
      foreach ($list as $func) {
      
         #-- doc filename
         if (file_exists($fn = "$dir/function.".strtr($func, "_", "-").".html")) {
            $html = file_get_contents($fn);
            
            #-- update if no hint found yet
            if (!preg_match('/\(.*?(EMU|UP).*?\)/i', $html)) {
               $l = strpos($html, ")"); 
               $html = substr($html, 0, $l)
                     . ", EMU"
                     . substr($html, $l);
               file_put_contents($fn, $html);
               
               $chng += 1;
            }
         }
      }
      
      echo "$chng documentation files updated.\n";
   }

   #-- add some special files
   $add_files = array(
      array(
         "func"=>"gzdecode",
         "text"=>"PGh0bWw+PGhlYWQ+PHRpdGxlPmd6ZGVjb2RlPC90aXRsZT48L2hlYWQ+Cjxib2R5Pgo8ZGl2IGFsaWduPSJjZW50ZXIiPnVwZ3JhZGUucGhwIGRvYzwvZGl2Pgo8dGFibGUgYm9yZGVyPSIwIiB3aWR0aD0iMTAwJSIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj48dHI+CiAgPHRkIGFsaWduPSJsZWZ0Ij48YSBocmVmPSJmdW5jdGlvbi5nemRlZmxhdGUuaHRtbCI+YmFjazwvYT48L3RkPgogIDx0ZCBhbGlnbj0icmlnaHQiPjxhIGhyZWY9ImZ1bmN0aW9uLmd6ZW5jb2RlLmh0bWwiPm5leHQ8L2E+PC90ZD4KPC90cj48L3RhYmxlPgo8aHIgYWxpZ249IkxFRlQiIHdpZHRoPSIxMDAlIj4KCjxoMT5nemRlY29kZTwvaDE+Cgo8cD4oUEhQIDYsIEVNVSk8L3A+CgpnemRlY29kZSZuYnNwOy0tJm5ic3A7RGVjb2RlcyBhIGd6aXAgY29tcHJlc3NlZCBzdHJpbmc8L2Rpdj4KCjxoMj5EZXNjcmlwdGlvbjwvaDI+CgpzdHJpbmcgPGIgY2xhc3M9Im1ldGhvZG5hbWUiPmd6ZGVjb2RlPC9iPiAoIHN0cmluZyBkYXRhIFssIGludCBtYXhsZW5dKTxicj4KPGJyPgo8cD5UaGlzIGZ1bmN0aW9uIGRlY29kZXMgYSBzdHJpbmcgY29tcHJlc3NlZCBieSB0aGUgCjxhIGhyZWY9ImZpbGU6Ly8vdXNyL3NoYXJlL21hbi9tYW4xL2d6aXAuMS5neiI+Z3ppcCgxKTwvYT4gdXRpbGl0eSBvcgp0aGUgPGEgY2xhc3M9ImZ1bmN0aW9uIiBocmVmPSJmdW5jdGlvbi5nemVuY29kZS5odG1sIj5nemVuY29kZSgpPC9hPgpmdW5jdGlvbi4gVGhlIG9wdGlvbmFsIHBhcmFtZXRlciAnbWF4bGVuJyBsaW1pdHMgdGhlIGxlbmd0aCBvZiB0aGUgcmV0dXJuZWQKc3RyaW5nIC0gaWYgdGhlIGluZmxhdGlvbiBwcm9jZXNzIHJldHVybmVkIGEgYmlnZ2VyIHJlc3VsdCBpdCB3b3VsZCBiZSBkcm9wcGVkLgo8L3A+Cgo8cD5UaGUgZ3ppcCBmb3JtYXQgaW50ZXJuYWxseSB1c2VzIHRoZSBkZWZsYXRlIGFsZ29yaXRobSwgYW5kIGFkZHMgYSBmZXcKY2hlY2tzdW1zIGFuZCBvcHRpb25hbCBtZXRhIGRhdGEgZmllbGRzLiBJdCBpcyByZWd1bGFyaWx5IHVzZWQgYXMKY29udGVudC1jb2RpbmcgaW4gSFRUUCByZXF1ZXN0cyBhbmQgcmVzcG9uc2VzLiBTZWUKPGEgaHJlZj0iaHR0cDovL3d3dy5mYXFzLm9yZy9yZmNzL3JmYzE5NTIiPlJGQzE5NTI8L2E+IGZvciB0aGUgZm9ybWF0CmRlc2NyaXB0aW9uLjwvcD4KCjxwPgpTZWUgYWxzbyA8YSBocmVmPSJmdW5jdGlvbi5nemVuY29kZS5odG1sIj48YiBjbGFzcz0iZnVuY3Rpb24iPmd6ZW5jb2RlKCk8L2I+PC9hPgphbmQgPGEgaHJlZj0iZnVuY3Rpb24uZ3ppbmZsYXRlLmh0bWwiPjxiIGNsYXNzPSJmdW5jdGlvbiI+Z3ppbmZsYXRlKCk8L2I+PC9hPi4KPC9wPgoKPHA+Rm9yIGNvbXBhdGliaWxpdHkgd2l0aCBvbGRlciBQSFAgdmVyc2lvbnMgKGFuZCBmb3IgcGVvcGxlIHRoYXQgYXJlCnVud2lsbGluZyB0byBsb2FkICd1cGdyYWRlLnBocCcpLCB5b3UgY2FuIHVzZSBmb2xsb3dpbmcgKHVuY2xlYW4pCndvcmthcm91bmQgZm9yIGRlY29tcHJlc3NpbmcgZ3ppcGVkIGRhdGE6PGJyPgo8YnI+CjxiPkV4YW1wbGUgMTwvYj46PGJyPgo8YnI+Cjxjb2RlPgombmJzcDsgICRnemRhdGEgPSBnemVuY29kZSgiSSdtIGdldHRpbmcgY29tcHJlc3NlZC4uLiIpOzxicj4KPGJyPgombmJzcDsgICRzdHIgPSBmdW5jdGlvbl9leGlzdHMoImd6ZGVjb2RlIik8YnI+CiZuYnNwOyAmbmJzcDsgJm5ic3A7ICA/IGd6ZGVjb2RlKCRnemRhdGEpPGJyPgombmJzcDsgJm5ic3A7ICZuYnNwOyAgOiBnemluZmxhdGUoc3Vic3RyKCRnemRhdGEsIDEwLCAtOCkpOzxicj4KPGJyPgo8L2NvZGU+CjwvcD4KCjxocj4KPHRhYmxlIGJvcmRlcj0iMCIgd2lkdGg9IjEwMCUiIGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCI+PHRyPgogIDx0ZCB3aWR0aD0iMzMlIiBhbGlnbj0ibGVmdCI+PGEgaHJlZj0iZnVuY3Rpb24uZ3pkZWZsYXRlLmh0bWwiPmJhY2s8L2E+PGJyPmd6ZGVmbGF0ZTwvdGQ+CiAgPHRkIHdpZHRoPSIzMyUiIGFsaWduPSJjZW50ZXIiPjxhIGhyZWY9InJlZi56bGliLmh0bWwiPnVwPC9hPjxicj56bGliIG92ZXJ2aWV3PC90ZD4KICA8dGQgd2lkdGg9IjMzJSIgYWxpZ249InJpZ2h0Ij48YSBocmVmPSJmdW5jdGlvbi5nemVuY29kZS5odG1sIj5uZXh0PC9hPjxicj5nemVuY29kZTwvdGQ+CjwvdHI+PC90YWJsZT4KCjwvYm9keT4KPC9odG1sPgo=",
         "sect"=>"zlib", "after"=>"gzencode",
         "desc"=>"Decode a gzip compressed string",
      ),
   );
   foreach ($add_files as $data) {
      extract($data);
      if (!file_exists($fn = "$dir/function.$func.html")
||1) {
         echo "adding \"$fn\"\n";
         file_put_contents($fn, base64_decode($text));

         #-- update function list page
         $fn = array("$dir/ref.$sect.html", "$dir/index.functions.html");
         update_files($fn, "/(<a\s+href=\"function.$after)/ims",
            "<a href=\"function.$func.html\">$func</a> -- $desc.</dt>\n<dt> $1"
         ); 
      }
   }

}


#-- inject something into a file
function update_files($list, $regex, $replace) {
   if (!is_array($list)) {
      $list = array($list);
   }
   foreach ($list as $fn) {
echo "+$fn\n";
      $html = file_get_contents($fn);
      $html = preg_replace($regex, $replace, $html);
      file_put_contents($fn, $html);
   }
}

?>

Deleted dtools/_dt.

1
2
3
4
5
6
7
8
#!/bin/sh
# runs the `doctests` utility for a given (param) function,
# simply has some custom pathnames built-in
MAN=/usr/local/doc/php5-doc/
PHP=php412

DIR=$(dirname $(dirname $(realpath $0)))
$DIR/dtools/doctests $PHP $MAN $@
<
<
<
<
<
<
<
<
















Deleted dtools/_notdefined.

1
2
3
#!/usr/bin/perl -p

s/^(\s*)(define\("(.+?)".+\);)/$1if (!defined("$3")) { $2 }/;
<
<
<






Deleted dtools/ckavail.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?php
/*
   Run this first with an older PHP interpreter, and then with a newer
   version. This way you get a list (once) of added functions (the func
   list is stored in a temporary file).
*/
$DATA_FILE = "/tmp/ckavail.lst";

#-- load previous list
if ($f = @fopen($DATA_FILE, "rb")) {
   $oldl = unserialize(fread($f, 1<<20));
   fclose($f);
}
//echo "OLD=";print_r($oldl);

#-- current func list
$newl = get_defined_stuff();
//echo "NEW=";print_r($newl);

#-- save this one
if ($f = fopen($DATA_FILE, "wb")) {
   fwrite($f, serialize($newl));
   fclose($f);
}
else {
   echo "ERROR(could not save current list)\n";
}

#-- comparison of  current / last run
echo "old(".count($oldl["functions"])."), new(".count($newl["functions"]).")\n";
if ($oldl) {

   #-- funcs
   $new = array_diff($newl["functions"], $oldl["functions"]);
   echo "New functions added between PHP $oldl[version] and current $newl[version] interpreter:\n";
   print_r($new);

   #-- constants
   $new = array_diff(array_keys($newl["constants"]), array_keys($oldl["constants"]));
   echo "\nNewly added constants:\n";
   print_r($new);

   #-- classes
   $new = array_diff($newl["classes"], $oldl["classes"]);
   echo "\nAnd classes:\n";
   print_r($new);

}
else {
   echo "Now start this script a 2nd time with the newer interpreter version.\n";
}


function get_defined_stuff() {
   $rl = array();
   $f = get_defined_functions();
   while ($f["internal"]) {
      $f = $f["internal"];
   }
   $rl["functions"] = $f;
   $c = get_defined_constants();
   $rl["constants"] = $c;
   $c = get_declared_classes();
   $rl["classes"] = $c;
   $rl["version"] = PHP_VERSION;
   return($rl);
}


?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































































































Deleted dtools/compact.

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh

#
#  creates comment+whitespace free version of upgrade.php script
#

cd `dirname $0`
cd ..

php -q -w upgrade.php | perl -pe 's/\s*([{}()\[\]=\-\/\$<>+*",;!&|])\s*|\n/$1/gmis;' > contrib/upgrade.php.shortened

ls -l upgrade.php contrib/upgrade.php*
<
<
<
<
<
<
<
<
<
<
<
<
























Deleted dtools/doctests.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/usr/local/bin/php -qC
<?php
/*
   Makes small test scripts, which get extracted from the PHP manual
   on the fly (but not every function has one there, suddenly).
*/

#-- config
$PAUSE = 1;   // (use 3) break between tests; you should use `|less` instead
$CLEAN = 0;   // remove test scripts after use
$MANY = 1;    // create one testing script per function


#-- help
if (count($_SERVER["argv"]) < 3) {
   echo<<<END

Usage: doctest  [php-interpreter]  [/path/to/your/php/manual/]

   Runs the examples from your locally installed PHP manual (any language
   will work, but get the latest!) with the given PHP interpreter version
   (use an older version to really test the emulated functions). You need
   lynx or w3m installed also. Use only under U*ix/Linux.

   Pipe the output through |less, |more or |most, there are built-in
   delays. Rarely example scripts may not run (they are examples only).

END;
}

#-- proceed
else {

   #-- args
   $php = $_SERVER["argv"][1];
   $php = trim(`which $php`);
   if (!$php) {
      die(__FILE__.": Given PHP interpreter not in your %PATH!\n");
   }
   $dir = $_SERVER["argv"][2];
   if (!is_dir($dir) || !file_exists("$dir/function.print.html")) {
      die(__FILE__.": PHP manual does not live under '$dir'.\n");
   }
   ($html = `which w3m`) or ($html = `which lynx`);
   if (!($html = trim($html))) {
      die(__FILE__.": lynx or w3m required.\n");
   }
   $tmp = "/tmp/upgrade.php.doctest.tmp";
   $tmpdir = $tmp;
   if ($MANY) { @unlink($tmpdir); @mkdir($tmpdir); }

   #-- load emulation script
   $emu = realpath(dirname(__FILE__) . "/../upgrade.php");
   $emu2 = dirname($emu)."/ext/array.php";
   $emu3 = dirname($emu)."/ext/mime.php";
   require($emu);

   #-- get function names
   $text = file_get_contents($emu);
   preg_match_all("/function[ ]+([_\w\d]+)\s*\(/", $text, $uu);
   $funcs = $uu[1];
   #-- or use user-specified list
   if (count($_SERVER["argv"]) >= 4) {
      $funcs = array_slice($_SERVER["argv"], 3);
   }

   #-- generate list of really emulated functions
   $simulated = `echo '<?php echo serialize(get_defined_functions()); ?>' | $php -q`;
   $simulated = unserialize($simulated);
   $simulated = $simulated["internal"];

   #-- all
   foreach ($funcs as $func) {
      if (file_exists($fn = "$dir/function.".strtr($func, "_", "-").".html")) {
         echo "checking function '\033[31m$func\033[37m'... ";

         #-- only run over emulated stuff
         if (in_array($func, $simulated)) {
            echo "NOT EMULATED (with your PHP version)... ";
            // continue;
         }

         #-- grep example scripts
         $text = `$html -dump $fn`;
         preg_match_all("/<\?php(.+?)\?".">/ms", $text, $uu);

         #-- exec each
         if ($n = count($uu[1])) {

            #-- note
            echo "$n examples:\n\n";

            #-- multiple scripts to run
            foreach ($uu[1] as $i=>$scr) {

               #-- fix output-less scripts: find last assigned-to variable name
               if (!strpos($scr, "echo") && !strpos($scr, "print")) {
                  if (preg_match('/^.+(\$[_\w\d\[\"\'\]]+)\s*=/s', $scr, $uu)) {
                     $scr .= "\n\n#-- auto-added\nprint_r($uu[1]);\n";
                  }
                  else {
                     $scr .= "\n\n#-- this script gives no useful output, or does it?";
                  }
               }

               #-- fix compatibility to older PHP versions
               $scr = preg_replace('/(\s)private(\s\$)/', '$1var$2', $scr);

               #-- output sample script text from doc
               if ($i) {
                  echo "\n++++++++++++++++++++++++++++\n\n";
                  sleep($PAUSE);
               }
               echo "\033[1;30m<?php $scr\n?".">\033[0;37m\n";

               #-- create temp script, run it
               if ($MANY) {
                  $tmp = "$tmpdir/$func#$i.php";
               }
               $scr = ltrim($scr);
               file_put_contents(
                  $tmp,
                  "<?php\n\n".
                  "#-- a test script for emulated function '$func'\n".
                  "if (function_exists('$func')) { echo \"ATTENTION: the native '$func' function will engage for this test\\n\"; }\n".
                  "include('$emu');\n".
                  "include('$emu2');\n".
                  "include('$emu3');\n".
                  "error_reporting(E_ALL);\n\n".
                  "#-- example[$i] as taken from PHP manual page '$fn'\n".
                  "$scr\n".
                  "\n?".">"
               );
               echo "==>\033[32m\n";
               passthru("$php $tmp");
               echo "\033[0;37m\n\n";
            }

            #-- pause before next func/script
            sleep($PAUSE);
            echo "\n-------------------------------------------------------------------\n\n";
         }

         else {
            echo "NO EXAMPLES found in doc, skipping";
         }
         echo "\n";
      }
   }

   #-- clean up
   if ($CLEAN) {
      unlink($tmp);
   }
}

#-- even more clean
if ($MANY && CLEAN) { @rmdir($tmpdir); }

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































Deleted dtools/listemu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/local/bin/php -qC
<?php
/*
   Prints the list of emulated functions.
*/

#-- basedir
$dir = realpath(dirname(__FILE__) . "/../");

#-- grep for function definitions
$text = "";
$text .= implode("", file("$dir/upgrade.php"));
$text .= implode("", file("$dir/ext/array.php"));
$text .= implode("", file("$dir/ext/bcmath.php"));
$text .= implode("", file("$dir/ext/gettext.php"));
$text .= implode("", file("$dir/ext/mime.php"));
$text .= implode("", file("$dir/ext/old.php"));
$text .= implode("", file("$dir/ext/posix.php"));
$text .= implode("", file("$dir/ext/ctype.php"));
$text .= implode("", file("$dir/ext/odbc.php"));
if (preg_match_all("/function[ ]+([_\w\d]+)\s*\(/", $text, $uu)) {
   $list = array_unique($uu[1]);
}

#-- print
echo "Following functions can be emulated currently:\n";
foreach ($list as $func) {
   echo " $func\n";
}

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































Deleted dtools/php-commandline/PhpFunctionCall.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/php -qC
<?php

   #-- function name
   $func = $_SERVER["argv"][0];
   $func = substr($func, strrpos($func, "/") + 1);

   #-- args
   $args = $_SERVER["argv"];
   array_shift($args);

   #-- stdin as arg
   if (!count($args)) {
      if (($f = fopen("php://stdin", "rb"))
      and ($input = fread($f, 1<<22))) {
         array_unshift($args, $input);
         fclose($f);
      }
   }

   #-- do
   $output = call_user_func_array($func, $args);
   echo $output;

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















































Deleted dtools/php-commandline/README.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47


  BEWARE: GIMMICK!!

  If you run Linux and work on the console occasionally, you probably love
  commandline tools. If you further develop PHP scripts, then you probably
  sometimes wish to test PHP functions on the fly and more easily (without
  typing yet another test script).

  If that's the case, here is a simple script to simplify this. To install
  follow these steps:


  1. Create a $HOME/bin/php directory
     (and add ~/bin/php/ to your shell PATH, of course)

  2. Move the contents of this ./ dir into ~/bin/php/

  3. Run "./make_symlinks" in this directory.

  4. Eventually adapt the interpreter shebang #! in the PhpFuncCall script.


  This will create a lot of symlinks to the "PhpFunctionCall" script. You
  then can run PHP functions on the terminal like:


   localhost:~$   base64_encode  AbcDef_1234


  Of course this is not useful for all PHP functions, because some must be
  used in conjunction or do not return displayable results. And some have
  already been removed from the list. You can of course create special PHP
  scripts, like the example 'phpecho' that call other PHP code or function
  groups, of course.

  If you run an older PHP version, then -sure-, you might want to include
  upgrade.php from within 'PhpFunctionCall'.
  


  WINDOWS

  No. Using that under Windows with its frustrating commandline window makes
  little sense.


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































Deleted dtools/php-commandline/make_symlinks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/bin/sh

SCRIPT=PhpFunctionCall
FUNCS="json_encode json_decode inet_ntop inet_pton error_get_last strptime
htmlspecialchars_decode zend_version strlen strcmp strncmp strcasecmp
strncasecmp each error_reporting define defined get_parent_class
method_exists class_exists interface_exists function_exists
get_included_files get_required_files is_subclass_of is_a get_class_vars
get_object_vars get_class_methods trigger_error user_error set_error_handler
restore_error_handler set_exception_handler restore_exception_handler
get_declared_classes get_declared_interfaces get_defined_functions
get_defined_vars create_function get_resource_type get_loaded_extensions
extension_loaded get_extension_funcs get_defined_constants debug_backtrace
debug_print_backtrace xmlrpc_encode xmlrpc_decode xmlrpc_decode_request
xmlrpc_encode_request xmlrpc_get_type xmlrpc_set_type xmlrpc_is_fault
utf8_encode utf8_decode token_get_all token_name constant bin2hex sleep
usleep time_nanosleep time mktime gmmktime strftime gmstrftime strtotime
date idate gmdate getdate localtime checkdate flush wordwrap
htmlspecialchars htmlentities html_entity_decode get_html_translation_table
sha1 sha1_file md5 md5_file crc32 iptcparse iptcembed getimagesize
image_type_to_mime_type phpinfo phpversion phpcredits php_logo_guid
php_real_logo_guid php_egg_logo_guid zend_logo_guid php_sapi_name php_uname
php_ini_scanned_files strnatcmp strnatcasecmp substr_count strspn strcspn
strtok strtoupper strtolower strpos stripos strrpos strripos strrev hebrev
hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr
stristr strrchr str_shuffle str_word_count str_split strpbrk substr_compare
strcoll money_format substr substr_replace quotemeta ucfirst ucwords strtr
addslashes addcslashes rtrim str_replace str_ireplace str_repeat count_chars
chunk_split trim ltrim strip_tags similar_text explode implode setlocale
localeconv nl_langinfo soundex levenshtein chr ord parse_str str_pad chop
strchr sprintf printf vprintf vsprintf fprintf vfprintf sscanf fscanf
parse_url urlencode urldecode rawurlencode rawurldecode http_build_query
readlink linkinfo symlink link unlink exec system escapeshellcmd
escapeshellarg passthru shell_exec proc_open proc_close proc_terminate
proc_get_status proc_nice rand srand getrandmax mt_rand mt_srand
mt_getrandmax getservbyname getservbyport getprotobyname getprotobynumber
getmyuid getmygid getmypid getmyinode getlastmod base64_decode base64_encode
convert_uuencode convert_uudecode abs ceil floor round sin cos tan asin acos
atan atan2 sinh cosh tanh asinh acosh atanh expm1 log1p pi is_finite is_nan
is_infinite pow exp log log10 sqrt hypot deg2rad rad2deg bindec hexdec
octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip
getenv putenv getopt microtime gettimeofday getrusage uniqid
quoted_printable_decode convert_cyr_string get_current_user set_time_limit
get_cfg_var get_magic_quotes_gpc get_magic_quotes_runtime
import_request_variables error_log call_user_func call_user_func_array
call_user_method call_user_method_array serialize unserialize var_dump
var_export debug_zval_dump print_r unregister_tick_function highlight_file
show_source highlight_string php_strip_whitespace php_check_syntax ini_get
ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path
restore_include_path setcookie setrawcookie header headers_sent headers_list
connection_aborted connection_status ignore_user_abort parse_ini_file
is_uploaded_file move_uploaded_file gethostbyaddr gethostbyname
gethostbynamel dns_check_record checkdnsrr dns_get_mx getmxrr dns_get_record
intval floatval doubleval strval gettype settype is_null is_resource is_bool
is_long is_float is_int is_integer is_double is_real is_numeric is_string
is_array is_object is_scalar is_callable ereg ereg_replace eregi
eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind
rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate
fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file
file_get_contents file_put_contents fgetcsv flock get_meta_tags
set_file_buffer get_headers realpath fnmatch fsockopen pfsockopen pack
unpack get_browser crypt opendir closedir chdir chroot getcwd rewinddir
readdir dir scandir glob fileatime filectime filegroup fileinode filemtime
fileowner fileperms filesize filetype file_exists is_writable is_writeable
is_readable is_executable is_file is_dir is_link stat lstat chown chgrp
chmod touch clearstatcache disk_total_space disk_free_space diskfreespace
mail ezmlm_hash openlog syslog closelog define_syslog_variables lcg_value
metaphone ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush
ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents
ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort
arsort sort rsort usort uasort uksort shuffle array_walk
array_walk_recursive count end prev next reset current key min max in_array
array_search extract compact array_fill range array_multisort array_push
array_pop array_shift array_unshift array_splice array_slice array_merge
array_merge_recursive array_keys array_values array_count_values
array_reverse array_reduce array_pad array_flip array_change_key_case
array_rand array_unique array_intersect array_uintersect
array_intersect_assoc array_uintersect_assoc array_intersect_uassoc
array_uintersect_uassoc array_diff array_udiff array_diff_assoc
array_udiff_assoc array_diff_uassoc array_udiff_uassoc array_sum
array_filter array_map array_chunk array_combine array_key_exists pos sizeof
key_exists assert assert_options version_compare ftok str_rot13
stream_get_filters output_add_rewrite_var output_reset_rewrite_vars
date_sunrise date_sunset spl_classes class_parents class_implements
use_soap_error_handler is_soap_fault simplexml_load_file
simplexml_load_string simplexml_import_dom session_name session_module_name
session_save_path session_id session_regenerate_id session_decode
session_register session_unregister session_is_registered session_encode
session_start session_destroy session_unset session_set_save_handler
session_cache_limiter session_cache_expire session_set_cookie_params
session_get_cookie_params session_write_close session_commit posix_kill
posix_getpid posix_getppid posix_getuid posix_setuid posix_geteuid
posix_seteuid posix_getgid posix_setgid posix_getegid posix_setegid
posix_getgroups posix_getlogin posix_getpgrp posix_setsid posix_setpgid
posix_getpgid posix_getsid posix_uname posix_times posix_ctermid
posix_ttyname posix_isatty posix_getcwd posix_mkfifo posix_getgrnam
posix_getgrgid posix_getpwnam posix_getpwuid posix_getrlimit
posix_get_last_error posix_errno posix_strerror preg_match preg_match_all
preg_replace preg_replace_callback preg_split preg_quote preg_grep
pcntl_fork pcntl_waitpid pcntl_wait pcntl_signal pcntl_wifexited
pcntl_wifstopped pcntl_wifsignaled pcntl_wexitstatus pcntl_wtermsig
pcntl_wstopsig pcntl_exec pcntl_alarm pcntl_getpriority pcntl_setpriority
mime_content_type iconv ob_iconv_handler iconv_get_encoding
iconv_set_encoding iconv_strlen iconv_substr iconv_strpos iconv_strrpos
iconv_mime_encode iconv_mime_decode iconv_mime_decode_headers gd_info
imagetypes jpeg2wbmp png2wbmp image2wbmp imagelayereffect imagecolormatch
imagefilter dom_import_simplexml ctype_alnum ctype_alpha ctype_cntrl
ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space
ctype_upper ctype_xdigit readgzfile gzrewind gzclose gzeof gzgetc gzgets
gzgetss gzread gzopen gzpassthru gzseek gztell gzwrite gzputs gzfile
gzcompress gzuncompress gzdeflate gzinflate gzencode ob_gzhandler
zlib_get_coding_type"


# start
if [ -e $SCRIPT ]
then

   for F in $FUNCS
   do

      ln -s $SCRIPT $F

   done

fi
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































































































































































Deleted dtools/php-commandline/phpecho.

1
2
3
#!/bin/sh

echo "<?php print_r($1); ?>" | php
<
<
<






Deleted dtools/updoc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/local/bin/php -qC
<?php
/*
   Adds hints about emulation functions to your local PHP documentation.
*/

#-- help
if ($_SERVER["argc"] < 2) {

   echo<<<END

Usage: updoc [.../upgrade.php] /path/to/your/php-doc/directory/
 
   This script will update your PHP documentation, if you have the
   (DocBook-converted) multi-html-files version installed. The first
   parameter must be the filepath to the 'upgrade.php' script, so the
   names of the emulated functions are known.

   You will afterwards find the abbreviation "EMU" in the required-
   PHP-version line throughout the documentation, so you know which
   functions you could safely use from now on (= without backwards
   compatibility stomachaches).


END;

}

#-- run
else {
   error_reporting(0);

   #-- params
   $emu = $_SERVER["argv"][1];
   $dir = $_SERVER["argv"][2];
   if (!$dir) {
      $dir = $emu;
      $emu = dirname(__FILE__)."/../upgrade.php";
   }
   if (!is_dir($dir)) {
      die("The given 'PHP doc directory' of \"$dir\" isn't!\n");
   }
   if (!file_exists($emu)) {
      die("Couldn't find 'upgrade.php' script under the given name \"$emu\".\n");
   }
   
   #-- grep for function definitions
   $text = implode("", file($emu));
   if (preg_match_all("/function[ ]+([_\w\d]+)\s*\(/", $text, $uu)) {
      $list = $uu[1];
   }
   
   #-- go thru doc
   if ($list) {
      $chng = 0;
      foreach ($list as $func) {
      
         #-- doc filename
         if (file_exists($fn = "$dir/function.".strtr($func, "_", "-").".html")) {
            $f = fopen($fn, "r");
            $html = fread($f, 1<<20);
            fclose($f);
            
            #-- update if no hint found yet
            if (!preg_match('/\(.*?(EMU|UP).*?\)/i', $html)) {
               $l = strpos($html, ")"); 
               $html = substr($html, 0, $l)
                     . ", EMU"
                     . substr($html, $l);
               $f = fopen($fn, "w");
               fwrite($f, $html);
               fclose($f);
               
               $chng += 1;
            }
         }
      }
      
      echo "$chng documentation files updated.\n";
   }

   #-- add some special files
   $add_files = array(
      array(
         "func"=>"gzdecode",
         "data"=>"PGh0bWw+PGhlYWQ+PHRpdGxlPmd6ZGVjb2RlPC90aXRsZT48L2hlYWQ+Cjxib2R5Pgo8ZGl2IGFsaWduPSJjZW50ZXIiPnVwZ3JhZGUucGhwIGRvYzwvZGl2Pgo8dGFibGUgYm9yZGVyPSIwIiB3aWR0aD0iMTAwJSIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIj48dHI+CiAgPHRkIGFsaWduPSJsZWZ0Ij48YSBocmVmPSJmdW5jdGlvbi5nemRlZmxhdGUuaHRtbCI+YmFjazwvYT48L3RkPgogIDx0ZCBhbGlnbj0icmlnaHQiPjxhIGhyZWY9ImZ1bmN0aW9uLmd6ZW5jb2RlLmh0bWwiPm5leHQ8L2E+PC90ZD4KPC90cj48L3RhYmxlPgo8aHIgYWxpZ249IkxFRlQiIHdpZHRoPSIxMDAlIj4KCjxoMT5nemRlY29kZTwvaDE+Cgo8cD4oUEhQIDYsIEVNVSk8L3A+CgpnemRlY29kZSZuYnNwOy0tJm5ic3A7RGVjb2RlcyBhIGd6aXAgY29tcHJlc3NlZCBzdHJpbmc8L2Rpdj4KCjxoMj5EZXNjcmlwdGlvbjwvaDI+CgpzdHJpbmcgPGIgY2xhc3M9Im1ldGhvZG5hbWUiPmd6ZGVjb2RlPC9iPiAoIHN0cmluZyBkYXRhIFssIGludCBtYXhsZW5dKTxicj4KPGJyPgo8cD5UaGlzIGZ1bmN0aW9uIGRlY29kZXMgYSBzdHJpbmcgY29tcHJlc3NlZCBieSB0aGUgCjxhIGhyZWY9ImZpbGU6Ly8vdXNyL3NoYXJlL21hbi9tYW4xL2d6aXAuMS5neiI+Z3ppcCgxKTwvYT4gdXRpbGl0eSBvcgp0aGUgPGEgY2xhc3M9ImZ1bmN0aW9uIiBocmVmPSJmdW5jdGlvbi5nemVuY29kZS5odG1sIj5nemVuY29kZSgpPC9hPgpmdW5jdGlvbi4gVGhlIG9wdGlvbmFsIHBhcmFtZXRlciAnbWF4bGVuJyBsaW1pdHMgdGhlIGxlbmd0aCBvZiB0aGUgcmV0dXJuZWQKc3RyaW5nIC0gaWYgdGhlIGluZmxhdGlvbiBwcm9jZXNzIHJldHVybmVkIGEgYmlnZ2VyIHJlc3VsdCBpdCB3b3VsZCBiZSBkcm9wcGVkLgo8L3A+Cgo8cD5UaGUgZ3ppcCBmb3JtYXQgaW50ZXJuYWxseSB1c2VzIHRoZSBkZWZsYXRlIGFsZ29yaXRobSwgYW5kIGFkZHMgYSBmZXcKY2hlY2tzdW1zIGFuZCBvcHRpb25hbCBtZXRhIGRhdGEgZmllbGRzLiBJdCBpcyByZWd1bGFyaWx5IHVzZWQgYXMKY29udGVudC1jb2RpbmcgaW4gSFRUUCByZXF1ZXN0cyBhbmQgcmVzcG9uc2VzLiBTZWUKPGEgaHJlZj0iaHR0cDovL3d3dy5mYXFzLm9yZy9yZmNzL3JmYzE5NTIiPlJGQzE5NTI8L2E+IGZvciB0aGUgZm9ybWF0CmRlc2NyaXB0aW9uLjwvcD4KCjxwPgpTZWUgYWxzbyA8YSBocmVmPSJmdW5jdGlvbi5nemVuY29kZS5odG1sIj48YiBjbGFzcz0iZnVuY3Rpb24iPmd6ZW5jb2RlKCk8L2I+PC9hPgphbmQgPGEgaHJlZj0iZnVuY3Rpb24uZ3ppbmZsYXRlLmh0bWwiPjxiIGNsYXNzPSJmdW5jdGlvbiI+Z3ppbmZsYXRlKCk8L2I+PC9hPi4KPC9wPgoKPHA+Rm9yIGNvbXBhdGliaWxpdHkgd2l0aCBvbGRlciBQSFAgdmVyc2lvbnMgKGFuZCBmb3IgcGVvcGxlIHRoYXQgYXJlCnVud2lsbGluZyB0byBsb2FkICd1cGdyYWRlLnBocCcpLCB5b3UgY2FuIHVzZSBmb2xsb3dpbmcgKHVuY2xlYW4pCndvcmthcm91bmQgZm9yIGRlY29tcHJlc3NpbmcgZ3ppcGVkIGRhdGE6PGJyPgo8YnI+CjxiPkV4YW1wbGUgMTwvYj46PGJyPgo8YnI+Cjxjb2RlPgombmJzcDsgICRnemRhdGEgPSBnemVuY29kZSgiSSdtIGdldHRpbmcgY29tcHJlc3NlZC4uLiIpOzxicj4KPGJyPgombmJzcDsgICRzdHIgPSBmdW5jdGlvbl9leGlzdHMoImd6ZGVjb2RlIik8YnI+CiZuYnNwOyAmbmJzcDsgJm5ic3A7ICA/IGd6ZGVjb2RlKCRnemRhdGEpPGJyPgombmJzcDsgJm5ic3A7ICZuYnNwOyAgOiBnemluZmxhdGUoc3Vic3RyKCRnemRhdGEsIDEwLCAtOCkpOzxicj4KPGJyPgo8L2NvZGU+CjwvcD4KCjxocj4KPHRhYmxlIGJvcmRlcj0iMCIgd2lkdGg9IjEwMCUiIGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCI+PHRyPgogIDx0ZCB3aWR0aD0iMzMlIiBhbGlnbj0ibGVmdCI+PGEgaHJlZj0iZnVuY3Rpb24uZ3pkZWZsYXRlLmh0bWwiPmJhY2s8L2E+PGJyPmd6ZGVmbGF0ZTwvdGQ+CiAgPHRkIHdpZHRoPSIzMyUiIGFsaWduPSJjZW50ZXIiPjxhIGhyZWY9InJlZi56bGliLmh0bWwiPnVwPC9hPjxicj56bGliIG92ZXJ2aWV3PC90ZD4KICA8dGQgd2lkdGg9IjMzJSIgYWxpZ249InJpZ2h0Ij48YSBocmVmPSJmdW5jdGlvbi5nemVuY29kZS5odG1sIj5uZXh0PC9hPjxicj5nemVuY29kZTwvdGQ+CjwvdHI+PC90YWJsZT4KCjwvYm9keT4KPC9odG1sPgo=",
         "sect"=>"zlib", "after"=>"gzencode",
         "desc"=>"Decode a gzip compressed string",
      ),
   );
   foreach ($add_files as $data) {
      extract($data);
      if (!file_exists($fn = "$dir/function.$func.html")
||1) {
         echo "adding \"$fn\"\n";
         $f = fopen($fn, "w");
         fwrite($f, base64_decode($data));
         fclose($f);

         #-- update function list page
         $fn = array("$dir/ref.$sect.html", "$dir/index.functions.html");
         update_files($fn, "/(<a\s+href=\"function.$after)/ims",
            "<a href=\"function.$func.html\">$func</a> -- $desc.</dt>\n<dt> $1"
         ); 
      }
   }

}


#-- inject something into a file
function update_files($list, $regex, $replace) {
   if (!is_array($list)) {
      $list = array($list);
   }
   foreach ($list as $fn) {
echo "+$fn\n";
      $f = fopen($fn, "r");
      $html = fread($f, 1<<20);
      fclose($f);
      $html = preg_replace($regex, $replace, $html);
      $f = fopen($fn, "w");
      fwrite($f, $html);
      fclose($f);
   }
}

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































Changes to ext/array.php.

1
2

3
4
5
6
7
8
9






10
11
12
13
14
15
16
17
<?php
/*

   Extended PHP array functions - _diff and _intersect() for associative
   arrays and/or with callback functions (for keys and/or values). These
   are too rarely used and exotic to be part of the core "upgrade.php"
   script.
   
   NOTHING IN HERE WAS SERIOUSLY TESTED. Please grab the definitions from
   "PEAR::PHP_Compat" if you want reliable and tested versions.






*/


#-- diff associative arrays with two user callbacks
#   (if this looks complicated to you, don't even try to look at the manual)
if (!function_exists("array_udiff_uassoc")) {
   function array_udiff_uassoc() {
      $in = func_get_args();

|
>
|
|
|
|
|
|
|
>
>
>
>
>
>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
/**
 *
 *  Extended PHP array functions - _diff and _intersect() for associative
 *  arrays and/or with callback functions (for keys and/or values). These
 *  are too rarely used and exotic to be part of the core "upgrade.php"
 *  script.
 *  
 *  NOTHING IN HERE WAS SERIOUSLY TESTED. Please grab the definitions from
 *  PEAR::PHP_Compat if you want reliable and tested versions.
 *
 *
 *  @group ARRAY_FUNCS_4_0
 *  @since 4.0
 *  @untested
 *
 */


#-- diff associative arrays with two user callbacks
#   (if this looks complicated to you, don't even try to look at the manual)
if (!function_exists("array_udiff_uassoc")) {
   function array_udiff_uassoc() {
      $in = func_get_args();

Deleted ext/base64.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
/*
   This script implements the base64-encoding functions and base32 and
   base16 as described in RFC3548.
*/
if (!function_exists("base16_encode")) {


   #-- URL and filename safe variants of base64-encoding
   function base64_encode_safe($str) {
      return strtr(base64_encode($str), "+/", "-_");
   }
   function base64_decode_safe($b64) {
      return base64_decode(strtr($str, "-_", "+/"));
   }


   #-- base16
   function base16_encode($str) {
      $str = unpack("H".(2*strlen($str)), $str);
      $str = chunk_split($str[1]);
      return($str);
   }
   function base16_decode($b16) {
      $b16 = preg_replace("/\s+/", '', $b16);
      $b16 = pack("H*", $b16);
      return($b16);
   }


   #-- base32
   function base32_encode() {
      
      # strtoupper()
      # "A-Z,0-7,="
   }

}
?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































































Changes to ext/bcmath.php.

1
2

3
4
5
6



7
8
9
10
11
12
13
14
15
16









17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
..
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<?php
/*

   Emulates mathematical functions with arbitrary precision (bcmath)
   using POSIX systems 'dc' utility or either GMP or PHPs bigint
   extension module as fallback (were faster, but wouldn't allow to
   set precisions).



*/


#-- BSD/Linux dc(1)
if (!function_exists("bcadd") && is_executable("/usr/bin/dc")) {

   #-- invokes commandline 'dc' utility (faster than with 'bc')
   #   (later version should use proc_open() for safer and faster bi-directional I/O)
   function dc___exec($calc, $scale=NULL) {
      global $bc___scale;










      #-- assemble dc expression
      $calc = str_replace(' -', ' _', $calc);  // convert minus signs for dc
      if (isset($scale) || ($scale = $bc___scale)) {
         $calc = ((int)$scale) . "k" . $calc;  // inject precision directive
      }
      $calc = escapeshellarg($calc);   // could be non-integer from elsewhere
      
      #-- prevent any command execution from within dc
      # (for speed reasons we don't assert parameters to be fully numeric)
      if (strpos($calc, "!")) { return; }

      #-- do
      return str_replace("\\\n", "", `/usr/bin/dc -e $calc`);
   }

   #-- global state variable
   $GLOBALS["bc___scale"] = 0;  //ini_get("bcmath.scale");  // =0
   function bcscale($scale=NULL) {

      $GLOBALS["bc___scale"] = $scale;
   }

   #-- wrapper calls
   function bcadd($a, $b, $scale=NULL) {
      return dc___exec(" $a $b +nq", $scale);
   }
   function bcsub($a, $b, $scale=NULL) {
................................................................................
   }
   function bc___scaledown(&$a, $scale) {
      if (isset($scale) && ($dot = strpos($a, $dot))) {
         $a = substr($a, $dot + $scale) . "0";
      }
   }

}//shell version



#-- GMP
if (!function_exists("bcadd") && function_exists("gmp_strval")) {
   function bcadd($a, $b) {
      return gmp_strval(gmp_add($a, $b));
   }
   function bcsub($a, $b) {
      return gmp_strval(gmp_sub($a, $b));
   }
   function bcmul($a, $b) {
      return gmp_strval(gmp_mul($a, $b));
   }
   function bcdiv($a, $b, $precision=NULL) {
      $qr = gmp_div_qr($a, $b);
      $q = gmp_strval($qr[0]);
      $r = gmp_strval($qr[1]);
      if ((!$r) || ($precision===0)) {
         return($q);
      }
      else {
         if (isset($precision)) {
            $r = substr($r, 0, $precision);
         }
         return("$q.$r");
      }
   }
   function bcmod($a, $b) {
      return gmp_strval(gmp_mod($a, $b));
   }
   function bcpow($a, $b) {
      return gmp_strval(gmp_pow($a, $b));
   }
   function bcpowmod($x, $y, $mod) {
      return gmp_strval(gmp_powm($x, $y, $mod));
   }
   function bcsqrt($x) {
      return gmp_strval(gmp_sqrt($x));
   }
   function bccomp($a, $b) {
      return gmp_cmp($a, $b);
   }
   function bcscale($scale="IGNORED") {
      trigger_error("bcscale(): ignored", E_USER_ERROR);
   }
}//gmp emulation



#-- bigint
// @dl("php_big_int".PHP_SHLIB_SUFFIX))
if (!function_exists("bcadd") && function_exists("bi_serialize")) {
   function bcadd($a, $b) {
      return bi_to_str(bi_add($a, $b));
   }
   function bcsub($a, $b) {
      return bi_to_str(bi_sub($a, $b));
   }
   function bcmul($a, $b) {
      return bi_to_str(bi_mul($a, $b));
   }
   function bcdiv($a, $b) {
      return bi_to_str(bi_div($a, $b));
   }
   function bcmod($a, $b) {
      return bi_to_str(bi_mod($a, $b));
   }
   function bcpow($a, $b) {
      return bi_to_str(bi_pow($a, $b));
   }
   function bcpowmod($a, $b, $c) {
      return bi_to_str(bi_powmod($a, $b, $c));
   }
   function bcsqrt($a) {
      return bi_to_str(bi_sqrt($a));
   }
   function bccomp($a, $b) {
      return bi_cmp($a, $b);
   }
   function bcscale($scale="IGNORED") {
      trigger_error("bcscale(): ignored", E_USER_ERROR);
   }
}


?>

|
>
|
|
<
<
>
>
>
|








|
>
>
>
>
>
>
>
>
>



<
|
<
|


|







<
|
>
|







 







<
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

31

32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51
52
..
79
80
81
82
83
84
85

86
87
88



















































































89
<?php
/**
 *
 *  Emulates mathematical functions with arbitrary precision (bcmath)
 *  using POSIX systems 'dc' utility. Cannot work in PHP 'safe mode'.


 * 
 *  @requires realmode
 *
 */


#-- BSD/Linux dc(1)
if (!function_exists("bcadd") && is_executable("/usr/bin/dc")) {

   #-- invokes commandline 'dc' utility (faster than with 'bc')
   #   (later version should use proc_open() for safer and faster bi-directional I/O)
   function dc___exec($calc, $scale=NULL) {
      static $saved_scale=0;
      
      #-- bcscale() set
      if ($calc=="SETSCALE") {
         $saved_scale = (int)$scale;
         return;
      }
      elseif (!isset($scale)) {
         $scale = $saved_scale;
      }

      #-- assemble dc expression
      $calc = str_replace(' -', ' _', $calc);  // convert minus signs for dc

      $calc = $scale . "k" . $calc;    // inject precision directive

      $calc = escapeshellarg($calc);   // could contain non-integers from elsewhere
      
      #-- prevent any command execution from within dc
      #   (for speed reasons we don't assert parameters to be fully numeric)
      if (strpos($calc, "!")) { return; }

      #-- do
      return str_replace("\\\n", "", `/usr/bin/dc -e $calc`);
   }

   #-- global state variable

   function bcscale($scale=0) {
      //ini_get("bcmath.scale");  // =0
      dc___exec("SETSCALE", $scale);
   }

   #-- wrapper calls
   function bcadd($a, $b, $scale=NULL) {
      return dc___exec(" $a $b +nq", $scale);
   }
   function bcsub($a, $b, $scale=NULL) {
................................................................................
   }
   function bc___scaledown(&$a, $scale) {
      if (isset($scale) && ($dot = strpos($a, $dot))) {
         $a = substr($a, $dot + $scale) . "0";
      }
   }


}





















































































?>

Added ext/contrib/exceptions.php.























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
<?php
/*
   simplistic exception handling for PHP4
   --------------------------------------
   
   As you might know, PHP5 introduced exceptions, similiar to Javas. This
   feature of course cannot be used for PHP4-compatible scripts, and it can
   in no way be emulated by a functional API emulation like "upgrade.php".

   To use an exception-like scheme in PHP4 you'd have to agree on conventions
   - lots of. And exceptions won't look object-oriented anymore and not be
   compliant with the PHP5 scheme - the names are in fact held incompatible
   to avoid conflicts in the language semantics (reserved words).
   

   interfaces
   ----------
  
    - class Exception 
    - global variable $_EXCEPTION (- should better be a list of excptn objs?)
    - _try() function
    - _throw() function
    - _catch() function


   howto
   -----
   
    - prefix a block of commands with _try();
      this will initialize exception handling (evtl. resets internal vars)
    - errors are thrown, by calling _throw() with an Exception-class derived
      object instance as parameter, and returning immediately
    - exceptions are "catched" in if() statements, the _catch() function
      with a classname as parameter returns false or the $_EXCEPTION object
    - you shouldn't use set_exception_handler(), but $_EXCEPTION="funcname";

    #-- main code      
    _try();
    {
       sub_call();
    }
    if ($e = _catch("Special_Case")) {
       echo $e->broken_file();
    }
    if ($e = _catch("Exception")) {
       echo "Something broke, I'd say.";
    }
    
    #-- error-prone
    function sub_call() {
       // ...
       _throw(new Exception("error",255)); return();
    }

    
   note
   ----
   
   Please don't send hatemails only because you feel the syntax is too
   far away from PHP5s native exception handling and counter to that in
   other languages. And the underscores in this agreement are just to
   prevent conflicts with PHP5 constructs - this is not yet another case
   of PHP-underscoritis ;)
   
   -> there has been another PHP framework which implemented exceptions
      long before PHP5 came out; I just don't know anymore which it was
      //@TODO: build a search engine similiar to Google to find that out
*/


#-- base class for exceptions
if (!class_exists("exception")) {
   class Exception
   {
      #-- attributes
      var $message = "";
      var $code = 0;
      var $file = NULL;
      var $line = NULL;
      var $backtrace = NULL;
      
      #-- constructor
      function Exception($message="", $code=0) {
      
         #-- values
         $this->message = $message;
         $this->code = $code;
         
         #-- debugging
         $this->backtrace = debug_backtrace();
         array_shift($this->backtrace);
         $this->file = @$this->backtrace[0]["file"];
         $this->line = @$this->backtrace[0]["line"];
      }
      
      #-- get_ wrappers
      function getMessage() {
         return($this->message);
      }
      function getCode() {
         return($this->code);
      }
      function getFile() {
         return($this->file);
      }
      function getLine() {
         return($this->line);
      }
      function getTrace() {
         return($this->backtrace);
      }
      function getTraceAsString() {
         return(var_export($this->backtrace, TRUE));
      }
      
      #-- output
      function __toString() {
         return($this->message);
      }
   }
}



#-- initialize exception handling for next block
function _try()
{
   global $_EXCEPTION;

   #-- clean up
   if (!is_string($_EXCEPTION) || !function_exists($_EXCEPTION)) {
      $_EXCEPTION = new Object();
   }
}


#-- use for throwing errors
function _throw($obj) {
   global $_EXCEPTION;

   #-- quick
   if (is_string($_EXCEPTION) && function_exists($_EXCEPTION)) {
      $_EXCEPTION($obj);
   }

   #-- what do we do if there's already an exception?
   if ($_EXCEPTION) {
      // ???
      trigger_error("_throw: there is already an unhandled exception on the stack", E_USER_ERROR);
   }

   #-- generate object from error message
   if (!is_object($obj)) {
      $_EXCEPTION = new Exception("$obj");
   }

   #-- pass
   $_EXCEPTION = $obj;

   return(true);
   // break 5;  (after throwing an exception, you should
   //           exit from your current function quickly)
}


#-- check if exception thrown
function &_catch($classname="Exception") {
   global $_EXCEPTION;
   static $e;

   #-- checked for a specific error type / exception class
   if (is_object($_EXCEPTION) && (($classname == "*") || is_a($_EXCEPTION, $classname))) {
      $e = &$_EXCEPTION;   //@FIX: remove reference passing, seems unnecessary
      unset($_EXCEPTION);  // this doesn't clean the global var  [but _try() does]
   }
   else {
      $e = false;
   }

   #-- give out extracted exception   
   return $e;
}


#-- functional additions
if (!function_exists("debug_backtrace")) {
   function debug_backtrace() {
      return array();
   }
}


#-- sets global state
if (!function_exists("set_exception_handler")) {
   // quick hack, should use a different func name
   function set_exception_handler($func) {
      global $_EXCEPTION;
      $_EXCEPTION = $func;
   }
}


?>

Added ext/contrib/fix.php.





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php
/*
  api: PHP
  type: intercept
  title: PHP fixes
  descriptions: removes bogus magic_quotes and left over superglobals
  priority: auto
  category: library
  conflicts: strike_register_globals, strip_wonderful_slashes

   Outdated and bogus PHP settings (register_globals and magic_quotes) are
   defended by this script, so code cannot be negatively impacted. It can
   always be loaded as it doesn't cause problems or speed disadvantages on
   correctly configured servers. THE "PHP.INI" SHOULD BE FIXED PREFERABLY.
*/

 #-- strike register_globals (injected variables)
 if (ini_get("register_globals") == "1") {
    ewiki_recursive_unset($GLOBALS, $_REQUEST);
    ini_set("register_globals", 0);
 }

 #-- strip any \'s if magic_quotes (variable garbaging) is still enabled
 if (ini_get("magic_quotes_gpc") && get_magic_quotes_gpc()) {
    ewiki_recursive_stripslashes($_REQUEST);
    ewiki_recursive_stripslashes($_GET);
    ewiki_recursive_stripslashes($_POST);
    ewiki_recursive_stripslashes($_COOKIE);
    ewiki_recursive_stripslashes($_ENV);
    ewiki_recursive_stripslashes($_SERVER);
    ini_set("magic_quotes_gpc", 0);
 }

 #-- now that one is really dumb
 set_magic_quotes_runtime(0);


 #-- implementation
 function ewiki_recursive_unset(&$TO, $FROM) {
    foreach ($FROM as $var=>$value) {
       if (isset($TO[$var]) && ($TO[$var]==$FROM[$var])) {
          unset($TO[$var]);
          unset($TO[$var]);   // double unset to work around ZE-num/assoc-hashcode bug
       }
    }
 }
 function ewiki_recursive_stripslashes(&$var) {
    if (is_array($var)) {
       foreach ($var as $key=>$item) {
          ewiki_recursive_stripslashes($var[$key]);
       }
    }
    else {
       $var = stripslashes($var);
    }
 }

?>

Added ext/contrib/hiddenerrors.php.



































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
/*
   The error handler provided here will feed all errors and warnings
   into HTTP headers of the form "X-Error-NNNNN: ...", so they can't
   disturb page output or make XML documents invalid. This allows to
   turn on complete error_reporting() without any functionality loss
   due to premature output.
   You of course need a good Web browser that can easily display all
   response headers then for developing.
*/

set_error_handler("ewiki_http_header_errors");
ini_set("html_errors", 0);

function ewiki_http_header_errors($errno, $msg, $file, $line, $lvars) {

   static $error_types = array(
      E_PARSE => "PARSE ERROR",
      E_ERROR => "ERROR",
      E_WARNING => "WARNING",
      E_NOTICE => "NOTICE",
      E_STRICT => "STRICT",
      E_USER_ERROR => "USER ERROR",
      E_USER_WARNING => "USER WARNING",
      E_USER_NOTICE => "USER NOTICE",
   );
   ($errtype = $error_types[$errno]) or ($errtype = "UNDEF ERROR");
   
   #-- check for @ and disabled errors
   $emask = get_cfg_var("error_reporting");
   if (! ($emask & $errno)) {
      return;
   }

   #-- output
   $msg = strtr($msg, "\r\n\t\f", "    ");
   $msg = "$errtype: $msg in $file, line #$line";
   if (headers_sent()) {
      print "\n<!--<div class=\"php-error\">$msg</div>-->\n";
   }
   else {
      $no = crc32($msg);
      $no = ($no & 0xFFFF) ^ ($no >> 16);
      header("X-Error-$no: $msg");
      if ($errno == E_FATAL) { header("Status: 500 Something bad happened"); }
   }
}

?>

Added ext/contrib/http.php.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
<?php
/*
  api: PHP
  type: functions
  category: library
  priority: optional
  provides: http-request
  title: HTTP requests
  description: implements HTTP protocol, various request methods supported
  url: http://freshmeat.net/p/upgradephp
  version: 11.3

   This snippet implements HTTP queries, and allows for most request
   methods, content types and encodings. It is useful for contacting
   scripts made to serve HTML forms.
    - does neither depend upon wget or curl, nor any other extension
    - you can add ->$params (form variables) on the fly, it's a hash
    - if the initial URL contains a query string, the vars will be
      extracted first
    - set the ->$enc very carefully, because many CGI apps and HTTP
      servers can't deal with it (else "gzip" and "deflate" are nice)
    - there are abbreviations for the content ->$type values (namely
      "form" , "url" and "php")
    - user:password@ pairs may be included in the initially given URL
    - headers always get normalized to "Studly-Caps"
    - won't support keep-alive connections
    - for PUT and other methods, the ->$params var may just hold the
      request body
    - files can be added to the ->params array as hash with specially
      named fields: "content"/"data", and "filename"/"name" , "type"
    - you can add authentication information using the standard notation
      "http://user:passw@www.example.com/..." for ->$url and ->$proxy

   A response object will have a ->$content field, ->$headers[] and
   ->len, ->type attributes as well. You could also ->decode() the
   body, if it is app/vnd.php.serialized or app/x-www-form-urlencoded.
   
   Public Domain (use freely, transform into any other license, like
   LGPL, BSD, MPL, ...; but if you change this into GPL please be so
   kind and leave your users a hint where to find the free version).
*/


#-- request objects
class http_request {

   var $method = "GET";
   var $proto = "HTTP/1.1";
   var $url = "";
   var $params = array();   // URL/form post vars, or single request body str
   var $headers = array();
   var $cookies = array();
   var $type = "url";       // content-type, abbrv. for x-www-form-...
   var $enc = false;        // "gzip" or "deflate"
   var $error="", $io_err=0, $io_err_s="";
   var $active_client = 1;  // enables redirect-following
   var $redirects = 3;
   var $proxy = false;      // set to "http://host:NN/"
   var $timeout = 15;


   #-- constructor
   function http_request($method="GET", $url="", $params=NULL) {
      $this->headers["User-Agent"] = "http_query/17.2 {$GLOBALS[ewiki_config][ua]}";
      $this->headers["Accept"] = "text/html, application/xml;q=0.9, text/xml;q=0.7, xml/*;q=0.6, text/plain;q=0.5, text/*;q=0.1, image/png;q=0.8, image/*;q=0.4, */*+xml;q=0.3; application/x-msword;q=0.001, */*;q=0.075";
      $this->headers["Accept-Language"] = "en, eo, es;q=0.2, fr;q=0.1, nl;q=0.1, de;q=0.1";
      $this->headers["Accept-Charset"] = "iso-8859-1, utf-8";
      $this->headers["Accept-Feature"] = "textonly, tables, !tcpa, !javascript, !activex, !graphic";
      $this->headers["Accept-Encoding"] = "deflate, gzip, compress, x-gzip, x-bzip2";
      //$this->headers["Referer"] = '$google';
      $this->headers["TE"] = "identity, chunked, binary, base64";
      $this->headers["Connection"] = "close";
      //$this->headers["Content-Type"] = & $this->type;
      if (isset($params)) {
         $this->params = $params;
      }
      if (strpos($method, "://")) {
         $url = $method;  # glue for incompat PEAR::Http_Request
         $method = "GET";
      }
      $this->method($method);
      $this->setURL($url);
   }


   #-- sets request method
   function method($str = "GET") {
      $this->method = $str;
   }

   #-- special headers
   function setcookie($str="name=value", $add="") {
      $this->cookies[strtok($str,"=")] = strtok("\000").$add;
   }


   #-- deciphers URL into server+path and query string
   function setURL($url) {
      if ($this->method == "GET") {
         $this->url = strtok($url, "?");
         if ($uu = strtok("\000")) {
            $this->setQueryString($uu);
         }
      }
      else {
         $this->url = $url;
      }
   }
   
   
   #-- decodes a query strings vars into the $params hash
   function setQueryString($qs) {
      $qs = ltrim($qs, "?");
      parse_str($qs, $this->params);
   }


   #-- returns params as querystring for GET requests
   function getQueryString() {
      $qs = "";
      if (function_exists("http_build_query")) {
         $qs = http_build_query($this->params);
      }
      else {
         foreach ($this->params as $n=>$v) {
            $qs .= "&" . urlencode($n) . "=" . urlencode($v);
         }
         $qs = substr($qs, 1);
      }
      return($qs);
   }


   #-- transforms $params into request body
   function pack(&$path) {
      $m = strtoupper($this->method);

      #-- GET, HEAD
      if (($m == "GET") || ($m == "HEAD")) {
         $BODY = "";
         $path .= (strpos($path, "?") ? "&" : "?") . $this->getQueryString();
      }

      #-- POST
      elseif (($m == "POST") && is_array($this->params)) {

         #-- known encoding types
         $type = $this->type($this->type, 0);
         if ($type == "url") {
            $BODY = $this->getQueryString($prep="");
         }
         elseif ($type == "php") {
            $BODY = serialize($this->params);
         }
         elseif ($type == "form") {
            // boundary doesn't need checking, unique enough
            $bnd = "snip-".dechex(time())."-".md5(serialize($this->params))
                 . "-".dechex(rand())."-snap";
            $BODY = "";
            foreach ($this->params as $i=>$v) {
               $ct = "text/plain";
               $inj = "";
               if (is_array($v)) {
                  ($ct = $v["ct"].$v["type"].$v["content-type"]) || ($ct = "application/octet-stream");
                  $inj = ' filename="' . urlencode($v["name"].$v["file"].$v["filename"]) . '"';
                  $v = $v["data"].$v["content"].$v["body"];
               }
               $BODY .= "--$bnd\015\012"
                     . "Content-Disposition: form-data; name=\"".urlencode($i)."\"$inj\015\012"
                     . "Content-Type: $ct\015\012"
                     . "Content-Length: " . strlen($v) . "\015\012"
                     . "\015\012$v\015\012";
            }
            $BODY .= "--$bnd--\015\012";
            $ct = $this->type("form") . "; boundary=$bnd";
         }
         #-- ignore
         else {
            $this->error = "unsupported POST encoding";
          // return(false);
            $BODY = & $this->params;
         }

         $this->headers["Content-Type"] = isset($ct) ? $ct : $this->type($type, 1);
      }

      #-- PUT, POST, PUSH, P*
      elseif ($m[0] == "P") {
         $BODY = & $this->$params;
      }

      #-- ERROR (but don't complain)
      else {
         $this->error = "unsupported request method '{$this->method}'";
       //  return(false);
         $BODY = & $this->params;
      }

      return($BODY);
   }


   #-- converts content-type strings from/to shortened nick
   function type($str, $long=1) {
      $trans = array(
         "form" => "multipart/form-data",
         "url" => "application/x-www-form-urlencoded",
         "php" => "application/vnd.php.serialized",
      );
      $trans["multi"] = &$trans["form"];
      if ($long) {
         $new = $trans[$str];
      }
      else {
         $new = array_search($str, $trans);
      }
      return( $new ? $new : $str );
   }


   #-- initiate the configured HTTP request ------------------------------
   function go($force=0, $asis=0) {

      #-- prepare parts
      $url = $this->prepare_url();
      if (!$url && !$force) { return; }
      $BODY = $this->body($url);
      if (($BODY===false) && !$force) { return; }
      $HEAD = $this->head($url);

      #-- open socket
      if (!$this->connect($url)) {
         return;
      }

      #-- send request data
      fwrite($this->socket, $HEAD);
      fwrite($this->socket, $BODY);
      $HEAD = false;
      $BODY = false;

      #-- read response, end connection
      while (!feof($this->socket) && (strlen($DATA) <= 1<<22)) {
         $DATA .= fread($this->socket, 32<<10);
#echo "fread(".strlen($DATA).") ";
      }
      fclose($this->socket);
      unset($this->socket);

      #-- for raw http pings
      if ($asis) { 
         return($DATA);
      }

      #-- decode response
      $r = new http_response();
      $r->from($DATA);        // should auto-unset $DATA

      #-- handle redirects
      if ($this->active_client) {
         $this->auto_actions($r);
      }

      #-- fin      
      return($r);
   }

   #-- alias
   function start($a=0, $b=0) { 
      return $this->go($a, $b);
   }
   
   
   #-- creates socket connection
   function connect(&$url) {
      if ((isset($this->socket) and !feof($this->socket))
      or ($this->socket = fsockopen($url["host"], $url["port"], $this->io_err, $this->io_err_s, $this->timeout))) {
         socket_set_blocking($this->socket, true);
         socket_set_timeout($this->socket, $this->timeout, 555);
         return(true);
      }
      else {
         $this->error = "no socket/connection";
         return(false);
      }
   }


   #-- separate URL into pieces, prepare special headers
   function prepare_url() {
      $this->setURL($this->url);
      if (!$this->proxy) {
         $url = parse_url($this->url);
         if (strtolower($url["scheme"]) != "http") {
            $this->error = "unsupported protocol/scheme";
            return(false);
         }
         if (!$url["host"]) { return; }
         if (!$url["port"]) { $url["port"] = 80; }
         if (!$url["path"]) { $url["path"] = "/"; }
         if ($url["query"]) { $url["path"] .= "?" . $url["query"]; }
         $proxy = "";
      }
      else {
         $url = parse_url($this->proxy);
         $url["path"] = $this->url;
         $proxy = "Proxy-";
         $this->headers["Proxy-Connection"] = $this->headers["Connection"];
      }

      #-- inj auth headers
      if ($url["user"] || $url["pass"]) {
         $this->headers[$proxy."Authorization"] = "Basic " . base64_encode("$url[user]:$url[pass]");
      }
      
      return($url);
   }


   #-- generates request body (if any), must be called before ->head()
   function body(&$url) {

      #-- encoding of variable $params as request body (according to reqmethod)
      $BODY = $this->pack($url["path"]);
      if ($BODY === false) {
         return false;
      }
      elseif ($len = strlen($BODY)) {
         $this->headers["Content-Length"] = $len;
      }
      $enc_funcs = array("gzip"=>"gzencode", "deflate"=>"gzinflate", "bzip2"=>"bzcompress", "x-bzip2"=>"bzcompress", "compress"=>"gzcompress");
      if ((strlen($BODY) >= 1024) && ($f = $enc_funcs[$this->enc]) && function_exists($f)) {
         $BODY = $f($BODY);
         $this->headers["Content-Encoding"] = $this->enc;
         $this->headers["Content-Length"] = strlen($BODY);
      }
      return($BODY);
   }


   #-- generates request head part
   function head(&$url) {
   
      #-- inject cookie header (if any)
      if ($this->cookies) {
         $c = "";
         foreach ($this->cookies as $i=>$v) {
            $c .= "; " . urlencode($i) . "=" . urlencode($v);
         }
         $this->headers["Cookie"] = substr($c, 2);
         $this->headers["Cookie2"] = '$Version="1"';
      }
      
      #-- request head
      $CRLF = "\015\012";
      $HEAD  = "{$this->method} {$url[path]} {$this->proto}$CRLF";
      $HEAD .= "Host: {$url[host]}$CRLF";
      foreach ($this->headers as $h=>$v) {
         $HEAD .= trim($h) . ": " . strtr(trim($v), "\n", " ") . $CRLF;
      }
      $HEAD .= $CRLF;
      return($HEAD);
   }

   #-- perform some things automatically (redirects)
   function auto_actions(&$r) {

      #-- behaviour table
      static $bhv = array(
         "failure" => "204,300,304,305,306",
         "clean_::POST" => "300,301,302,303,307",
         "clean_::PUT" => "300,301,302,303,307",
         "clean_::GET" => "300",  // $params:=undef
         "GET_::POST" => "303",
         "GET_::PUT" => "303",    // downgrade $method:=GET
      );
   
      #-- failure
      if (strstr($this->behaviour_table["failure"], $r->status)) {
         return;
      }

      #-- HTTP redirects
      if (($pri_url=$r->headers["Location"]) || ($pri_url=$r->headers["Uri"])) {

         if ((($this->redirects--) >= 0) && ($r->status >= 300) && ($r->status < 400)) {
            $m = strtoupper($this->method);
            if (strstr($this->behaviour_table["clean_::$m"], $r->status)) {
               unset($this->params);
            }
            if (strstr($this->behaviour_table["GET_::$m"], $r->status)) {
               $this->method("GET");
            }
            $this->setURL($pri_url);
            $this->go();
         }
      }
   }
   
   #-- aliases for compatiblity to PEAR::HTTP_Request
   function sendRequest() {
      return $this->go();
   }
   function setBasicAuth($user, $pw) {
      $this->url = preg_replace("#//(.+?@)?#", "//$user@$pw", $this->url);
   }
   function setMethod($m) {
      $this->method($m);
   }
   function setProxy($host, $port=8080, $user="", $pw="") {
      $auth = ($pw ? "$user:$pw@" : ($user ? "$user@" : ""));
      $this->proxy = "http://$auth$server:$port";
   }
   function addHeader($h, $v) {
      $this->headers[$h] = $v;
   }
   function getResponseStatus() {
      $this->headers[$h] = $v;
   }
}
class http_query extends http_request {
   /* this is just an alias */
}




#-- every query result will be encoded in such an object --------------------
class http_response {

   var $status = 520;
   var $status_str = "";
   var $headers_str = "";
   var $headers = array();
   var $len = 0;
   var $type = "message/x-raw";
   var $content = "";
   
   
   function http_response() {
   }
   

   #-- fill object from given HTTP response BLOB   
   function from(&$SRC) {
      $this->breakHeaders($SRC);  // split data into body + headers
      $SRC = false;
      $this->decodeHeaders();     // normalize header names
      $this->headerMeta();
      $this->decodeTransferEncodings();    // chunked
      $this->decodeContentEncodings();     // gzip, deflate
      $this->len = strlen($this->content);
   }


   #-- separates headers block from response body part
   function breakHeaders(&$DATA) {
      $l = strpos($DATA, "\012\015\012"); $skip = 3;
      $r = strpos($DATA, "\012\012");
      if ($r && ($r<$l)) { $l = $r; $skip = 2; }
      if (!$l) { $l = strlen($DATA); }
      $this->headers_str = rtrim(substr($DATA, 0, $l), "\015");
      $this->content = substr($DATA, $l + $skip);
      $this->body = & $this->content;
      $this->data = & $this->content;  // aliases
      $this->ct = & $this->type;
   }


   #-- splits up the $headers_str into an array and normalizes header names
   function decodeHeaders() {

      #-- normalize linebreaks
      $str = & $this->headers_str;
//      $str = str_replace("\n ", " ", $str);
      $str = str_replace("\r", "", $str);
      
      #-- strip headline
      $nl = strpos($str, "\n") + 1;
      $this->proto = strtok(substr($str, 0, $nl), " ");
      $this->status = (int) strtok(" ");
      $this->status_str = strtok("\000\r\n");
      if ($this->status == 100) {
         $this->full_duplex = 1;
      }

      #-- go through lines, split name:value pairs
      foreach (explode("\n", substr($str, $nl)) as $line) {

         $i = trim(strtok($line, ":"));
         $v = trim(strtok("\000"));

         #-- normalize name look&feel
         $i = strtr(ucwords(strtolower(strtr($i, "-", " "))), " ", "-");

         #-- add to, if key exists
         if (!empty($this->headers[$i])) {
            $this->headers[$i] .= ", ".$v;
         }
         else {
            $this->headers[$i] = $v;
         }

      }
   }


   #-- extract interesting values
   function headerMeta() {
      $this->len = strlen($this->content);
      $this->type = trim(strtok(strtolower($this->headers["Content-Type"]), ";"));
   }
   

   #-- strip any content transformation
   function decodeTransferEncodings() {
      $enc = trim(strtok(strtolower($this->headers["Transfer-Encoding"]), ",;"));
      if ($enc) {
         switch ($enc) {
#echo "ENC($enc) ";
            case "chunked":
               $this->decodeChunkedEncoding();
               break;
            case "base64":
               $this->content = base64_decode($this->content);
               $this->len = strlen($this->content);
               break;
            case "identity": case "binary":
            case "7bit": case "8bit":
               break;
            default:
               trigger_error("http_response::decodeTransferEncodings: unkown TE of '$enc'\n", E_WARNING);
         }
      }
   }


   #-- scripts on HTTP/1.1 servers may send fragmented response
   function decodeChunkedEncoding() {

      $data = "";	# decoded data
      $p = 0;		# current string position
#file_put_contents("/tmp/1", $this->content);

      while ($p < strlen($this->content)) {
         #-- read len token
         $n = strtok(substr($this->content, $p, 20), "\n");
#echo "CHUNK($p,$n) ";
         $p += strlen($n)+1;
#echo "CHUNK2($p,$n) ";

         #-- make integer
         $n = hexdec(trim($n));
         if ($n===0) {
            break;
         }
         elseif (!$n) {
            break; //WARN
         }
         $n += 1;

         #-- read data
         $data .= substr($this->content, $p, $n);
         $p += $n + 1;
#echo "CHUNK3($p,$n) ";
      }

      $this->content = $data;
      unset($data);
      $this->len = strlen($this->content);
   }


   #-- uncompress response body
   function decodeContentEncodings() {
      $enc = trim(strtok(strtolower($this->headers["Content-Encoding"]), ";,"));
      $dat = &$this->content;
      if ($enc == "deflate") {
         $dat = gzinflate($dat);
      }
      elseif (($enc == "gzip") || ($enc == "x-gzip")) {
         if (function_exists("gzdecode")) {
            $dat = gzdecode($dat);
         }
         else {
            $dat = gzinflate(substr($dat, 10, strlen($dat)-18));
         }
      }
      elseif ($enc == "compress") {
         $dat = gzuncompress($dat);
      }
      elseif (($enc == "x-bzip2") || ($enc == "bzip2")) {
         if (function_exists("bzdecompress")) {
            $dat = bzdecompress($dat);
         }
         else trigger_error("http_response::decodeContentEncoding: bzip2 decoding isn't supported with this PHP interpreter version", E_WARNING);
      }
      $this->len = strlen($this->content);
   }


   #-- can handle special content-types (multipart, serialized, form-data)
   function decode() {
      $t = http_request::type($this->type, 0);
      if ($t == "php") {
         return(unserialize($this->content));
      }
      elseif ($t == "url") {
         parse_str($this->content, $r);
         return($r);
      }
      elseif ($t == "form") {
         // oh, not yet exactly
      }
   }

   #-- aliases for compatiblity to PEAR::HTTP_Request
   function getResponseBody() {
      return $this->content;
   }
   function getResponseStatus() {
      return $this->status;
   }
   function getResponseCode() {
      return $this->status;
   }
   function getResponseHeader($i=NULL) {
      if (!isset($i)) {
         return $this->headers;
      }
      $i = strtolower($i);
      foreach ($this->headers as $h=>$v) {
         if (strtolower($h)==$i) {
            return $v;
         }
      }
   }
}



?>

Added ext/contrib/http.txt.





























































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

Note: This class and file will be renamed into "xhttp..." in the near
feature, to prevent clashes with the old PEAR class.

http.php

This script provides the easy to use "http_request" class ("http_query"
is an alias). You can contact forms or simply retrieve files with it.
Unlike fopen_wrappers, you get the response headers alongside and the
received file will be decompressed on-the-fly (it should also be faster
due to more supported compression methods).

There are some options, you can set before starting the request. Most
important aspect is, that you can add form ->params[] one after the
other for GET and POST requests. You can also use a proxy or include
authentication passwords in the initially given url, and of course
inject or override a few ->headers[] when it makes sense.



usage

It is really easy, you only must take care to always give the method
parameter before the URL ("GET" or "POST" in most cases), look at
the following:

  <?example

      #-- prepare
      $query = new http_request("GET", "http://example.com/form.php");
      $query->params["q"] = "search-this-...";

      #-- do request
      $result = $query->go();

      #-- use result
      if ($result && ($result->status == 200)) {
         echo $result->content;
      }
  ?>

Note, that we could have included the "q" parameter simply appended to
the URL in such simple cases ("http://example.com/form.php?q=search-...").

You can also do "POST" requests (normal for forms), but that you than
must decide about the encoding format. There are two for POST requests,
the default is always urlencoding (like with GET requests) with
  <?example 
      $query->type = "url";    // corresponds to "app/x-www-form-urlencoded"
  ?>
but many bigger forms however require the MIME type for form-data:
  <?example 
      $query->type = "form";    // translates to "multipart/form-data"
  ?>
You see, there are easy to remember abbreviations for this.

The form variables you want to transport are simply appended to the URL
for GETs or "url"-coded requests, but you could use the $query->params[]
array also here.

If you do a "POST" request, you do likewise; or you could also just assign
the $query->params a string blob to transfer as content (if the remote app
can deal with it or expects that, or you already have encoded eveything
into a valid form request).
If you just want to add upload-files to a "POST" request, then do this as
follows:
  <?example
      $query->params["fileformname"] = array(
         "filename" => "original-name.zip",
         "type" => "application/octet-stream",
         "content" => "$READ_FROM_FILE_DATA...",
      );
  // or
      $query->params["2nd_file"] = array(
         "ct" => "x.ml/my-format",
         "name" => "../../where/is/it/from.txt",
         "data" => file_get_contents(".../from.txt"),
      );
  ?>
"body" is a third alias for the "content" field here. If you don't set
the "type" or "ct" flag it will get "application/octet-stream" per default
(this is a good default). You could simply load the "ext/mime" script to
have the best possible MIME type here.



     start an request
     
     Use the ->go() method to start a prepared HTTP request. The only
     alias existing today is ->start(); simply derive or edit this class
     to add your preferred name for this likewise (->do() cannot be used
     as it is a PHP reserved word, sorry ;)

     There are two options to ->go(), the first $force will override a few
     problems, and with the second ($asis) set to 1 or true, you won't get
     a result object, but the plain HTTP response blob (headers and response
     body as one large string variable).



     authentication
     
     If the remote site requires authentification, you would simply give
     this within the URL:
      <?example
         $query = new http_request("GET", "http://user:passw@example.com/...");
           // or later:
         $query->setURL("http://username:pw2@server.../")
           // or even:
         $query->url = "http://name:password@localhost/form.php";
      ?>



     proxy
     
     You can also acccess a form or remote file using a proxy server easily,
     just follow this:
      <?example
         $query = new http_request("PUT", "...");
         $query->proxy = "http://servername.proxy.org:3219/";
           // ...
         $result = $query->go();
      ?>
     You could also give a password or username for your proxy server, if
     you need it (works the same as for above).




reponses

The $result value from the above examples should normally be an object,
it will be a scalar (false) only if something went really wrong.

It will have at least a ->status field, which is typically 200 for
succeeded requests. Everything above 500 means an server error, values
above 400 a transport and request error (= we did something wrong) and
a 300 response status means a redirection was issued.

For fulfilled requests you can access the returned file/data simply as
"$result->content" or "$result->body" or even "$result->data" (two aliases
again).

You will also have a "$result->headers[]" array, which will hold all
response HTTP headers in normalized form. Typically this means:
  <?example
      echo $result->headers["Content-Type"] . "\n";
      echo $result->headers["Date"] . "\n";
      echo $result->headers["Last-Modified"] . "\n";
      echo $result->headers["Content-Length"] . "\n";
      echo $result->headers["Etag"] . "\n";    // (beware of the lcased "t" !)
      echo $result->headers["Content-Encoding"] . "\n";
      ...
      print_r($result->headers);  // much better here ;)
  ?>
[[ Elsewhere the field names would be completely lowercased or fully
uppercase, we have CamelCase here, with the hyphens still in of course. ]]

Please note, that a known "Content-Encoding" was already removed from the
received ->content. And there is also a more correct "$result->len" and a
"$result->type" shorthand.

A few response types are understand as application data, and in this case
you can call the $result->decode() function and get a PHP variable/array
from the body.



     redirects
     
     If you expect HTTP redirects (->status codes from 300 till 375), then
     the default settings are ok for you, many will automatically be catched
     and the form data or file request will succeed at the replied URL.

     To tack/catch these cases yourself, simply disable that behaviour with:
      <?example
         $query->active_client = 0;
      ?>



PHP-RPC

Not yet!  But this is probably what it will look like:

  If you control both ends of the Wire, you shouldn't use the slow and
  buggy (not everything works with everything else) XML-RPC protocol for
  calling remote functions, but instead use the high speed PHP serialize
  encoding to transfer data.

  The "http_request" class can natively encode values as such. The MIME
  type "application/vnd.php.serialized" has been registered explicitely
  for this purpose (as alternative to "multipart/form-data" encoding,
  and it is type-safe as opposed to the "/x-www-form-urlencoded" format).
  Perl and JS implementations exist (probably also one for Python), so
  plattform-independence should be given.

  PHP-RPC shall inherit (not yet negotiated) some structure from the old
  XML-RPC protocol. That is, a few names are identical. If you start an
  request you would therefore do following:

<?php

    function phprpc($server, $function, $args=array()) {

       #-- init
       $query = new http_request("POST", $server);

       #-- set content
       $query->type = "php";  // here corresponds to "app/vnd.php.serialized"
       $query->params
         = array(
              "method" => $function,
              "params" => $args,
           );

       #-- start
       $result = $query->go();
       if ($result && ($result->status == 200)) {

          $r = $result->decode();
          if ($good = $r["result"]) {
             return($good);
          }
          return($r);
       }
    }
?>

  You of course need a server part to make use of this. Simply try the
  "ext/phprequest", in which case you would do the following:

<?php

   include("ext/phprequest.php")
   if (count($_POST) && ($method = $_POST["method"])
   and ($params = $_POST["params"]))
   {
      #-- call known/registered functions
      $method = strtolower($method);
      if ($method == "my.func") {
         $r = call_user_func_array("my_func", $params);
      }
      elseif ($method == "system.time") {
         $r = time();
      }
      elseif ($method == "sytem.listmethods") {
         $r = get_defined_functions();
         $r = $r["user"];
      }

      #-- if succeeded
      if ($r) { 
         header("Content-Type: application/vnd.php.serialized");
         header("Content-Encoding: deflate");
         $r = array("result" => $r);
         die(gzdeflate(serialize($r));
      }
   }

   #-- your normal script can go on here
   //...
?>

  You can inject this into anywhere as it only engages, if a PHP-RPC
  request was detected. 



Added ext/contrib/is_utf8.php.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

#-- test if string uses UTF-8 encoding
# http://www.w3.org/International/questions/qa-forms-utf-8.en.php
# (Martin Drst, W3C)
function is_utf8($field) {
   return preg_match(
      '/^( [\09\0A\0D\x20-\x7E]               # ASCII
         | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
         |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
         | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
         |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
         |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
         | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
         |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
      )*$/x',
      $field
   );
}

?>

Added ext/contrib/pdo-2006-01-29.tar.gz.

cannot compute difference between binary files

Added ext/contrib/php5oo.php.















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
/**
 * Some functions from PHP5, that aren't actually senseful to replicate
 * for PHP4. The new native object semantics cannot be emulated anyhow.
 *
 * - see also ext/contrib/exceptions.php
 *
 */



 
/**
 * Make a real object copy. This is a token in PHP5, not a function.
 *
 * Uses serialize-trick from PHP_Compat, because PHP4 references can
 * neither be detected nor resolved otherwise.
 *
 * @stub
 * @since 5.0
 */
if (!function_exists("clone") && PHP_VERSION < "5.0") {
   eval('
   function clone($obj) {
   
      // this however duplicates sub-objects and arrays too
      $new = unserialize(serialize(($obj));
     
      if (method_exists($new, "__clone")) {
         $new->__clone();
      }

      return $new;
   }
   ');
}


?>

Added ext/contrib/phprequest.php.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
/*
   Allows http "POST" and "PUSH" requests with a Content-Type of
   "application/vnd.php.serialized". This isn't used in the wild.
*/

if (empty($_POST)
and (strtoupper($_SERVER["REQUEST_METHOD"][0]) == "P")
and (strtolower(trim(strtok($_SERVER["CONTENT_TYPE"], ";,(")))
     == "application/vnd.php.serialized"))   
{
   #-- search for bare request body
   if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
      $_POST = $GLOBALS["HTTP_RAW_POST_DATA"];
   }
   else {
      $f = fopen("php://input", "rb");
      $_POST = fread($f, 1<<22);
      fclose($f);
   }

   #-- uncompress and decode, if something found
   if ($_POST) {

      #-- strip known/supported encodings
      $enc = trim(strtok(strtolower($_SERVER["HTTP_CONTENT_ENCODING"]), ",;"));
      if ($enc == "deflate") {
         $_POST = gzinflate($_POST);
      }
      elseif ($enc == "compress") {
         $_POST = gzuncompress($_POST);
      }
      elseif ($enc == "gzip") {
         $_POST = function_exists("gzdecode") ? gzdecode($_POST) : gzinflate(substr($_POST, 10, strlen($_POST) - 18));
      }
      elseif (($enc == "x-bzip2") or ($enc == "bzip2")) {
         $_POST = function_exists("bzdecompress") ? bzdecompress($_POST) : NULL;
      }

      #-- decipher
      if ($_POST) {
         $_POST = unserialize($_POST);
      }
      #-- merge
      if ($_POST) {
         $_REQUEST = array_merge($_REQUEST, $_POST);
      }

   }
}

?>

Added ext/contrib/xmlrpc.php.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
<?php define("XMLRPC_VERSION", "0.3.10");
# api: PHP
# type: api
# provides: rpc, xml-rpc
# version: 0.3.10
# category: library
# priority: optional
# title: XML-RPC client and server
# description: serves remote procedure calls
# homepage: http://freshmeat.net/p/upgradephp
#
#  Supports XML-RPC (text/xml) and XML+RPC (application/rpc+xml) compressed,
#  and can be used as client or server interface. Works without XMLRPC and
#  XML extensions, but utilizes them for optimal speed whenever available.
#
#   XXXX   XXXX MMM     MMM LLL              RRRRRRR   PPPPPPP    CCCCCCC
#    XXXX XXXX  MMMM   MMMM LLL      +++     RRRRRRRR  PPPPPPPP  CCCCCCCCC
#     XXXXXXX   MMMMM MMMMM LLL      +++     RRR   RRR PPP   PPP CCC    CCC
#      XXXXX    MMMMMMMMMMM LLL  +++++++++++ RRR   RRR PPP   PPP CCC
#       XXX     MMM MMM MMM LLL  +++++++++++ RRRRRRRR  PPPPPPPP  CCC
#      XXXXX    MMM  M  MMM LLL      +++     RRRRRRR   PPPPPPP   CCC
#     XXXXXXX   MMM     MMM LLL      +++     RRR  RRR  PPP       CCC    CCC
#    XXXX XXXX  MMM     MMM LLLLLLL          RRR   RRR PPP       CCCCCCCCC
#   XXXX   XXXX MMM     MMM LLLLLLL          RRR   RRR PPP        CCCCCCC
#
#  This is Public Domain. (c) 2004 WhoEver wants to. [milky*erphesfurtde]


#-- config
define("XMLRPC_PLUS", 0);        # use XML+RPC per default
define("XMLRPC_AUTO_TYPES", 0);  # detect base64+datetime strings and automatically generate the according xmlrpc object representations then
define("XMLRPC_AUTO_UTF8", 1);   # de/convert anything from and to UTF-8 automatically - if yourscripts use Latin1 natively, but the RPC server expects/sends UTF-8
define("XMLRPC_CHARSET", "utf-8");  # used in responses and requests
define("XMLRPC_AUTODISCOVERY", 0);  # "connections" automatically create methods
define("XMLRPC_FAST", 1);        # use PHPs XML-RPC extension where possible
define("XMLRPC_OO", 1);          # return XML-RPC/HTTP errors as objects
define("XMLRPC_DEBUG", 0);       # output error hints, write /tmp dumps - set this to 1, 2 or 3

#-- _server() settings
define("XMLRPC_LOG", "/tmp/xmlrpc.".@$_SERVER["SERVER_NAME"].".log");

#-- general data
#  (don't change the following, most are auto-configured values)
define("XMLRPC_UA", "xml+rpc/".XMLRPC_VERSION." (PHP/".PHP_VERSION."; ".PHP_OS.")");
define("XMLRPC_MIME_NEW", "application/rpc+xml");
define("XMLRPC_MIME_OLD", "text/xml");
define("XMLRPC_MIME", XMLRPC_MIME_OLD);
define("XMLRPC_ACCEPT", XMLRPC_MIME_NEW.", ".XMLRPC_MIME_OLD."; q=0.5");
define("XMLRPC_EPI", function_exists("xmlrpc_decode_request"));

#-- init
error_reporting(0);
if (isset($_SERVER["HTTP_CONTENT_TYPE"]) && empty($_SERVER["CONTENT_TYPE"])) {
   $_SERVER["CONTENT_TYPE"] = $_SERVER["HTTP_CONTENT_TYPE"];   // older CGI implementations
}




############################################################################
#                                                                          #
#  client part                                                             #
#                                                                          #
############################################################################


#-- Issue a request, call can take any number of arguments.
#     $result = xmlrpc("http://example.com/RPC2/", "method1", $arg1 ...);
#     $result = xmlrpc("xml+rpc://here.org/RPC3/", "ns.function", ...);
#   Results automatically have <datetime> values converted into Unix
#   timestamps and <base64> unpacked into strings.
#
function xmlrpc($server, $method=NULL /*, ... */) {
   if ($method) {
      $params = func_get_args();
      shift($params); shift($params);
      return
        xmlrpc_request($server, $method, $params);
   }
   else {
      return
        new xmlrpc_connection($server);
   }
}



#--  Generate and send request, decode response.
function xmlrpc_request($url, $method, $params=array(), $plus=XMLRPC_PLUS, $gzip=0) {
   global $xmlrpc_response_headers, $xmlrpc_error;
   
   #-- init whole lib for request (we are not-OO here)
   $xmlrpc_error = false;
   $xmlrpc_response_headers = array();
   
   #-- encapsulate req, transmit it
   $socket = xmlrpc_request_send($url, $method, $params, $plus, $gzip);
   if (!$socket) {
      return xmlrpc_error(-32768, "no connection", 0, "GLOBALVARS");
   }

   #-- wait for, read response
   $response = "";
   while (!feof($socket) && (strlen($DATA) <= 768<<10)) {
      $response .= fread($socket, 4<<10);
   }
   fclose($socket);
   if (XMLRPC_DEBUG >= 3) {
      echo "<code>$response</code>";
   }

   #-- decode answer and give results
   return xmlrpc_response_decode($response);
}


#-- an alias
function xmlrpc_call($url, $method, $params=array(), $plus=XMLRPC_PLUS, $gzip=0) {
   return xmlrpc_request($url, $method, $params, $plus, $gzip);
}



#-- marshall request parameters into array, hash, xml string
function xmlrpc_request_send($url, $method, &$params, $plus, $gzip, $blocking=true) {

   #-- get connection data
   $c = parse_url($url);
   ($host = $c["host"]);
   ($port = @$c["port"]) or ($port = 80);
   ($path = $c["path"]) or ($path = "/");
   if (strpos($c["scheme"], "+")) {
      $plus++;
   }
   if (strpos($c["scheme"], "gzip")) {
      $gzip++;
   }
   if (!$host) { return(NULL); }
   $inj = "";
   if ($str = $c["user"]) {
      if ($c["pass"]) { $str .= ":" . $c["pass"]; }
      $inj = "Authorization: Basic " . base64_encode($str) . "\n";
   }
   
   #-- mk request HTTP+XML block from params
   $request = xmlrpc_request_marshall($method, $params);
   $request = xmlrpc_request_http($request, $path, $host, $plus, $gzip, $inj);

   #-- connect, send request
   if ($socket = fsockopen($host, $port, $io_err, $io_err_s, 30)) {
      socket_set_blocking($socket, $blocking);
      socket_set_timeout($socket, 17, 555);
   }
   else {
      echo "Could not connect to '<b>$host</b>:$port$path' - error $io_err: $io_err_s.<br>\n";
      return(NULL);
   }
   fputs($socket, $request);

   #-- done here
   return($socket);
}


#-- marshall function call into XML+HTTP string
function xmlrpc_request_marshall($method, &$params) {

   #-- use xmlrpc-epi
   if (XMLRPC_FAST && XMLRPC_EPI) {
      $query = xmlrpc_encode_request($method, $params);
      return($query);
   }

   #-- build query
   $query = array(
      "methodCall" => array(
         "methodName" => array( ",0"=>$method ),
         "params" => array()
      )
   );
   foreach ($params as $i=>$p) {
      $query["methodCall"]["params"]["param,$i"] = xmlrpc_compact_value($p);
   }
   $query = array2xml($query, 1, 'encoding="'.XMLRPC_CHARSET.'" ');

   #-- encode?
   if (XMLRPC_AUTO_UTF8) {
      $query = utf8_encode($query);
   }
   
   return($query);   
}


#-- enclose body into HTTP request string
function xmlrpc_request_http(&$query, $path, $host, $plus, $gzip, $inj_header="") {

   #-- build request
   $n = "\015\012";
   $request = "POST $path HTTP/1.0$n"
            . "Host: $host$n"
            . ($inj_header ? str_replace("\n", $n, $inj_header) : "")
            . "User-Agent: " . XMLRPC_UA . "$n"
            . "Accept: ".XMLRPC_ACCEPT."$n"
            . (!XMLRPC_DEBUG ? "Accept-Encoding: deflate$n" : "")
            . "Content-Type: ".($plus ? XMLRPC_MIME_NEW : XMLRPC_MIME_OLD)
                              ."; charset=".XMLRPC_CHARSET."$n";

   #-- compress?
   if ($gzip) {
      $query = gzdeflate($query);
      $request .= "Content-Encoding: deflate$n";
   }
   $request .= "Content-Length: " . strlen($query) . "$n" . "$n";
   $request .= $query . "$n";

   return($request);
}


#-- unpack response from HTTP and XML representation
function xmlrpc_response_decode(&$response) {
   global $xmlrpc_response_headers;

   #-- split into headers and content
   $l1 = strpos($response, "\n\n");
   $l2 = strpos($response, "\n\r\n");
   if ($l2 && (!$l1 || ($l2<$l1))) {
      $head = substr($response, 0, $l2);
      $response = substr($response, $l2+3);
   }
   else {
      $head = substr($response, 0, $l1);
      $response = substr($response, $l2+2);
   }

   #-- decode headers, decompress body
   foreach (explode("\n", $head) as $line) {
      $xmlrpc_response_headers[strtolower(trim(strtok($line, ":")))] = trim(strtok("\000"));
   }
   if ($enc = trim(@$xmlrpc_response_headers["content-encoding"])) {
      if (($enc == "gzip") || ($enc == "x-gzip")) {
         $response = gzinflate(substr($response, 10, strlen($response)-18));
      }
      elseif (($enc == "compress") || ($enc == "x-compress")) {
         $response = gzuncompress($response);
      }
      elseif (($enc == "deflate") || ($enc == "x-deflate")) {
         $response = gzinflate($response);
      }
   }

   $r = xmlrpc_response_unmarshall($response);
   if (XMLRPC_DEBUG) {var_dump($r);}
   return($r);
}


#-- decode XML-RPC from string into array and extract its actual meaning
function xmlrpc_response_unmarshall(&$response) {
   global $xmlrpc_response_headers;

   #-- strip encoding
   if (XMLRPC_AUTO_UTF8) {
      xmlrpc_decode_utf8xml($response, @$xmlrpc_response_headers["content-type"].@$xmlrpc_response_headers["content-charset"]);
   }

   if (XMLRPC_DEBUG >= 4) { fwrite(fopen("/tmp/xmlrpc:resp_in_xml","w"), $response); }
   
   #-- use xmlrpc-epi
   if (XMLRPC_FAST && XMLRPC_EPI) {
      $r = xmlrpc_decode_request($response, $uu);
      xmlrpc_epi_decode_xtypes($r);
      if (is_array($r) && (count($r)==2) && isset($r["faultCode"]) && isset($r["faultString"])) {
         return xmlrpc_error($r["faultCode"], $r["faultString"], 1, "GLOBALVARS");
      }
      else {
         return($r);
      }
   }


   #-- unmarshall XML
   $response = xml2array($response);

   #-- fetch content (one returned element)
   if ($r = @$response["methodResponse,0"]["params,0"]["param,0"]["value,0"]) {
      $r = xmlrpc_decode_value($r);
      return($r);
   }
  
   #-- error cases
   #  (we should rather return an error object here)
   if (($r = @$response["methodResponse,0"]["fault,0"]["value,0"]) && ($r = xmlrpc_decode_value($r))) { 
      return xmlrpc_error($r["faultCode"], $r["faultString"], 1, "GLOBALVARS");
   }
   else {
      return xmlrpc_error(-32600, "xml+rpc: invalid response", 0, "GLBLVRS");
   }
   return(NULL);
}



#-- Establish a virtual XML+RPC or XML-RPC server connection (a pseudo
#   handshake is used to determine supported protocol / extensions).
class xmlrpc_connection {

   #-- init
   function xmlrpc_connection($url, $autodiscovery=0) {
      global $xmlrpc_response_headers;
      $this->server = $url;
      $this->plus = 0;
      $this->gzip = 0;

      #-- handshake to check supported protocol
      $funcs = $this->call("system.getVersion");
      $this->plus = (strpos($xmlrpc_response_headers["accept"], XMLRPC_MIME_NEW) !== false);
      $this->gzip = (strpos($xmlrpc_response_headers["accept_encoding"], "deflate") !== false);
      
      #-- auto-discovery, create 'method' names
      if ($funcs && (XMLRPC_AUTODISCOVERY || $autodiscovery)) {
         foreach ($funcs as $fn) {
            $short = $fn;
            if ($l = strpos($fn, ".")) {
               $short = substr($fn, $l + 1);
               if (substr($fn, 0, $l) == "system") { continue; }
            }
            $this->short = create_function("", "return xmlrpc_request('{$this->server}','$fn',func_get_args(),{$this->plus},{$this->gzip});");
         }
      }
   }
   
   #-- generical call (needs func name)
   function call($method /*, ... */) {
      $params = func_get_args();
      shift($params);
      $r = xmlrpc_request($this->serverm, $method, $params, $this->plus, $this->gzip);
      return($r);
   }
}

#-- an alias
class xmlrpc extends xmlrpc_connection {
}




############################################################################
#                                                                          #
#  server implementation                                                   #
#                                                                          #
############################################################################


#-- Check request and execute function if registered in $xmlrpc_methods[]
#   array.
function xmlrpc_server() {

   global $xmlrpc_methods;

   #-- server is active
   define("XMLRPC_SERVER", getmypid());
   if (XMLRPC_DEBUG) { error_reporting(E_ALL^E_NOTICE); }
   ob_start();

   #-- standard reply headers
   header("Accept: ".XMLRPC_MIME_NEW.", ".XMLRPC_MIME_OLD."; q=0.5");
   header("Accept-Encoding: deflate");
   header("X-Server: " . XMLRPC_UA);
   header("Connection: close");
   header("Cache-Control: private");

   #-- fixes for PHP/Apache
   if (function_exists("getallheaders")) {
      foreach (getallheaders() as $i=>$v) {
         $_SERVER[strtoupper(strtr("HTTP_$i", "-", "_"))] = $v;
      }
   }

   #-- check and get call
   $allowed = array(
      "REQUEST_METHOD" => array("POST", "PUT", "CALL"),
      "CONTENT_TYPE" => array(XMLRPC_MIME_NEW, XMLRPC_MIME_OLD),
   );
   foreach ($allowed as $WHAT=>$WHICH) {
      if (!in_array(trim(strtok($WRONG=$_SERVER[$WHAT], ";,(")), $WHICH)) {
         header("Status: 400 Go Away, Stupid!");
         if (!$WRONG) {
            $WRONG = "undefined";
         }
         die("<h2>Error</h2>Your request was bogus, <b>$WHAT</b> must be <i>"
             . implode("</i> or <i>", $WHICH) . "</i>, but yours was '<tt>$WRONG</tt>'.\n");
      }
   }
   if (!($xml_request = xmlrpc_fetch_post_chunk())) {
      header("Status: 500 How Sad");
      die("<h2>Error</h2>Could not fetch POST data.\n");
   }

   #-- decipher incoming XML request string
   $method = "";
   if (XMLRPC_FAST && XMLRPC_EPI) {
      $params = xmlrpc_decode_request($xml_request, $method);
      xmlrpc_epi_decode_xtypes($params);
   }
   else {
      $params = xmlrpc_request_unmarshall($xml_request, $method);
   }

   
   #-- add the few system.methods()
   //if (empty($xmlrpc_methods)) {
   //   $xmlrpc_methods = get_defined_functions();
   //}
   $xmlrpc_methods["system"] = "xmlrpc_system_methods";   # a class

   #-- call
   $result = xmlrpc_exec_method($method, $params);

   #-- send back result
   if (isset($result)) {
      if (isset($result)) {
         $resp["methodResponse"]["params"]["param"] = xmlrpc_compact_value($result);
      }
      else {
         $resp["methodResponse"]["params"] = array();
      }

      xmlrpc_send_response($resp);
   }
   else {
      $result = xmlrpc_error(0, "No Result");
      xmlrpc_send_response($result);
   }
}



#-- decode <methodCall> XML string into understandable chunks,
#   gives $params as return value and $method name via pass-by-ref
function xmlrpc_request_unmarshall(&$xml_request, &$method) {

   #-- mangle charset
   if (XMLRPC_AUTO_UTF8) {
      xmlrpc_decode_utf8xml($xml_request, $_SERVER["CONTENT_TYPE"].$_SERVER["HTTP_CONTENT_CHARSET"]);
   }

   #-- decode XML string into PHP arrays
   $call = xml2array($xml_request, 1);
   $xml_request = NULL;

   $call = $call["methodCall,0"];
   if (!$call) {
      xmlrpc_send_response(xmlrpc_error(-32600, "Bad Request, <methodCall> missing"));
   }
   $method = $call["methodName,0"][",0"];
   if (!$method) {
      xmlrpc_send_response(xmlrpc_error(-32600, "Bad Request, <methodName> missing"));
   } 

   $params = array();
   foreach ($call["params,1"] as $uu => $param) {
      $params[] = xmlrpc_decode_value($param["value,0"]);
   }

   return($params);
}



#-- Call the requested method (using the XML-method to PHP-function mapping
#   table and hints).
function xmlrpc_exec_method($method, $params) {

   global $xmlrpc_methods;
   if (XMLRPC_DEBUG >= 2) { error_reporting(E_ALL^E_NOTICE); }

   #-- check if allowed call
   $rf = strtr($method, ".", "_");
   $cl = strtok($method, ".");
   if (!$xmlrpc_methods[$method] && !$xmlrpc_methods[$cl]
      && !in_array($method, $xmlrpc_methods)
      && !in_array($rf, $xmlrpc_methods) && !in_array($cl, $xmlrpc_methods) )
   {
      xmlrpc_send_response(xmlrpc_error(-32601));
   }

   #-- real function call
   if ($php_func_name = $xmlrpc_methods[$method]) {
      $rf = $method = $php_func_name;
   }
   if (function_exists($rf)) {
      $result = call_user_func_array($rf, $params);
      if (XMLRPC_DEBUG >= 4) { fwrite(fopen("/tmp/xmlrpc:func_call_res","w"),serialize(array($rf,$result,$params))); }
      return($result);
   }
   #-- PHP object method calls
   else {
      $class = strtok($method, ".");
      $method = strtok("\000");
      if ($uu = $xmlrpc_methods[$class]) {
         $class = $uu;
      }
      if ($class && class_exists($class) && $method) {
         $obj = new $class;
         if (method_exists($obj, $method)) {
            $result = call_user_method_array($method, $obj, $params);  //<DEPRECATED>
            return($result);
         }
      }
   }

   #-- else error
   xmlrpc_send_response(xmlrpc_error(-32601));
}



#-- Get POST data from PHP (if it gives it to us).
function xmlrpc_fetch_post_chunk() {
   global $HTTP_RAW_POST_DATA;

   $data = false;
   if ($f = fopen("php://input", "rb")) {
      $data = fread($f, 0x0100000);
      fclose($f);
   }
   if (empty($data)) {
      ini_set("always_populate_raw_post_data", "true");  // well, maybe(!?)
      $data = $HTTP_RAW_POST_DATA;
      $HTTP_RAW_POST_DATA = "";
   }
   $enc = trim(strtolower($_SERVER["HTTP_CONTENT_ENCODING"]));
   $funcs = array("deflate"=>"gzinflate", "gzip"=>"gzdecode", "compress"=>"gzuncompress", "x-gzip"=>"gzdecode", "x-bzip2"=>"bzuncompress");
   if ($enc && ($pf = $funcs[$enc]) && function_exists($pf)) {
      $data = $pf($data);
   }
   return($data);
}


#-- converts UTF-8 documents into Latin-1 ones
function xmlrpc_decode_utf8xml(&$xml, $ct) {
   if (strpos(strtolower($ct), "utf-8") or preg_match('/<\?xml[^>]+encoding=["\']utf-8/i', $xml)) {
      $xml = utf8_decode($xml);
      $xml = preg_replace('/(<\?xml[^>]+encoding=["\'])utf-8(["\'])/i', '$1iso-8859-1$2', $xml, 1);
   }
}



#-- Creates an error object.
function xmlrpc_error($no=-32500, $str="", $type=1, $into_vars=0) {
   global $xmlrpc_error, $xmlrpc_errorcode;
   $errors = array(
           0 => "No Result",
      -32300 => "Transport error",
      -32400 => "Internal Server Error",
      -32500 => "Application error",
      -32600 => "Invalid message format / Bad request",
      -32601 => "Method does not exist",
      -32602 => "Parameter type mismatch",
      -32603 => "Internal XML-RPC error",
      -32604 => "Too many parameters",
      -32700 => "Not well-formed XML",
      -32701 => "Unsupported encoding - only ISO-8859-1 and UTF-8 capable",
      -32702 => "Invalid characters, encoding mismatch",
   );
   #-- build response xml/array
   if (!($str) && !($str = $errors[$no])) {
      $str = "Unknown Error";
   }
   if ($into_vars && !XMLRPC_OO) {
      $xmlrpc_error = $str;
      $xmlrpc_errorcode = $no;
      return(NULL);
   }
   else {
      return new xmlrpc_error($no, $str, $type);
   }
}


#-- error object
class xmlrpc_error {

   var $type = 1;   // else an HTTP error
   var $no;
   var $str;
   
   function xmlrpc_error($no, $str, $type=1) {
      $this->type = $type;
      $this->no = $no;
      $this->str = $str;
   }
   
   function send() {
      $error = xmlrpc_compact_value(array(
         "faultCode" => $no,
         "faultString" => $str,
      ));
      $resp = array(
         "methodResponse" => array(
            "fault" => $error
         )
      );
      xmlrpc_send_response($resp);
   }
}


#-- Sends a response.
function xmlrpc_send_response($r) {

   #-- error objects send itself (by calling _send_response() again ;-)
   if (is_object($r)) {
      $r->send();
   }

   #-- answer XML-RPC and XML+RPC requests
   $ct = trim(strtok(strtolower($_SERVER["CONTENT_TYPE"]), ";,("));  // from original request
   $cs = XMLRPC_CHARSET;
   header("Content-Type: $ct; charset=\"$cs\"");
   
   #-- make XML document from it
   if (is_array($r)) {
      $r = array2xml($r, 1, 'encoding="'.$cs.'" ');
   }

   #-- compress answer?
   if (!headers_sent()) {
      $enc = trim(strtolower($_SERVER["HTTP_ACCEPT_ENCODING"]));
      $funcs = array("deflate"=>"gzdeflate", "gzip"=>"gzencode", "compress"=>"gzcompress", "x-gzip"=>"gzencode", "x-bzip2"=>"bzcompress");
      if ($enc && ($pf = $funcs[$enc]) && function_exists($pf)) {
         header("Content-Encoding: $enc");
         $r = $pf($r);
      }
   }

   #-- send
   if (ob_get_level()) {
      #-- this prevents that PHP errors appear as garbage in our response
      $add .= "<!--\n" . ob_get_contents() . "\n-->";
      ob_end_clean();
   }
   header("Content-Length: " . strlen($r));
   print $r . $add;
   die;
}



#-- Provides "system.*" method namespace.
class xmlrpc_system_methods {

   function listMethods() {
      global $xmlrpc_methods;
      $r = array();
      foreach ($xmlrpc_methods as $i=>$i2) {
         $real = is_int($i) ? $i2 : $i;
         if (class_exists($real) && ($i2=$real) || class_exists($i2)) {
            foreach (get_class_methods($i2) as $add) {
               $r[] = $real.".".$add;
            }
         }
         else {
            $r[] = $real;
         }
      }
      return($r);
   }

   function time() {
      return new xmlrpc_datetime(time());
   }
}


############################################################################
#                                                                          #
#  misc functions                                                          #
#                                                                          #
############################################################################


function xmlrpc_log($message) {
}

function xmlrpc_die($error="", $str="") {
}



############################################################################
#                                                                          #
#  data representation mangling                                            #
#                                                                          #
############################################################################


#-- Makes compact-array2xml datavar from a PHP variable.
function xmlrpc_compact_value($var, $n=0) {

   #-- create compact-array2xml tree
   $root = array(
      "value,$n" => array(),
   );
   $r = &$root["value,$n"];

   #-- detect PHP values to be complex types in XML-RPC
   if (XMLRPC_AUTO_TYPES && is_string($var)) {
      if ((strlen($var) >= 64) && preg_match('/^[\w]+=*$/', $var)) {
         $var = new xmlrpc_base64($var);
      }
      elseif ((strlen($var)==17) && ($var[8]=="T") && preg_match('/^\d{8}T\d\d:\d\d:\d\d$/', $var)) {
         $var = new xmlrpc_datetime($var);
      }
   }

   #-- complex types
   if (is_object($var)) {
      $r = $var->out();
   }
   #-- arrays and hashes(structs)
   elseif (is_array($var)) {
      if (isset($var[0]) || empty($var)) {
         $r = array("array,$n" => array("data,0" => array()));
         $r = &$r["array,$n"]["data,0"];
         foreach ($var as $n=>$val) {
            $r = array_merge($r, xmlrpc_compact_value($val, $n));
         }
      }
      else {
         $r = array("struct,$n"=>array());
         $r = &$r["struct,$n"];
         $n = 0;
         foreach ($var as $i=>$val) {
            $r["member,$n"] = array_merge(array(
               "name,0" => array(",0" => "$i"),
            ), xmlrpc_compact_value($val, 1));
            $n++;
         }
      }
   }
   #-- simple types
   elseif (is_bool($var)) {
      $r = array(
         "boolean,$n" => array(",0" => ($var?1:0)),
      );
   }
   elseif (is_int($var)) {
      $r = array(
         "int,$n" => array(",0" => $var),
      );
   }
   elseif (is_float($var)) {
      $r = array(
         "double,$n" => array(",0" => $var),
      );
   }
   elseif (is_string($var)) {
      $r = array(
         "string,$n" => array(",0" => $var),
      );
   }
   return($root);
}


#-- Makes a PHP array from a compact-xml2array representation. $value must
#   always be the xml2array elements _below_ the ["value,0"] or ["data,0"]
#   or ["member,N"] entry.
function xmlrpc_decode_value($value) {
   $val = NULL;
   foreach ($value as $i=>$d) {

      #-- use single (text) content xml2array entry as actual $d var
      if (is_array($d) && isset($d[",0"])) {
         $d = $d[",0"];
      }

      #-- convert into PHP var based on type
      $type = strtok($i, ",");
      switch ($type) {

         case "array":
            $val = array();
            foreach ($d["data,0"] as $i=>$value) {
               $val[] = xmlrpc_decode_value($value);
            }
            break;

         case "struct":
            $val = array();
            foreach ($d as $uu=>$d2) {
               if (($in=$d2["name,0"][",0"]) && ($pos2=1) || ($in=$d2["name,1"][",0"]) && ($pos2=0)) {
                  $val[$in] = xmlrpc_decode_value($d2["value,$pos2"]);
               }
            }
            break;

         case "":    # handles also '<value>s</value>' instead
         case "0":   # of '<value><string>s</string></value>'
         case "string":
            $val =  is_array($d) ? "" : (string)$d;
            break;

         case "base64":
            $val = (XMLRPC_AUTO_TYPES>=2) ? base64_decode($d) : (string)$d;
            if ((XMLRPC_AUTO_UTF8 >= 2) && ($uu = utf8_decode($val))) {
               $val = $uu;
            }
            break;
            
      // case "real":  case "float":   // neither is allowed
         case "double":
            $val = (double)$d;
            break;
         case "i4":
         case "int":
            $val = (int)$d;
            break;

         case "boolean":
            $val = (boolean)$d;
            break;

         case "dateTime.iso8601":
            $val = xmlrpc_strtotime($d);
            break;

         default:
            if (defined("XMLRPC_SERVER")) {
               xmlrpc_send_response(xmlrpc_error(-32600, "Unknown data type '$type'"));
            }
            else {
               echo $xmlrpc_error = "UNKNOWN XML-RPC DATA TYPE '$type'<br>\n";
               $xmlrpc_errorcode = -32207;
            }
#           echo "<!-- UNKNOWN TYPE $type -->\n";
#           xmlrpc_log("bad data type '$type' enountered");
      }
   }
   return($val);
}


#-- More complex XML-RPC data types need object representation to
#   distinguish them from ordinary string and integer vars.
class xmlrpc_xtype {
   var $scalar = "";
   var $xmlrpc_type = "string";
   var $tag = "string";
   function xmlrpc_type($str) {
      $this->data = $str;
   }
   function out() {
      return array($this->tag.",0" => array(",0"=>$this->scalar));
   }
}
class xmlrpc_base64 extends xmlrpc_xtype {
   function xmlrpc_base64($str) {
      $this->tag = "base64";
      $this->xmlrpc_type = "base64";
      if (XMLRPC_AUTO_UTF8 >= 2) {
         $str = utf8_encode($str);
      }
      if (!preg_match("/^[=\w\s]+$/", $str)) {
         $this->encode=1;
      }
      $this->scalar = $str;
   }
   function out() {
      if (isset($this->encode)) {
         $this->scalar = chunk_split(base64_encode($this->scalar), 74, "\n");
      }
      return xmlrpc_xtype::out();
   }
}
class xmlrpc_datetime extends xmlrpc_xtype {
   function xmlrpc_datetime($t) {
      $this->tag = "dateTime.iso8601";
      $this->xmlrpc_type = "datetime";
      if (($t > 0) && ($t[8] != "T")) {
         $this->timestamp = $t;
         $t = xmlrpc_timetostr($t);
      }
      $this->scalar = $t;
   }
}

#-- Further simplify use of the above ones.
function xmlrpc_base64($string) {
   return(new xmlrpc_base64($string));
}
function xmlrpc_datetime($timestr) {
   return(new xmlrpc_datetime($timestr));
}


#-- Deciphers ISO datetime string into UNIX timestamp.
function xmlrpc_strtotime($str) {
   $tm = explode(":", substr($str, 9));
   $t = mktime($tm[0], $tm[1], $tm[2], substr($str, 4, 2), substr($str, 6, 2), substr($str, 0, 4));
   return($t);
}
function xmlrpc_timetostr($time) {
   return(gmstrftime("%Y%m%dT%T", $time));
}


#-- helping hand for the xmlrpc-epi extension of php
function xmlrpc_epi_decode_xtypes(&$r) {
   if (is_object($r) && isset($r->xmlrpc_type)) {
      if (isset($r->timestamp)) {
         $r = $r->timestamp;
      }
      else {
         $r = $r->scalar;
      }
   }
   elseif (is_array($r)) {
      foreach ($r as $i=>$v) {
         xmlrpc_epi_decode_xtypes($r[$i]);
      }
   }
}




############################################################################
#                                                                          #
#  simplified XML parser                                                   #
#                                                                          #
############################################################################


#-- Encode the two chars & and < into htmlentities (there is nothing said
#   about the possible other entities in the XML-RPC spec).
function xml_entities($str) {
   $e = array(
      "&" => "&amp;",
      "<" => "&lt;",
//      ">" => "&gt;",
   );
   return(strtr($str, $e));
}
function xml_decode_entities($str) {
   $e = array(
      "&lt;" => "<",
      "&gt;" => ">",
      "&apos;" => "'",
      "&quot;" => '"',
      "&amp;" => "&",
   );
   if (strpos($e, "&#") !== false) {
      $e = preg_replace('/&#(\d+);/e', 'chr($1)', $e);
      $e = preg_replace('/&#x([\da-fA-F]+);/e', 'chr(hexdec("$1"))', $e);
   }
   return(strtr($str, $e));
}


#-- Can split simplified XML into a PHP array structure. The now used
#   'compact' format will yield tag sub arrays with an "*,0" index and
#   just [",0"] for text nodes.
function xml2array($xml, $compact="ALWAYS") {
   $r = array();
   if (function_exists("xml_parser_create") && (strlen($xml) >= 512)) {
      $r = xml2array_php($xml);
   }
   else {
      xml2array_parse($xml, $r, $compact);
   }
   return($r);
}


#-- Recursively builds an array of the chunks fetched via strtok() from
#   the original XML input string.
function xml2array_parse(&$string, &$r, $compact=1) {
   $n = 0;
   do {
      #-- split chunks
      $l = strpos($string, "<");
      $p = strpos($string, ">", $l);
      $text = $attr=$close = $tag = false;
      if ($l === false) {
         $text = $string;
         $string = false;
      }
      else {
         $tag = strtok(substr($string, $l+1, $p-$l-1), " ");
         if ((strncmp($tag, "![CDATA[", 8)==0) && ($p = strpos($string, "]]>", $l))) {
            $text = substr($string, $l+9, $p-$l-9);
         }
         else {
            if ($l) {
               $text = xml_decode_entities(substr($string, 0, $l));
            }
            $attr = strtok("\000");
            $close = $attr && ($attr[strlen($attr)-1]=="/");
            $string = substr($string, $p+1);
         }
      }
      #-- insert text/body content into array
      if (trim($text)) {
#         if ($compact) {
             $r[",$n"] = $text;
#         }
#         else {
#            $r[] = $text;
#         }
         $n++;
      }
      #-- recurse for tags
      if ($tag && ($tag[0] >= 'A')) {    #-- don't read <? <! </ pseudo-tags
#         if ($compact) {
             $r["$tag,$n"] = array();
             $new = &$r["$tag,$n"];
#         } else {
#            $r[] = array($tag => array());
#            $new = &$r[count($r)-1][$tag];
#         }
         if (!$close) {
            xml2array_parse($string, $new, $compact);
         }
         $n++;
      }
      #-- stop if no more tags or content
      if (empty($tag) && empty($text) || empty($string)) {
         $tag = "/";
      }
   } while ($tag[0] != "/");
}


#-- Uses the XML extension of PHP to convert an XML stream into the
#   compact array representation.
function xml2array_php(&$xml, $compact=1) {

   $p = xml_parser_create(xml_which_charset($xml));
   xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, false);
   xml_parser_set_option($p, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");

   xml_parse_into_struct($p, $xml, $struct);

   $a = array();  // will hold all tag nodes
   $tree = array(&$a);  // stack of pointers to last node of any tree level
   $in = &$a;           // pointer to last created node

   foreach ($struct as $t) {
      unset($value);
      extract($t);

      $depth = count($tree) - 1;
      $in = &$tree[$depth];
      $tag .= "," . count($in);
//echo "#$depth, TAG=\"$tag\", TYP=$type, LEV=$level, VAL=$value\n";

      switch ($type[1]) {

         #--  OpEN
         case "p":
            $in[$tag] = array();
            if ($type=="open") {
               $tree[] = &$in[$tag];
            }
            if (isset($value) && trim($value)) {
               $in[$tag][",0"] = $value;
            }
            break;

         #--  CoMPLETE
         case "o":
            $in[$tag] = array();
            if (isset($value) && trim($value)) {
               $in[$tag][",0"] = $value;
            }
            break;

         #--  ClOSE
         case "l":
            array_pop($tree);
            break;

         #--  CdATA - usually just whitespace
         case "d":
            if (isset($value) && trim($value)) {
               $in[",".count($in)] = $value;
            }
            break;
         
         default:
            // case "attribute":
            // and anything else we do not want
      }
      
   }
   
   return($a);
}



function xml_which_charset(&$xml) {
   return( strpos(strtok($xml, "\n"), '-8859-1"') ? "iso-8859-1" : "utf-8" );
}



############################################################################
#                                                                          #
#  simplified XML creator                                                  #
#                                                                          #
############################################################################


#-- This is the opposite of the above xml2array, and can also work with the
#   so called $compact format.
function array2xml($r, $compact=1, $ins="") {
   $string = "<?xml version=\"1.0\" $ins?>";
   array2xml_push($string, $r, $compact);
   return($string);
}


#-- Recursively throws out the XMLified tree generated by the xml2array()
#   'parser' function.
function array2xml_push(&$string, &$r, $compact, $ind=-1) {
   $old_ind = ++$ind - 1;
   if ($old_ind < 0) { $old_ind = 0; }
   foreach ($r as $i=>$d) {
      $d = &$r[$i];
      if (is_scalar($d)) {
         $string .= xml_entities($d);
      }
      elseif (is_array($d)) {
         if ($compact) {
            $i = strtok($i, ","); 
         }
         $ls = str_repeat(" ", $ind);
         $string .= "\n$ls<$i>";
         $string .=  array2xml_push($string, $d, $compact, $ind);
         $ls = str_repeat(" ", $old_ind);
         $string .= "</$i>\n$ls";
      }
   }
}




?>

Added ext/contrib/xmlrpc.txt.





































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

XML-RPC is a "standard" (well, not yet exactly) for accessing remotely
provided 'Web services'. More exactly it is just a complicated encoding
standard for calling functions and procedures on a remote Web server
(and getting its calculation or data request results of course).

It is still in wide use for many interesting features like accessing
database content, searching, data conversion, and so on. It started as
a lightweight alternative to SOAP, which currently is more on the rise.
While SOAP is much more bloated, also XML-RPC is not the quickest RPC
format available, is not really standards-compliant (bogus specs over
the time), and so has probably only a limited lifetime now.
Therefore you should try to provide your services and access others`
via vanilla HTTP requests (form or url encoding), when possible; use
the "http.php" class for this.

(There is also a faster PHP-RPC standard on the rise, which provides
type-safe data transport over compressed and fast connections, without
the encoding overhead and charset issues when using XML-RPC.)



xmlrpc.php

The 'xmlrpc.php' script implements the XML-RPC spec., but adds a few
extensions, namely use of the (yet unregistered) "application/rpc+xml"
MIME type and compressed HTTP transportation. It uses a builtin stupid
XML parser (for the highly simplified XML-RPC message content) and thus
is totally independent of any PHP extensions. It of course takes
advantage of the XML extension where present (a lot faster), and it even
can make use of Epinions XML-RPC extension for PHP (really fast than).

It is mostly not object-oriented, but extremely easy to use for building
XML-RPC servers or calling remote procedures.


configuration

There are a few constants and variables that the 'xmlrpc.php' script
respects.

XMLRPC_PLUS
   If set to 1 enables use of the "application/rpc+xml" MIME type and
   request compression per default (for server and client). In 2004
   still not the recommended setting.

XMLRPC_AUTO_TYPES
   Allows the request encoder to automatically determine the <base64>
   and <dateTime.iso8061> types, even if you just used them as scalar PHP
   values. Otherwise you had to use 'new xmlrpc_base64("STrinG==")' and
   'new xmlrpc_datetime("20001020T00:00:00")' to prepare such values.

XMLRPC_AUTO_UTF8
   Takes care of transforming the complete RPC messages into/from UTF-8,
   what is useful if your scripts deal only with Latin1 and always expect
   this. <base64> are also de/encoded if you set this constant to 2.

XMLRPC_CHARSET
   The whole script is currently optimized to produce UTF-8 and decode
   requests from/into Latin-1 for your scripts.

XMLRPC_FAST
   Enables use of Epinions XML-RPC extension module for PHP automatically
   where available. You only want to disable this for debugging purposes.

XMLRPC_OO
   Engages error result objects, else you had to use the two global vars
   "$xmlrpc_error" and "$xmlrpc_errorstr" to detect such cases. If you
   enable it you must however compare all xmlrpc_request() result values
   against being an object (what does not happen for succeeded XML-RPC
   requests).

XMLRPC_AUTODISCOVERY
   If you create a "xmlrpc" or "xmlrpc_connection" object and this is
   enabled, you would get the object with function names of the
   automatically instantiated methods of the remotely provided service
   wrapped into one object (not yet), much like in the Python library
   for xmlrpc.

XMLRPC_LOG
   Creates a log file for incoming requests to the _server() part of xmlrpc
   (whenerver you activate it with the _server() call).


There are also a few automatically defined values, which you shouldn't
care about:

XMLRPC_MIME
   Contains the currently selected default MIME type for transport.
XMLRPC_MIME_NEW
   Contains the newer MIME type value. Do not change.
XMLRPC_MIME_OLD
   For compatibility with older XML-RPC clients and servers. Do not change.
XMLRPC_ACCEPT
   Again the MIME Types wrapped into a HTTP Accept: header for requests
   and responses.
XMLRPC_EPI
   Tells if the Epinions extension is available.


server configuration

$xmlrpc_methods[]
   Every accessible method (for remote calls) must be defined here, for
   use with the xmlrpc_server(). There is a separate section on this one.


making xmlrpc() requests

You can call a remote procedure by just using the short xmlrpc() call
syntax:

  $result = xmlrpc("http://example.com/rpc.php", "the.function", 1, 2, 3);

Where 1, 2 and 3 would be parameters to "the.function" on the remote server.
The number of parameters is not limited, and you do not need to give one at
all (if the remote procedure does not require them. The parameter values
are automatically encoded into XML-RPC representations except for <base64>
and <dateTime.iso8061> ones, for which you needed to create objects first.
The $result of course recieved in ordinary PHP representation of the remote
functions result value.


       xmlrpc_request()
       
       Is basically the same as calling the xmlrpc() function, but that
       all parameters given to the remote function are now to be passed
       as array in the third parameter:

         $params = array(  "param1", "param2", "param3"  );
         $r = xmlrpc_request("server.com:80", "remoteMethod", $params);

       Also a fourth parameter to xmlrpc_request (boolean) says if to
       use the old XML-RPC or the faster XML+RPC interface. But beware,
       that this could fail if you connect to an older server.


       xmlrpc_connection
       
       You can also establish a 'connection' (this is purely virtual) to
       a remote XML-RPC server, using a xmlrpc_connection object as follows:

         $xc = new xmlrpc_connection("http://example.com/rpc.php");

       Then you could regularily call remote functions on that server:

         $result1 = $xc->call("function1");
         $result2 = $xc->call("function2", 2, $result1, 0x5F02);

       The xmlrpc_connection automatically chooses XML+RPC if available
       with the remote server.


       data types
       
       Unless XMLRPC_AUTO_TYPES was enabled (discouraged, because this is
       considered 'unreliable type guessing') you need to explicetely mark
       parameters passed to the xmlrpc() or xmlrpc_request() calls for
       their later XML-RPC type.

       To do so, you have the two class types 'xmlrpc_datetime' and
       'xmlrpc_base64' availabe. Use them as follows:

          $param1 = new xmlrpc_base64(  base64_encode($string1)  );
          $p2 = new xmlrpc_datetime(  time() + 60*60*24*7  );
          $r = xmlrpc("www.server.com/rpc/", "function1", $param1, $p2);

       Please note, that you needed to call base64_encode() yourself, and
       that the _datetime() can also use standard Unix timestamps as input.

       The XML-RPC <dateTime.iso8601> entites are, btw, automatically
       converted into Unix timestamps, if returned as result from xmlrpc()
       and xmlrpc_request() calls. This happens regardless of
       XMLRPC_AUTO_TYPES.

       If XMLRPC_AUTO_TYPES is set to 2, then even <base64> result values
       would be automatically converted into their plain (binary) string
       representation.


       "Bugs"
       
       pass-by-reference is not possible ;)



xmlrpc_server() use

To make a set of functions available for remote calls, you would create
an interface script and make its URL public. Assuming that you had a
subdirectory "./myrpc" on your server, you would likely want to create 
the file "./myrpc/index.php" with following content:

   <?php

      $xmlrpc_methods = array(
         "myFunction",
         "mySecondOne",
      );
 
      include("xmlrpc.php");
      xmlrpc_server();
   ?>

So, by calling the xmlrpc_server() you make all registered functions
($xmlrpc_methods) available with the URL "xml+rpc://example.com/myrpc/" for
remote calls.


       $xmlrpc_methods[]
       
       All function names you list in this array (before calling the
       xmlrpc_server() function) will be available for remote calls. The
       function names are mapped to remote method names by having the
       _ underscore as alias the the . dot, which is commonly used. So a
       function whose name was "tools_register" was available as remotely
       callable method "tools_register" or "tools.register".

       Also with xmlrpc_server() it is possible to register member methods
       of object classes as remotely callable methods. All you needed to
       do is list your class in $xmlrpc_methods[].

       You can also give aliases, both for function names and for object
       classes:

          $xmlrpc_methods["callable.methodname"] = "here_function_name";
          $xmlrpc_methods["section"] = "here_class_name";

       The member methods of a class cannot be aliased however.


       xmlrpc_server()
       
       Just fetches the current request, decodes it and executes the
       destination method (PHP function) if listed in the global
       $xmlrpc_methods[] variable.

       It automatically exits after sending the response or an error. So
       this is the last command in your xmlrpc wrapper script.


       xmlrpc_fetch_post_chunk()
       
       Begs PHP for the complete POST data stream. It only has two options
       to do so and may fail with some Webservers and earlier PHP versions.
       In either case try to set the "always_populate_raw_post_data" option
       in php.ini or from within a .htaccess file.

       To allow the server part to receive the XML-RPC message, you either
       need PHP 4.3 or later, or configure your PHP interpreter specifically
       to pass in the POSTed data stream. In you php.ini ([PHP] section) add:

         always_populate_raw_post_data = 1

       Or following in a .htaccess per-dir configuration
       file for Apache:

         php_option always_populate_raw_post_data=1


       xmlrpc_send_response()
       
       Is called from within xmlrpc_server() to send the response for the
       processed request (also sends error responses).


       xmlrpc_error()
       
       Creates a XML-RPC error result array.



---------------------------------------------------------------------------
internals
---------------------------------------------------------------------------
Unless you are interrested in an in-deep discussion of the "xmlrpc.php"
you should effectively stop reading here.


xmlrpc data representation encoders

This lib uses the simple xml2array() compact format to do the initial work
of converting a XML file into an array representation. Various design
restrictions of the XML-RPC message format then impose certain structures
inside of the xml2array-compact representation, what is taken adavantage of.

For example <struct> entries have in the compact representation sub-elements
like ["member,0"], ["member,1"], ["member,2"] and so on. Each of which then
has two sub elements: ["name,0"] and ["value,1"].

The XML-RPC <array> instead had one ["data,0"] with sub-arrays of
["value,0"], ["value,1"], ["value,2"] and so on, which would be recursively
feed through:


      xmlrpc_decode_value()
      
      Makes a PHP representation of a part (one must start it with the
      content of a ["value,0"]) from a xml2array()-compact representation
      made out of a XML-RPC message.


      xmlrpc_compact_value()
      
      Converts a PHP array or scalar variable into an array suitable for
      transformation into a XML-RPC message string using the array2xml()
      function then.



generic functions

The xml2array() and array2xml() functions are stupid XML parsers and
probably only suitable for XML-RPC messages.


       xml2array()
       
       Can decode a SimplifiedXML document into an array structure - and this
       in two formats. Internall xml+rpc uses only the so called "$compact
       format". If we had a XML document like the following:

       <xml>
         <more> <string> String </string>
         </more>
         <more> <string> String2 </string>
                <int>5</int>
         </more>
       </xml>

       It would return for the $compact=1 format, something like:

       array(
          "xml,0" => array(
             "more,0" => array(
                "string,0" = array(
                   ",0" => " String "
                )
             )
             "more,1" => array(
                "string,0" = array(
                   ",0" => " String2 "
                ),
                "int,1" = array(
                   ",0" => 5
                )
             )
          )
       );

       Where every tagname had a ","+NUMBER suffix, and text nodes would
       start with the comma. The numbers are always counted up in each
       nesting level from 0, regardless if it counted text or tag nodes.

       The not-compact format would hold another subarray to denote a deeper
       level tag node, but leave the text nodes as entries into the ordering
       array level. This was more suitable for XML like files, where you had
       mixed text and tag nodes in a level. For example:

       <html>
          string1
          <b>string2</b>
       </html>

       Would become in the not-compact format:

       array(
          0 => array(
             "html" => array(
                0 => "\n   string1\n   "
                1 => array(
                   "b" => array(
                       0 => "string2",
                   )
             )
          )
       )


       array2xml()
       
       Regenerates a XML stream from an array structure like the one emitted
       by xml2array().


other functions

If you want a different behaviour, you might want to alter one of
the following functions.


      xmlrpc_method_call()
      
      Is responsible in the _server() part for invoking the requested
      function. It does so by using the $xmlrpc_methods[] array as mapping
      to the PHP functions to activate.

      If you would like to have a better mapping support, or even to add
      parameter type and number checking, then this is where you would
      want to start editing the code.


Deleted ext/dba.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
/*
   Load this with plugins/db/dba.php if your PHP provides only the
   older dbm_*() functions.
*/


#-- fake dba_* using dbm_* functions
if (!function_exists("dba_open") && function_exists("dbm_open")) {

   function dba_open($path, $mode, $handler, $a1=0) {
      if ($handler == "dbm") {
         return(dbmopen($path, $mode));
      }
      else return(false);
   }

   function dba_popen($a, $b, $c, $d=0) {
      return(dba_open($a, $b, $c));
   }

   function dba_exists($key, $handle) {
      return(dbmexists($handle, $key));
   }

   function dba_fetch($key, $handle) {
      return(dbmfetch($handle, $key));
   }

   function dba_insert($key, $string, $handle) {
      return(dbminsert($handle, $key, $string));
   }

   function dba_replace($key, $string, $handle) {
      return(dbmreplace($handle, $key, $string));
   }

   function dba_delete($key, $handle) {
      return(dbmdelete($handle, $key));
   }

   function dba_firstkey($handle) {
      return($GLOBALS["dbm_lastkey"] = dbmfirstkey($handle));
   }

   function dba_nextkey($handle) {
      return(dbmnextkey($handle, $GLOBALS["dbm_lastkey"]));
   }

   function dba_close($handle) {
      return(dbmclose($handle));
   }

   function dba_handlers() {
      return(array("dbm"));
   }

}


?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































Changes to ext/exotic.php.

1
2
3
4
5
6
7
8
9
10
11
12
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
/*
   Following funtions have been removed from the core emulation script, because
   they are considered too special to be commonly used in WWW scripts. Anybody
   using them, probably takes extra precautions prior calling them (you could
   still load this script). Some of these functions could also be too difficult
   to be reimplemented 100% exactly.
*/



#-- calls PHP interpreter itself (really only works with 4.3 onwards)
................................................................................
      $fn = escapeshellcmd($fn);
      $result = system("php -lqCf '$fn'", $err);
      return($err==0);
   }
}


#-- print enumerated lsit of last-called functions
if (!function_exists("debug_print_backtrace") && function_exists("debug_backtrace")) {
   function debug_print_backtrace() {
      $d = debug_backtrace();
      foreach ($d as $i=>$info) {
         #-- index
         echo "#" . ($i) . "  ";
         




|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
/*
   Following funtions have been removed from the core emulation script, because
   they are considered too special to be commonly used in WWW scripts. Anybody
   using these, probably takes extra precautions prior calling them (you could
   still load this script). Some of these functions could also be too difficult
   to be reimplemented 100% exactly.
*/



#-- calls PHP interpreter itself (really only works with 4.3 onwards)
................................................................................
      $fn = escapeshellcmd($fn);
      $result = system("php -lqCf '$fn'", $err);
      return($err==0);
   }
}


#-- print enumerated list of last-called functions
if (!function_exists("debug_print_backtrace") && function_exists("debug_backtrace")) {
   function debug_print_backtrace() {
      $d = debug_backtrace();
      foreach ($d as $i=>$info) {
         #-- index
         echo "#" . ($i) . "  ";
         

Deleted ext/fakezlib.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<?php
/*
   This script simulates the gz*() functions, without actually providing
   compression functionality. The generated data streams will be correct,
   but reading compressed files isn't possible.
   
   Not very useful; should only be used if there is no other way. But if
   your provider seriously doesn't have PHP with builtin zlib support,
   you seriously were better off simply switching to someone else...
*/


 #-- fake zlib
 if (!function_exists("gzopen")) {

    function gzopen($fp, $mode) {
       $mode = preg_replace('/[^carwb+]/', '', $mode);
       return(fopen($fp, $mode));
    }
    function gzread($fp, $len) {
       return(fread($fp, $len));
    }
    function gzwrite($fp, $string) {
       return(fwrite($fp, $string));
    }
    function gzputs($fp, $string) {
       return(fputs($fp, $string));
    }
    function gzclose($fp) {
       return(fclose($fp));
    }
    function gzeof($fp) {
       return(feof($fp));
    }
    function gzseek($fp, $offs) {
       return(fseek($fp, $offs, SEEK_SET));
    }
    function gzrewind($fp) {
       return(frewind($fp));
    }
    function gztell($fp) {
       return(ftell($fp));
    }

    function gzpassthru($fp) {
       while (!gzeof($fp)) {
          print(gzred($fp, 1<<20));
       }
       gzclose($fp);
    }
    function readgzfile($fn) {
       if ($fp = gzopen($fn, "rb")) {
          gzpassthru($fp);
       }
    }
   
    function gzfile($fn) {
       return(file($fn));
    }

    function gzgetc($fp) {
       return(fgetc($fp));
    }
    function gzgets($fp, $len) {
       return(fgets($fp, $len));
    }
    function gzgetss($fp, $len, $allowedtags="") {
       return(fgetss($fp, $len, $allowedtags));
    }

 }


 #-- fake compression methods
 if (!function_exists("gzdeflate")) {

    // only returns uncompressed deflate streams
    function gzdeflate($data, $level=0) {
        $gz = "";
        $end = strlen($data);
        $p = 0;
        do {
           $c = $end - $pos;
           if ($c >= 65536) {
              $c = 0xFFFF;
              $end = 0x00;
           }
           else {
              $end = 0x01;
           }
           $gz .= pack("Cvv",
                     ($end << 7) + (00 << 5),  // LAST=0/1, BTYPE=00
                     $c,                       // LEN
                     $c ^ 0xFFFF               // NLEN
                  );
           $gz .= substr($data, $p, $c);
           $p += $c;
        }
        while ($p < $end);
        return($gz);
    }

    // only can strip deflate headers, cannot decompress
    function gzinflate($data, $length=NULL) {
       $end = strlen($data);
       $gz = "";
       if (isset($length) && (($max*0.99) > $length)) {
          trigger_error("gzinflate(): gave up, decompressed string is likely longer than requested", E_USER_ERROR);
          return;
       }
       $out = "";
       $p = 0;
       do {
          $head = ord($data[$p]);
          $last = ($head >> 7);
          if (($head & 0x60) != 00) {
             trigger_error("gzinflate(): cannot decode compressed stream", E_USER_ERROR);
             return;
          }
          $head = unpack("v1LEN/v1NLEN", substr($data, $p+1, 4));
          $c = $head["LEN"];
          if (($c ^ 0xFFFF) != $head["NLEN"]) {
             trigger_error("gzinflate(): data error in stream", E_USER_ERROR);
             return;
          }
          $p += 5;
          $out .= substr($data, $p, $c);
          $p += $c;
       }
       while (($p < $end) && !$last);
       return($out);
    }


//    function gzcompress() {
//    }
//    function gzuncompress() {
//    }

    // without real compression support again
    function gzencode($data, $level=0) {
       $isize = strlen($data);
       $crc32 = crc32($data);
       $gz = "";
       {
          $gz .= pack("nCCVCC",
             $_ID = 0x1f8b,
             $_CM = 0x08,  // deflate fmt
             $_FLG = 0x00, // nothing extra
             $_MTIME = time(),
             $_XFL = 0x00, // no bonus flags
             $_OS = 255    // "unknown"
          );
          $gz .= gzdeflate($data);
          $gz .= pack("VV", $crc32, $isize);
       }
       return($gz);
    }

 }

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































































Deleted ext/filter.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?php

/**
 * @todo
 *
 * filter_*() functions can probably be reimplemented for PHP5.0 and PHP4.x
 *
 *
 */

/*

    [1230] => filter_input
    [1231] => filter_var
    [1232] => filter_input_array
    [1233] => filter_var_array
    [1234] => filter_list
    [1235] => filter_has_var
    [1236] => filter_id

    [1071] => INPUT_POST
    [1072] => INPUT_GET
    [1073] => INPUT_COOKIE
    [1074] => INPUT_ENV
    [1075] => INPUT_SERVER
    [1076] => INPUT_SESSION
    [1077] => INPUT_REQUEST
    [1078] => FILTER_FLAG_NONE
    [1079] => FILTER_REQUIRE_SCALAR
    [1080] => FILTER_REQUIRE_ARRAY
    [1081] => FILTER_FORCE_ARRAY
    [1082] => FILTER_NULL_ON_FAILURE
    [1083] => FILTER_VALIDATE_INT
    [1084] => FILTER_VALIDATE_BOOLEAN
    [1085] => FILTER_VALIDATE_FLOAT
    [1086] => FILTER_VALIDATE_REGEXP
    [1087] => FILTER_VALIDATE_URL
    [1088] => FILTER_VALIDATE_EMAIL
    [1089] => FILTER_VALIDATE_IP
    [1090] => FILTER_DEFAULT
    [1091] => FILTER_UNSAFE_RAW
    [1092] => FILTER_SANITIZE_STRING
    [1093] => FILTER_SANITIZE_STRIPPED
    [1094] => FILTER_SANITIZE_ENCODED
    [1095] => FILTER_SANITIZE_SPECIAL_CHARS
    [1096] => FILTER_SANITIZE_EMAIL
    [1097] => FILTER_SANITIZE_URL
    [1098] => FILTER_SANITIZE_NUMBER_INT
    [1099] => FILTER_SANITIZE_NUMBER_FLOAT
    [1100] => FILTER_SANITIZE_MAGIC_QUOTES
    [1101] => FILTER_CALLBACK
    [1102] => FILTER_FLAG_ALLOW_OCTAL
    [1103] => FILTER_FLAG_ALLOW_HEX
    [1104] => FILTER_FLAG_STRIP_LOW
    [1105] => FILTER_FLAG_STRIP_HIGH
    [1106] => FILTER_FLAG_ENCODE_LOW
    [1107] => FILTER_FLAG_ENCODE_HIGH
    [1108] => FILTER_FLAG_ENCODE_AMP
    [1109] => FILTER_FLAG_NO_ENCODE_QUOTES
    [1110] => FILTER_FLAG_EMPTY_STRING_NULL
    [1111] => FILTER_FLAG_ALLOW_FRACTION
    [1112] => FILTER_FLAG_ALLOW_THOUSAND
    [1113] => FILTER_FLAG_ALLOW_SCIENTIFIC
    [1114] => FILTER_FLAG_SCHEME_REQUIRED
    [1115] => FILTER_FLAG_HOST_REQUIRED
    [1116] => FILTER_FLAG_PATH_REQUIRED
    [1117] => FILTER_FLAG_QUERY_REQUIRED
    [1118] => FILTER_FLAG_IPV4
    [1119] => FILTER_FLAG_IPV6
    [1120] => FILTER_FLAG_NO_RES_RANGE
    [1121] => FILTER_FLAG_NO_PRIV_RANGE


*/

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































Changes to ext/gettext.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
/*
  api: PHP
  type: functions
  title: gettext()
  description: emulates gettext functionality
  priority: auto
  category: library

   This include script simulates gettext() functionality.
    - It could read translation data from .mo and .po files.
    - Lookup of plural forms mostly work (but not 100% compliant,
      no real interpreter for Plural-Forms: expression).
    - Categories/codesets are ignored.

   Besides using setlocale() you should change the $_ENV["LANG"] var
   to the desired language manually. Additionally all your scripts
   could contain following (may also work with standard gettext):
     $_ENV["LANGUAGE"] = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
   What's often more user-friendly than hardwired server-side values.
*/


#-- emulate only if not present in current PHP interpreter
if (!function_exists("gettext")) {

   #-- all-in-one combined implementation





|













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
/*
  api: PHP
  type: functions
  title: gettext()
  description: emulates PHP gettext extension functionality
  priority: auto
  category: library

   This include script simulates gettext() functionality.
    - It could read translation data from .mo and .po files.
    - Lookup of plural forms mostly work (but not 100% compliant,
      no real interpreter for Plural-Forms: expression).
    - Categories/codesets are ignored.

   Besides using setlocale() you should change the $_ENV["LANG"] var
   to the desired language manually. Additionally all your scripts
   could contain following (may also work with standard gettext):
     $_ENV["LANGUAGE"] = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
   That's often more user-friendly than hardwired server-side values.
*/


#-- emulate only if not present in current PHP interpreter
if (!function_exists("gettext")) {

   #-- all-in-one combined implementation

Deleted ext/gettext.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

PHP-only gettext emulation
--------------------------

The "gettext.php" include script tries to reimplement GNU gettext in
pure PHP. It is incomplete and divergent in many ways, but seems to
work well in its goal to be a quick drop-in replacement.

You load the script, like you'd include the "upgrade.php" script, and
then have the family of gettext functions always available - if they
are compiled in into your PHP binary or not. This way you can freely
use standardized i18n features safely on any web server and with all
your applications.

There are however a few minor obstacles and differences in between
the original and the emulation which you have to take care of. Most
of the incompatibilites descend from lousily documented behaviour of
the original and from lack of extensqive testing of the emulated
versions.

 - You should use setlocale() before any bindtextdomain(), because
   this emulation does load the .mo/.po data files only once.

 - The emulation only ever loads one translation file (it never
   retrieves translation strings from different localizations,
   so it is less useful in conjunction with Accept-Language header
   settings - where multiple languages could be given).
   [Original gettext may or may not load from multiple files??]

 - To be compliant with the native implementation, you have to make
   sure, that the .mo files are built from the *.po source files.
   (The emulation tries to work on both, but it really shouldn't do
   that.)

 - Order of environment variable precedence is:
     1. LANGUAGE
     2. LC_ALL
     3. LC_MESSAGE
     4. LANG                    (multiple langs)
     5. setlocale()
     6. HTTP_ACCEPT_LANGUAGE    (incompliant with GNU gettext)

 - There is a second variant of the script, which tries to handle
   plural forms. This has multiple limitations:
     - does not employ a full Plural-Forms parser (a C expression
       which must be interpreted at runtime)
     - matches and works only with a few built-in language plural
       form syntaxes and orderings
     - and it's fully untested as of yet

 - It constructs a global $_GETTEXT[] variable which contains all
   messages and translations at runtime in-memory. That means, it
   is far more memory-hungry and less scalable than the original
   GNU libintl in C.



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















































































































Changes to ext/mime.php.

1
2
3
4
5
6

7


8
9
10
11
12
13
14
<?php
/*
   Simulates the mime_magic extension. Was originally implemented for
   [http://nanoweb.si.kz/], but that mime magic data reading was
   reinjected for this version (more unclean, though).
   You still need to get the "mime_magic" file to use this, please see

   file(1) for more informations.


   Also simulates the image type/mime/ext functions.
*/


#-- mime-magic, type will be detected by analyzing the content
if (!function_exists("mime_content_type")) {
   function mime_content_type($fn) {





<
>
|
>
>







1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
<?php
/*
   Simulates the mime_magic extension. Was originally implemented for
   [http://nanoweb.si.kz/], but that mime magic data reading was
   reinjected for this version (more unclean, though).


   It uses the system-wide "mime_magic" file to do this. See file(1).
   On Windows you might need to install it first.
   
   Also simulates the image type/mime/ext functions.
*/


#-- mime-magic, type will be detected by analyzing the content
if (!function_exists("mime_content_type")) {
   function mime_content_type($fn) {

Added ext/nonstandard/base64.php.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
/**
 *
 * This script implements the base64-encoding functions and base32 and
 * base16 as described in RFC3548.
 *
 * @since never
 * @nonstandard
 *
 */
if (!function_exists("base16_encode")) {


   #-- URL and filename safe variants of base64-encoding
   function base64_encode_safe($str) {
      return strtr(base64_encode($str), "+/", "-_");
   }
   function base64_decode_safe($b64) {
      return base64_decode(strtr($str, "-_", "+/"));
   }


   #-- base16
   function base16_encode($str) {
      $str = unpack("H".(2*strlen($str)), $str);
      $str = chunk_split($str[1]);
      return($str);
   }
   function base16_decode($b16) {
      $b16 = preg_replace("/\s+/", '', $b16);
      $b16 = pack("H*", $b16);
      return($b16);
   }


   #-- base32
   function base32_encode() {
      
      # strtoupper()
      # "A-Z,0-7,="
   }

}
?>

Deleted ext/odbc.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<?php

die("'odbc.php' is incomplete. Don't use this yet.\n");

/*
   This is just another SQL interface wrapper. It reimplements the ODBC
   functions in PHP by itself chaining to PEAR::DB (a double wrapper,
   to simplify this initial version).
    - does not use integers as connection_id

   Because any mysql_*() calls are easier replaced with odbc_() funcs,
   but at the same time offer the same degree of database independence,
   this can often make more sense than transitioning to PEAR::DB or the
   ADOdb classes.
    - PEAR::DB provides the saner OO-interface
    - ADOdb is slightly faster, but has a less nicely abstracted API
*/


#-- declare odbc interface functions
if (!function_exists("odbc_connect")) {

   #-- load PEAR::DB
   require_once("DB.php");


   #-- initialize connection
   function odbc_connect($dsn, $user, $password, $cursor_type=NULL) {

      #-- mangle $dsn for PEAR
      $dsn = str_replace("://", "://$user:$password@", $dsn);
      // ... rename dbtype identifiers

      #-- connect
      $c = DB::connect($dsn);
      if (!PEAR::isError($c)) {
         return($c);
      }
   }

   #-- incomplete
   function odbc_pconnect($dsn, $user, $password, $cursor_type=NULL) {
      return odbc_connect($dsn, $user, $password, $cursor_type);
   }
   
   #-- end connection
   function odbc_close($db) {
      $db->disconnect();
   }
   
   
   #-- SQL command execution
   function odbc_exec($db, $query) {
      return $db->query($db);
   }
   function odbc_do($db, $query) {
      return odbc_exec($db, $query);
   }


   #-- sql pre-parsing
   function odbc_prepare($db, $query) {
      return( array($db, $db->prepare($db)) );
   }
   #-- and execution of prepared query
   function odbc_execute($pq, $args=NULL) {
      return $pq[0]->execute($pq[1], $args);
   }


   #-- return result row
   function odbc_fetch_array($res) {
      return $res->fetchRow(DB_FETCHMODE_ASSOC);
   }
   function odbc_fetch_row($res) {
      return $res->fetchRow(DB_FETCHMODE_ORDERED);
   }
   function odbc_fetch_object($res) {
      return $res->fetchRow(DB_FETCHMODE_OBJECT);
   }
   function odbc_fetch_into($res, $count, &$array) {
      $array = array();
      while ($count--) {
         $array[] =  $res->fetchRow(DB_FETCHMODE_ORDERED);
      }
   }
   
   
   #-- more functions on result sets
   function odbc_free_result(&$res) {
      $res->free();
      $res = NULL;
   }
   function odbc_next_result($res) {
      return $res->nextResult();
   }
   function odbc_num_fields($res) {
      return $res->numCols();
   }
   function odbc_num_rows($res) {
      return $res->numRows();
   }
   
   
   #-- and there's more
   //...

   

}


?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































































































































Deleted ext/old.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
<?php
/*
   Here we collect PHP functions for versions before 4.1 - it should be
   noted that 4.0.x versions can't be made compatible with newer
   versions anyhow, because the newer superglobals ($_GET, $_REQUEST) are
   missing. Most of this is untested.
   Have a look at PEAR::PHP_Compat for emulation of some of these (it's
   not complete in this regard, too).
*/

#---------------------------------------------------------------- 4.0.7 ---

#-- simulate superglobals
# you still had to put "global $_REQUEST,$_GET,..." into any function that
# used them - so this workaround is not all too useful anyhow, you should
# not accept PHP versions prior 4.0.7 for your scripts in any case!
if (!isset($GLOBALS["_REQUEST"])) {
   $GLOBALS["_GET"] = & $HTTP_GET_VARS;
   $GLOBALS["_POST"] = & $HTTP_POST_VARS;
   $GLOBALS["_SERVER"] = & $HTTP_SERVER_VARS;
   $GLOBALS["_ENV"] = & $HTTP_ENV_VARS;
   $GLOBALS["_COOKIE"] = & $HTTP_COOKIE_VARS;
   $GLOBALS["_FILES"] = & $HTTP_POST_FILES;
   $GLOBALS["_REQUEST"] = array_merge($HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS);
}


#---------------------------------------------------------------- 4.0.6 ---


#-- uses callback function to remove entries from array
if (!function_exists("array_filter")) {
   function array_filter($array, $callback="is_int") {
      foreach ($array as $key=>$val) {
         if (!call_user_func_array($callback, array($val))) {
            unset($array[$key]);
         }
      }
      return($array);
   }
}


#-- uses callback function to change array values, multiple input arrays
if (!function_exists("array_map")) {
   function array_map() {
      $arrays = get_func_args();
      $callback = shift($arrays);
      $r = &$arrays[0];
      foreach ($r as $key=>$val) {
         $val = call_user_func_array($callback, $arrays);
         $r[$key] = $val;
      }
      return($r);
   }
}


#-- checks for existence or only syntax of function or obj/class+method name
if (!function_exists("is_callable")) {
   function is_callable($var, $syntax_only=0) {
      $a = get_func_args();
      if (count($a) >= 3) {
         $fin = & $a[2];
      }

      #-- class/object+method
      if (is_array($var)) {
         if (count($var)!=2) {
            return false;
         }
         list($obj, $method) = $var;
         $class = $obj;
         if (is_object($obj)) {
            $class = get_class($obj);
         }

         if ($syntax_only) {
            $r = preg_match('/^\w+$/', $method);
            if (!is_object($obj)) {
               $r = $r && preg_match('/^\w+$/', $obj);
            }
         }
         else {
            if (is_object($obj)) {
               $r = method_exists($obj, $method);
            }
            else {
               $all = get_class_methods($obj);
               $r = in_array($method, $all);
            }
         }
         if ($r) { $fin = strtolower("$class:$method"); }
      }
      #-- simple function name
      elseif (is_string($var)) {
         if ($syntax_only) {
            $r = preg_match('/^\w+$/', $var);
         }
         else {
            $r = function_exists($var);
         }
         if ($r) { $fin = strtolower($var); }
      }
      #-- ooops
      else {
         $r = false;
      }
      return $r;
   }
}




#---------------------------------------------------------------- 4.0.5 ---
# chroot


#-- return index of value in array
if (!function_exists("array_search")) {
   function array_search($value, $array, $strict=false) {
      $strict = $strict ? true : false;
      foreach ($array as $key=>$v) {
         if ($strict&&($v===$value) || !$strict&&($v==$value)) {
            return($key);
         }
      }
      return(NULL);  // PHP prior 4.2 also did so
   }
}


#-- recursively collapse array into one value (via user callback)
if (!function_exists("array_reduce")) {
   function array_reduce($array, $callback, $value=NULL) {
      foreach ($array as $v) {
         if (is_array($v)) {
            $v = array_reduce($v, $callback);
         }
         else {
            $v = call_user_func_array($callback, array($value, $v));
         }
         $value = $v;
      }
      return($value);
   }
}


#-- checks variable to be of a simple type
if (!function_exists("is_scalar")) {
   function is_scalar($var) {
      return( !is_array($var) && !is_object($var) );
   }
}

#-- only static value (mix of C/English/European/US)
if (!function_exists("localeconv")) {
   function localeconv() {
      return array (
        'decimal_point' => '.',
        'thousands_sep' => '',
        'int_curr_symbol' => 'EUR ',   // more international than USD
        'currency_symbol' => '',      // unnamed/trans currency symbol
        'mon_decimal_point' => '.',
        'mon_thousands_sep' => ',',
        'positive_sign' => '',
        'negative_sign' => '-',
        'int_frac_digits' => 2,
        'frac_digits' => 2,
        'p_cs_precedes' => 1,
        'p_sep_by_space' => 0,
        'n_cs_precedes' => 1,
        'n_sep_by_space' => 0,
        'p_sign_posn' => 1,
        'n_sign_posn' => 1,
        'grouping' => array (0=>3, 1=>3,),
        'mon_grouping' => array(0=>3, 1=>3,),
      );
   }
}


#-- function by name
if (!function_exists("call_user_func_array")) {
   function call_user_func_array($callback, $param_array=array()) {
      if ($param_array) {
         $param_array = array_values($param_array);
         $params = "'" . implode("','", $param_array) . "'";
      }
      if (is_array($callback)) {
         $obj = &$callback[0];
         $method = $callback[1];
         if (!method_exists($obj, $method)) {
            trigger_error("call_user_method_array: method '$method' does not exist", E_ERROR);
         }
         elseif (is_object($obj)) {
            eval("return \$obj->$method($params);");
         }
         else {
            eval("return $obj::$method($params);");
         }
      }
      elseif (!function_exists("$callback")) {
         trigger_error("call_user_func_array: function '$method' does not exist", E_ERROR);
      }
      else {
         switch (count($param_array)) {
            case 0:
               return $callback();
            case 1:
               return $callback($param_array[0]);
            case 2:
               return $callback($param_array[0], $param_array[1]);
            case 3:
               return $callback($param_array[0], $param_array[1], $param_array[2]);
            case 4:
               return $callback($param_array[0], $param_array[1], $param_array[2], $param_array[3]);
            default:
               eval("return $callback($params);");
         }
      }
   }
   function call_user_method_array($method, &$obj, $param_array=array()) {
      call_user_func_array(array(&$obj, $method), $param_array);
   }
}




#---------------------------------------------------------------- 4.0.4 ---



#-- adds all values of given array into total sum
if (!function_exists("array_sum")) {
   function array_sum($array) {
      $sum = 0;
      foreach ($array as $val) {
         $sum += $val;
      }
      return $sum;
   }
}

#-- value of constant (if their name was returned as string from somewhere)
if (!function_exists("constant")) {
   function constant($name) {
      if (defined($name)) {
         eval("return $name");
      }
      else {
         return NULL;
      }
   }
}

#-- more a language construct
if (!function_exists("is_null")) {
   function is_null($var) {
      return($var === NULL);
   }
}



#---------------------------------------------------------------- 4.0.3 ---
# register_tick_function
# unregister_tick_function

if (!function_exists("pathinfo")) {
   function pathinfo($fn) {
      preg_match("#^(?:(.+)/)?([^/]+?(?:\.([^/\.]+))?)$#", $fn, $uu);
      return array(
         "dirname" => $uu[1],
         "basename" => $uu[2],
         "extension" => $uu[3],
      );
   }
}

if (!function_exists("escapeshellarg")) {
   function escapeshellarg($arg) {
      $arg = str_replace("'", "'\\''", $arg);
      return "'$arg'";
   }
}

if (!function_exists("is_uploaded_file")) {
   function is_uploaded_file($fn) {
      ( $dir = get_cfg_var("upload_tmp_dir") )
       or
      ( $dir = dirname(tempnam("", "")) );
      return( realpath($dir) == realpath(dirname($fn)) );
   }
}

if (!function_exists("move_uploaded_file")) {
   function move_uploaded_file($fn, $dest) {
      if (is_uploaded_file($fn)) {
         return copy($fn, $dest) && unlink($fn);
      }
   }
}


#---------------------------------------------------------------- 4.0.2 ---
# ob_get_length



if (!function_exists("strncasecmp")) {
   function strncasecmp($str1, $str2, $len=0) {
      if ($len > 0) {
         $str1 = substr($str1, 0, $len);
         $str2 = substr($str2, 0, $len);
      }
      return strcasecmp($str1, $str2);
   }
}


if (!function_exists("wordwrap")) {
   function wordwrap($text, $width=75, $break="\n", $hardcut=0) {
      $out = "";
      foreach (explode("\n", $text) as $line) {
         if ($out) {
            $out .= "\n";
         }
         while (strlen($line)) {
            if ($hardcut) {
               $l = $width;
            }
            else {
               $l = strrpos(substr($text, 0, $width), " ");
               if ($l && ($l < strlen($line))) {
                  $l = strlen($line);
               }
               if ($l === false) {
                  $l = $width;
               }
            }
            $out .= substr($line, 0, $l);
            $out .= "\n";
            $line = substr(0, $l);
         }
      }
      return($out);
   }
}

if (!function_exists("php_uname")) {
   function php_uname($mode="a") {
      switch ($mode) {
         case "s":  $p = "--kernel-name";  break;
         case "n":  $p = "--node-name";  break;
         case "r":  $p = "--release";  break;
         case "v":  $p = "--kernel-version";  break;
         case "m":  $p = "--machine";  break;
         default:  $p = "--all";  break;
      }
      return `uname $p`;
   }
}



#---------------------------------------------------------------- 4.0.1 ---
# levensth
# fflush() - unimplementable
# array_unique
# array_diff
# array_intersect
# array_merge_recursive
# crc32
# fscanf
# sscanf
# str_pad
# set_file_buffer
# spliti

if (!function_exists("php_sapi_name")) {
   function php_sapi_name() {
      if (isset($_ENV["CGI_INTERFACE"])) {
         return "cgi";
      }
      elseif (strpos($_ENV["SERVER_SOFTWARE"], "Apache") !== false) {
         return "apache";
      }
      // ...
      else {
         return "cgi";  // the silly "cli" variation didn't exist before 4.2
      }
   }
}

?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































































































































































































































































































































































































































































































































































































































































































































































Deleted ext/openssl.php.

1
2
3
4
5
<?php
/*
   Ok, that's a joke. (Not that this wasn't possible, though ...)
*/
?>
<
<
<
<
<










Added ext/pdo.pgsql.php.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
<?php if (!class_exists("PDO_PGSQL")) {
/** File PDO_pgsql.class.php		*
 *(C) Andrea Giammarchi [2005/10/13]	*/

// Requires PDOStatement_pgsql.class.php , drived by PDO.class.php file
#<builtin>#require_once('PDOStatement_pgsql.class.php');

/**
 * Class PDO_pgsql
 * 	This class is used from class PDO to manage a PostgreSQL database.
 *      Look at PDO.clas.php file comments to know more about PostgreSQL connection.
 * ---------------------------------------------
 * @Compatibility	>= PHP 4
 * @Dependencies	PDO.class.php
 * 			PDOStatement_pgsql.class.php
 * @Author		Andrea Giammarchi
 * @Site		http://www.devpro.it/
 * @Mail		andrea [ at ] 3site [ dot ] it
 * @Date		2005/10/13
 * @LastModified	2005/10/14 12:30
 * @Version		0.1 - tested
 */ 
class PDO_pgsql {
	
	/**
	 * 'Private' variables:
	 *	__connection:Resource		Database connection
         *	__dbinfo:String			Database connection params
         *      __persistent:Boolean		Connection mode, is true on persistent, false on normal (deafult) connection
         *      __errorCode:String		Last error code
         *      __errorInfo:Array		Detailed errors
	 *      __result:Resource		Last query resource
	 */
	var $__connection;
	var $__dbinfo;
	var $__persistent = false;
	var $__errorCode = '';
	var $__errorInfo = Array('');
	var $__result = null;
	
	/**
	 * Public constructor:
	 *	Checks connection and database selection
         *       	new PDO_pgsql( &$host:String, &$db:String, &$user:String, &$pass:String )
	 * @Param	String		Database connection params
	 */
	function PDO_pgsql(&$string_dsn) {
		if(!@$this->__connection = &pg_connect($string_dsn))
			$this->__setErrors('DBCON', true);
		else
			$this->__dbinfo = &$string_dsn;
	}
	
	/** NOT NATIVE BUT MAYBE USEFULL FOR PHP < 5.1 PDO DRIVER
	 * Public method
         * Calls pg_close function.
	 *	this->close( Void ):Boolean
         * @Return	Boolean		True on success, false otherwise
	 */
	function close() {
		$result = is_resource($this->__connection);
		if($result)
			pg_close($this->__connection);
		return $result;
	}
	
	/**
	 * Public method:
	 *	Returns a code rappresentation of an error
         *       	this->errorCode( void ):String
         * @Return	String		String rappresentation of the error
	 */
	function errorCode() {
		return $this->__errorCode;
	}
	
	/**
	 * Public method:
	 *	Returns an array with error informations
         *       	this->errorInfo( void ):Array
         * @Return	Array		Array with 3 keys:
         * 				0 => error code
         *                              1 => error number
         *                              2 => error string
	 */
	function errorInfo() {
		return $this->__errorInfo;
	}
	
	/**
	 * Public method:
	 *	Excecutes a query and returns affected rows
         *       	this->exec( $query:String ):Mixed
         * @Param	String		query to execute
         * @Return	Mixed		Number of affected rows or false on bad query.
	 */
	function exec($query) {
		$result = 0;
		$this->__uquery($query);
		if(!is_null($this->__result))
			$result = pg_affected_rows($this->__result);
		if(is_null($result))
			$result = false;
		return $result;
	}
	
	/** NOT REALLY SUPPORTED, returned value is not last inserted id
	 * Public method:
	 *	Returns pg_last_oid function
         *       	this->lastInsertId( void ):String
         * @Return	String		OID returned from Postgre
	 */
	function lastInsertId() {
		$result = 0;
		if(!is_null($this->__result))
			$result =  pg_last_oid($this->__result);
		return $result;
	}
	
	/**
	 * Public method:
	 *	Returns a new PDOStatement
         *       	this->prepare( $query:String, $array:Array ):PDOStatement
         * @Param	String		query to prepare
         * @Param	Array		this variable is not used but respects PDO original accepted parameters
         * @Return	PDOStatement	new PDOStatement to manage
	 */
	function prepare($query, $array = Array()) {
		return new PDOStatement_pgsql($query, $this->__connection, $this->__dbinfo);
	}
	
	/**
	 * Public method:
	 *	Executes directly a query and returns an array with result or false on bad query
         *       	this->query( $query:String ):Mixed
         * @Param	String		query to execute
         * @Return	Mixed		false on error, array with all info on success
	 */
	function query($query) {
		$query = pg_prepare($this->__connection, "__pdo_query__", $query);
		$query = pg_execute($this->__connection, "__pdo_query__");
		$this->__errorCode = &$query->state;
		if($query) {
			$result = Array();
			while($r = pg_fetch_assoc($query))
				array_push($result, $r);
		}
		else {
			$result = false;
			$this->__setErrors('SQLER');
		}
		return $result;
	}
	
	/**
	 * Public method:
	 *	Quotes correctly a string for this database
         *       	this->quote( $string:String ):String
         * @Param	String		string to quote
         * @Return	String		a correctly quoted string
	 */
	function quote($string) {
		return ("'".pg_escape_string($string)."'");
	}
	
	
	// NOT TOTALLY SUPPORTED PUBLIC METHODS
        /**
	 * Public method:
	 *	Quotes correctly a string for this database
         *       	this->getAttribute( $attribute:Integer ):Mixed
         * @Param	Integer		a constant [	PDO_ATTR_SERVER_INFO,
         * 						PDO_ATTR_SERVER_VERSION,
         *                                              PDO_ATTR_CLIENT_VERSION,
         *                                              PDO_ATTR_PERSISTENT	]
         * @Return	Mixed		correct information or false
	 */
	function getAttribute($attribute) {
		$result = false;
		switch($attribute) {
			case PDO_ATTR_SERVER_INFO:
				$result = pg_parameter_status($this->__connection, 'server_encoding');
				break;
			case PDO_ATTR_SERVER_VERSION:
				$result = pg_parameter_status($this->__connection, 'server_version');
				break;
			case PDO_ATTR_CLIENT_VERSION:
				$result = pg_parameter_status($this->__connection, 'server_version');
				$result .= ' '.pg_parameter_status($this->__connection, 'client_encoding');
				break;
			case PDO_ATTR_PERSISTENT:
				$result = $this->__persistent;
				break;
		}
		return $result;
	}
	
	/**
	 * Public method:
	 *	Sets database attributes, in this version only connection mode.
         *       	this->setAttribute( $attribute:Integer, $mixed:Mixed ):Boolean
         * @Param	Integer		PDO_* constant, in this case only PDO_ATTR_PERSISTENT
         * @Param	Mixed		value for PDO_* constant, in this case a Boolean value
         * 				true for permanent connection, false for default not permament connection
         * @Return	Boolean		true on change, false otherwise
	 */
	function setAttribute($attribute, $mixed) {
		$result = false;
		if($attribute === PDO_ATTR_PERSISTENT && $mixed != $this->__persistent) {
			$result = true;
			$this->__persistent = (boolean) $mixed;
			pg_close($this->__connection);
			if($this->__persistent === true)
				$this->__connection = &pg_connect($this->__dbinfo);
			else
				$this->__connection = &pg_pconnect($this->__dbinfo);
		}
		return $result;
	}
	
	
	// UNSUPPORTED PUBLIC METHODS
	function beginTransaction() {
		return false;
	}
	
	function commit() {
		return false;
	}
	
	function rollBack() {
		return false;
	}
	
	
	// PRIVATE METHODS [ UNCOMMENTED ]
	function __setErrors($er) {
		if(!is_string($this->__errorCode))
			$errno = $this->__errorCode;
		if(!is_resource($this->__connection)) {
			$errno = 1;
			$errst = pg_last_error();
		}
		else {
			$errno = 1;
			$errst = pg_last_error($this->__connection);
		}
		$this->__errorCode = &$er;
		$this->__errorInfo = Array($this->__errorCode, $errno, $errst);
	}
	
	function __uquery(&$query) {
		if(!@$this->__result = pg_query($this->__connection, $query)) {
			$this->__setErrors('SQLER');
			$this->__result = null;
		}
		return $this->__result;
	}
}
?><?php
/** File PDOStatement_pgsql.class.php	*
 *(C) Andrea Giammarchi [2005/10/13]	*/

/**
 * Class PDOStatement_pgsql
 * 	This class is used from class PDO_pgsql to manage a PostgreSQL database.
 *      Look at PDO.clas.php file comments to know more about PostgreSQL connection.
 * ---------------------------------------------
 * @Compatibility	>= PHP 4
 * @Dependencies	PDO.class.php
 * 			PDO_pgsql.class.php
 * @Author		Andrea Giammarchi
 * @Site		http://www.devpro.it/
 * @Mail		andrea [ at ] 3site [ dot ] it
 * @Date		2005/10/19
 * @LastModified	2006/01/29 09:30 [fixed execute bug]
 * @Version		0.1b - tested
 */ 
class PDOStatement_pgsql {
	
	/**
	 * 'Private' variables:
	 *	__connection:Resource		Database connection
         *	__dbinfo:Array			Array with 4 elements used to manage connection
         *      __persistent:Boolean		Connection mode, is true on persistent, false on normal (deafult) connection
         *      __query:String			Last query used
         *      __result:Resource		Last result from last query
         *      __fetchmode:Integer		constant PDO_FETCH_* result mode
         *      __errorCode:String		Last error string code
         *      __errorInfo:Array		Last error informations, code, number, details
         *      __boundParams:Array		Stored bindParam
	 */
	var $__connection;
	var $__dbinfo;
	var $__persistent = false;
	var $__query = '';
	var $__result = null;
	var $__fetchmode = PDO::FETCH_BOTH;
	var $__errorCode = '';
	var $__errorInfo = Array('');
	var $__boundParams = Array();
	
	/**
	 * Public constructor:
	 *	Called from PDO to create a PDOStatement for this database
         *       	new PDOStatement_pgsql( &$__query:String, &$__connection:Resource, $__dbinfo:String )
	 * @Param	String		query to prepare
         * @Param	Resource	database connection
         * @Param	String		database file name
	 */
	function PDOStatement_pgsql(&$__query, &$__connection, &$__dbinfo) {
		$this->__query = &$__query;
		$this->__connection = &$__connection;
		$this->__dbinfo = &$__dbinfo;
	}
	
	/**
	 * Public method:
	 *	Replace ? or :named values to execute prepared query
         *       	this->bindParam( $mixed:Mixed, &$variable:Mixed, $type:Integer, $lenght:Integer ):Void
         * @Param	Mixed		Integer or String to replace prepared value
         * @Param	Mixed		variable to replace
         * @Param	Integer		this variable is not used but respects PDO original accepted parameters
         * @Param	Integer		this variable is not used but respects PDO original accepted parameters
	 */
	function bindParam($mixed, &$variable, $type = null, $lenght = null) {
		if(is_string($mixed))
			$this->__boundParams[$mixed] = $variable;
		else
			array_push($this->__boundParams, $variable);
	}
	
	/**
	 * Public method:
	 *	Checks if query was valid and returns how may fields returns
         *       	this->columnCount( void ):Void
	 */
	function columnCount() {
		$result = 0;
		if(!is_null($this->__result))
			$result = pg_num_fields($this->__result);
		return $result; 
	}
	
	/**
	 * Public method:
	 *	Returns a code rappresentation of an error
         *       	this->errorCode( void ):String
         * @Return	String		String rappresentation of the error
	 */
	function errorCode() {
		return $this->__errorCode;
	}
	
	/**
	 * Public method:
	 *	Returns an array with error informations
         *       	this->errorInfo( void ):Array
         * @Return	Array		Array with 3 keys:
         * 				0 => error code
         *                              1 => error number
         *                              2 => error string
	 */
	function errorInfo() {
		return $this->__errorInfo;
	}
	
	/**
	 * Public method:
	 *	Excecutes a query and returns true on success or false.
         *       	this->exec( $array:Array ):Boolean
         * @Param	Array		If present, it should contain all replacements for prepared query
         * @Return	Boolean		true if query has been done without errors, false otherwise
	 */
	function execute($array = Array()) {
		if(count($this->__boundParams) > 0)
			$array = &$this->__boundParams;
		$__query = $this->__query;
		if(count($array) > 0) {
			foreach($array as $k => $v) {
				if(!is_int($k) || substr($k, 0, 1) === ':') {
					if(!isset($tempf))
						$tempf = $tempr = array();
					array_push($tempf, $k);
					array_push($tempr, "'".pg_escape_string($v)."'");
				}
				else {
					$parse = create_function('$v', 'return "\'".pg_escape_string($v)."\'";');
					$__query = preg_replace("/(\?)/e", '$parse($array[$k++]);', $__query);
					break;
				}
			}
			if(isset($tempf))
				$__query = str_replace($tempf, $tempr, $__query);
		}
		if(is_null($this->__result = &$this->__uquery($__query)))
			$keyvars = false;
		else
			$keyvars = true;
		$this->__boundParams = array();
		return $keyvars;
	}
	
	/**
	 * Public method:
	 *	Returns, if present, next row of executed query or false.
         *       	this->fetch( $mode:Integer, $cursor:Integer, $offset:Integer ):Mixed
         * @Param	Integer		PDO_FETCH_* constant to know how to read next row, default PDO_FETCH_BOTH
         * 				NOTE: if $mode is omitted is used default setted mode, PDO_FETCH_BOTH
         * @Param	Integer		this variable is not used but respects PDO original accepted parameters
         * @Param	Integer		this variable is not used but respects PDO original accepted parameters
         * @Return	Mixed		Next row of executed query or false if there is nomore.
	 */
	function fetch($mode = PDO_FETCH_BOTH, $cursor = null, $offset = null) {
		if(func_num_args() == 0)
			$mode = &$this->__fetchmode;
		$result = false;
		if(!is_null($this->__result)) {
			switch($mode) {
				case PDO_FETCH_NUM:
					$result = pg_fetch_row($this->__result);
					break;
				case PDO_FETCH_ASSOC:
					$result = pg_fetch_assoc($this->__result);
					break;
				case PDO_FETCH_OBJ:
					$result = pg_fetch_object($this->__result);
					break;
				case PDO_FETCH_BOTH:
				default:
					$result = pg_fetch_array($this->__result);
					break;
			}
		}
		if(!$result)
			$this->__result = null;
		return $result;
	}
	
	/**
	 * Public method:
	 *	Returns an array with all rows of executed query.
         *       	this->fetchAll( $mode:Integer ):Array
         * @Param	Integer		PDO_FETCH_* constant to know how to read all rows, default PDO_FETCH_BOTH
         * 				NOTE: this doesn't work as fetch method, then it will use always PDO_FETCH_BOTH
         *                                    if this param is omitted
         * @Return	Array		An array with all fetched rows
	 */
	function fetchAll($mode = PDO_FETCH_BOTH) {
		$result = array();
		if(!is_null($this->__result)) {
			switch($mode) {
				case PDO_FETCH_NUM:
					while($r = pg_fetch_row($this->__result))
						array_push($result, $r);
					break;
				case PDO_FETCH_ASSOC:
					while($r = pg_fetch_assoc($this->__result))
						array_push($result, $r);
					break;
				case PDO_FETCH_OBJ:
					while($r = pg_fetch_object($this->__result))
						array_push($result, $r);
					break;
				case PDO_FETCH_BOTH:
				default:
					while($r = pg_fetch_array($this->__result))
						array_push($result, $r);
					break;
			}
		}
		$this->__result = null;
		return $result;
	}
	
	/**
	 * Public method:
	 *	Returns, if present, first column of next row of executed query
         *       	this->fetchSingle( void ):Mixed
         * @Return	Mixed		Null or next row's first column
	 */
	function fetchSingle() {
		$result = null;
		if(!is_null($this->__result)) {
			$result = @pg_fetch_row($this->__result);
			if($result)
				$result = $result[0];
			else
				$this->__result = null;
		}
		return $result;
	}
	
	/**
	 * Public method:
	 *	Returns number of last affected database rows
         *       	this->rowCount( void ):Integer
         * @Return	Integer		number of last affected rows
         * 				NOTE: works with INSERT, UPDATE and DELETE query type
	 */
	function rowCount() {
		$result = 0;
		if(!is_null($this->__result))
			$result = pg_affected_rows($this->__result);
		return $result;
	}
	
	
	// NOT TOTALLY SUPPORTED PUBLIC METHODS	
	/**
	 * Public method:
	 *	Quotes correctly a string for this database
         *       	this->getAttribute( $attribute:Integer ):Mixed
         * @Param	Integer		a constant [	PDO_ATTR_SERVER_INFO,
         * 						PDO_ATTR_SERVER_VERSION,
         *                                              PDO_ATTR_CLIENT_VERSION,
         *                                              PDO_ATTR_PERSISTENT	]
         * @Return	Mixed		correct information or false
	 */
	function getAttribute($attribute) {
		$result = false;
		switch($attribute) {
			case PDO_ATTR_SERVER_INFO:
				$result = pg_parameter_status($this->__connection, 'server_encoding');
				break;
			case PDO_ATTR_SERVER_VERSION:
				$result = pg_parameter_status($this->__connection, 'server_version');
				break;
			case PDO_ATTR_CLIENT_VERSION:
				$result = pg_parameter_status($this->__connection, 'server_version');
				$result .= ' '.pg_parameter_status($this->__connection, 'client_encoding');
				break;
			case PDO_ATTR_PERSISTENT:
				$result = $this->__persistent;
				break;
		}
		return $result;
	}
	
	/**
	 * Public method:
	 *	Sets database attributes, in this version only connection mode.
         *       	this->setAttribute( $attribute:Integer, $mixed:Mixed ):Boolean
         * @Param	Integer		PDO_* constant, in this case only PDO_ATTR_PERSISTENT
         * @Param	Mixed		value for PDO_* constant, in this case a Boolean value
         * 				true for permanent connection, false for default not permament connection
         * @Return	Boolean		true on change, false otherwise
	 */
	function setAttribute($attribute, $mixed) {
		$result = false;
		if($attribute === PDO_ATTR_PERSISTENT && $mixed != $this->__persistent) {
			$result = true;
			$this->__persistent = (boolean) $mixed;
			pg_close($this->__connection);
			if($this->__persistent === true)
				$this->__connection = &pg_connect($this->__dbinfo);
			else
				$this->__connection = &pg_pconnect($this->__dbinfo);
		}
		return $result;
	}
	
	/**
	 * Public method:
	 *	Sets default fetch mode to use with this->fetch() method.
         *       	this->setFetchMode( $mode:Integer ):Boolean
         * @Param	Integer		PDO_FETCH_* constant to use while reading an execute query with fetch() method.
         * 				NOTE: PDO_FETCH_LAZY and PDO_FETCH_BOUND are not supported
         * @Return	Boolean		true on change, false otherwise
	 */
	function setFetchMode($mode) {
		$result = false;
		switch($mode) {
			case PDO_FETCH_NUM:
			case PDO_FETCH_ASSOC:
			case PDO_FETCH_OBJ:
			case PDO_FETCH_BOTH:
				$result = true;
				$this->__fetchmode = &$mode;
				break;
		}
		return $result;
	}
	
	
	// UNSUPPORTED PUBLIC METHODS
        function bindColumn($mixewd, &$param, $type = null, $max_length = null, $driver_option = null) {
		return false;
	}
	
	function __setErrors($er) {
		if(!is_string($this->__errorCode))
			$errno = $this->__errorCode;
		if(!is_resource($this->__connection)) {
			$errno = 1;
			$errst = pg_last_error();
		}
		else {
			$errno = 1;
			$errst = pg_last_error($this->__connection);
		}
		$this->__errorCode = &$er;
		$this->__errorInfo = Array($this->__errorCode, $errno, $errst);
	}
	
	function __uquery(&$query) {
		if(!@$query = pg_query($this->__connection, $query)) {
			$this->__setErrors('SQLER');
			$query = null;
		}
		return $query;
	}
	
}


}//if!class_exists
?>

Changes to ext/pdo.php.

1
2







3


4
5
6
7
8
9



















10
11
12
13





















































































































































14







15





















































































16









17

18
19
20
21
22
23
24














































































































































































































































































































































































































































































































































































































































25
<?php
/*







   api: PHP


   
   TODO.
   However, PDO cannot be emulated fully, not on PHP4 especially, because
   the SPL and meta object semantics won't work there. Eventually a subset
   can be reimplemented however. (Would be more useful than ADO and PEARDB
   at least.)



















*/


#-- stub





















































































































































if (!function_exists()) {







   function pdo_drivers() {





















































































      return array();









   }

}


#-- PDO
if (!class_exists("pdo")) {
}















































































































































































































































































































































































































































































































































































































































?>
|
|
>
>
>
>
>
>
>
|
>
>
|
<
<
<
<
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
|
|
|
<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13





14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293


294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
<?php if(!class_exists('PDO')) {
/**
 * title: PDO
 * description: PDO emulation for PHP 5.0 and 4.x, with PDO_MySQL built-in
 * author: Andrea Giammarchi
 * author_url: http://www.devpro.it/
 * license: PHPL 2.02
 * url: http://webscripts.softpedia.com/script/PHP-Clases/PDO-for-PHP-4-12854.html
 * version: 0.1b
 * api: php
 * priority: auto
 * category: database
 *





 *
 * File PDO.class.php			*
 * 	Porting of native PHP 5.1 PDO	*
 *      object usable with PHP 4.X.X	*
 *      and PHP 5.0.X version.		*
 * ------------------------------------ *     
 * (C) Andrea Giammarchi [2005/10/19]	*
 * ____________________________________
 *
 *
 * This package includes the PDO MySQL driver. To also get support for
 * Postgres and SQLite, include pdo.pgsql.php and .sqlite.php as well.
 * Of course it's not a complete implementation, but believed to be
 * compatible to even the early PHP4 versions.
 *
 * IMPORTANT: For compatibility with PHP 5.0 and this emulation, you must
 * use the global PDO constants, and not the static PDO:: class versions.
 * PDO_FETCH_ASSOC, PDO_ATTR_*, ... as seen below.
 *
 */

	

// SUPPORTED STATIC ENVIROMENT VARIABLES
define('PDO_ATTR_SERVER_VERSION', 4);	// server version
define('PDO_ATTR_CLIENT_VERSION', 5);	// client version
define('PDO_ATTR_SERVER_INFO', 6);	// server informations
define('PDO_ATTR_PERSISTENT', 12);	// connection mode, persistent or normal

// SUPPORTED STATIC PDO FETCH MODE VARIABLES
define('PDO_FETCH_ASSOC', 2);		// such mysql_fetch_assoc
define('PDO_FETCH_NUM', 3);		// such mysql_fetch_row
define('PDO_FETCH_BOTH', 4);		// such mysql_fetch_array
define('PDO_FETCH_OBJ', 5);		// such mysql_fetch_object

// UNSUPPORTED STATIC PDO FETCH MODE VARIABLES
define('PDO_FETCH_LAZY', 1);		// usable but not supported, default is PDO_FETCH_BOTH and will be used
define('PDO_FETCH_BOUND', 6);		// usable but not supported, default is PDO_FETCH_BOTH and will be used

/**
 * Class PDO
 * 	PostgreSQL, SQLITE and MYSQL PDO support for PHP 4.X.X or PHP 5.0.X users, compatible with PHP 5.1.0 (RC1).
 *
 * DESCRIPTION [directly from http://us2.php.net/manual/en/ref.pdo.php]
 * 	The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP.
 *      Each database driver that implements the PDO interface can expose database-specific features as regular extension functions.
 *      Note that you cannot perform any database functions using the PDO extension by itself;
 *      you must use a database-specific PDO driver to access a database server.
 *
 * HOW TO USE
 * 	To know how to use PDO driver and all its methods visit php.net wonderful documentation.
 *      http://us2.php.net/manual/en/ref.pdo.php
 *      In this class some methods are not available and actually this porting is only for MySQL, SQLITE and PostgreSQL.
 *
 * LIMITS
 * 	For some reasons ( time and php used version with this class ) some PDO methods are not availables and
 *      someother are not totally supported.
 *      
 *      PDO :: UNSUPPORTED METHODS:
 *      	- beginTransaction 	[ mysql 3 has not transaction and manage them is possible only with a direct BEGIN 
 *              			  or COMMIT query ]
 *              - commit
 *              - rollback
 *              
 *      PDO :: NOT TOTALLY SUPPORTED METHODS:
 *      	- getAttribute		[ accepts only PDO_ATTR_SERVER_INFO, PDO_ATTR_SERVER_VERSION,
 *              			  PDO_ATTR_CLIENT_VERSION and PDO_ATTR_PERSISTENT attributes ]
 *              - setAttribute		[ supports only PDO_ATTR_PERSISTENT modification ]
 *              - lastInsertId		[ only fo PostgreSQL , returns only pg_last_oid ]
 *
 *      - - - - - - - - - - - - - - - - - - - - 
 *              
 *      PDOStatement :: UNSUPPORTED METHODS:
 *      	- bindColumn 		[ is not possible to undeclare a variable and using global scope is not
 *              			  really a good idea ]
 *              
 *      PDOStatement :: NOT TOTALLY SUPPORTED METHODS:
 *      	- getAttribute		[ accepts only PDO_ATTR_SERVER_INFO, PDO_ATTR_SERVER_VERSION,
 *              			  PDO_ATTR_CLIENT_VERSION and PDO_ATTR_PERSISTENT attributes ]
 *              - setAttribute		[ supports only PDO_ATTR_PERSISTENT modification ]
 *              - setFetchMode		[ supports only PDO_FETCH_NUM, PDO_FETCH_ASSOC, PDO_FETCH_OBJ and
 *              			  PDO_FETCH_BOTH database reading mode ]
 * ---------------------------------------------
 * @Compatibility	>= PHP 4
 * @Dependencies	PDO_mysql.class.php
 *                      PDO_sqlite.class.php
 *                      PDOStatement_mysql.class.php
 *                      PDOStatement_sqlite.class.php
 * @Author		Andrea Giammarchi
 * @Site		http://www.devpro.it/
 * @Mail		andrea [ at ] 3site [ dot ] it
 * @Date		2005/10/13
 * @LastModified	2005/12/01 21:40
 * @Version		0.1b - tested, supports only PostgreSQL, MySQL or SQLITE databases
 */ 
class PDO {
	
	/** Modified on 2005/12/01 to support new PDO constants on PHP 5.1.X */
	/*
	--won't work with php4--
	const FETCH_ASSOC = PDO_FETCH_ASSOC;
	const FETCH_NUM = PDO_FETCH_NUM;
	const FETCH_BOTH = PDO_FETCH_BOTH;
	const FETCH_OBJ = PDO_FETCH_OBJ;
	const FETCH_LAZY = PDO_FETCH_LAZY;
	const FETCH_BOUND = PDO_FETCH_BOUND;
	const ATTR_SERVER_VERSION = PDO_ATTR_SERVER_VERSION;
	const ATTR_CLIENT_VERSION = PDO_ATTR_CLIENT_VERSION;
	const ATTR_SERVER_INFO = PDO_ATTR_SERVER_INFO;
	const ATTR_PERSISTENT = PDO_ATTR_PERSISTENT;
	*/
	function FETCH_ASSOC(){return PDO_FETCH_ASSOC;}
	function FETCH_NUM(){return PDO_FETCH_NUM;}
	function FETCH_BOTH(){return PDO_FETCH_BOTH;}
	function FETCH_OBJ(){return PDO_FETCH_OBJ;}
	function FETCH_LAZY(){return PDO_FETCH_LAZY;}
	function FETCH_BOUND(){return PDO_FETCH_BOUND;}
	function ATTR_SERVER_VERSION(){return PDO_ATTR_SERVER_VERSION;}
	function ATTR_CLIENT_VERSION(){return PDO_ATTR_CLIENT_VERSION;}
	function ATTR_SERVER_INFO(){return PDO_ATTR_SERVER_INFO;}
	function ATTR_PERSISTENT(){return PDO_ATTR_PERSISTENT;}
	
	/**
	 * 'Private' variables:
	 *	__driver:PDO_*		Dedicated PDO database class
	 */
	var $__driver;
	
	/**
	 * Public constructor
	 *	http://us2.php.net/manual/en/function.pdo-construct.php
	 */
	function PDO($string_dsn, $string_username = '', $string_password = '', $array_driver_options = null) {
		$con = &$this->__getDNS($string_dsn);
		if($con['dbtype'] === 'mysql') {
			#<builtin>#require_once('PDO_mysql.class.php');
			if(isset($con['port']))
				$con['host'] .= ':'.$con['port'];
			$this->__driver = new PDO_mysql(
				$con['host'],
				$con['dbname'],
				$string_username,
				$string_password
			);
		}
		elseif($con['dbtype'] === 'sqlite2' || $con['dbtype'] === 'sqlite') {
			#<builtin>#require_once('PDO_sqlite.class.php');
			$this->__driver = new PDO_sqlite($con['dbname']);
		}
		elseif($con['dbtype'] === 'pgsql') {
			#<builtin>#require_once('PDO_pgsql.class.php');
			$string_dsn = "host={$con['host']} dbname={$con['dbname']} user={$string_username} password={$string_password}";
			if(isset($con['port']))
				$string_dsn .= " port={$con['port']}";
			$this->__driver = new PDO_pgsql($string_dsn);
		}
	}
	
	/** UNSUPPORTED
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-begintransaction.php
	 */
	function beginTransaction() {
		$this->__driver->beginTransaction();
	}
	
	/** NOT NATIVE BUT MAYBE USEFULL FOR PHP < 5.1 PDO DRIVER
	 * Public method
	 * Calls database_close function.
	 *	this->close( Void ):Boolean
	 * @Return	Boolean		True on success, false otherwise
	 */
	function close() {
		return $this->__driver->close();
	}
	
	/** UNSUPPORTED
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-commit.php
	 */
	function commit() {
		$this->__driver->commit();
	}
	
	/** 
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-exec.php
	 */
	function exec($query) {
		return $this->__driver->exec($query);
	}
	
	/** 
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-errorcode.php
	 */
	function errorCode() {
		return $this->__driver->errorCode();
	}
	
	/** 
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-errorinfo.php
	 */
	function errorInfo() {
		return $this->__driver->errorInfo();
	}
	
	/** NOT TOTALLY UNSUPPORTED
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-getattribute.php
	 */
	function getAttribute($attribute) {
		return $this->__driver->getAttribute($attribute);
	}
	
	/** 
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-lastinsertid.php
	 */
	function lastInsertId() {
		return $this->__driver->lastInsertId();
	}
	
	/** 
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-prepare.php
	 */
	function prepare($query, $array = Array()) {
		return $this->__driver->prepare($query, $array = Array());
	}
	
	/** 
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-query.php
	 */
	function query($query) {
		return $this->__driver->query($query);
	}
	
	/** 
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-quote.php
	 */
	function quote($string) {
		return $this->__driver->quote($string);
	}
	
	/** UNSUPPORTED
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-rollback.php
	 */
	function rollBack() {
		$this->__driver->rollBack();
	}
	
	/** NOT TOTALLY UNSUPPORTED
	 * Public method
	 *	http://us2.php.net/manual/en/function.pdo-setattribute.php
	 */
	function setAttribute($attribute, $mixed) {
		return $this->__driver->setAttribute($attribute, $mixed);
	}
	
	// PRIVATE METHOD [uncommented]
	function __getDNS(&$string) {
		$result = array();
		$pos = strpos($string, ':');
		$parameters = explode(';', substr($string, ($pos + 1)));
		$result['dbtype'] = strtolower(substr($string, 0, $pos));
		for($a = 0, $b = count($parameters); $a < $b; $a++) {
			$tmp = explode('=', $parameters[$a]);
			if(count($tmp) == 2)
				$result[$tmp[0]] = $tmp[1];
			else
				$result['dbname'] = $parameters[$a];
		}
		return $result;
	}
}







?><?php
/** File PDO_mysql.class.php		*
 *(C) Andrea Giammarchi [2005/10/13]	*/

// Requires PDOStatement_mysql.class.php , drived by PDO.class.php file
#<builtin>#require_once('PDOStatement_mysql.class.php');

/**
 * Class PDO_mysql
 * 	This class is used from class PDO to manage a MySQL database.
 *      Look at PDO.clas.php file comments to know more about MySQL connection.
 * ---------------------------------------------
 * @Compatibility	>= PHP 4
 * @Dependencies	PDO.class.php
 * 			PDOStatement_mysql.class.php
 * @Author		Andrea Giammarchi
 * @Site		http://www.devpro.it/
 * @Mail		andrea [ at ] 3site [ dot ] it
 * @Date		2005/10/13
 * @LastModified	2005/18/14 12:30
 * @Version		0.1 - tested
 */ 
class PDO_mysql {
	
	/**
	 * 'Private' variables:
	 *	__connection:Resource		Database connection
         *	__dbinfo:Array			Array with 4 elements used to manage connection
         *      __persistent:Boolean		Connection mode, is true on persistent, false on normal (deafult) connection
         *      __errorCode:String		Last error code
         *      __errorInfo:Array		Detailed errors
	 */
	var $__connection;
	var $__dbinfo;
	var $__persistent = false;
	var $__errorCode = '';
	var $__errorInfo = Array('');
	
	/**
	 * Public constructor:
	 *	Checks connection and database selection
         *       	new PDO_mysql( &$host:String, &$db:String, &$user:String, &$pass:String )
	 * @Param	String		host with or without port info
         * @Param	String		database name
         * @Param	String		database user
         * @Param	String		database password
	 */
	function PDO_mysql(&$host, &$db, &$user, &$pass) {
		if(!@$this->__connection = &mysql_connect($host, $user, $pass))
			$this->__setErrors('DBCON');
		else {
			if(!@mysql_select_db($db, $this->__connection))
				$this->__setErrors('DBER');
			else
				$this->__dbinfo = Array($host, $user, $pass, $db);
		}
	}
	
	/** NOT NATIVE BUT MAYBE USEFULL FOR PHP < 5.1 PDO DRIVER
	 * Public method
         * Calls mysql_close function.
	 *	this->close( Void ):Boolean
         * @Return	Boolean		True on success, false otherwise
	 */
	function close() {
		$result = is_resource($this->__connection);
		if($result) {
			mysql_close($this->__connection);
		}
		return $result;
	}
	
	/**
	 * Public method:
	 *	Returns a code rappresentation of an error
         *       	this->errorCode( void ):String
         * @Return	String		String rappresentation of the error
	 */
	function errorCode() {
		return $this->__errorCode;
	}
	
	/**
	 * Public method:
	 *	Returns an array with error informations
         *       	this->errorInfo( void ):Array
         * @Return	Array		Array with 3 keys:
         * 				0 => error code
         *                              1 => error number
         *                              2 => error string
	 */
	function errorInfo() {
		return $this->__errorInfo;
	}
	
	/**
	 * Public method:
	 *	Excecutes a query and returns affected rows
         *       	this->exec( $query:String ):Mixed
         * @Param	String		query to execute
         * @Return	Mixed		Number of affected rows or false on bad query.
	 */
	function exec($query) {
		$result = 0;
		if(!is_null($this->__uquery($query)))
			$result = mysql_affected_rows($this->__connection);
		if(is_null($result))
			$result = false;
		return $result;
	}
	
	/**
	 * Public method:
	 *	Returns last inserted id
         *       	this->lastInsertId( void ):Number
         * @Return	Number		Last inserted id
	 */
	function lastInsertId() {
		return mysql_insert_id($this->__connection);
	}
	
	/**
	 * Public method:
	 *	Returns a new PDOStatement
         *       	this->prepare( $query:String, $array:Array ):PDOStatement
         * @Param	String		query to prepare
         * @Param	Array		this variable is not used but respects PDO original accepted parameters
         * @Return	PDOStatement	new PDOStatement to manage
	 */
	function prepare($query, $array = Array()) {
		return new PDOStatement_mysql($query, $this->__connection, $this->__dbinfo);
	}
	
	/**
	 * Public method:
	 *	Executes directly a query and returns an array with result or false on bad query
         *       	this->query( $query:String ):Mixed
         * @Param	String		query to execute
         * @Return	Mixed		false on error, array with all info on success
	 */
	function query($query) {
		$query = @mysql_unbuffered_query($query, $this->__connection);
		if($query) {
			$result = Array();
			while($r = mysql_fetch_assoc($query))
				array_push($result, $r);
		}
		else {
			$result = false;
			$this->__setErrors('SQLER');
		}
		return $result;
	}
	
	/**
	 * Public method:
	 *	Quotes correctly a string for this database
         *       	this->quote( $string:String ):String
         * @Param	String		string to quote
         * @Return	String		a correctly quoted string
	 */
	function quote($string) {
		return ('"'.mysql_escape_string($string).'"');
	}
	
	
	// NOT TOTALLY SUPPORTED PUBLIC METHODS
        /**
	 * Public method:
	 *	Quotes correctly a string for this database
         *       	this->getAttribute( $attribute:Integer ):Mixed
         * @Param	Integer		a constant [	PDO_ATTR_SERVER_INFO,
         * 						PDO_ATTR_SERVER_VERSION,
         *                                              PDO_ATTR_CLIENT_VERSION,
         *                                              PDO_ATTR_PERSISTENT	]
         * @Return	Mixed		correct information or false
	 */
	function getAttribute($attribute) {
		$result = false;
		switch($attribute) {
			case PDO_ATTR_SERVER_INFO:
				$result = mysql_get_host_info($this->__connection);
				break;
			case PDO_ATTR_SERVER_VERSION:
				$result = mysql_get_server_info($this->__connection);
				break;
			case PDO_ATTR_CLIENT_VERSION:
				$result = mysql_get_client_info();
				break;
			case PDO_ATTR_PERSISTENT:
				$result = $this->__persistent;
				break;
		}
		return $result;
	}
	
	/**
	 * Public method:
	 *	Sets database attributes, in this version only connection mode.
         *       	this->setAttribute( $attribute:Integer, $mixed:Mixed ):Boolean
         * @Param	Integer		PDO_* constant, in this case only PDO_ATTR_PERSISTENT
         * @Param	Mixed		value for PDO_* constant, in this case a Boolean value
         * 				true for permanent connection, false for default not permament connection
         * @Return	Boolean		true on change, false otherwise
	 */
	function setAttribute($attribute, $mixed) {
		$result = false;
		if($attribute === PDO_ATTR_PERSISTENT && $mixed != $this->__persistent) {
			$result = true;
			$this->__persistent = (boolean) $mixed;
			mysql_close($this->__connection);
			if($this->__persistent === true)
				$this->__connection = &mysql_pconnect($this->__dbinfo[0], $this->__dbinfo[1], $this->__dbinfo[2]);
			else
				$this->__connection = &mysql_connect($this->__dbinfo[0], $this->__dbinfo[1], $this->__dbinfo[2]);
			mysql_select_db($this->__dbinfo[3], $this->__connection);
		}
		return $result;
	}
	
	
	// UNSUPPORTED PUBLIC METHODS
	function beginTransaction() {
		return false;
	}
	
	function commit() {
		return false;
	}
	
	function rollBack() {
		return false;
	}
	
	
	// PRIVATE METHODS [ UNCOMMENTED ]
	function __setErrors($er) {
		if(!is_resource($this->__connection)) {
			$errno = mysql_errno();
			$errst = mysql_error();
		}
		else {
			$errno = mysql_errno($this->__connection);
			$errst = mysql_error($this->__connection);
		}
		$this->__errorCode = &$er;
		$this->__errorInfo = Array($this->__errorCode, $errno, $errst);
	}
	
	function __uquery(&$query) {
		if(!@$query = mysql_query($query, $this->__connection)) {
			$this->__setErrors('SQLER');
			$query = null;
		}
		return $query;
	}
}







?><?php
/** File PDOStatement_mysql.class.php	*
 *(C) Andrea Giammarchi [2005/10/13]	*/

/**
 * Class PDOStatement_mysql
 * 	This class is used from class PDO_mysql to manage a MySQL database.
 *      Look at PDO.clas.php file comments to know more about MySQL connection.
 * ---------------------------------------------
 * @Compatibility	>= PHP 4
 * @Dependencies	PDO.class.php
 * 			PDO_mysql.class.php
 * @Author		Andrea Giammarchi
 * @Site		http://www.devpro.it/
 * @Mail		andrea [ at ] 3site [ dot ] it
 * @Date		2005/10/13
 * @LastModified	2006/01/29 09:30 [fixed execute bug]
 * @Version		0.1b - tested
 */ 
class PDOStatement_mysql {
	
	/**
	 * 'Private' variables:
	 *	__connection:Resource		Database connection
         *	__dbinfo:Array			Array with 4 elements used to manage connection
         *      __persistent:Boolean		Connection mode, is true on persistent, false on normal (deafult) connection
         *      __query:String			Last query used
         *      __result:Resource		Last result from last query
         *      __fetchmode:Integer		constant PDO_FETCH_* result mode
         *      __errorCode:String		Last error string code
         *      __errorInfo:Array		Last error informations, code, number, details
         *      __boundParams:Array		Stored bindParam
	 */
	var $__connection;
	var $__dbinfo;
	var $__persistent = false;
	var $__query = '';
	var $__result = null;
	var $__fetchmode = PDO::FETCH_BOTH;
	var $__errorCode = '';
	var $__errorInfo = Array('');
	var $__boundParams = Array();
	
	/**
	 * Public constructor:
	 *	Called from PDO to create a PDOStatement for this database
         *       	new PDOStatement_sqlite( &$__query:String, &$__connection:Resource, $__dbinfo:Array )
	 * @Param	String		query to prepare
         * @Param	Resource	database connection
         * @Param	Array		4 elements array to manage connection
	 */
	function PDOStatement_mysql(&$__query, &$__connection, &$__dbinfo) {
		$this->__query = &$__query;
		$this->__connection = &$__connection;
		$this->__dbinfo = &$__dbinfo;
	}
	
	/**
	 * Public method:
	 *	Replace ? or :named values to execute prepared query
         *       	this->bindParam( $mixed:Mixed, &$variable:Mixed, $type:Integer, $lenght:Integer ):Void
         * @Param	Mixed		Integer or String to replace prepared value
         * @Param	Mixed		variable to replace
         * @Param	Integer		this variable is not used but respects PDO original accepted parameters
         * @Param	Integer		this variable is not used but respects PDO original accepted parameters
	 */
	function bindParam($mixed, &$variable, $type = null, $lenght = null) {
		if(is_string($mixed))
			$this->__boundParams[$mixed] = $variable;
		else
			array_push($this->__boundParams, $variable);
	}
	
	/**
	 * Public method:
	 *	Checks if query was valid and returns how may fields returns
         *       	this->columnCount( void ):Void
	 */
	function columnCount() {
		$result = 0;
		if(!is_null($this->__result))
			$result = mysql_num_fields($this->__result);
		return $result; 
	}
	
	/**
	 * Public method:
	 *	Returns a code rappresentation of an error
         *       	this->errorCode( void ):String
         * @Return	String		String rappresentation of the error
	 */
	function errorCode() {
		return $this->__errorCode;
	}
	
	/**
	 * Public method:
	 *	Returns an array with error informations
         *       	this->errorInfo( void ):Array
         * @Return	Array		Array with 3 keys:
         * 				0 => error code
         *                              1 => error number
         *                              2 => error string
	 */
	function errorInfo() {
		return $this->__errorInfo;
	}
	
	/**
	 * Public method:
	 *	Excecutes a query and returns true on success or false.
         *       	this->exec( $array:Array ):Boolean
         * @Param	Array		If present, it should contain all replacements for prepared query
         * @Return	Boolean		true if query has been done without errors, false otherwise
	 */
	function execute($array = Array()) {
		if(count($this->__boundParams) > 0)
			$array = &$this->__boundParams;
		$__query = $this->__query;
		if(count($array) > 0) {
			foreach($array as $k => $v) {
				if(!is_int($k) || substr($k, 0, 1) === ':') {
					if(!isset($tempf))
						$tempf = $tempr = array();
					array_push($tempf, $k);
					array_push($tempr, '"'.mysql_escape_string($v).'"');
				}
				else {
					$parse = create_function('$v', 'return \'"\'.mysql_escape_string($v).\'"\';');
					$__query = preg_replace("/(\?)/e", '$parse($array[$k++]);', $__query);
					break;
				}
			}
			if(isset($tempf))
				$__query = str_replace($tempf, $tempr, $__query);
		}
		if(is_null($this->__result = &$this->__uquery($__query)))
			$keyvars = false;
		else
			$keyvars = true;
		$this->__boundParams = array();
		return $keyvars;
	}
	
	/**
	 * Public method:
	 *	Returns, if present, next row of executed query or false.
         *       	this->fetch( $mode:Integer, $cursor:Integer, $offset:Integer ):Mixed
         * @Param	Integer		PDO_FETCH_* constant to know how to read next row, default PDO_FETCH_BOTH
         * 				NOTE: if $mode is omitted is used default setted mode, PDO_FETCH_BOTH
         * @Param	Integer		this variable is not used but respects PDO original accepted parameters
         * @Param	Integer		this variable is not used but respects PDO original accepted parameters
         * @Return	Mixed		Next row of executed query or false if there is nomore.
	 */
	function fetch($mode = PDO_FETCH_BOTH, $cursor = null, $offset = null) {
		if(func_num_args() == 0)
			$mode = &$this->__fetchmode;
		$result = false;
		if(!is_null($this->__result)) {
			switch($mode) {
				case PDO_FETCH_NUM:
					$result = mysql_fetch_row($this->__result);
					break;
				case PDO_FETCH_ASSOC:
					$result = mysql_fetch_assoc($this->__result);
					break;
				case PDO_FETCH_OBJ:
					$result = mysql_fetch_object($this->__result);	
					break;
				case PDO_FETCH_BOTH:
				default:
					$result = mysql_fetch_array($this->__result);
					break;
			}
		}
		if(!$result)
			$this->__result = null;
		return $result;
	}
	
	/**
	 * Public method:
	 *	Returns an array with all rows of executed query.
         *       	this->fetchAll( $mode:Integer ):Array
         * @Param	Integer		PDO_FETCH_* constant to know how to read all rows, default PDO_FETCH_BOTH
         * 				NOTE: this doesn't work as fetch method, then it will use always PDO_FETCH_BOTH
         *                                    if this param is omitted
         * @Return	Array		An array with all fetched rows
	 */
	function fetchAll($mode = PDO_FETCH_BOTH) {
		$result = array();
		if(!is_null($this->__result)) {
			switch($mode) {
				case PDO_FETCH_NUM:
					while($r = mysql_fetch_row($this->__result))
						array_push($result, $r);
					break;
				case PDO_FETCH_ASSOC:
					while($r = mysql_fetch_assoc($this->__result))
						array_push($result, $r);
					break;
				case PDO_FETCH_OBJ:
					while($r = mysql_fetch_object($this->__result))
						array_push($result, $r);
					break;
				case PDO_FETCH_BOTH:
				default:
					while($r = mysql_fetch_array($this->__result))
						array_push($result, $r);
					break;
			}
		}
		$this->__result = null;
		return $result;
	}
	
	/**
	 * Public method:
	 *	Returns, if present, first column of next row of executed query
         *       	this->fetchSingle( void ):Mixed
         * @Return	Mixed		Null or next row's first column
	 */
	function fetchSingle() {
		$result = null;
		if(!is_null($this->__result)) {
			$result = @mysq