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

βŒˆβŒ‹ βŽ‡ branch:  upgrade.php


Check-in Differences

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

Difference From 39c9fa23ab988246 To 1bd07841f1a52350

2014-04-24
02:23
Add ellipse … paramized call support and ->is handler. check-in: ab91327edb user: mario tags: trunk
02:22
(no comment) check-in: 1bd07841f1 user: mario tags: trunk
02:21
Fixes for json_encode bugs ce9ff32a53, 7412bf040f check-in: 86352370f9 user: mario tags: trunk
2010-06-22
17:03
upgradephp-15 check-in: 51e3884900 user: mario tags: trunk
17:03
upgradephp-14 check-in: 39c9fa23ab user: mario tags: trunk
17:03
upgradephp-13 check-in: b5c10771ec user: mario tags: trunk

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*users·sf·net>

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*erphesfurt·de]


#-- 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
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

PHP downwards compatibility functions
-------------------------------------
The "upgrade.php" package implements features and functions from
newer PHP versions. It defines them as pure PHP code. Functions
get defined dynamically, at runtime. All emulated functions use
names identical to the original implementation. But won't perturb
if the native functions exist.

So this is really a drop-in replacement. It allows you to use all
PHP features regardless of the current PHP interpreter. You just
have to include() this single script to remove any backward
compatibility woes.
This allows relying on the newer, more powerful PHP functions. The
use and retyping of workarounds gets superfluous. Your application
remains "PHP 4.1+ COMPATIBLE" while actually using PHP5.4 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


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 native PHP setups 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 PHP5.5 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 < "5.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 really 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/php40array" 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. It adds notes to version
compatibility strings on each page, when an upgradephp equivalent
exists.

· 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).


The other cmdline scripts are used for developing upgrade.php:

· "cmpversion" 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.

· "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/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/projects/upgradephp> for any 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/ - the origin.


Author
------
The current maintainer can be contacted under <milky*users·sf·net>

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



ChangeLog
---------

v19
  - Adds new PHP5.5 functions: array_column(), json_last_error_msg(),
    boolval()
  - Ships with password_compat[MITL] from Anthony Ferrara, which add
    password_hash() and password_verify() from PHP5.5
  - Minor additions to json_encode and json_decode

v18
  - Anthon Pang contributed mysqli_set_charset() and E_DEPRECATED const
  - Also contrib/safe_serialize and unserialize() implementations by Anthon
  - TMPDIR support for sys_get_temp_dir()
  - gzdecode is now an official PHP 5.4 function.
  - hex2bin
  - session_status
  - zlib_encode / zlib_decode
  - http_redirect, http_response_code, http_send_content_type
  - get_declared_traits (stub), class_uses (stub), get_declared_traits (stub)
  - json_encode: JSON_HEX_AMP, JSON_HEX_TAG, JSON_HEX_APOS, JSON_HEX_QUOT,
    (5.3.3 addition) JSON_NUMERIC_CHECK,
    (5.4.0 addition) JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES
    and JSON_UNESCAPED_UNICODE.
  - json_decode: added flag JSON_BIGINT_AS_STRING, JSON_OBJECT_AS_ARRAY,
    and the non-standard JSON_PARSE_JAVASCRIPT
  - basic basic json_last_error() function

v17
  - new emulation of pspell extension using cmdline tool
  - escaping fixed in json_encode(), ignores utf-8 now
  - a few php 5.2 array functions added
  - str_getcsv, parse_ini_string, quoted_printable_encode
  - inet_pton, inet_ntop, 
  - fixes to sys_get_tmp_dir, error_get_last, property_exists, uuencode,
    get_headers, vprintf, import_request_variables
  - test-up script is now used for executing documentation tests,
    old PEAR test script is nonfunctional

v16
  - json_decode() array-conversion fix by Gerhard (tinned-software.net)
  - object-oriented input $_REQUEST filter wrapper in contrib/
  - some old code moved to contrib/archive/

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/cmpversion.



































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?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 = __FILE__.".data";



#-- load previous list
$DATA = array();
if (file_exists($DATA_FILE)) {
   $DATA = include($DATA_FILE);   // should contain return array(...
}

#-- current func list
$DATA[strtok(PHP_VERSION, "-")] = get_defined_stuff();
ksort($DATA);

#-- save this one
if ($f = fopen($DATA_FILE, "wb")) {
   fwrite($f, '<? return ' . var_export($DATA, TRUE) . ';');
   fclose($f);
}
else die("couldn't save back");



#-- comparison of  current / last run
print "available versions: " . implode(", ", array_keys($DATA)) . "\n";
$old_version = @$_SERVER["argv"][1]  or  $old_version = key($DATA);
$new_version = @$_SERVER["argv"][2]  or  $new_version = PHP_VERSION;
print "comparing \x1b[31m$old_version\x1b[39m and \x1b[32m$new_version\x1b[39m:\n";

#-- list
$oldl = $DATA[$old_version];
$newl = $DATA[$new_version];
echo "old(".count($oldl["functions"])."), new(".count($newl["functions"]).")\n";
if ($oldl) {

   #-- funcs
   $new = array_diff($newl["functions"], $oldl["functions"]);
   echo "\x1b[32mNew functions:\x1b[39m\n";
   print_r($new);

   #-- constants
   $new = array_diff(array_keys($newl["constants"]), array_keys($oldl["constants"]));
   echo "\n\x1b[32mNewly added constants:\x1b[39m\n";
   print_r($new);

   #-- classes
   $new = array_diff($newl["classes"], $oldl["classes"]);
   echo "\n\x1b[32mAnd classes:\x1b[39m\n";
   print_r($new);

}



/**
 * assemble list of defined functions/etc
 *
 */
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/cmpversion.data.

more than 10,000 changes

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
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
#!/usr/bin/php -q
<?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 = 0;   // (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 = php_interpreter();
   $dir = get_manual();
   $html = get_lynx();
   $tmpdir = $tmp = tmp();


   #-- load emulation script
   chdir(".");
   system("./doc/devtools/test-up");
   # dirname(dirname(__FILE__)) );
   $upgrade_php = "upgrade.php";
   $test_up = "test-up.php";
   $emu2 = "ext/array.php";
   $emu3 = "ext/mime.php";
   require($upgrade_php);



   #-- get function names
   $funcs = emulated_functions();

   #-- generate list of really emulated functions
   $simulated = simulated();
   $dont = array("time_nanosleep");



   #-- all
   $funcs = emulated_functions();
   foreach ($funcs as $func) {

      # read from php-manual
      if (($fn = func2fn($func))
       and !in_array($func, $dont) )
#      and $ALL || in_array($func, $simulated) )
      {
         echo "checking function '\033[31m$func\033[37m'... ";


         #-- grep example scripts
         $tests = example_scripts($func);

         #-- exec each
         if ($n = count($tests)) {

            #-- multiple scripts to run
            foreach ($tests as $i=>$script) {

               add_output($script);   // add print or echo if missing

               up_version($script, $func);   // use test-up.php "up_functionname"

               #-- output sample script text from doc
               print_script($script);

               #-- create temp script, run it
               if ($MANY) {
                  $tmp = "$tmpdir/$func#$i.php";
               }
               $script = ltrim($script);
               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('$test_up');\n".
#                  "#include('$emu2');\n".
#                  "#include('$emu3');\n".
                  "error_reporting(E_ALL);\n\n".
                  "#-- example[$i] as taken from PHP manual page '$fn'\n".
                  "$script\n".
                  "\n?".">"
               );
               echo "==>\033[32m\n";
               passthru("$php $tmp 2>&1");
               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); }





   function emulated_functions($upgrade_php = "upgrade.php") {
      preg_match_all("/function[ ]+(?:up_)?([_\w\d]+)\s*\(/", file_get_contents($upgrade_php), $uu);
      return $uu[1];
   }


function php_interpreter() {
   $php = $_SERVER["argv"][1];
   $php = trim(`which $php`);
   if (!$php) {
      die(__FILE__.": Given PHP interpreter not in your %PATH!\n");
   }
   return $php;
}

function get_manual() {
   $dir = $_SERVER["argv"][2];
   if (!is_dir($dir) || !file_exists("$dir/function.print.html")) {
      die(__FILE__.": PHP manual does not live under '$dir'.\n");
   }
   return $dir;
}
function get_lynx() {
   ($html = `which w3m`) or ($html = `which lynx`);
   if (!($html = trim($html))) {
      die(__FILE__.": lynx or w3m required.\n");
   }
   return $html;
}
function tmp() {
   global $MANY;
   $tmp = "/tmp/upgrade.php.doctest.tmp";
   $tmpdir = $tmp;
   if ($MANY) { @unlink($tmpdir); @mkdir($tmpdir); }
   return $tmp;
}

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


function func2fn($func) {
   global $dir;
  $fn = "$dir/function.".strtr($func, "_", "-").".html";
  if (file_exists($fn)) { return $fn; }
}


function example_scripts($func) {
   global $html;
   $fn = func2fn($func);
   $text = `$html -dump $fn`;
   preg_match_all("/<\?php(.+?)\?".">/ms", $text, $uu);
   return($uu[1]);
}


function add_output(&$scr) {
               #-- fix output-less scripts: find last assigned-to variable name
               if (!preg_match("/echo|print|var_dump/", $scr)) {
                  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);
}
function up_version(&$scr, $func) {
   $scr = preg_replace("/$func/", "up_$func", $scr);
}

function print_script($scr) {
   global $i, $PAUSE;
               #-- 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";
}

?>

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
#!/usr/bin/php -q
<?php
/*
   Prints the list of emulated functions.
*/

#-- basedir
$dir = dirname(dirname(dirname(__FILE__)));

#-- read files
$text = file_get_contents("$dir/upgrade.php");
foreach (glob("$dir/ext/*.php") as $add) {
   $text .= file_get_contents($add);
}

#-- grep
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/devtools/test-up.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
#!/bin/sh

echo "generate test-up.php, with if function_exists() removed, all emulations prefixed by up_"

egrep -v '^if [(]!function_exists|^[}]' upgrade.php \
    | perl -pe 'if (/^   function ([\w_\d]+)/) { $save = $1; }; if ($save) { s/$save/up_$save/m; }' \
    > upgrade.php.prefixed

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
58
59

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. You
then have the family of gettext functions always available - wether
compiled 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 the emulated version have not been tested
*extensively*.

 - 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 mixed together).
   [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,
                                 but deemed senseful for PHP)

 - 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 (= not tested with a
       real-world plural .po/.mo translation package)

 - 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
874
875
#!/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.
define("DETAILED", 0);
error_reporting(E_ERROR|E_WARNING);
$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" => "Hallφchen
",
  "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);
   }
}

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
































































































































































































































































Deleted ext/array.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
<?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();
      $key_cb = array_pop($in);
      $val_cb = array_pop($in);
      $arr1 = array_shift($in);
      $r = array();
      
      foreach ($arr1 as $i=>$v) {
         #-- in each array, compare against each key/value pair
         foreach (array_keys($in) as $c) {
            foreach ($in[$c] as $i2=>$v2) {
               
               $key_cmp = call_user_func_array($key_cb, array($i, $i2));
               if ($key_cmp == 0) {

                  #-- ok, in this case we must compare the data as well
                  $val_cmp = call_user_func_array($val_cb, array($v, $v2));
                  if ($val_cmp == 0) {
                     continue 3;
                  }
               }
            }
         }

         #-- this combination isn't really found anywhere else
         $r[$i] = $v;
      }
      return($r);
   }
}


#-- same, but that keys now are compared normally (without callback)
if (!function_exists("array_udiff_assoc")) {
   function array_udiff_assoc() {
      $in = func_get_args();
      $val_cb = array_pop($in);
      $arr1 = array_shift($in);
      $r = array();
      
      #-- compare against each key/value pair in other arrays
      foreach ($arr1 as $i=>$v) {
         foreach (array_keys($in) as $c) {
            if (isset($in[$c][$i])) {
               #-- now compare data by callback
               $cmp = call_user_func_array($val_cb, array($v, $in[$c][$i]));
               if ($cmp == 0) {
                   continue 2;
               }
            }
         }
         #-- everything exists only in array1
         $r[$i] = $v;
      }
      return($r);
   }
}


#-- ....
if (!function_exists("array_diff_uassoc")) {
   function array_diff_uassoc() {
      $in = func_get_args();
      $key_cb = array_pop($in);
      $arr1 = array_shift($in);
      $num = count($in);
      $r = array();
      
      foreach ($arr1 as $i=>$v) {
         #-- in other arrays?
         for ($c=0; $c<$num; $c++) {
            foreach ($in[$c] as $i2=>$v2) {
               if ($v == $v2) {
                  $cmp = call_user_func_array($key_cb, array($i, $i2));
                  if ($cmp == 0) {
                     continue 3;
                  }
               }
            }
         }
         #-- exists only in array1
         $r[$i] = $v;
      }
      return($r);
   }
}


#-- diff array, keys ignored, callback for comparing values
if (!function_exists("array_udiff")) {
   function array_udiff() {
      $in = func_get_args();
      $val_cb = array_pop($in);
      $arr1 = array_shift($in);
      $num = count($in);
      $r = array();
      foreach ($arr1 as $i=>$v) {
         #-- check other arrays
         for ($c=0; $c<$num; $c++) {
            foreach ($in[$c] as $v2) {
               $cmp = call_user_func_array($val_cb, array($v, $v2));
               if ($cmp == 0) {
                  continue 3;
               }
            }
         }
         #-- exists only in array1
         $r[$i] = $v;
      }
      return($r);
   }
}












#-- same for intersections
if (!function_exists("array_uintersect_uassoc")) {
   function array_uintersect_uassoc() {
      $in = func_get_args();
      $key_cb = array_pop($in);
      $val_cb = array_pop($in);
      $all = array();
      $conc = count($in);
      foreach ($in[0] as $i=>$v) {
         #-- must exist in each array (at least once, callbacks may match fuzzy)
         for ($c=1; $c<$conc; $c++) {
            $ok = false;
            foreach ($in[$c] as $i2=>$v2) {
               $key_cmp = call_user_func_array($key_cb, array($i, $i2));
               $val_cmp = call_user_func_array($val_cb, array($v, $v2));
               if (($key_cmp == 0) && ($val_cmp == 0)) {
                  $ok = true;
                  break;
               }
            }
            if (!$ok) {
               continue 2;
            }
         }
         #-- exists in all arrays
         $all[$i] = $v;
      }
      return($all);
   }
}




#-- intersection again
if (!function_exists("array_uintersect_assoc")) {
   function array_uintersect_assoc() {
      $in = func_get_args();
      $val_cb = array_pop($in);
      $all = array();
      $conc = count($in);
      foreach ($in[0] as $i=>$v) {
         #-- test for that entry in any other array
         for ($c=1; $c<$conc; $c++) {
            if (isset($in[$c][$i])) {
               $cmp = call_user_func_array($val_cb, array($v, $in[$c][$i]));
               if ($cmp == 0) { continue; }
            }
            #-- failed
            continue 2;
         }
         #-- exists in all arrays
         # (but for fuzzy matching: only the first entry will be returned here)
         $all[$i] = $v;
      }
      return($all);
   }
}





#-- array intersection, no keys compared, but callback for values
if (!function_exists("array_uintersect")) {
   function array_uintersect() {
      $in = func_get_args();
      $val_cb = array_pop($in);
      $arr1 = array_shift($in);
      $num = count($in);
      $r = array();

      foreach ($arr1 as $i=>$v) {
         #-- must have equivalent value in all other arrays
         for ($c=0; $c<$num; $c++) {
            foreach ($in[$c] as $i2=>$v2) {
               $cmp = call_user_func_array($val_cb, array($v, $v2));
               if ($cmp == 0) {
                  continue 2; //found
               }
            }
            continue 2; //failed
         }
         #-- everywhere
         $r[$i] = $v;
      }
      return($r);
   }
}




#-- diff array, keys ignored, callback for comparing values
if (!function_exists("array_intersect_uassoc")) {
   function array_intersect_uassoc() {
      $args = func_get_args();
      $key_cb = array_pop($args);
      $array1 = array_shift($args);
      $num = count($args);
      $all = array();
      foreach ($array1 as $i=>$v) {
         #-- look through other arrays
         for ($c=0; $c<$num; $c++) {
            $ok = 0;
            foreach ($args[$c] as $i2=>$v2) {
               $cmp = call_user_func_array($key_cb, array($i, $i2));
               if (($cmp == 0) && ($v == $v2)) {
                  $ok = 1;
                  continue 2;
               }
            }
            if (!$ok) { 
               continue 2;
            }
         }
         #-- found in all arrays
         if ($ok) {
            $diff[$i] = $v;
         }
      }
      return($diff);
   }
}


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




















































































































































































































































































































































































































































































































































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
<?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) {

|
>
|
|
<
>
|
>
|








>
>
>
>
>
>
>
>
|
>



<
|
<
|


|







<
|
>
|







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
/**
 *
 *  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) {
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
   }
   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);
   }
}


?>







<
|


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

79
80
81
82
83
84
85

86
87
88



















































































89
   }
   function bc___scaledown(&$a, $scale) {
      if (isset($scale) && ($dot = strpos($a, $dot))) {
         $a = substr($a, $dot + $scale) . "0";
      }
   }


}





















































































?>

Added ext/contrib/archive/bcmath.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
<?php
/**
 * These two alternate bcmath implementations don't emulate arbitrary
 * precision at all. And therefore have been removed from bcmath.php.
 *
 */


#-- 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);
   }
}


?>

Added ext/contrib/archive/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/fix_magic_quotes.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
<?php
/**
 * api: php
 * type: intercept
 * title: PHP fixes
 * descriptions: removes bogus magic_quotes and left over superglobals
 * version: 1.2
 * priority: auto
 * autoexec: 1
 * category: library
 * conflicts: strike_register_globals, strip_wonderful_slashes
 *
 *  Outdated and bogus PHP settings (register_globals and magic_quotes) are
 *  undone by this script. This avoids negative impact on contemporary code.
 *
 *  This variant can be manually included, or used as auto_prepend_file=
 *  via .user.ini or .htaccess declarations. Preferrably of course, the main
 *  php.ini should be fixed.
 *
 **/


 #-- implementation
 if (!function_exists("upgradephp_recursive_stripslashes")) {
    function upgradephp_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 upgradephp_recursive_stripslashes(&$var) {
       if (is_array($var)) {
          foreach ($var as $key=>$item) {
             upgradephp_recursive_stripslashes($var[$key]);
          }
       }
       else {
          $var = stripslashes($var);
       }
    }
 }


 #-- strike register_globals (injected variables)
 if (ini_get("register_globals") == "1") {
    upgradephp_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() && !defined("MAGIC_QUOTES_DISABLED")) {
    upgradephp_recursive_stripslashes($_REQUEST);
    upgradephp_recursive_stripslashes($_GET);
    upgradephp_recursive_stripslashes($_POST);
    upgradephp_recursive_stripslashes($_COOKIE);
    upgradephp_recursive_stripslashes($_ENV);
    upgradephp_recursive_stripslashes($_SERVER);
    ini_set("magic_quotes_gpc", 0);
    define("MAGIC_QUOTES_DISABLED", 1) or trigger_error("fix_magic_quotes has been invoked twice");
 }


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



?>

Added ext/contrib/header_errors.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_query.class.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() {

      $bin = "";	# 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
         $bin .= substr($this->content, $p, $n);
         $p += $n + 1;
#echo "CHUNK3($p,$n) ";
      }

      $this->content = $bin;
      unset($bin);
      $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_query.class.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

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 an 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's really easy, you just have to take care to always give the method
parameter before the URL ("GET" or "POST" in most cases):

  <?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-...").

For POST request you have to decide about the encoding format. There are
two options, the default is always urlencoding (like with GET requests):
  <?example 
      $query->type = "url";    // corresponds to "app/x-www-form-urlencoded"
  ?>
many bigger forms however require the MIME type for form-data:
  <?example 
      $query->type = "form";    // translates to "multipart/form-data"
  ?>

Any 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 as well.

PUT / POST requests are initiated likewise. But you could also just assign
a string blob to $query->params, if that's to be transfered as content.
(If the remote app can deal with / expects that. Of if you already have
encoded eveything into a valid form request).

For adding upload-files to a normal POST request, just do this however:
  <?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/input.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
<?php
 /**
  * api: php
  * title: Input $_REQUEST wrappers
  * type: interface
  * description: provides sanitization by encapsulating request superglobals against raw access
  * version: 2.5
  * revision: $Id$
  * license: Public Domain
  * depends: php:filter, php >5.0, html_purifier
  * config: <const name="INPUT_DIRECT" type="multi" value="disallow" multi="disallow|raw|log" description="filter method for direct $_REQUEST[var] access" />
  *         <const name="INPUT_QUIET" type="bool" value="0" multi="0=report all|1=no notices|2=no warnings" description="suppress access and behaviour notices" />
  * throws: E_USER_NOTICE, E_USER_WARNING, OutOfBoundsException
  *
  * Using these object wrappers ensures a single entry point and verification
  * spot for all user data. They wrap all superglobals and filter HTTP input
  * through sanitizing methods. For auditing casual and unverified access.
  *
  * Standardly they wrap: $_REQUEST, $_GET, $_POST, $_SERVER, $_COOKIE
  * And provide convenient access to filtered data:
  *   $_GET->int("search_q")                      // method
  *   $_POST->text["commentfield"]                // array syntax
  *   $_REQUEST->text->ascii->strtolower["xyz"]   // filter chains
  *
  * Available filter methods are:
  *   ->int
  *   ->float
  *   ->boolean
  *   ->name
  *   ->id
  *   ->words
  *   ->text
  *   ->ascii
  *   ->nocontrol
  *   ->spaces
  *   ->q
  *   ->escape
  *   ->regex
  *   ->in_array
  *   ->html
  *   ->purify
  *   ->json
  *   ->length
  *   ->range
  *   ->default
  * And most useful methods of the php filter extension.
  *   ->email
  *   ->url ->uri ->http
  *   ->ip
  *   ->ipv4->public
  * PHP string modification functions:
  *   ->strtolower
  *   ->addslashes
  *   ->urlencode
  *   ->strip_tags
  *   ->htmlentities
  * Automatic filter chain handler:
  *   ->array
  * Fetch multiple variables at once:
  *   ->list["var1,key,name"]
  * Process multiple entries as array:
  *   ->multi->http_build_query["id,token"]
  * Possible but should be used very consciously:
  *   ->xss
  *   ->sql
  *   ->mysql
  *   ->log
  *   ->raw
  *
  * You can also pre-define a standard filter-chain for all following calls:
  *   $_GET->nocontrol->iconv->utf7->xss->always();
  *
  * Using $__rules[] a set of filter rules can be preset per variable name.
  *
  * Some filters are a mixture of sanitizing and validation. Basically
  * all can also be used independently of the superglobals with their
  * underscore name, $str = input::_text($str);
  *
  * For the superglobals it's also possible to count($_GET); or check with
  * just $_POST() if there are contents. (Use this in lieu of empty() test.)
  * There are also the three functions ->has ->no ->keys() for array lookup.
  *
  * Defining new filters can be done as methods, or since those are picked
  * up too, as plain global functions. It's also possible to assign function
  * aliases or attach closures:
  *   $_POST->_newfilter = function($s) { return modified($s); }
  * Note that the assignment name must have an underscore prefixed.
  *
  * --
  *
  * Input validation of course is no substitute for secure application logic,
  * parameterized sql and proper output encoding. But this methodology is a
  * good base and streamlines input data handling.
  *
  * Filter methods can be bypassed in any number of ways. There's no effort
  * made at prevention here. But it's recommended to simply use ->raw() when
  * needed - not all input can be filtered anyway. This way an audit handler
  * could always attach there - when desired.
  *
  * The goal is not to coerce, but encourage security via API *simplicity*.
  *
  */


/**
 * Handler name for direct $_REQUEST["array"] access.
 *
 *   "raw" = reports with warning,
 *   "disallow" = throws an exception
 */
defined("INPUT_DIRECT") or
define("INPUT_DIRECT", "raw");

/**
 * Notice suppression.
 *
 *   0 = report all,
 *   1 = no notices,
 *   2 = ignore non-existant filter
 */
defined("INPUT_QUIET") or
define("INPUT_QUIET", 0);


/**
 * @class Request variable input wrapper.
 *
 * The methods are defined with underscore prefix, but supposed to be used without
 * when invoked on the superglobal arrays:
 *
 * @method int   int[$field] converts input into integer
 * @method float float[$field]
 * @method name  name[$field] removes any non-alphanumeric characters
 * @method id    id[$field] alphanumeric string with dots
 * @method text  text[$field] textual data with interpunction
 *
 */  
class input implements ArrayAccess, Countable, Iterator {



    /**
     * Data filtering functions.
     *
     * These methods are usually not to be called directly. Instead use
     * $_GET->filtername["varname"] syntax without preceeding underscore
     * to access variable content.
     *
     * Categories: [e]=escape, [w]=whitelist, [b]=blacklist, [s]=sanitize, [v]=validate
     *
     */

    
    /**
     * [w]
     * Integer.
     *
     */
    function _int($data) {
        return (int)$data;
    }

    /**
     * [w]
     * Float.
     *
     */
    function _float($data) {
        return (float)$data;
    }
    
    /**
     * [w]
     * Alphanumeric strings.
     * (e.g. var names, letters and numbers, may contain international letters)
     *
     */
    function _name($data) {
        return preg_replace("/\W+/u", "", $data);
    }

    /**
     * [w]
     * Identifiers with underscores and dots,
     * like "xvar.1_2.x"
     *
     */
    function _id($data) {
        return preg_replace("#(^[^a-z_]+)|[^\w\d_.]+|([^\w_]$)#i", "", $data);
    }
    
    /**
     * [w]
     * Flow text with whitespace,
     * minimal interpunction allowed.
     *
     */
    function _words($data, $extra="") {
        return preg_replace("/[^\w\d\s,._\-+$extra]+/u", " ", strip_tags($data));
    }

    /**
     * [w]
     * Human-readable text with many special/interpunction characters:
     *  " and ' allowed, but no <, > or \
     *
     */
    function _text($data) {
        return preg_replace("/[^\w\d\s,._\-+?!;:\"\'\/`Β΄()*=]+/u", " ", strip_tags($data));
    }
    
    /**
     * Acceptable filename characters.
     *
     * Alphanumerics and dot (but not as first character).
     * You should use `->basename` as primary filter anyway.
     *
     * @t whitelist
     *
     */
    function _filename($data) {
        return preg_replace("/^[.\s]|[^\w._+-]/", "_", $data);
    }
    
    #_datetime($name) { ... }  // as in HTML5
    #_session_id($name) { ... }  // e.g. verify last IP, stale session, user-agent
    #_
    
    /**
     * [b]
     * Filter non-ascii text out.
     * Does not remove control characters. (Similar to FILTER_FLAG_STRIP_HIGH.)
     * 
     */
    function _ascii($data) {
        return preg_replace("/[\\200-\\377]+/", "", $data);
    }

    /**
     * [b]
     * Remove control characters. (Similar to FILTER_FLAG_STRIP_LOW.)
     * 
     */
    function _nocontrol($data) {
        return preg_replace("/[\\000-\\010\\013\\014\\016-\\037\\177\\377]+/", "", $data); // all except \r \n \t
    }
    
    /**
     * [e] 
     * Exchange \r \n \t and \f \v \0 for normal spaces.
     * 
     */
    function _spaces($data) {
        return strtr($data, "\r\n\t\f\v\0", "      ");
    }

    /**
     * [x]
     * Regular expression filter.
     *
     * This either extracts (preg_match) data if you have a () capture group,
     * or functions as filter (pref_replace) if there's a [^ character class.
     * 
     */
    function _regex($data, $rx="", $match=1) {
        # validating
        if (strpos($rx, "(")) {
            if (preg_match($rx, $data, $result)) {
                return($result[$match]);
            }
        }
        # cropping
        elseif (strpos($rx, "[^")) {
            return preg_replace($rx, "", $data);
        }
    }
    
    /**
     * [w]
     * Miximum string length.
     *
     */
    function _length($data, $max=65535) {
        return substr($data, 0, $max);
    }
    
    /**
     * [w]
     * Range ensures value is between given minimum and maximum.
     * (Does not convert to integer itself.)
     *
     */
    function _range($data, $min, $max) {
        return ($data > $max) ? $max : (($data < $min) ? $min : $data);
    }

    /**
     * [b]
     * Fallback value for absent/falsy values.
     *
     */
    function _default($data, $default) {
        return empty($data) ? $default : $data;
    }

    /**
     * [w] 
     * Boolean recognizes 1 or 0 and textual values like "false" and "off" or "no".
     *
     */
    function _boolean($data) {
        if (empty($data) || $data==="0" || in_array(strtolower($data), array("false", "off", "no", "n", "wrong", "not", "-"))) {
            return false;
        }
        elseif ($data==="1" || in_array(strtolower($data), array("true", "on", "yes", "right", "y", "ok"))) {
            return true;
        }
        else return NULL;
    }

    /**
     * [w]
     * Ensures field is in array of allowed values.
     *
     * Works with arrays, but also string list. If you supply a "list,list,list" then
     * the comparison is case-insensitive.
     *
     */
    function _in_array($data, $array) {
        if (is_array($array) ? in_array($data, $array) : in_array(strtolower($data), explode(",", strtolower($array)))) {
            return $data;
        }
    }
    
    
    ###### filter_var() wrappers #########

    /**
     * [w]
     * Common case email syntax.
     *
     * (Close to RFC2822 but disallows square brackets or double quotes, no verification of TLDs,
     * doesn't restrict underscores in domain names, ignores i@an and anyone@localhost.)
     *
     */
    function _email($data, $validate=1) {
        $data = preg_replace("/[^\w!#$%&'*+/=?_`{|}~@.\[\]\-]/", "", $data);  // like filter_var
        if (!$validate || preg_match("/^(?!\.)[.\w!#$%&'*+/=?^_`{|}~-]+@(?:(?!-)[\w-]{2,}\.)+[\w]{2,6}$/i", trim($data))) {
            return $data;
        }
    }

    /**
     * [s] 
     * URI characters. (Actually IRI)
     *
     */
    function _uri($data) {
    # we should encode all-non chars
        return preg_replace("/[^-\w\d\$.+!*'(),{}\|\\~\^\[\]\`<>#%\";\/?:@&=]+/u", "", $data);  // same as SANITIZE_URL
    }
    
    /**
     * [w]
     * URL syntax
     *
     * This is an alias for FILTER_VALIDATE_URL. Beware that it lets a few unwanted schemes
     * through (file:// and mailto:) and what you'd consider misformed URLs (http://http://whatever).
     *
     */
    function _url($data) {
        return filter_var($data, FILTER_VALIDATE_URL);
    }

    /**
     * [v]
     * More restrictive HTTP/FTP url syntax.
     * No usernames allowed, no empty port, pathnames/qs/anchor are not checked.
     *
     # see also http://internet.ls-la.net/folklore/url-regexpr.html
     */
    function _http($data) {
        return preg_match("~
            (?(DEFINE)  (?<byte> 2[0-4]\d |25[0-5] |1\d\d |[1-9]?\d)  (?<ip>(?&byte)(\.(?&byte)){3})  (?<hex>[0-9a-fA-F]{1,4})  )
        ^   (?<proto>https?|ftps?)  ://
            # (?<user> \w+(:\w+)?@ )?
            ( (?<host>  (?:[a-z][a-z\d_\-\$]*\.?)+)
             |(?<ipv6>  \[     (?! [:\w]*:::          # ASSERT: no triple ::: colons
                                 |(:\w+){8}|(\w+:){8} # not more than 7 : colons
                                 |(\w*:){7}\w+\.      # not more than 6 : if there's a .
                                 | [:\w]*::[:\w]+:: ) # double :: colon must be unique
                               (?= [:\w]*::           # don't count if there is one ::
                                 |(\w+:){6}\w+[:.])   # else require six : and one . or :
              (?: :|(?&hex):)+((?&hex)|(?&ip)|:) \])  # MATCH: combinations of HEX : IP
             |(?<ipv4>  (?&ip) )     )
            (?<port> :\d{1,5} )?   # the integer isn't optional if port : colon present (unlike FILTER_VALIDATE_URL)
            (?<path> [/][^?#\s]* )?
            (?<qury> [?][^#\s]* )?
            (?<frgm> [#]\S* )?
        \z~ix", $data, $uu) ? $data : NULL;#(print_r($uu) ? $data : $data)
    }
    
/*
# http://phpcentral.com/208-url-validation-in-php.html

$urlregex = "^(https?|ftp)\:\/\/([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?
[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)*(\:[0-9]{2,5})?
(\/([a-z0-9+\$_-]\.?)+)*\/?(\?[a-z+&\$_.-][a-z0-9;:@/&%=+\$_.-]*)?(#[a-z_.-][a-z0-9+\$_.-]*)?\$";
*/

    /**
     * [w] 
     * IP address
     *
     */
    function _ip($data) {
        return filter_var($data, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4|FILTER_FLAG_IPV6) ? $data : NULL;
    }

    /**
     * [w]
     * IPv4 address
     *
     */
    function _ipv4($data) {
        return filter_var($data, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? $data : NULL;
    }
    
    /**
     * [w]
     * must be public IP address
     *
     */
    function _public($data) {
        return filter_var($data, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE) ? $data : NULL;
    }


    ###### format / representation #########
    
    
    /**
     * [v]
     * HTML5 datetime / datetime_local, date, time
     *
     */
    function _datetime($data) {
        return preg_match("/^\d{0}\d\d\d\d -(0\d|1[012]) -([012]\d|3[01]) T ([01]\d|2[0-3]) :[0-5]\d :[0-5]\d   (Z|[+-]\d\d:\d\d|\.\d\d)$/x", $data) ? $data : NULL;
    }
    function _date($data) {
        return preg_match("/^\d\d\d\d -(0\d|1[012]) -([012]\d|3[01])$/x", $data) ? $data : NULL;
    }
    function _time($data) {
        return preg_match("/^([01]\d|2[0-3]) :[0-5]\d :[0-5]\d  (\.\d\d)?$/x", $data) ? $data : NULL;
    }

    /**
     * [v]
     * HTML5 color
     *
     */
    function _color($data) {
        return preg_match("/^#[0-9A-F]{6}$/i", $data) ? strtoupper($data) : NULL;
    }


    /**
     * [w]
     * Telephone numbers (HTML5 <input type=tel> makes no constraints.)
     *
     */
    function _tel($data) {
        $data = preg_replace("#[/.\s]+#", "-", $data);
        if (preg_match("/^(\+|00)?(-?\d{2,}|\(\d+\)){2,}(-\d{2,}){,3}(\#\d+)?$/", $data)) {
            return trim($data, "-");
        }
    }


    /**
     * [v]
     * Verify minimum consistency (RFC4627 regex) and decode json data.
     *
     */
    function _json($data) { 
        if (!preg_match('/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/', preg_replace('/"(\\.|[^"\\])*"/g', '', $data))) {
            return json_decode($data);
        }
    }
    
    /**
     * [v]
     * XML tree.
     *
     */
    function _xml($data) {
        return simplexml_load_string($data);
    }

    /**
     * [w]
     * Clean html string via HTMLPurifier.
     *
     */
    function _purify($data) {
        $h = new HTMLPurifier;
        return $h->purify( $data );
    }

    /**
     * [e]
     * HTML escapes.
     *
     * This is actually an output filter. But might be useful to mirror input back into
     * form fields instantly `<input name=field value="<?= $_GET->html["field"] ?>">`
     *
     * @param $data string
     * @return string
     */
    function _html($data) {

        return htmlspecialchars($data, ENT_QUOTES, "UTF-8", false);
    }

    /**
     * [e]
     * Escape all significant special chars.
     *
     */
    function _escape($data) {
        return preg_replace("/[\\\\\[\]\{\}\[\]\'\"\`\Β΄\$\!\&\?\/\>\<\|\*\~\;\^]/", "\\$1", $data);
    }

    /**
     * [e]
     * Addslashes
     *
     */
    function _q($data) {
        return addslashes($data);
    }

    /**
     * [b]
     * Minimal XSS detection.
     * Attempts no cleaning, just bails if anything looks suspicious.
     *
     * If something is XSS contaminated, it's spam and not worth to process further.
     * WEAK filters are better than no filters, but you should ultimatively use ->html purifier instead.
     *
     */
    function _xss($data) {
        if (preg_match("/[<&>]/", $data)) {   // looks remotely like html
            $html = $data;
            
            // remove filler
            $html = preg_replace("/&#(\d);*/e", "ord('$1')", $html);   // escapes
            $html = preg_replace("/&#x(\w);*/e", "ord(dechex('$1'))", $html);   // escapes
            $html = preg_replace("/[\x00-\x20\"\'\`\Β΄]/", "", $html);   //  whitespace + control characters, also any quotes
            $html .= preg_replace("#/\*[^<>]*\*/#", "", $html);   // in-JS obfuscation comments

            // alert patterns
            if (preg_match("#[<<]/*(\?import|applet|embed|object|script|style|!\[CDATA\[|title|body|link|meta|base|i?frame|frameset|i?layer)#iUu", $html, $uu)
             or preg_match("#[<>]\w[^>]*(\w{3,}[=:]+(javascript|ecmascript|vbscript|jscript|python|actionscript|livescript):)#iUu", $html, $uu)
             or preg_match("#[<>]\w[^>]*(on(mouse\w+|key\w+|focus\w*|blur|click|dblclick|reset|select|change|submit|load|unload|error|abort|drag|Abort|Activate|AfterPrint|AfterUpdate|BeforeActivate|BeforeCopy|BeforeCut|BeforeDeactivate|BeforeEditFocus|BeforePaste|BeforePrint|BeforeUnload|Begin|Blur|Bounce|CellChange|Change|Click|ContextMenu|ControlSelect|Copy|Cut|DataAvailable|DataSetChanged|DataSetComplete|DblClick|Deactivate|Drag|DragEnd|DragLeave|DragEnter|DragOver|DragDrop|Drop|End|Error|ErrorUpdate|FilterChange|Finish|Focus|FocusIn|FocusOut|Help|KeyDown|KeyPress|KeyUp|LayoutComplete|Load|LoseCapture|MediaComplete|MediaError|MouseDown|MouseEnter|MouseLeave|MouseMove|MouseOut|MouseOver|MouseUp|MouseWheel|Move|MoveEnd|MoveStart|OutOfSync|Paste|Pause|Progress|PropertyChange|ReadyStateChange|Repeat|Reset|Resize|ResizeEnd|ResizeStart|Resume|Reverse|RowsEnter|RowExit|RowDelete|RowInserted|Scroll|Seek|Select|SelectionChange|SelectStart|Start|Stop|SyncRestored|Submit|TimeError|TrackChange|Unload|URLFlip)[^<\w=>]*[=:]+)[^<>]{3,}#iUu", $html, $uu)
             or preg_match("#[<>]\w[^>]*(\w{3,}[=:]+(-moz-binding:))#iUu", $html, $uu)
             or preg_match("#[<>]\w[^>]*(style[=:]+[^<>]*(expression\(|behaviour:|script:))#iUu", $html, $uu))
            {
                $this->_log($data, "DETECTED XSS PATTERN ({$uu['1']}),");
                $data = "";
                die("input::_xss");
            }
        }
        return $data;
    }

    /**
     * [w]
     * Cleans utf-8 from invalid sequences and alternative representations.
     * (BEWARE: performance drain)
     *
     */
    function _iconv($data) {
        return iconv("UTF-8", "UTF-8//IGNORE", $data);
    }

    /**
     * [b]
     * Few dangerous UTF-7 sequences
     * (only necessary if output pages don't have a charset specified)
     *
     */
    function _utf7($data) {
        return preg_replace("/[+]A(D[w40]|C[IYQU])(-|$)?/", "", $data);;
    }

    /**
     * [e] 
     * Escape for concatenating data into sql query.
     * (suboptimal, use parameterized queries instead)
     *
     */
    function _sql($data) {
        INPUT_QUIET or trigger_error("SQL escaping of input variable '$this->__varname'.", E_USER_NOTICE);
        return db()->quote($data);  // global object
    }
    function _mysql($data) {
        INPUT_QUIET or trigger_error("SQL escaping of input variable '$this->__varname'.", E_USER_NOTICE);
        return mysql_real_escape_string($data);
    }
    



    ###### pseudo filters ##############


    /**
     * [x]
     * Unfiltered access should obviously be avoided. But it's not always possible,
     * so this method exists and will just trigger a notice in debug mode.
     *
     */
    function _raw($data) {
        INPUT_QUIET or trigger_error("Unfiltered input variable \${$this->__title}['{$this->__varname}'] accessed.", E_USER_NOTICE);
        return $data;
    }
    /**
     * [x]
     * Unfiltered access, but logs variable name and value.
     *
     */
    function _log($data, $reason="manual log") {
        syslog(LOG_NOTICE, "php7://input:_log@{$_SERVER['SERVER_NAME']} accessing \${$this->__title}['{$this->__varname}'] variable, $reason, content=" . substr($this->_id(json_encode($data)), 0, 48));
        return $data;
    }

    /**
     * [b]
     * Abort with fatal error. (Used as fallback for INPUT_DIRECT access.)
     *
     */
    function _disallow($data) {
        throw OutOfBoundsException("Direct \$_REQUEST[\"$this->__varname\"] is not allowed, add ->filter method, or change INPUT_DIRECT if needed.");
    }



   

    ######  implementation  ################################################




    /**
     * Array data from previous superglobal.
     *
     * (It's pointless to make this a priv/proteced attribute, as raw data could be accessed
     * in any number of ways. Not the least would be to just not use the input filters.)
     *
     */
    var $__vars = array();

    
    /**
     * Name of superarray this filter object wraps.
     * (e.g. "_GET" or "_SERVER")
     *
     */
    var $__title = "";


    /**
     * Currently accessed array key.
     *
     */
    var $__varname = "";


    /**
     * Amassed filter list.
     * Each ->method->chain name will be appended here. Gets automatically reset after
     * a succesful variable access.
     *
     * Each entry is in `array("methodname", array("param1", 2, 3))` format.
     *
     */
    var $__filter = array();  // filterchain method stack


    /**
     * Automatically appended filter list. (Simply combined with current `$__filter`s).
     *
     */
    var $__always = array();


    /**
     * Currently accessed array keys.
     *
     */
    var $__rules = array(     // pre-defined varname filters
        // "varname.." => array(  array("length",array(256), array("nocontrol",array())  ),
    );


    /**
     * Initialize object from
     *
     * @param array  one of $_REQUEST, $_GET or $_POST etc.
     */
    function __construct($_INPUT, $title="") {
        $this->__vars = $_INPUT;   // stripslashes on magic_quotes_gpc might go here, but we have no word if we actually receive a superglobal or if it wasn't already corrected
        $this->__title = $title;
    }

    
    /**
     * Sets default filter chain.
     * These are ALWAYS applied in CONJUNCTION to ->manually->specified->filters.
     *
     */
    function always() {
        $this->__always = $this->__filter;
        $this->__filter = array();
    }
    
    
    /**
     * Normalize array keys (to UPPER case), for e.g. $_SERVER vars.
     *
     */
    function key_case($case=CASE_UPPER) {
        $this->__vars = array_change_key_case($this->__vars, $case);
    }
    
    
    /**
     * Executes current filter or filter chain on given $varname.
     *
     */
    function filter($varname, $reset_filter_afterwards=NULL) {

        // direct/raw access can occour if invoked via offsetGet[] or filter() method called directly
        if (empty($this->__filter)) {
            $this->__filter[] = array(INPUT_DIRECT, array());

            // or apply a pre-defined filter chain
            if (isset($this->__rules[$varname])) {
                // must be in internal nested format
                $this->__filter = $this->rules[$varname];
            }
        }

        // retrieve value for selected input variable
        $this->__varname = $varname;
        if (isset($this->__vars[$varname])) {
            $data = $this->__vars[$varname];
        }
        elseif (count($this->__filter) and ("list" == $this->__filter[0][0])) {
            $data = NULL;    // do nothing, as values will be fetched by a multiplex handler
        }
        else {
            INPUT_QUIET or trigger_error("Undefined input variable \${$this->__title}['{$this->__varname}']", E_USER_NOTICE);   // undecorative
            $data = NULL;    // run through filters anyway (log)
        }
        
        // implicit ->array filter handling for lists (= if value is an array)
        $ARRAY = (ARRAY("array",(array)NULL));  # complex trigger token
        if (is_array($data) && !in_array($ARRAY, $this->__filter)) {
            array_unshift($this->__filter, array("array", array()));
        }
        
        // apply filters (we're building an ad-hoc merged array here, because ->apply works on the reference, and some filters expect ->__filter to contain the complete current list)
        $this->__filter = array_merge($this->__filter, $this->__always);
        $data = $this->apply($data, $this->__filter);
        
        // the Traversable array interface resets the filter list after each request, see ->current()
        if ($reset_filter_afterwards) {
            $this->__filter = $reset_filter_afterwards;
        }

        // done
        return $data;
    }


    /**
     * Runs list of filters on data. Uses either methods, bound closures, or global functions
     * if the filter name matches.
     *
     * It works on an array reference and with array_shift() because filters are allowed to
     * modify the list at runtime (->array requires to).
     *
     */
    function apply($data, &$filterchain) {
        while ($f = array_shift($filterchain)) {
            list($filtername, $args) = $f;
            
            // an override function name or closure was set
            if (isset($this->{"_$filtername"})) {
                $filtername = $this->{"_$filtername"};
            }
            // call _filter method
            if (is_string($filtername) && method_exists($this, "_$filtername")) {
                $data = call_user_func_array(array($this, "_$filtername"), array_merge(array($data), (array)$args));
            }
            // ordinary php function, or closure, or rebound method
            elseif (is_callable($filtername)) {
                $data = call_user_func($filtername, $data);
            }
            else {
                INPUT_QUIET>=2 or trigger_error("unknown filter '" . (is_scalar($filtername) ? $filtername : "closure") . "', falling back on wiping non-alpha characters from '{$this->__varname}'", E_USER_WARNING);
                $data = $this->_name($data);
            }
        }
        return $data;
    }


    /**
     * @multiplex
     *
     * List data / array value handling.
     *
     * This virtual filter hijacks the original filter chain, and applies it
     * to sub values.
     *
     */
    function _array($data) {

        // save + swap out the current filter chain
        list($multiplex, $this->__filter) = array($this->__filter, array());

        // iteratively apply original filter chain on each array entry
        $data = (array) $data;
        foreach (array_keys($data) as $i) {
            $chain = $multiplex;
            $data[$i] = $this->apply($data[$i], $chain);
        }

        return $data;
    }


    /**
     * @multiplex
     *
     * Grab a collection of input variables, names delimited by comma.
     * Implicitly makes it an ->_array() list.
     * The _array handler is implicitly used for indexed values. _list
     * and _multi can be used for associative arrays, given a key list.
     * 
     * @example  extract($_GET->list->text["name,title,date,email,comment"]);
     * @php5.4+  $_GET->list[['key1','key2','key3']];
     *
     * @bugs  hacky, improper way to intercept, fetches from $__vars[] directly,
     *        uses $__varname instead of $data, may prevent replays,
     *        main will trigger a notice anyway as VAR1,VAR2,.. is undefined
     *
     */
    function _list($keys, $pass_array=FALSE) {

        // get key list
        if (is_array($this->__varname)) {
            $keys = $this->__varname;
        }
        else {
            $keys = explode(",", $this->__varname);
        }

        // slice out named values from ->__vars
        $data = array_intersect_key($this->__vars, array_flip($keys));

        // chain to _array multiplex handler
        if (!$pass_array) {
            return $this->_array($data);
        }
        // process fetched list as array (for user-land functions like http_build_query)
        else {
            return $data;
        }
    }
    
    /**
     * Processes collection of input variables.
     * Passes list on as array to subsequent filters.
     *
     */
    function _multi($keys) {
        return $this->_list($keys, "process_as_array");
    }


    
    /**
     * @hide
     *
     * Ordinary method calls are captured here. Any ->method("name") will trigger
     * the filter and return variable data, just like ->method["name"] would. It
     * just allows to supply additional method parameters.
     *
     */
    function __call($filtername, $args) {  // can have arguments
        $this->__filter[] = array($filtername, array_slice($args, 1));
        return $this->filter($args[0]);
    }

    
    /**
     * @hide
     *
     * Wrapper to capture ->name->chain accesses.
     *
     */
    function __get($filtername) {
        //
        // we could do some heuristic chaining here,
        // if the last entry in the ->attrib->attrib list is not a valid method name,
        // but a valid varname, we should execute the filter chain rather than add.
        //
        $this->__filter[] = array($filtername, array());  // add filter to list
        return $this;  // fluent interface
    }
    


    /**
     * @hide ArrayAccess
     *
     * Normal $_ARRAY["name"] syntax access is redirected through the filter here.
     *
     */
    function offsetGet($varname) {
        // never chains
        return $this->filter($varname);
    }

    /**
     * @hide ArrayAccess
     *
     * Needed for commonplace isset($_POST["var"]) checks.
     *
     */
    function offsetExists($name) {
        return isset($this->__vars[$name]);
    }

    /**
     * @hide
     * Sets value in array. Note that it only works for array["xy"]= top-level
     * assignments. Subarrays are always retrieved by value (due to filtering)
     * and cannot be set item-wise.
     *
     * @discouraged
     * Manipulating the input array is indicative for state tampering and thus
     * throws a notice per default.
     *
     */
    function offsetSet($name, $value) {
        INPUT_QUIET or trigger_error("Manipulation of input variable \${$this->__title}['{$this->__varname}']", E_USER_NOTICE);
        $this->__vars[$name] = $value;
    }
    
    /**
     * @hide
     * Removes entry.
     *
     * @discouraged
     * Triggers a notice per default.
     *
     */
    function offsetUnset($name) {
        INPUT_QUIET or trigger_error("Removed input variable \${$this->__title}['{$this->__varname}']", E_USER_NOTICE);
        unset($this->__vars[$name]);
    }



    /**
     * Generic array features.
     * Due to being reserved words `isset` and `empty` need custom method names here:
     *
     *  ->has(isset)
     *  ->no(empty)
     *  ->keys()
     * 
     * Has No Keys seems easy to remember.
     *
     */

    /**
     * isset/array_key_exists check.
     *
     */
    function has($name) {
        return isset($this->__vars[$name]);
    }
    
    /**
     * empty() probing,
     * Tests if variable is absent or falsy.
     *
     */
    function no($name) {
        return empty($this->__vars[$name]);
    }
    
    /**
     * Returns list of all contained keys.
     *
     */
    function keys() {
        return array_keys($this->__vars);
    }


    /**
     * @hide Traversable
     *
     * Allows to loop over all array entries in a foreach loop. A supplied filterlist
     * is reapplied for each iteration.
     *
     * - Basically all calls are mirrored onto ->__vars` internal array pointer.
     * 
     */
    function current() {
        return $this->filter(key($this->__vars), /*reset_filter_afterwards=to what it was before*/$this->__filter);
    }
    function key() {
        return key($this->__vars);
    }
    function next() {
        return next($this->__vars);
    }
    function rewind() {
        return reset($this->__vars);
    }
    function valid() {
        if (key($this->__vars) !== NULL) {
            return TRUE;
        }
        else {
            // also reset the filter list after we're done traversing all entries
            $this->__filters=array();
            return FALSE;
        }
    }


    /**
     * @hide Countable
     * 
     */
    function count() {
        return count($this->__vars);
    }
    
    
    /**
     * @hide Allows testing variable presence with e.g. if ( $_POST() )
     *       Alternatively $_POST("var") is an alias to $_POST["var"].
     *
     */
    function __invoke($varname=NULL) {
    
        // treat it as variable access
        if (!is_null($varname)) {
            return $this->offsetGet($varname);
        }
        
        // do the count() call
        else {
            return $this->count();
        }
    }

}



/**
 * @autorun
 *
 */
$_SERVER = new input($_SERVER, "_SERVER");
$_REQUEST = new input($_REQUEST, "_REQUEST");
$_GET = new input($_GET, "_GET");
$_POST = new input($_POST, "_POST");
$_COOKIE = new input($_COOKIE, "_COOKIE");
#$_SESSION
#$_ENV
#$_FILES required a special handler

//          print_r(  $_SERVER->list->text[[USER,HOME]]  );



?>

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 Dόrst, 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_mysql.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
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
<?php
/**
 * api: php
 * title: Procedural pdo_* interface mimicking mysql_* functions
 * version: 0.9.3
 * priority: EXPERIMENTAL
 * license: Public Domain
 * type: functions
 * suggests: upgradephp
 * config:  <const name="PDO_HELPFUL" type="select" value="0=None|1=Notice|2=Syntax" help="Provide additional notices for common pitfalls"/>   <const name="PDO_SEEKABLE" type="int" value="0" help="Adds a faux cursor wrapper atop PDOStatement to allow seeking across result rows. Set to 1 to enable, or any larger integer for caching rows."/>
 * category: library
 * url: http://fossil.include-once.org/upgradephp/finfo?name=ext/contrib/pdo_mysql.php
 * requires: php (>= 5.1.3), php:pdo
 * doc: http://stackoverflow.com/a/20767765
 *
 *
 * The dated mysql_* functions are chaperoned by deprecation nagging and cursorily
 * mentions of PDO and MSQLI. Forced-switching APIs is kinda pointless however when
 * bound parameters go unmentioned and code rewriting remains prohibitive.
 *
 * This collection of functions provide pdo_ lookalikes for most mysql_* functions.
 * Rewriting is as simple as changing to:
 *
 *   pdo_connect       <-  mysql_connect
 *   pdo_query         <-  mysql_query
 *   pdo_result        <-  mysql_result
 *   pdo_fetch_array   <-  mysql_fetch_array
 *   pdo_escape_string <-  mysql_real_escape_string
 *
 * With the addition of an extended pdo_query() interface the cumbersome SQL
 * concatenation and easily forgotten escaping are obsolete:
 *
 *   mysql_query("SELECT whatever FROM tbl WHERE id='$id' OR x=$x");
 *                                                      \       \
 * Becomes:                                               \      \
 *                                                          \     \
 *   pdo_query("SELECT whatever FROM tbl WHERE id=? OR x=?", $id, $x);
 *                                                \      \--------/
 *                                                 \---------/
 *
 * It's as simple as moving interpolated variables from the query into separate
 * parameters, and leaving plain question mark ? placeholders (without quotes)
 * in the SQL.
 * Just keep track of a matching value-to-placeholder order.
 *
 * For variables separated out that way, any previous ***_real_escape_string
 * applying becomes redundant. (Though the long-winded escaping+intermingling
 * approach was still possible if you'd unreasonably prefer).
 * Get rid of or fix any oldschool sanitize() function once you have converted
 * every innovocation to bound parameters.
 *
 *
 * Caveats and tips
 *
 *   HANDLES    pdo_query() and pdo_connect() return objects instead of
 *     resource handles. Commonly used plain boolean if() result tests may
 *     remain. But replace any is_resource() checks with is_object().
 *
 *   FREEING    You neither need pdo_close() or pdo_free_result() anymore.
 *     Just unset the result handles, it's all cleaned up automatically.
 *
 *   SEEKING    The old mysql extension was a memory hog. It did buffer all
 *     result data, so could seek back and forth. For PDO results it's best
 *     to just iterate over them only once. Consider using a foreach()
 *     preferrably.
 *     If you need arbitrary  pdo_result(), _fetch_lengths(), _data_seek()
 *     access, please enable PDO_SEEKABLE. It does refetch if need be for
 *     out-of-order retrieval. (Mysqld itself provides enough buffering.)
 *
 *   BOUND PARAMETERS    In SQL only values can be bound parameters with ?
 *     placeholders. Identifiers like table names, column names can't. You
 *     still have to use interpolation (with withelisting) for those.
 *     Likewise can't LIMIT ?,? clauses be used in pdo_query(). Use
 *     typecasted interpolated numbers there.
 *
 *   NAMED PARAMETERS    Besides ? placeholders there are also :named_keys.
 *     pdo_query() supports those too if passed as a single array with
 *     :key => value pairs.  You can only use either or.
 *
 *   SOMETHING DOESN'T WORK    Before asking for personal support anywhere
 *     on the Internet, please have the courtesy to `print pdo_error();`
 *     first. Always enable `error_reporting(E_ALL);` and `display_errors`
 *     and keep the `PDO_HELPFUL` constant enabled while developing.
 *
 *   GLOBAL OBJECT   The pdo_ wrappers keep the default connection in the
 *     global $pdo variable. Whose name is unlikely to clash with existing
 *     code, but potentially compatible with recent as by-product.
 *
 *
 * Rewriting advise
 *
 *   HYBRID    You can mix the old-style function use with PDO-esque
 *     accessing of result sets. For example
 *
 *         pdo_query("SELECT *")->fetchAll()
 *
 *     Packs all results into one list of row arrays.
 *     Which is also significantly shorter than:
 *
 *         while ($row = pdo_fetch_assoc($result)) {
 *            $array[] = $row;
 *         }
 *
 *     But PDO even allows to directly loop over the $result object.
 *
 *         foreach (pdo_query("SELECT * FROM tbl") as $assoc) {}
 *
 *     Currently doesn't work for PDOStatement_Seekable wrapped results.
 *
 *   TRANSITION   Likewise can you access PDO itself from the global handle,
 *     if you want to progressively switch to the native interface:
 *
 *         $pdo->prepare("INSERT INTO log VALUES (?)")->execute(array($msg));
 *
 *     You can still mix in pdo_query() and other function wrappers, if you
 *     utilize the $pdo variable from the shared scope, or pass it as $link
 *     parameter.
 *
 *
 *
 *
 *
 *
 */




// provide development tips (deprecated and redundant functions), set to 2 for SQL syntax warnings about unbound strings
defined("PDO_HELPFUL") or
define("PDO_HELPFUL", 1);


// apply PDO wrapper for random-access row seeking / faux cursor
defined("PDO_SEEKABLE") or
define("PDO_SEEKABLE", 1);  // set this to a higher integer (e.g. 500) to enable a cache for random access


// upgradephp
defined("E_USER_DEPRECATED") or
define("E_USER_DEPRECATED", E_USER_NOTICE);




// define functions just once
if (!function_exists("pdo_query")) {




  /**
   * Return the number of rows affected by last query.
   *
   */
  function pdo_affected_rows($stmt=NULL) {
     return pdo_stmt($stmt)->rowCount();
  }




  /**
   * What mysql thinks the charset of strings in PHP to be.
   *
   */
  function pdo_client_encoding($link=NULL) {
     return pdo_query("SELECT @@character_set_client AS cs", pdo_handle($link))->fetchObject()->cs;
  }
  



  /**
   * Disconnect by removing $pdo object.
   *
   */  
  function pdo_close($link=NULL) {
     PDO_HELPFUL and pdo_trigger_error("pdo_close() Does not need to be called usually. Just unset() your database handle.", E_USER_DEPRECATED);

     if ($link) {
        unset($link);
     }
     else {
        $GLOBALS["pdo"] = /*unset with*/ new pdo_dummy("No database connection. You had just disconnected using pdo_close()!");
     }
  }




  /**
   * Connect to database.
   *
   * Also stores the newest PDO handle in the global `$pdo` variable.
   *
   */  
  function pdo_connect($server=NULL, $user=NULL, $pass=NULL, $new_link=FALSE, $client_flags=0x0000, $pconnect=0x0000) {
     
     // get params
     $server or $server = ini_get("mysql.default_host");
     $user or $user = ini_get("mysql.default_user");
     $pass or $pass = ini_get("mysql.default_password");


     // prepare Data Source Name
     $dsn = "mysql:";
     
     // servername contains a socket path
     if (strpos($server, "/")) {
        strpos($server, ":") and $server = substr($server, strpos($server, ":") + 1);
        $dsn .= "unix_socket=$server";
     }
     // or hostname and optional port
     else {
        if (strpos($server, ":")) {
           list($server, $port) = explode($server, ":");
           $dsn .= "host=$server;port=$port";
        }
        else {
           $dsn .= "host=$server";
        }
     }
     //("we don't have a dbname= at this point");
     

     // driver flags
     $flags = array(
        PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
        #PDO::MYSQL_ATTR_INIT_COMMAND => '',   // first SQL command after connect
        #PDO::MYSQL_ATTR_DIRECT_QUERY => true, // direct queries, no prepared statements
        #PDO::MYSQL_ATTR_FOUND_ROWS => true,   // rowCount() for SELECTs, not sure if this is an init parameter, or Statement setting
     );
     if ($client_flags & MYSQL_CLIENT_COMPRESS) {
        $flags[PDO::MYSQL_ATTR_COMPRESS] = 1;
     }
     if ($client_flags & MYSQL_CLIENT_SSL) {
        $flags[PDO::MYSQL_ATTR_SSL_KEY] = "client.pem";
        $flags[PDO::MYSQL_ATTR_SSL_CERT] = "cert.pem";
        $flags[PDO::MYSQL_ATTR_SSL_CA] = "ca.pem";
     }
     if ($client_flags & MYSQL_CLIENT_IGNORE_SPACE) {
        $flags[PDO::MYSQL_ATTR_IGNORE_SPACE] = 1;
     }
     if ($client_flags & 128) {
        $flags[PDO::MYSQL_ATTR_LOCAL_INFILE] = 1;
     }
     if ($pconnect) {
        $flags[PDO::ATTR_PERSISTENT] = 1;
     }
     

     // instantiate connection
     try {
        $pdo = new PDO($dsn, $user, $pass, $flags);
     }
     catch (RuntimeException $pdo) {
        PDO_HELPFUL and pdo_trigger_error("pdo_connect() Failed. {$pdo->getMessage()}", E_USER_WARNING);
        return new pdo_dummy("Database connection had failed [ErrCode{$pdo->getCode()}].");
     }
     
     // set PDO flags
     $pdo->setAttribute(PDO::ATTR_ERRMODE, (PDO_HELPFUL ? PDO::ERRMODE_WARNING : PDO::ERRMODE_SILENT)); //or PDO::ERRMODE_EXCEPTION
     $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
     $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
     $pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
     $pdo->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
     $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);


     // done     
     return pdo_handle($pdo, "SET_HANDLE_AS_DEFAULT");
  }




  /**
   * CREATE DATABASE
   *
   */
  function pdo_create_db($dbname, $link=NULL) {
     $dbname = str_replace("`", "``", $dbname);
     return (bool)pdo_query("CREATE DATABASE `$dbname`", pdo_handle($link));
  }




  /**
   * Move pointer in result set.
   *
   */
  function pdo_data_seek($stmt, $row_number) {
      !PDO_SEEKABLE and pdo_trigger_error("pdo_data_seek() PDO_MySQL driver does not support cursors. Enable PDO_SEEKABLE.", E_USER_WARNING);
      pdo_stmt($stmt)->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_ABS, $row_number);
  }
  



  /**
   * Return one entry from _list_dbs().
   *
   */
  function pdo_db_name($stmt, $row, $field="Database") {
     return pdo_result($stmt, $row, $field);
  }




  /**
   * Combo of _select_db() and _query().
   *
   */
  function pdo_db_query($dbname, $query, $link=NULL, $params=NULL) {
     PDO_HELPFUL and pdo_trigger_error("pdo_db_query() is redundant. Use pdo_select_db() and pdo_query().", E_USER_DEPRECATED);

     if (pdo_select_db($dbname, pdo_handle($link))) {
        $params = func_get_args();
        array_shift($params);
        return call_user_func_array("pdo_query", $params);
     }
  }




  /**
   * DROP DATABASE
   *
   */
  function pdo_drop_db($dbname, $link=NULL) {
     $dbname = str_replace("`", "``", $dbname);
     return (bool)pdo_query("DROP DATABASE `$dbname`", pdo_handle($link));
  }




  /**
   * Get numeric error code for last failed database query.
   *
   */
  function pdo_errno($link=NULL) {
     $error = pdo_handle($link)->errorInfo();
     return $error[1];
  }




  /**
   * Get error message for last failed request.
   *
   */
  function pdo_error($link=NULL) {
     #
     #### Possibly better to also keep a $pdo_last_stmt to get possible errors from there?
     #    PDO::errorInfo might be empty
     #    Keeping PDO::ERRMODE_WARNING per default isn't as advisable for production setups.
     #
     #    Similar wrapper in https://www.kitware.com/svn/CDash/trunk/cdash/pdocore.php
     #    also just uses PDO::errorInfo
     #
     global $pdo_last_stmt;
     $link = pdo_handle($link);

     # we don't really know what ran last, PDO:: or PDOStatement::
     if (!empty($pdo_last_stmt)) {
        $error = $pdo_last_stmt[spl_object_hash($link)]->errorInfo();
     }
     else {
        $error = $link->errorInfo();
     }
     return $error[2];
  }




  /**
   * String escaping, alias to _real_escape_string()
   *
   */
  function pdo_escape_string($str, $link=NULL) {
     return pdo_real_escape_string($str, $link);
  }




  /**
   * Get result row.
   * Note you still have to use the MYSQL_ constants, _BOTH, _ASSOC, or _NUMeric array.
   *
   */
  function pdo_fetch_array($stmt, $type=3) {
  
     $map = array(
         MYSQL_ASSOC/*1*/ => PDO::FETCH_ASSOC/*2*/,
         MYSQL_NUM/*2*/ => PDO::FETCH_NUM/*3*/,
         MYSQL_BOTH/*3*/ => PDO::FETCH_BOTH/*4*/,
         // no consistency so far, so let's embrace and extend it:
         0=>4, "assoc"=>2, "num"=>3, "both"=>4, "ASSOC"=>2, "NUM"=>3, "BOTH"=>4, "MYSQL_ASSOC"=>2, "MYSQL_NUM"=>3, "MYSQL_BOTH"=>4,
     );
  
     return pdo_stmt($stmt)->fetch(isset($map[$type]) ? $map[$type] : $type);
  }




  /**
   * Get result row.
   * Always an associative array as result.
   *
   */
  function pdo_fetch_assoc($stmt) {
     return pdo_stmt($stmt)->fetch(PDO::FETCH_ASSOC);
  }




  /**
   * Get table attributes/meta for a column.
   * Doesn't match up 1:1.
   *
   * See also http://www.phpcl***es.org/browse/file/47988.html
   * (discovered too late, similar intent except for the class wrapping,
   * the getColumnMeta conversion seems more complete);
   * so maybe lets use _list_fields() / SHOW COLUMNS FROM .. for details
   # Doc ~/php/php-5.5.5/ext/pdo_mysql/mysql_statement.c for PDO types
   *
   */
  function pdo_fetch_field($stmt, $column_id) {
  
     // map meta types to what mysql_fetch_field returned
     $native_map = array(
         "BOOL"=>"bool", "NULL"=>"null", "BLOB"=>"blob",
         "LONG"=>"int", "LONGLONG"=>"int", "BIT"=>"int", "ENUM"=>"int", "DECIMAL"=>"int",
         "VAR_STRING"=>"string", "STRING"=>"string", "VARCHAR"=>"string",
         "YEAR"=>"string",
     );
     $pdo_map = array(
         PDO::PARAM_STR => "string",
         PDO::PARAM_INT => "int",
         PDO::PARAM_BOOL => "bool",
         PDO::PARAM_NULL => "null",
         PDO::PARAM_LOB => "blob",
     );

     // PDO meta field set (no conflicting locals, so extract() will do)
     extract(pdo_stmt($stmt)->getColumnMeta($column_id));
     
     // convert format
     return (object)array(
        "name" => $name,
        "table" => $table,
        "def" => NULL,  // undocumented
        "max_length" => $len,  // PDO reads from ->max_len, but doesn't match up with libmysqls results
        "not_null" => in_array("not_null", $flags),
        "primary_key" => in_array("primary_key", $flags),
        "unique_key" => in_array("unique_key", $flags),
        "multiple_key" => in_array("multiple_key", $flags),
        "numeric" => $native_type == "LONG",
        "blob" => $native_type == "BLOB",
        "type" => isset($native_type) ? $native_map[$native_type] : $pdo_map[$pdo_type],
        "unsigned" => in_array("unsigned", $flags),
        "zerofill" => in_array("zerofill", $flags),
     );
  }




  /**
   * Returns the list of strlen()s for the last result row.
   *
   */
  function pdo_fetch_lengths($stmt) {
  
      // no can do
      if (!PDO_SEEKABLE or !$stmt instanceof PDOStatement_Seekable) {
         pdo_trigger_error("pdo_fetch_lengths() Cannot retrieve the last row to calculate string lengths, no cursor available. Enable PDO_SEEKABLE." . (PDO_HELPFUL ? " Better yet do the field length calculation yourself with <a>array_map('strlen',\$row)</a> on the last pdo_fetch_row()." : ""), E_USER_WARNING);
      }

      // with _Seekable the last row is always cached
      return array_map("strlen", pdo_stmt($stmt)->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_PRIOR));
  }




  /**
   * Get result row as object.
   *
   */
  function pdo_fetch_object($stmt, $classname="stdClass", $params=array()) {
     return pdo_stmt($stmt)->fetchObject($classname, $params);
  }
  



  /**
   * Get result row as indexed list.
   *
   */
  function pdo_fetch_row($stmt) {
     return pdo_stmt($stmt)->fetch(PDO::FETCH_NUM);
  }




  /**
   * _fetch_field() meta data broken up into individual functions.
   *
   */
  function pdo_field_flags($stmt, $col) {
     $meta = pdo_stmt($stmt)->getColumnMeta($col);
     return implode(" ", $meta["flags"]);
  }
  function pdo_field_len($stmt, $col) {
     return pdo_fetch_field($stmt, $col)->max_length;
  }
  function pdo_field_name($stmt, $col) {
     return pdo_fetch_field($stmt, $col)->name;
  }
  function pdo_field_seek($stmt, $col) {
     pdo_trigger_error("pdo_field_seek() Has no effect. Please use the \$col parameter for all pdo_field_*() functions.", E_USER_WARNING);
  }
  function pdo_field_table($stmt, $col) {
     return pdo_fetch_field($stmt, $col)->table;
  }
  function pdo_field_type($stmt, $col) {
     return pdo_fetch_field($stmt, $col)->type;
  }




  /**
   * Unallocating a query result.
   *
   * This call has little practical use.
   * Rather just unset() your pdo_query $result object variables.
   *
   */
  function pdo_free_result($stmt) {
     ###PDO_HELPFUL and trigger_error("pdo_free_result() usage is mostly redundant. PHP cleans up resource handles/objects if you just unset() them, or move out of scope.", E_USER_DEPRECATED);

     // free up some resources
     try {
        pdo_stmt($stmt)->fetchAll();
        pdo_stmt($stmt)->closeCursor();
     }
     catch (PDOException $e) {
        // yeah, let's ignore that
     }

     // unsetting here has no effect on the outer scope
     $stmt = NULL;
  }




  /**
   * Get libmysql/mysqlnd client version.
   *
   */
  function pdo_get_client_info($link=NULL) {
     return pdo_handle($link)->getAttribute(PDO::ATTR_CLIENT_VERSION);
  }




  /**
   * Get Connection: STATUS
   * mostly "Localhost via UNIX socket"
   *
   */
  function pdo_get_host_info($link=NULL) {
     return pdo_handle($link)->getAttribute(PDO::ATTR_CONNECTION_STATUS);
  }
  



  /**
   * MySQL protocol version.
   *
   */
  function pdo_get_proto_info($link=NULL) {
     return pdo_query("SELECT @@protocol_version AS ver", pdo_handle($link))->fetchObject()->ver;
  }




  /**
   * Mysqld/Mariadb server version.
   *
   */
  function pdo_get_server_info($link=NULL) {
     return pdo_query("SELECT VERSION() as version", pdo_handle($link))->fetchObject()->version;
  }




  /**
   * Show last queries.
   *
   * @stub  We don't keep a log currently.
   *
   # See ~/php/php-5.5.5/ext/mysql/php_mysql.c
   # haven't looked up what libmysql does here; presumably PHP keeps the query log
   *
   */
  function pdo_info($link=NULL) {
     return "";
  }




  /**
   * Last inserted ID.
   *
   */
  function pdo_insert_id($link=NULL) {
     return pdo_handle($link)->lastInsertId();
     //pdo_query("SELECT last_insert_id() AS id", $link)->fetchObject()->id;
  }




  /**
   * SHOW DATABASES
   *
   */
  function pdo_list_dbs($link=NULL) {
     return pdo_query("SHOW DATABASES", pdo_handle($link));
  }




  /**
   * Show table definition.
   *
   */
  function pdo_list_fields($dbname, $table, $link=NULL) {
     $dbname = str_replace("`", "``", $dbname);
     $table = str_replace("`", "``", $table);
     return pdo_query("SHOW COLUMNS FROM `$dbname`.`$table`", pdo_handle($link))->fetchAll();
  }




  /**
   * Retrieves the current MySQL server threads.
   *
   */
  function pdo_list_processes($link=NULL) {
     return pdo_query("SHOW FULL PROCESSLIST", pdo_handle($link));
  }




  /**
   * SHOW TABLES result set.
   *
   */
  function pdo_list_tables($dbname, $link=NULL) {
     $dbname = str_replace("`", "``", $dbname);
     return pdo_query("SHOW TABLES FROM `$dbname`", pdo_handle($link));
  }




  /**
   * Number of fields (columns) in the result rows.
   *
   */
  function pdo_num_fields($stmt) {
     return pdo_stmt($stmt)->columnCount();
  }




  /**
   * Amount of results for last SELECT query.
   *
   # See: http://stackoverflow.com/a/883523
   #
   #  * PDOStmt::rowCount() works for UPDATE/INSERT/DELETE,
   #    but also SELECT since pdo_query() sets ::MYSQL_ATTR_FOUND_ROWS then.
   #
   #  * FOUND_ROWS() is a nice alternative,
   #    But only if _num_rows() is called just after the _query() or no
   #    intermediate query was run, no second database connection is open.
   #
   #  * mysql_ did actually use fetchAll()+count()
   #
   */
  function pdo_num_rows($stmt=NULL) {
  
     /* Unsolicited advise; maybe redundant now that there's two fallbacks.
        Users utilizing _num_rows() however are likely to for($i)-iterate over
        the resultset with indexed pdo_result() calls [which won't work].
     */
     //PDO_HELPFUL and pdo_trigger_error("pdo_num_rows() Should be avoided. To get the number of results, instead use \$result->fetchAll() to get the complete row list and just count() it.", E_USER_NOTICE);

     // let's try this anyway
     if ($num = pdo_stmt($stmt)->rowCount()) {
        return $num;
     }
     
     // fallback
     return pdo_query("SELECT FOUND_ROWS() as num")->fetchObject()->num;
  }




  /**
   * Open a persistent PDO connection.
   *
   */
  function pdo_pconnect($server, $user, $pass, $new_link=FALSE, $client_flags=0x0000, $pconnect=0x0000) {
     return pdo_connect($server, $user, $pass, $new_link, $client_flags, $pconnect=TRUE);
  }




  /**
   * Keep connection open.
   * (Doesn't actually do that. But mysqlnd/pdo_mysql implicitly.)
   *
   */
  function pdo_ping($link=NULL) {
     return pdo_query("SELECT 1", pdo_handle($link)) ? true : false;
  }




  /**
   * Run query.
   *
   * Note that this can be invoked with just a SQL string:
   *
   *   pdo_query("SELECT 1,2,3");
   *
   * Or with bound parameters:
   *
   *   pdo_query("SELECT ?,?,?", 1, 2, 3);
   *
   * Or an indexed array of bound parameters:
   *
   *   pdo_query("SELECT :a, :b, :c", $array);
   *
   * And an optional database connection $link either before or after a parameter list:
   *
   *   pdo_query("SELECT 1,?,?", $link, 2, 3);
   *   pdo_query("SELECT 1,?,?", 2, 3, $link);
   *
   */
  function pdo_query($sql, $link=NULL, $params=NULL) {

     // separate params from $sql and $link     
     $params = func_get_args();
     $sql = TRIM( array_shift($params) );
     $flags = array();
     $direct = false;
     

     // find pdo $link     
     if (count($params)) {
        // $link can be the first element
        if (is_object(reset($params))) {
           $link = array_shift($params);
        }
        // or the last
        elseif (is_object(end($params))) {
           $link = array_pop($params);
        }
     }
     // or we use the default $pdo
     $link = pdo_handle($link);

     
     // is $params a list to pdo_query(), or just one array with :key=>value pairs?
     if (count($params)==1 && is_array($params[0])) {
        $params = array_shift($params);
     }


     // add PDO_MySQL driver flag / workaround for specific query types
     switch (strtoupper(substr($sql, 0, strspn(strtoupper($sql), "SELECT,USE,CREATE")))) {

        // ought to make ->rowCount() work
        case "SELECT":
           $flags[PDO::MYSQL_ATTR_FOUND_ROWS] = true;
           break;

        // temporarily disable prepared statement mode for unbindable directives
        case "USE":
           $direct = true;
           $link->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
           #$flags[PDO::MYSQL_ATTR_DIRECT_QUERY] = true; // has no effect as stmt flag, also overwritten by setAttr EMULATE_PREPARES
           break;

        default:
     }
     
     
     // add syntax notices?
     if (PDO_HELPFUL>=2) {
        strpos($sql, "'") and pdo_trigger_error("pdo_query() It looks like you're still using single ' quotes in your SQL. This indicates plain or interpolated strings or variables in SQL context. Investigate if parameter binding `pdo_query(\"SELECT ?, ?\", \$var1, \$var2)` would fit.");
        strpos($sql, '"') and pdo_trigger_error("pdo_query() You are using double \" quotes in your SQL. Beware that this is ambiguous. In MySQLs default mode these indicate interpolated string variables (don't do that, use bound parameters), while in MySQL ANSI mode they quote identifiers (table or column name).");
     }


     // unparameterized query()
     if ($direct) {
        $stmt = $link->query($sql);
        $link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
     }
     // or prepare() and execute()
     else {
        if ($stmt = $link->prepare($sql, $flags)) {   // no try-catch in _WARNING mode
           $stmt->execute($params);
        }
     }

     
     // result
     if (!$stmt and PDO_HELPFUL) {
        pdo_trigger_error("pdo_query() SQL query failed, see pdo_error()", E_USER_WARNING);
     }
     elseif (PDO_SEEKABLE & !$direct) {
        return new PDOStatement_Seekable($stmt, $params);
     }
     else {
        return $stmt;
     }
  }




  /**
   * Escape *strings* for use in SQL context.
   *
   * Note that you still need to enclose string values in 'single quotes' when
   * interpolating/concatenating it into queries.
   *
   * And you shouldn't keep using this function, if you already use ? placeholders
   * with separate value parameters to pdo_query().
   *
   */
  function pdo_real_escape_string($str, $link=NULL) {
     return substr(pdo_handle($link)->quote($str), 1, -1);
  }




  /**
   * Return one field from a result row.
   *
   */
  function pdo_result($stmt, $row, $field=0) {
  
     // Scroll to and retrieve the given $row (maybe it's buffered even)
     if (PDO_SEEKABLE) {
        $rows = array(
           $row => pdo_stmt($stmt)->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_ABS, $row)
        );
     }
     
     // workaround: fetch everything, works just once
     else {
        pdo_trigger_error("pdo_result() Can currently only be used once, for fetching a value from the first \$row. Scrolling only works with PDO_SEEKABLE enabled.", E_USER_WARNING);

        $rows = pdo_stmt($stmt)->fetchAll(PDO::FETCH_BOTH);
        #static $rows[hash(stmt)]; //would otherwise bind the result set here
     }

     
     // check if found
     if (isset($rows[$row][$field])) {
        return $rows[$row][$field];
     }
     else {
        pdo_trigger_error("pdo_result() Couldn't find row [$row] and column `$field`.");
     }
     
  }




  /**
   * USE database_name;
   *
   */
  function pdo_select_db($dbname, $link=NULL) {
     $dbname = str_replace("`", "``", $dbname);
     return (bool)pdo_query("USE `$dbname`", pdo_handle($link));
  }


  
  
  /**
   * Set charset used for strings from client, in transport, and for result data.
   *
   */
  function pdo_set_charset($charset, $link=NULL) {
     $charset = pdo_handle($link)->quote($charset);
     return (bool)pdo_query("SET NAMES $charset", pdo_handle($link));
  }




  /**
   * Return server status and some settings.
   *
   * @requires: php (>= 5.5) | upgradephp
   */
  function pdo_stat() {
     return array_column(pdo_query("SHOW STATUS")->fetchAll(), "Value", "Variable_name");
  }




  /**
   * SHOW TABLES [$i] after pdo_list_tables()
   *
   */
  function pdo_tablename($stmt, $i) {
     return pdo_result($stmt, $i, 0);
  }




  /**
   * Returns the connection/thread ID.
   * It's unique among all connected clients.
   *
   */
  function pdo_thread_id($link=NULL) {
     return pdo_query("SELECT connection_id() AS id", pdo_handle($link))->fetchObject()->id;
  }




  /**
   * Switch to unbuffered mode before issuing SQL query.
   *
   */
  function pdo_unbuffered_query($sql, $link=NULL, $params=NULL) {
  
     // find optional $link param
     $params = func_get_args();
     $link = array_filter($params, "is_object");
     $link = pdo_handle($link ? reset($link) : NULL);
     $link->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
     
     // invoke real pdo_query()
     $result = call_user_func_array("pdo_query", $params);

     // reset to buffered mode
     $link->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
     
     // done
     return $result;
  }






  ##############################  helper functions  #############################



  
  /**
   * Determine if to use the current PDO $link, or the last used handle
   * which is kept in global `$pdo`;
   *
   */
  function pdo_handle($link, $connect=0) {
     global $pdo;

     // got a PDO handle as parameter already
     if (is_object($link)) {

        // implicitly update
        if ($connect && !is_a($link, "pdo_dummy")) {
           $pdo = $link;
        }
     }
     
     // last used handle
     elseif (isset($pdo) && is_object($pdo)) {
        $link = $pdo;
     }
     
     // not connected yet
     else {
        $link = new pdo_dummy("You don't have an open database connection, but tried to invoke a call anyway.");
     }

     return $link;
  }




  /**
   * Check if statement (result handle) is usable.
   *
   */
  function pdo_stmt($stmt) {

     if (is_object($stmt)) {
        return $stmt;
     }
     else {
        return new pdo_dummy("Your last query was unsuccessful and returned FALSE instead of a fetchable result. See pdo_error() to find out why.");
     }
  }


  
  
  /**
   * Error messages.
   *
   * Augments the actual origin path/filename and linenumber.
   * Adds some HTML prettyfication.
   *
   */
  function pdo_trigger_error($msg, $level=E_USER_NOTICE) {

     // locate source of last pdo_*() invocation
     foreach ((debug_backtrace()) as $src) {
     
        // skip any functions in the current file
        if (empty($src["file"])) {
           $src["file"] = "{main}";
           $src["line"] = "-";
        }
        if ($src["file"] != __FILE__) {
           $dir = dirname($src["file"]);
           $file = basename($src["file"]);
           $msg .= " - caused by $dir/<b>$file</b>, line <b>$src[line]</b>, when calling <a>$src[function]()</a>;";
           break;
        }
     }
     
     // pass on to actual error handler chain
     trigger_error($msg, (($level == 1<<14) && (PHP_VERSION < 5.3)) ? E_USER_NOTICE : $level);
  }



  /**
   * Provide userland faux cursor support. Simply refetches query results
   * for out-of-order seeking. It also implements a configurable-sized
   * cache, but per default just keeps the last row. (PDO_SEEKABLE can be
   * an integer to define the cache length).
   *
   */
  class PDOStatement_Seekable implements Iterator {

     // the actual PDOStatement
     private $stmt = NULL;
     // bound parameters for reexecution
     private $params = array();

     // row cursor
     private $i = -1;
     // available max key / rowcount
     private $max;
     // last fetched rows
     private $cache = array();


     // keep proxied PDOStatement and data necessary to rerun it
     function __construct($stmt, $params) {
        $this->stmt = $stmt;
        $this->params = $params;
        $this->max = $stmt->rowCount(/*PDO::MYSQL_ATTR_FOUND_ROWS*/) - 1;
     }


     // invoke wrapped PDOStatement
     function __call($func, $args) {
        return call_user_func_array(array($this->stmt, $func), $args);
     }


     // repopulate PDOStatement, reset cache and cursor
     function execute($params = NULL) {
        # Superposes the actual stmt::execute(), in case it's really a new query.
        # Note that rewinding also has to reset the cache, in case the table
        # contents changed meanwhile. So may result in a different set of result
        # rows alltogether. Which is really not wanted since this is all just
        # meant for seeking. (No way around that in a userland faux cursor.)
        $this->stmt->execute($params ? $params : $this->params);
        $this->max = $stmt->rowCount(/*PDO::MYSQL_ATTR_FOUND_ROWS*/) - 1;
        $this->i = -1;   // last fetched row
        $this->cache = array();
     }


     // fetch a single row
     function fetch($type=PDO::FETCH_ASSOC, $ori=PDO::FETCH_ORI_NEXT, $offset=0) {


        // calculate offset
        $last = & $this->i;
        $target = array(                                    
            PDO::FETCH_ORI_NEXT => $last + 1,
            PDO::FETCH_ORI_PRIOR => $last,
            PDO::FETCH_ORI_REL => $last + $offset,
            PDO::FETCH_ORI_FIRST => -1,
            PDO::FETCH_ORI_LAST => $this->max,
            PDO::FETCH_ORI_ABS => $offset,
        );
        $target = $target[$ori];
#print "seek($last->$target) ";

        
        // last row? got that covered!
        if (isset($this->cache[$target])) {
#print "seek(==) ";
            return $this->rowType($type, $this->cache[$target]);
        }
        

        // moving farther backwards
        if ($target < $last) {
#print "seek(<<) ";
            $this->execute();
        }

        
        // jump forwards
        while ($target > $last + 1) {
#print "seek(>>) ";
            $row = $this->stmt->fetch(PDO::FETCH_ASSOC);
            $last++;
            if (!$row) {
               return pdo_trigger_error("PDOStatement_Seekable::fetch() Scrolling past last row.", E_USER_WARNING) and $row;
            }
        }


        // actually fetch next row
        if ($row = $this->stmt->fetch(PDO::FETCH_ASSOC)) {
#print "seek(ft) ";
           assert($target == ++$last);
           // keep last row(s)
           if (count($this->cache) > PDO_SEEKABLE) {
              $this->cache = array_slice($this->cache, $last, - PDO_SEEKABLE, true);
           }
           $this->cache[$last] = $row;
        }
        return $this->rowType($type, $row);
     }


     // convert associative array to requested type
     function rowType($type, $row) {
        switch ($row ? $type : false) {
           case             false: return false;
           case    PDO::FETCH_NUM: return array_values($row);
           case   PDO::FETCH_BOTH: return array_merge($row, array_values($row));
           case  PDO::FETCH_ASSOC: return $row;
           case PDO::FETCH_OBJECT: return (object)$row;
        }
     }
     

     // Iterator handling
     function current() {
        return $this->fetch();
     }
     function rewind() {
        if ($this->i >= 0) {
           $this->execute();
        }
     }
     // PDOStatement itself implements just Traversable internally, not Iterator, so we have to handle the keys ourselves
     function key() {
        return $this->i >= 0 ? $this->i : NULL;
     }
     function next() {
        return $this->i + 1;
     }
     function valid() {
        return $this->i < $this->max;
     }


     # fetchAll
     # fetchObject
  }

  

  /**
   * For dummy PDO instances, to avoid fatal Call-to-member-function-on-non-object errors.
   *
   */
  class pdo_dummy {
  
     /**
      * Catch any ->prepare, ->quote, etc. calls when no proper PDO connection
      * or PDOStatement was passed.
      *
      */
     function __call($func, $args) {
        pdo_trigger_error("pdo_dummy::{$func}() {$this->msg}", E_USER_WARNING);
     }

     /**
      * Concretise error message.
      *
      */     
     public $msg;
     function __construct($msg = "You passed an invalid database or result handle..") {
        $this->msg = $msg;
     }
  
  }




  /**
   * Instantiate a placeholder until pdo_connect() was called.
   *
   */
  global $pdo;

  if (!isset($pdo) || !is_object($pdo)) {
     $pdo = new pdo_dummy("You haven't opened a pdo_connect() handle yet.");
  }  // pdo_handle() takes care already, but we could concretise the help message here



}




/**
 * Fallback code for absent/compiled-out mysql_ extension itself.
 * Should PHP 5.7/5.8 remove ext/mysql as surmised, we can just alias
 * the new pdo_* functions back onto mysql_*.
 * Though such unchanged codebases don't benefit from the more flexible
 * function signature / bound params then.
 *
 */
if (!function_exists("mysql_query")) {

   // autogenerated via ReflectionFunction (parameter properties unknown for internal functions)
   function mysql_connect($hostname=NULL, $username=NULL, $password=NULL, $new=NULL, $flags=NULL) { return pdo_connect(func_get_args()); }
   function mysql_pconnect($hostname=NULL, $username=NULL, $password=NULL, $flags=NULL) { return pdo_pconnect(func_get_args()); }
   function mysql_close($link_identifier=NULL) { return pdo_close(func_get_args()); }
   function mysql_select_db($database_name=NULL, $link_identifier=NULL) { return pdo_select_db(func_get_args()); }
   function mysql_query($query=NULL, $link_identifier=NULL) { return pdo_query(func_get_args()); }
   function mysql_unbuffered_query($query=NULL, $link_identifier=NULL) { return pdo_unbuffered_query(func_get_args()); }
   function mysql_db_query($database_name=NULL, $query=NULL, $link_identifier=NULL) { return pdo_db_query(func_get_args()); }
   function mysql_list_dbs($link_identifier=NULL) { return pdo_list_dbs(func_get_args()); }
   function mysql_list_tables($database_name=NULL, $link_identifier=NULL) { return pdo_list_tables(func_get_args()); }
   function mysql_list_fields($database_name=NULL, $table_name=NULL, $link_identifier=NULL) { return pdo_list_fields(func_get_args()); }
   function mysql_list_processes($link_identifier=NULL) { return pdo_list_processes(func_get_args()); }
   function mysql_error($link_identifier=NULL) { return pdo_error(func_get_args()); }
   function mysql_errno($link_identifier=NULL) { return pdo_errno(func_get_args()); }
   function mysql_affected_rows($link_identifier=NULL) { return pdo_affected_rows(func_get_args()); }
   function mysql_insert_id($link_identifier=NULL) { return pdo_insert_id(func_get_args()); }
   function mysql_result($result=NULL, $row=NULL, $field=NULL) { return pdo_result(func_get_args()); }
   function mysql_num_rows($result=NULL) { return pdo_num_rows(func_get_args()); }
   function mysql_num_fields($result=NULL) { return pdo_num_fields(func_get_args()); }
   function mysql_fetch_row($result=NULL) { return pdo_fetch_row(func_get_args()); }
   function mysql_fetch_array($result=NULL, $result_type=NULL) { return pdo_fetch_array(func_get_args()); }
   function mysql_fetch_assoc($result=NULL) { return pdo_fetch_assoc(func_get_args()); }
   function mysql_fetch_object($result=NULL, $class_name=NULL, $ctor_params=NULL) { return pdo_fetch_object(func_get_args()); }
   function mysql_data_seek($result=NULL, $row_number=NULL) { return pdo_data_seek(func_get_args()); }
   function mysql_fetch_lengths($result=NULL) { return pdo_fetch_lengths(func_get_args()); }
   function mysql_fetch_field($result=NULL, $field_offset=NULL) { return pdo_fetch_field(func_get_args()); }
   function mysql_field_seek($result=NULL, $field_offset=NULL) { return pdo_field_seek(func_get_args()); }
   function mysql_free_result($result=NULL) { return pdo_free_result(func_get_args()); }
   function mysql_field_name($result=NULL, $field_index=NULL) { return pdo_field_name(func_get_args()); }
   function mysql_field_table($result=NULL, $field_offset=NULL) { return pdo_field_table(func_get_args()); }
   function mysql_field_len($result=NULL, $field_offset=NULL) { return pdo_field_len(func_get_args()); }
   function mysql_field_type($result=NULL, $field_offset=NULL) { return pdo_field_type(func_get_args()); }
   function mysql_field_flags($result=NULL, $field_offset=NULL) { return pdo_field_flags(func_get_args()); }
   function mysql_escape_string($string=NULL) { return pdo_escape_string(func_get_args()); }
   function mysql_real_escape_string($string=NULL, $link_identifier=NULL) { return pdo_real_escape_string(func_get_args()); }
   function mysql_stat($link_identifier=NULL) { return pdo_stat(func_get_args()); }
   function mysql_thread_id($link_identifier=NULL) { return pdo_thread_id(func_get_args()); }
   function mysql_client_encoding($link_identifier=NULL) { return pdo_client_encoding(func_get_args()); }
   function mysql_ping($link_identifier=NULL) { return pdo_ping(func_get_args()); }
   function mysql_get_client_info() { return pdo_get_client_info(func_get_args()); }
   function mysql_get_host_info($link_identifier=NULL) { return pdo_get_host_info(func_get_args()); }
   function mysql_get_proto_info($link_identifier=NULL) { return pdo_get_proto_info(func_get_args()); }
   function mysql_get_server_info($link_identifier=NULL) { return pdo_get_server_info(func_get_args()); }
   function mysql_info($link_identifier=NULL) { return pdo_info(func_get_args()); }
   function mysql_set_charset($charset_name=NULL, $link_identifier=NULL) { return pdo_set_charset(func_get_args()); }
   function mysql_fieldname($result=NULL, $field_index=NULL) { return pdo_fieldname(func_get_args()); }
   function mysql_fieldtable($result=NULL, $field_offset=NULL) { return pdo_fieldtable(func_get_args()); }
   function mysql_fieldlen($result=NULL, $field_offset=NULL) { return pdo_fieldlen(func_get_args()); }
   function mysql_fieldtype($result=NULL, $field_offset=NULL) { return pdo_fieldtype(func_get_args()); }
   function mysql_fieldflags($result=NULL, $field_offset=NULL) { return pdo_fieldflags(func_get_args()); }
   function mysql_selectdb($database_name=NULL, $link_identifier=NULL) { return pdo_selectdb(func_get_args()); }
   function mysql_freeresult($result=NULL) { return pdo_freeresult(func_get_args()); }
   function mysql_numfields($result=NULL) { return pdo_numfields(func_get_args()); }
   function mysql_numrows($result=NULL) { return pdo_numrows(func_get_args()); }
   function mysql_listdbs($link_identifier=NULL) { return pdo_listdbs(func_get_args()); }
   function mysql_listtables($database_name=NULL, $link_identifier=NULL) { return pdo_listtables(func_get_args()); }
   function mysql_listfields($database_name=NULL, $table_name=NULL, $link_identifier=NULL) { return pdo_listfields(func_get_args()); }
   function mysql_db_name($result=NULL, $row=NULL, $field=NULL) { return pdo_db_name(func_get_args()); }
   function mysql_dbname($result=NULL, $row=NULL, $field=NULL) { return pdo_dbname(func_get_args()); }
   function mysql_tablename($result=NULL, $row=NULL, $field=NULL) { return pdo_tablename(func_get_args()); }
   function mysql_table_name($result=NULL, $row=NULL, $field=NULL) { return pdo_table_name(func_get_args()); }

   // and the few constants
   define("MYSQL_ASSOC", 1);
   define("MYSQL_NUM", 2);
   define("MYSQL_BOTH", 3);
   define("MYSQL_CLIENT_COMPRESS", 32);
   define("MYSQL_CLIENT_SSL", 2048);
   define("MYSQL_CLIENT_INTERACTIVE", 1024);
   define("MYSQL_CLIENT_IGNORE_SPACE", 256);
                            
}


?>

Added ext/contrib/php4_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/php5_clone.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/register_long_arrays.php.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
/**
 *
 * Manual register_long_arrays workaround to keep older scripts
 * running. Contributed by Pavel Titov.
 *
 */

if (!isset($HTTP_SERVER_VARS)) {
  $HTTP_SERVER_VARS = $_SERVER;
  $HTTP_POST_VARS = $_POST;
  $HTTP_ENV_VARS = $_ENV;
  $HTTP_GET_VARS = $_GET;
  $HTTP_COOKIE_VARS = $_COOKIES;
  $HTTP_SESSION_VARS = $_SESSION;
  $HTTP_POST_FILES = $_FILES;
}

?>

Added ext/contrib/serialize.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
<?php
/*
 * @author anthon (dpt) pang (at) gmail (dot) com
 * @license Public Domain
 */

/*
 * Used to impose practical limits for safe_unserialize()
 */
define('MAX_SERIALIZED_INPUT_LENGTH', 4096);
define('MAX_SERIALIZED_ARRAY_LENGTH', 256);
define('MAX_SERIALIZED_ARRAY_DEPTH', 3);


/**
 * safe_serialize implementation
 *
 * @param mixed $value
 * @return string
 * @throw Exception if $value is malformed or contains unsupported types (e.g., resources, objects)
 */
function _safe_serialize( $value )
{
	if(is_null($value))
	{
		return 'N;';
	}
	if(is_bool($value))
	{
		return 'b:'.(int)$value.';';
	}
	if(is_int($value))
	{
		return 'i:'.$value.';';
	}
	if(is_float($value))
	{
		return 'd:'.$value.';';
	}
	if(is_string($value))
	{
		return 's:'.strlen($value).':"'.$value.'";';
	}
	if(is_array($value))
	{
		$out = '';
		foreach($value as $k => $v)
		{
			$out .= _safe_serialize($k) . _safe_serialize($v);
		}
		
		return 'a:'.count($value).':{'.$out.'}';
	}
	if(is_resource($value))
	{
		// built-in returns 'i:0;'
		throw new Exception('safe_serialize: resources not supported');
	}
	if(is_object($value) || gettype($value) == 'object')
	{
		throw new Exception('safe_serialize: objects not supported');
	}
	throw new Exception('safe_serialize cannot serialize: '.gettype($value));
}

/**
 * Safe serialize() replacement
 * - output a strict subset of PHP's native serialized representation
 *
 * @param mixed $value
 * @return string
 */
function safe_serialize( $value )
{
	// ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen()
	if (function_exists('mb_internal_encoding') &&
		(((int) ini_get('mbstring.func_overload')) & 2))
	{
		$mbIntEnc = mb_internal_encoding();
		mb_internal_encoding('ASCII');
	}

	try {
		$out = _safe_serialize($value);
	} catch(Exception $e) {
		$out = false;
	}

	if (isset($mbIntEnc))
	{
		mb_internal_encoding($mbIntEnc);
	}
	return $out;
}

/**
 * safe_unserialize implementation
 *
 * @param string $str
 * @return mixed
 * @throw Exception if $str is malformed or contains unsupported types (e.g., resources, objects)
 */
function _safe_unserialize($str)
{
	if(strlen($str) > MAX_SERIALIZED_INPUT_LENGTH)
	{
		throw new Exception('safe_unserialize: input exceeds ' . MAX_SERIALIZED_INPUT_LENGTH);
	}

	if(empty($str) || !is_string($str))
	{
		return false;
	}

	$stack = array();
	$expected = array();
	$state = 0;

	while($state != 1)
	{
		$type = isset($str[0]) ? $str[0] : '';

		if($type == '}')
		{
			$str = substr($str, 1);
		}
		else if($type == 'N' && $str[1] == ';')
		{
			$value = null;
			$str = substr($str, 2);
		}
		else if($type == 'b' && preg_match('/^b:([01]);/', $str, $matches))
		{
			$value = $matches[1] == '1' ? true : false;
			$str = substr($str, 4);
		}
		else if($type == 'i' && preg_match('/^i:(-?[0-9]+);(.*)/s', $str, $matches))
		{
			$value = (int)$matches[1];
			$str = $matches[2];
		}
		else if($type == 'd' && preg_match('/^d:(-?[0-9]+\.?[0-9]*(E[+-][0-9]+)?);(.*)/s', $str, $matches))
		{
			$value = (float)$matches[1];
			$str = $matches[3];
		}
		else if($type == 's' && preg_match('/^s:([0-9]+):"(.*)/s', $str, $matches) && substr($matches[2], (int)$matches[1], 2) == '";')
		{
			$value = substr($matches[2], 0, (int)$matches[1]);
			$str = substr($matches[2], (int)$matches[1] + 2);
		}
		else if($type == 'a' && preg_match('/^a:([0-9]+):{(.*)/s', $str, $matches) && $matches[1] < MAX_SERIALIZED_ARRAY_LENGTH)
		{
			$expectedLength = (int)$matches[1];
			$str = $matches[2];
		}
		else if($type == 'O')
		{
			throw new Exception('safe_unserialize: objects not supported');
		}
		else
		{
			throw new Exception('safe_unserialize: unknown/malformed type: '.$type);
		}

		switch($state)
		{
			case 3: // in array, expecting value or another array
				if($type == 'a')
				{
					if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH)
					{
						throw new Exception('safe_unserialize: array nesting exceeds ' . MAX_SERIALIZED_ARRAY_DEPTH);
					}

					$stack[] = &$list;
					$list[$key] = array();
					$list = &$list[$key];
					$expected[] = $expectedLength;
					$state = 2;
					break;
				}
				if($type != '}')
				{
					$list[$key] = $value;
					$state = 2;
					break;
				}

				throw new Exception('safe_unserialize: missing array value');

			case 2: // in array, expecting end of array or a key
				if($type == '}')
				{
					if(count($list) < end($expected))
					{
						throw new Exception('safe_unserialize: array size less than expected ' . $expected[0]);
					}

					unset($list);
					$list = &$stack[count($stack)-1];
					array_pop($stack);

					// go to terminal state if we're at the end of the root array
					array_pop($expected);
					if(count($expected) == 0) {
						$state = 1;
					}
					break;
				}
				if($type == 'i' || $type == 's')
				{
					if(count($list) >= MAX_SERIALIZED_ARRAY_LENGTH)
					{
						throw new Exception('safe_unserialize: array size exceeds ' . MAX_SERIALIZED_ARRAY_LENGTH);
					}
					if(count($list) >= end($expected))
					{
						throw new Exception('safe_unserialize: array size exceeds expected length');
					}

					$key = $value;
					$state = 3;
					break;
				}

				throw new Exception('safe_unserialize: illegal array index type');

			case 0: // expecting array or value
				if($type == 'a')
				{
					if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH)
					{
						throw new Exception('safe_unserialize: array nesting exceeds ' . MAX_SERIALIZED_ARRAY_DEPTH);
					}

					$data = array();
					$list = &$data;
					$expected[] = $expectedLength;
					$state = 2;
					break;
				}
				if($type != '}')
				{
					$data = $value;
					$state = 1;
					break;
				}

				throw new Exception('safe_unserialize: not in array');
		}
	}

	if(!empty($str))
	{
		throw new Exception('safe_unserialize: trailing data in input');
	}
	return $data;
}

/**
 * Safe unserialize() replacement
 * - accepts a strict subset of PHP's native serialized representation
 *
 * @param string $str
 * @return mixed
 */
function safe_unserialize( $str )
{
	// ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen()
	if (function_exists('mb_internal_encoding') &&
		(((int) ini_get('mbstring.func_overload')) & 2))
	{
		$mbIntEnc = mb_internal_encoding();
		mb_internal_encoding('ASCII');
	}

	try {
		$out = _safe_unserialize($str);
	} catch(Exception $e) {
		$out = '';
	}

	if (isset($mbIntEnc))
	{
		mb_internal_encoding($mbIntEnc);
	}
	return $out;
}

?>

Added ext/contrib/setcookie2.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

 
/**
 * Set-Cookie2 support, with a workaround for headers_sent.
 * Originally a rejected patch http://marc.info/?l=php-internals&m=118802375714734
 * Kind of redundant, since none of the current browsers seems to support it.
 *
 */
if (!function_exists("setcookie2")) {
   function setcookie2($name, $value="", $maxage=NULL, $comment=NULL, $commenturl=NULL, $path=NULL, $domain=NULL, $portlist=NULL, $secure=NULL, $httponly=NULL, $version=1) {

       if (strpbrk($name.$value, "\r\n\000\013\014")) {
           trigger_error("Invalid control characters in cookie name or value", E_USER_WARNING);
       }
       else {
           extract(array_map("urlencode", get_defined_vars()));
           $cookie = "$name=$value"
                   . ($maxage	? "; maxage=".intval($maxage)		: "")
                   . ($comment	? "; comment=\"$comment\""		: "")
                   .($commenturl? "; commenturl=\"$commenturl\""	: "")
                   . ($path	? "; path=\"$path\""			: "")
                   . ($domain	? "; domain=$domain"			: "")
                   . ($portlist	? "; portlist=\"$portlist\""		: "")
                   . ($secure	? "; secure"				: "")
                   . ($httponly	? "; httponly"				: "")
                   . ($version	? "; version=".intval($version)		: "");
           if (!headers_sent() || strstr(ini_get("defalt_mimetype"), "+xml")) {
               header("Set-Cookie2: $cookie");
           }
           else {
               trigger_error("Headers already sent. Using a meta http-equiv workaround", E_USER_NOTICE);
               print "<meta http-equiv=\"Set-Cookie2\" content=\"" . htmlspecialchars($cookie, ENT_QUOTES, "UTF-8") . "\">";
           }
       }
   }
}


Changes to ext/ctype.php.

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
   }
   function ctype_print($text) {
      return ctype_punct($text) && ctype_graph($text);
   }

}


/***<old>

#-- simple char-by-char comparisions
if (!function_exists("ctype_alnum")) {


   #-- true if string is made of letters and digits only
   function ctype_alnum($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = ord($text{$i});
         $r = $r and (
                ($c>=65) && ($c<=90)    // A-Z
             or ($c>=97) && ($c<=122)   // a-z
             or ($c>=48) && ($c<=59)    // 0-9
             or ($c>=192)          // Latin-1 letters
         );
      }
      return($r);
   }


   #-- only letters in given string
   function ctype_alpha($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = ord($text{$i});
         $r = $r and (
                ($c>=65) && ($c<=90)    // A-Z
             or ($c>=97) && ($c<=122)   // a-z
             or ($c>=192)          // Latin-1 letters
         );
      }
      return($r);
   }


   #-- only numbers in string
   function ctype_digit($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = ord($text{$i});
         $r = $r and ($c>=48) && ($c<=59);   // 0-9
      }
      return($r);
   }


   #-- hexadecimal numbers only
   function ctype_xdigit($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = ord($text{$i});
         $r = $r and (
                ($c>=48) && ($c<=59)    // 0-9
             or ($c>=65) && ($c<=70)    // A-F
             or ($c>=97) && ($c<=102)   // a-f
         );
      }
      return($r);
   }


   #-- hexadecimal numbers only
   function ctype_cntrl($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = ord($text{$i});
         $r = $r and ($c < 32);
      }
      return($r);
   }


   #-- hexadecimal numbers only
   function ctype_space($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = $text{$i};
         $r = $r and (
              ($c == " ") or ($c == "\240")
           or ($c == "\n") or ($c == "\r")
           or ($c == "\t") or ($c == "\f")
         );
      }
      return($r);
   }


   #-- all-uppercase
   function ctype_upper($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = ord($text{$i});
         $r = $r and (
                ($c>=65) && ($c<=90)    // A-Z
             or ($c>=192) && ($c<=223)  // Latin-1 letters
         );
      }
      return($r);
   }


   #-- all-lowercase
   function ctype_lower($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = ord($text{$i});
         $r = $r and (
                ($c>=97) && ($c<=122)   // a-z
             or ($c>=224) && ($c<=255)  // Latin-1 letters
         );
      }
      return($r);
   }


   #-- everything except spaces that produces a valid printable output
   #   (this probably excludes contral chars as well)
   function ctype_graph($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = ord($text{$i});
         $r = $r
           and ($c>=33)
           and ($c!=160)
           and (($c<=126) or ($c>=161));
      }
      return($r);
   }


   #-- everything printable, but no spaces+letters+digits
   function ctype_punct($text) {
      $r = true;
      for ($i=0; $i<strlen($text); $i++) {
         $c = ord($text{$i});
         $r = $r and (
                ($c>=33) && ($c<=47)   // !../
             or ($c>=58) && ($c<=64)   // :..@
             or ($c>=91) && ($c<=96)   // [..`
             or ($c>=123) && ($c<=126) // {..~
             or ($c>=161) && ($c<=191) // Latin-1 everything else
         );
      }
      return($r);
   }



//   - no idea what this means exactly
//
//   function ctype_print($text) {
//   }


}


</old>***/

?>







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

41
42
43
44
45
46
47


































































































































































48
   }
   function ctype_print($text) {
      return ctype_punct($text) && ctype_graph($text);
   }

}



































































































































































?>

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"));
   }

}


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


























































































































Deleted ext/exotic.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
<?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)
#   (you should use the PHP_Compat implementation of this preferably)
if (!function_exists("php_strip_whitespace")) {
   function php_strip_whitespace($fn) {
      // alternatives would be using te tokenizer or
      // some regexs to strip unwanted content parts
      // (PEAR::PHP_Compat simply calls the tokenizer)
      $fn = escapeshellcmd($fn);
      $text = `php -wqCf '$fn'`;
      if (!$text) {
         $text = implode("", file($fn));
      }
      return $text;
   }
}


#-- invocates PHP interpreter to do the syntax check (nothing else can do)
#   (you should use the PHP_Compat implementation of this preferably)
if (!function_exists("php_check_syntax")) {
   function php_check_syntax($fn) {
      $args = func_get_args();
      if (count($args)>1) {
         $result = & $args[1];
      }
      $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) . "  ";
         
         #-- function name
         if (isset($info["class"])) {
            echo "$info[class]::";
         }
         if (isset($info["object"])) {
            echo "\$$info[object]->";
         }
         echo "$info[function]";
         
         #-- args
         echo "(";
         foreach ($info["args"] as $a) {
            echo str_replace("\n", "", var_export($a, 1)) . ", ";
         }
         echo ")";
         
         #-- caller
         echo " called at [";
         if ($info["file"]) {
            echo $info["file"] . ":" . $info["line"];
         }
         else {
            echo "unknown_location";
         }
         echo "]\n";
      }
   }
}


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




































































































































































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.



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


















































































































Deleted ext/mime.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
<?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) {

      static $mime_magic_data;

      #-- fallback
      $type = false;

      #-- read in first 3K of given file
      if (is_dir($fn)) {
         return("httpd/unix-directory");
      }
      elseif (is_resource($fn) || ($fn = @fopen($fn, "rb"))) {
         $bin = fread($fn, $maxlen=3072);
         fclose($fn);
      }
      elseif (!file_exists($fn)) {
         return false;
      }
      else {
         return("application/octet-stream");   // give up
      }

      #-- use PECL::fileinfo when available
      if (function_exists("finfo_buffer")) {
         if (!isset($mime_magic_data)) {
            $mime_magic_data = finfo_open(MAGIC_MIME);
         }
         $type = finfo_buffer($bin);
         return($type);
      }
      
      #-- read in magic data, when called for the very first time
      if (!isset($mime_content_type)) {
      
         if ((file_exists($fn = ini_get("mime_magic.magicfile")))
          or (file_exists($fn = "/usr/share/misc/magic.mime"))
          or (file_exists($fn = "/etc/mime-magic"))   )
         {
            $mime_magic_data = array();

            #-- read in file
            $f = fopen($fn, "r");
            $fd = fread($f, 1<<20);
            fclose($f);
            $fd = str_replace("       ", "\t", $fd);

            #-- look at each entry
            foreach (explode("\n", $fd) as $line) {

               #-- skip empty lines
               if (!strlen($line) or ($line[0] == "#") or ($line[0] == "\n")) {
                  continue;
               }

               #-- break into four fields at tabs
               $l = preg_split("/\t+/", $line);
               @list($pos, $typestr, $magic, $ct) = $l;
#print_r($l);

               #-- ignore >continuing lines
               if ($pos[0] == ">") {
                  continue;
               }
               #-- real mime type string?
               $ct = strtok($ct, " ");
               if (!strpos($ct, "/")) {
                  continue;
               }

               #-- mask given?
               $mask = 0;
               if (strpos($typestr, "&")) {
                  $typestr = strtok($typestr, "&");
                  $mask = strtok(" ");
                  if ($mask[0] == "0") {
                     $mask = ($mask[1] == "x") ? hexdec(substr($mask, 2)) : octdec($mask);
                  }
                  else {
                     $mask = (int)$mask;
                  }
               }

               #-- strip prefixes
               if ($magic[0] == "=") {
                  $magic = substr($magic, 1);
               }

               #-- convert type
               if ($typestr == "string") {
                  $magic = stripcslashes($magic);
                  $len = strlen($magic);
                  if ($mask) { 
                     continue;
                  }
               }
               #-- numeric values
               else {

                  if ((ord($magic[0]) < 48) or (ord($magic[0]) > 57)) {
#echo "\nmagicnumspec=$line\n";
#var_dump($l);
                     continue;  #-- skip specials like  >, x, <, ^, &
                  }

                  #-- convert string representation into int
                  if ((strlen($magic) >= 4) && ($magic[1] == "x")) {
                     $magic = hexdec(substr($magic, 2));
                  }
                  elseif ($magic[0]) {
                     $magic = octdec($magic);
                  }
                  else {
                     $magic = (int) $magic;
                     if (!$magic) { continue; }   // zero is not a good magic value anyhow
                  }

                  #-- different types               
                  switch ($typestr) {

                     case "byte":
                        $len = 1;
                        break;
                        
                     case "beshort":
                        $magic = ($magic >> 8) | (($magic & 0xFF) << 8);
                     case "leshort":
                     case "short":
                        $len = 2;
                        break;
                     
                     case "belong":
                        $magic = (($magic >> 24) & 0xFF)
                               | (($magic >> 8) & 0xFF00)
                               | (($magic & 0xFF00) << 8)
                               | (($magic & 0xFF) << 24);
                     case "lelong":
                     case "long":
                        $len = 4;
                        break;

                     default:
                        // date, ldate, ledate, leldate, beldate, lebelbe...
                        continue;
                  }
               }
               
               #-- add to list
               $mime_magic_data[] = array($pos, $len, $mask, $magic, trim($ct));
            }
         }
#print_r($mime_magic_data);
      }
      
      
      #-- compare against each entry from the mime magic database
      foreach ($mime_magic_data as $def) {

         #-- entries are organized as follows
         list($pos, $len, $mask, $magic, $ct) = $def;
         
         #-- ignored entries (we only read first 3K of file for opt. speed)
         if ($pos >= $maxlen) {
            continue;
         }

         $slice = substr($bin, $pos, $len);
         #-- integer comparison value
         if ($mask) {
            $value = hexdec(bin2hex($slice));
            if (($value & $mask) == $magic) {
               $type = $ct;
               break;
            }
         }
         #-- string comparison
         else {
            if ($slice == $magic) {
               $type = $ct;
               break;
            }
         }
      }// foreach
      
      #-- built-in defaults
      if (!$type) {
      
         #-- some form of xml
         if (strpos($bin, "<"."?xml ") !== false) {
            return("text/xml");
         }
         #-- html
         elseif ((strpos($bin, "<html>") !== false) || (strpos($bin, "<HTML>") !== false)
         || strpos($bin, "<title>") || strpos($bin, "<TITLE>")
         || (strpos($bin, "<!--") !== false) || (strpos($bin, "<!DOCTYPE HTML ") !== false)) {
            $type = "text/html";
         }
         #-- mail msg
         elseif ((strpos($bin, "\nReceived: ") !== false) || strpos($bin, "\nSubject: ")
         || strpos($bin, "\nCc: ") || strpos($bin, "\nDate: ")) {
            $type = "message/rfc822";
         }
         #-- php scripts
         elseif (strpos($bin, "<"."?php") !== false) {
            return("application/x-httpd-php");
         }
         #-- plain text, C source or so
         elseif (strpos($bin, "function ") || strpos($bin, " and ")
         || strpos($bin, " the ") || strpos($bin, "The ")
         || (strpos($bin, "/*") !== false) || strpos($bin, "#include ")) {
            return("text/plain");
         }

         #-- final fallback
         else {
            $type = "application/octet-stream";
         }
      }
      
      

      #-- done
      return $type;
   }
}



#-- gives Media Type for the index numbers getimagesize() returned
if (!function_exists("image_type_to_mime_type")) {
   define("IMAGETYPE_GIF", 1);
   define("IMAGETYPE_JPEG", 2);
   define("IMAGETYPE_PNG", 3);
   define("IMAGETYPE_SWF", 4);
   define("IMAGETYPE_PSD", 5);  // post-4.3 from here ...
   define("IMAGETYPE_BMP", 6);
   define("IMAGETYPE_TIFF_II", 7);
   define("IMAGETYPE_TIFF_MM", 8);
   define("IMAGETYPE_JPC", 9);
   define("IMAGETYPE_JP2", 10);
   define("IMAGETYPE_JPX", 11);
   define("IMAGETYPE_JB2", 12);
   define("IMAGETYPE_SWC", 13);
   define("IMAGETYPE_IFF", 14);
   define("IMAGETYPE_WBMP", 15);
   define("IMAGETYPE_XBM", 16);
   define("IMAGETYPE_MNG", 77);
   define("IMAGETYPE_XPM", 88);
   define("IMAGETYPE_ZIF", 90);
   define("IMAGETYPE_PBM", 80);
   define("IMAGETYPE_PGM", 81);
   define("IMAGETYPE_PPM", 82);
   function image_type_to_mime_type($id) {
      static $mime = array(
         IMAGETYPE_GIF => "gif",
         IMAGETYPE_JPEG => "jpeg",
         IMAGETYPE_PNG => "png",
         IMAGETYPE_SWF => "application/x-shockwave-flash",
         IMAGETYPE_BMP => "bmp",
         IMAGETYPE_JP2 => "jp2",
         IMAGETYPE_WBMP => "vnd.wap.wbmp",
         IMAGETYPE_XBM => "xbm",
         IMAGETYPE_PSD => "x-photoshop",
         IMAGETYPE_TIFF_II => "tiff",
         IMAGETYPE_TIFF_MM => "tiff",
         IMAGETYPE_JPC => "application/octet-stream",
         IMAGETYPE_JP2 => "jp2",
//         IMAGETYPE_JPX => "",
//         IMAGETYPE_JB2 => "",
         IMAGETYPE_SWC => "application/x-shockwave-flash",
         IMAGETYPE_IFF => "iff",
         IMAGETYPE_XPM => "x-xpm",
         IMAGETYPE_ZIF => "unknown",
         IMAGETYPE_MNG => "video/mng",
         IMAGETYPE_PBM => "x-portable-bitmap",
         IMAGETYPE_PGM => "x-portable-greymap",
         IMAGETYPE_PPM => "x-portable-pixmap",
      );
      if (isset($mime[$id])) {
         $m = $mime[$id];
         strpos($m, "/") || ($m = "image/$m");
      }
      else {
         $m = "image/unknown";
      }
      return($m);
   }
}

#-- still in CVS
if (!function_exists("image_type_to_extension")) {
   function image_type_to_extension($id, $dot=true) {
      static $ext = array(
         0=>false,
         1=>"gif", 2=>"jpeg", 3=>"png",
         "swf", "psd", "bmp",
         "tiff", "tiff",
         "jpc", "jp2", "jpx", "jb2",
         "swc", "wbmp", "xbm",
         77=>"mng", 88=>"xpm", 90=>"zif",
         80=>"pbm", 81=>"pgm", 82=>"ppm",
      );
      $m = $ext[$id];
      if ($m && $dot) {
         $m = ".$m";
      }
      return($m);
   }
}



#-- we need this then, too
if (!function_exists("exif_imagetype")) {
   function exif_imagetype($fn) {
      $magic = array(
         "\211PNG" => IMAGETYPE_PNG,
         "\377\330" => IMAGETYPE_JPEG,
         "GIF89a" => IMAGETYPE_GIF,
         "GIF94z" => IMAGETYPE_ZIF,
         "FWS" => IMAGETYPE_SWF,
         "II" => IMAGETYPE_TIFF_II,
         "MM" => IMAGETYPE_TIFF_MM,
         "/* XPM" => IMAGETYPE_XPM,
         "BM" => IMAGETYPE_BMP,  // also for OS/2
         "\212MNG" => IMAGETYPE_MNG,
         "P1" => IMAGETYPE_PBM,
         "P4" => IMAGETYPE_PBM,
         "P2" => IMAGETYPE_PGM,
         "P5" => IMAGETYPE_PGM,
         "P3" => IMAGETYPE_PPM,
         "P6" => IMAGETYPE_PPM,
      );
      if ($f = fopen($fn, "rb")) {
         $bin = fread($f, 8);
         fclose($f);
         foreach ($magic as $scn=>$id) {
            if (!strncmp($bin, $scn, strlen($scn))) {
               return $id;
            }
         }
      }
   }
}

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












































































































































































































































































































































































































































































































































































































































































































































Added ext/nonstandard/base16.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/password.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
<?php
/**
 * api: php
 * title: password_compat
 * description: A Compatibility library with PHP 5.5's simplified password hashing API.
 * version: 04b9a75574
 * license: MITL
 * author: ircmaxell
 * url: https://github.com/ircmaxell/password_compat
 * type: functions
 * provides: password_hash, password_verify
 *
 * password_hash() and password_verify() provide a unified and easy to get right
 * hashing API. They're in core, but also available as full-fledged userland
 * compatibility implementation.
 *
 * See the manual for usage.
 *   http://php.net/manual/en/function.password-hash.php
 *
 * @author Anthony Ferrara <ircmaxell@php.net>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @copyright 2012 The Authors
 */

if (!defined('PASSWORD_DEFAULT')) {

    define('PASSWORD_BCRYPT', 1);
    define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);

    /**
     * Hash the password using the specified algorithm
     *
     * @param string $password The password to hash
     * @param int    $algo     The algorithm to use (Defined by PASSWORD_* constants)
     * @param array  $options  The options for the algorithm to use
     *
     * @return string|false The hashed password, or false on error.
     */
    function password_hash($password, $algo, array $options = array()) {
        if (!function_exists('crypt')) {
            trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING);
            return null;
        }
        if (!is_string($password)) {
            trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
            return null;
        }
        if (!is_int($algo)) {
            trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
            return null;
        }
        switch ($algo) {
            case PASSWORD_BCRYPT:
                // Note that this is a C constant, but not exposed to PHP, so we don't define it here.
                $cost = 10;
                if (isset($options['cost'])) {
                    $cost = $options['cost'];
                    if ($cost < 4 || $cost > 31) {
                        trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
                        return null;
                    }
                }
                // The length of salt to generate
                $raw_salt_len = 16;
                // The length required in the final serialization
                $required_salt_len = 22;
                $hash_format = sprintf("$2y$%02d$", $cost);
                break;
            default:
                trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
                return null;
        }
        if (isset($options['salt'])) {
            switch (gettype($options['salt'])) {
                case 'NULL':
                case 'boolean':
                case 'integer':
                case 'double':
                case 'string':
                    $salt = (string) $options['salt'];
                    break;
                case 'object':
                    if (method_exists($options['salt'], '__tostring')) {
                        $salt = (string) $options['salt'];
                        break;
                    }
                case 'array':
                case 'resource':
                default:
                    trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
                    return null;
            }
            if (strlen($salt) < $required_salt_len) {
                trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING);
                return null;
            } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
                $salt = str_replace('+', '.', base64_encode($salt));
            }
        } else {
            $buffer = '';
            $buffer_valid = false;
            if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
                $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
                if ($buffer) {
                    $buffer_valid = true;
                }
            }
            if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
                $buffer = openssl_random_pseudo_bytes($raw_salt_len);
                if ($buffer) {
                    $buffer_valid = true;
                }
            }
            if (!$buffer_valid && is_readable('/dev/urandom')) {
                $f = fopen('/dev/urandom', 'r');
                $read = strlen($buffer);
                while ($read < $raw_salt_len) {
                    $buffer .= fread($f, $raw_salt_len - $read);
                    $read = strlen($buffer);
                }
                fclose($f);
                if ($read >= $raw_salt_len) {
                    $buffer_valid = true;
                }
            }
            if (!$buffer_valid || strlen($buffer) < $raw_salt_len) {
                $bl = strlen($buffer);
                for ($i = 0; $i < $raw_salt_len; $i++) {
                    if ($i < $bl) {
                        $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
                    } else {
                        $buffer .= chr(mt_rand(0, 255));
                    }
                }
            }
            $salt = str_replace('+', '.', base64_encode($buffer));
        }
        $salt = substr($salt, 0, $required_salt_len);

        $hash = $hash_format . $salt;

        $ret = crypt($password, $hash);

        if (!is_string($ret) || strlen($ret) <= 13) {
            return false;
        }

        return $ret;
    }

    /**
     * Get information about the password hash. Returns an array of the information
     * that was used to generate the password hash.
     *
     * array(
     *    'algo' => 1,
     *    'algoName' => 'bcrypt',
     *    'options' => array(
     *        'cost' => 10,
     *    ),
     * )
     *
     * @param string $hash The password hash to extract info from
     *
     * @return array The array of information about the hash.
     */
    function password_get_info($hash) {
        $return = array(
            'algo' => 0,
            'algoName' => 'unknown',
            'options' => array(),
        );
        if (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) {
            $return['algo'] = PASSWORD_BCRYPT;
            $return['algoName'] = 'bcrypt';
            list($cost) = sscanf($hash, "$2y$%d$");
            $return['options']['cost'] = $cost;
        }
        return $return;
    }

    /**
     * Determine if the password hash needs to be rehashed according to the options provided
     *
     * If the answer is true, after validating the password using password_verify, rehash it.
     *
     * @param string $hash    The hash to test
     * @param int    $algo    The algorithm used for new password hashes
     * @param array  $options The options array passed to password_hash
     *
     * @return boolean True if the password needs to be rehashed.
     */
    function password_needs_rehash($hash, $algo, array $options = array()) {
        $info = password_get_info($hash);
        if ($info['algo'] != $algo) {
            return true;
        }
        switch ($algo) {
            case PASSWORD_BCRYPT:
                $cost = isset($options['cost']) ? $options['cost'] : 10;
                if ($cost != $info['options']['cost']) {
                    return true;
                }
                break;
        }
        return false;
    }

    /**
     * Verify a password against a hash using a timing attack resistant approach
     *
     * @param string $password The password to verify
     * @param string $hash     The hash to verify against
     *
     * @return boolean If the password matches the hash
     */
    function password_verify($password, $hash) {
        if (!function_exists('crypt')) {
            trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
            return false;
        }
        $ret = crypt($password, $hash);
        if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) {
            return false;
        }

        $status = 0;
        for ($i = 0; $i < strlen($ret); $i++) {
            $status |= (ord($ret[$i]) ^ ord($hash[$i]));
        }

        return $status === 0;
    }
}



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 = @mysql_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() {
		return mysql_affected_rows($this->__connection);
	}
	
	
	// 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;
	}
	
	/**
	 * 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_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);
		$this->__result = null;
	}
	
	function __uquery(&$query) {
		if(!@$query = mysql_query($query, $this->__connection)) {
			$this->__setErrors('SQLER');
			$query = null;
		}
		return $query;
	}
	
}




}//if!class_exists
?>

Added ext/pdo.sqlite.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
<?php if (!class_exists("PDO_SQLITE")) {
/** File PDO_sqlite.class.php		*
 *(C) Andrea Giammarchi [2005/10/13]	*/

// Requires PDOStatement_sqlite.class.php , drived by PDO.class.php file
#<builtin>#require_once('PDOStatement_sqlite.class.php');

/**
 * Class PDO_sqlite
 * 	This class is used from class PDO to manage a SQLITE version 2 database.
 *      Look at PDO.clas.php file comments to know more about SQLITE connection.
 * ---------------------------------------------
 * @Compatibility	>= PHP 4
 * @Dependencies	PDO.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/18/14 12:30
 * @Version		0.1 - tested
 */ 
class PDO_sqlite {
	
	/**
	 * 'Private' variables:
	 *	__connection:Resource		Database connection
         *	__dbinfo:String			Database filename
         *      __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_sqlite(&$string_dsn) {
		if(!@$this->__connection = &sqlite_open($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 sqlite_close function.
	 *	this->close( Void ):Boolean
         * @Return	Boolean		True on success, false otherwise
	 */
	function close() {
		$result = is_resource($this->__connection);
		if($result) {
			sqlite_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 = sqlite_changes($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 sqlite_last_insert_rowid($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_sqlite($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 = @sqlite_unbuffered_query($query, $this->__connection, $this->__dbinfo);
		if($query) {
			$result = Array();
			while($r = sqlite_fetch_array($query, SQLITE_ASSOC))
				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 ("'".sqlite_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 null
	 */
	function getAttribute($attribute) {
		$result = null;
		switch($attribute) {
			case PDO_ATTR_SERVER_INFO:
				$result = sqlite_libencoding();
				break;
			case PDO_ATTR_SERVER_VERSION:
			case PDO_ATTR_CLIENT_VERSION:
				$result = sqlite_libversion();
				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;
			sqlite_close($this->__connection);
			if($this->__persistent === true)
				$this->__connection = &sqlite_popen($this->__dbinfo);
			else
				$this->__connection = &sqlite_open($this->__dbinfo);
		}
		return $result;
	}
	
	
	// UNSUPPORTED PUBLIC METHODS
	function beginTransaction() {
		return false;
	}
	
	function commit() {
		return false;
	}
	
	function rollBack() {
		return false;
	}
	
	
	// PRIVATE METHODS
	function __setErrors($er, $connection = false) {
		if(!is_resource($this->__connection)) {
			$errno = 1;
			$errst = 'Unable to open or find database.';
		}
		else {
			$errno = sqlite_last_error($this->__connection);
			$errst = sqlite_error_string($errno);
		}
		$this->__errorCode = &$er;
		$this->__errorInfo = Array($this->__errorCode, $errno, $errst);
	}
	
	function __uquery(&$query) {
		if(!@$query = sqlite_query($query, $this->__connection)) {
			$this->__setErrors('SQLER');
			$query = null;
		}
		return $query;
	}
}
?><?php
/** File PDOStatement_sqlite.class.php	*
 *(C) Andrea Giammarchi [2005/10/13]	*/

/**
 * Class PDOStatement_sqlite
 * 	This class is used from class PDO_sqlite 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_sqlite.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_sqlite {
	
	/**
	 * '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:String )
	 * @Param	String		query to prepare
         * @Param	Resource	database connection
         * @Param	String		database file name
	 */
	function PDOStatement_sqlite(&$__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 = sqlite_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, "'".sqlite_escape_string($v)."'");
				}
				else {
					$parse = create_function('$v', 'return "\'".sqlite_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 = sqlite_fetch_array($this->__result, SQLITE_NUM);
					break;
				case PDO_FETCH_ASSOC:
					$result = sqlite_fetch_array($this->__result, SQLITE_ASSOC);
					break;
				case PDO_FETCH_OBJ:
					$result = sqlite_fetch_object($this->__result);
					break;
				case PDO_FETCH_BOTH:
				default:
					$result = sqlite_fetch_array($this->__result, SQLITE_BOTH);
					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 = sqlite_fetch_array($this->__result, SQLITE_NUM))
						array_push($result, $r);
					break;
				case PDO_FETCH_ASSOC:
					while($r = sqlite_fetch_array($this->__result, SQLITE_ASSOC))
						array_push($result, $r);
					break;
				case PDO_FETCH_OBJ:
					while($r = sqlite_fetch_object($this->__result))
						array_push($result, $r);
					break;
				case PDO_FETCH_BOTH:
				default:
					while($r = sqlite_fetch_array($this->__result, SQLITE_BOTH))
						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 = @sqlite_fetch_array($this->__result, SQLITE_NUM);
			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() {
		return sqlite_changes($this->__connection);
	}
	
	
	// 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 null
	 */
	function getAttribute($attribute) {
		$result = null;
		switch($attribute) {
			case PDO_ATTR_SERVER_INFO:
				$result = sqlite_libencoding();
				break;
			case PDO_ATTR_SERVER_VERSION:
			case PDO_ATTR_CLIENT_VERSION:
				$result = sqlite_libversion();
				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;
			sqlite_close($this->__connection);
			if($this->__persistent === true)
				$this->__connection = &sqlite_popen($this->__dbinfo);
			else
				$this->__connection = &sqlite_open($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, $connection = false) {
		if(!is_resource($this->__connection)) {
			$errno = 1;
			$errst = 'Unable to open database.';
		}
		else {
			$errno = sqlite_last_error($this->__connection);
			$errst = sqlite_error_string($errno);
		}
		$this->__errorCode = &$er;
		$this->__errorInfo = Array($this->__errorCode, $errno, $errst);
		$this->__result = null;
	}
	
	function __uquery(&$query) {
		if(!@$query = sqlite_query($query, $this->__connection)) {
			$this->__setErrors('SQLER');
			$query = null;
		}
		return $query;
	}
	
}



}//if!class_exists
?>

Added ext/php40.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
<?php
/**
 *
 * @group 4_0
 * @since 4.0
 * @untested
 *
 *
 * Here we collect PHP functions for versions before 4.1.
 *
 * YOU AIN'T GONNA NEED IT.
 *
 * 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 - or not **superglobal** at least.
 *
 */

#---------------------------------------------------------------- 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
      }
   }
}

?>

Added ext/php40array.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
<?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();
      $key_cb = array_pop($in);
      $val_cb = array_pop($in);
      $arr1 = array_shift($in);
      $r = array();
      
      foreach ($arr1 as $i=>$v) {
         #-- in each array, compare against each key/value pair
         foreach (array_keys($in) as $c) {
            foreach ($in[$c] as $i2=>$v2) {
               
               $key_cmp = call_user_func_array($key_cb, array($i, $i2));
               if ($key_cmp == 0) {

                  #-- ok, in this case we must compare the data as well
                  $val_cmp = call_user_func_array($val_cb, array($v, $v2));
                  if ($val_cmp == 0) {
                     continue 3;
                  }
               }
            }
         }

         #-- this combination isn't really found anywhere else
         $r[$i] = $v;
      }
      return($r);
   }
}


#-- same, but that keys now are compared normally (without callback)
if (!function_exists("array_udiff_assoc")) {
   function array_udiff_assoc() {
      $in = func_get_args();
      $val_cb = array_pop($in);
      $arr1 = array_shift($in);
      $r = array();
      
      #-- compare against each key/value pair in other arrays
      foreach ($arr1 as $i=>$v) {
         foreach (array_keys($in) as $c) {
            if (isset($in[$c][$i])) {
               #-- now compare data by callback
               $cmp = call_user_func_array($val_cb, array($v, $in[$c][$i]));
               if ($cmp == 0) {
                   continue 2;
               }
            }
         }
         #-- everything exists only in array1
         $r[$i] = $v;
      }
      return($r);
   }
}


#-- ....
if (!function_exists("array_diff_uassoc")) {
   function array_diff_uassoc() {
      $in = func_get_args();
      $key_cb = array_pop($in);
      $arr1 = array_shift($in);
      $num = count($in);
      $r = array();
      
      foreach ($arr1 as $i=>$v) {
         #-- in other arrays?
         for ($c=0; $c<$num; $c++) {
            foreach ($in[$c] as $i2=>$v2) {
               if ($v == $v2) {
                  $cmp = call_user_func_array($key_cb, array($i, $i2));
                  if ($cmp == 0) {
                     continue 3;
                  }
               }
            }
         }
         #-- exists only in array1
         $r[$i] = $v;
      }
      return($r);
   }
}


#-- diff array, keys ignored, callback for comparing values
if (!function_exists("array_udiff")) {
   function array_udiff() {
      $in = func_get_args();
      $val_cb = array_pop($in);
      $arr1 = array_shift($in);
      $num = count($in);
      $r = array();
      foreach ($arr1 as $i=>$v) {
         #-- check other arrays
         for ($c=0; $c<$num; $c++) {
            foreach ($in[$c] as $v2) {
               $cmp = call_user_func_array($val_cb, array($v, $v2));
               if ($cmp == 0) {
                  continue 3;
               }
            }
         }
         #-- exists only in array1
         $r[$i] = $v;
      }
      return($r);
   }
}












#-- same for intersections
if (!function_exists("array_uintersect_uassoc")) {
   function array_uintersect_uassoc() {
      $in = func_get_args();
      $key_cb = array_pop($in);
      $val_cb = array_pop($in);
      $all = array();
      $conc = count($in);
      foreach ($in[0] as $i=>$v) {
         #-- must exist in each array (at least once, callbacks may match fuzzy)
         for ($c=1; $c<$conc; $c++) {
            $ok = false;
            foreach ($in[$c] as $i2=>$v2) {
               $key_cmp = call_user_func_array($key_cb, array($i, $i2));
               $val_cmp = call_user_func_array($val_cb, array($v, $v2));
               if (($key_cmp == 0) && ($val_cmp == 0)) {
                  $ok = true;
                  break;
               }
            }
            if (!$ok) {
               continue 2;
            }
         }
         #-- exists in all arrays
         $all[$i] = $v;
      }
      return($all);
   }
}




#-- intersection again
if (!function_exists("array_uintersect_assoc")) {
   function array_uintersect_assoc() {
      $in = func_get_args();
      $val_cb = array_pop($in);
      $all = array();
      $conc = count($in);
      foreach ($in[0] as $i=>$v) {
         #-- test for that entry in any other array
         for ($c=1; $c<$conc; $c++) {
            if (isset($in[$c][$i])) {
               $cmp = call_user_func_array($val_cb, array($v, $in[$c][$i]));
               if ($cmp == 0) { continue; }
            }
            #-- failed
            continue 2;
         }
         #-- exists in all arrays
         # (but for fuzzy matching: only the first entry will be returned here)
         $all[$i] = $v;
      }
      return($all);
   }
}





#-- array intersection, no keys compared, but callback for values
if (!function_exists("array_uintersect")) {
   function array_uintersect() {
      $in = func_get_args();
      $val_cb = array_pop($in);
      $arr1 = array_shift($in);
      $num = count($in);
      $r = array();

      foreach ($arr1 as $i=>$v) {
         #-- must have equivalent value in all other arrays
         for ($c=0; $c<$num; $c++) {
            foreach ($in[$c] as $i2=>$v2) {
               $cmp = call_user_func_array($val_cb, array($v, $v2));
               if ($cmp == 0) {
                  continue 2; //found
               }
            }
            continue 2; //failed
         }
         #-- everywhere
         $r[$i] = $v;
      }
      return($r);
   }
}




#-- diff array, keys ignored, callback for comparing values
if (!function_exists("array_intersect_uassoc")) {
   function array_intersect_uassoc() {
      $args = func_get_args();
      $key_cb = array_pop($args);
      $array1 = array_shift($args);
      $num = count($args);
      $all = array();
      foreach ($array1 as $i=>$v) {
         #-- look through other arrays
         for ($c=0; $c<$num; $c++) {
            $ok = 0;
            foreach ($args[$c] as $i2=>$v2) {
               $cmp = call_user_func_array($key_cb, array($i, $i2));
               if (($cmp == 0) && ($v == $v2)) {
                  $ok = 1;
                  continue 2;
               }
            }
            if (!$ok) { 
               continue 2;
            }
         }
         #-- found in all arrays
         if ($ok) {
            $diff[$i] = $v;
         }
      }
      return($diff);
   }
}


?>

Deleted ext/posix.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
<?php
/*
   POSIX subsystem functions are emulated using regular commandline
   utilities or by invoking Perl.  Of course not the full spectrum
   of features can be simulated this way. You shouldn't rely on the
   emulation here, and just abort on PHP version without POSIX ext.
*/

if (!function_exists("posix_mkfifo") && strlen($_ENV["SHELL"]) && !ini_get("safe_mode")) {

   function posix_mkfifo($pathname, $mode=0400) {
      $cmd = "/usr/bin/mkfifo -m 0" . decoct($mode) . " " . escape_shell_arg($pathname);
      exec($cmd, $uu, $error);
      return(!$error);
   }
   
   function posix_getcwd() {
      return realpath(getcwd());
   }
   
   function posix_kill($pid, $sig) {
      $cmd = "kill -" . ((int)$sig) . " " . ((int)$pid);
      exec($cmd, $uu, $error);
      return(!$error);
   }

   function posix_uname() {
      return array(
         "sysname" => `/bin/uname -s`,
         "nodename" => `/bin/uname -n`,
         "release" => `/bin/uname -r`,
         "version" => `/bin/uname -v`,
         "machine" => `/bin/uname -m`,
         "domainname" => `/bin/domainname`,
      );
   }
}


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
















































































Added ext/pspell.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
<?php
/**
 * api: php
 * title: pspell emulation
 * description: aspell wrapper functions for PHP pspell extension
 * type: functions
 * support: untested
 * config: <var name="$__pspell[]" priority="never" description="helper variable">
 * version: 1.1
 * license: Public Domain
 * 
 * Has no support for replacement and personal dictionaries, nor wordlist files.
 * (Some of these features are possible with the aspell cmdline arguments eventually.)
 *
 * Only works with aspell binary, not ispell.
 *
 */


 
if (!function_exists("pspell_check")) {

   // helper variable, holds indexes to configured dictionaries
   global $__pspell;
   $__pspell[0] = array(
      // array names do match aspell --cmdline options 1:1
      "lang" => "en",
      "variety" => "",
      "jargon" => "",
      "encoding" => "utf-8",
      "ignore" => 1,
      "sug-mode" => "normal",
      // pspell_*() emu internal options prefixed with _
      "_mode" => 0,
      "_bin" => trim(`which aspell`),
      "_insert" => "",
   );

   // ??   
   define("PSPELL_FAST", 0x01);
   define("PSPELL_NORMAL", 0x02);
   define("PSPELL_BAD_SPELLERS", 0x04);
   define("PSPELL_RUN_TOGETHER", 0x08);
   define("PSPELL_ULTRA", 0x20);  // non-standard
   

   /**
    * Check if a single word exists in the dictionary as-is.
    *
    */
   function pspell_check($i, $word) {

      // exec
      $cmd = pspell_cmd($i, "check --dont-suggest");
      $word = escapeshellarg($word);
      $r = `echo $word | $cmd`;
      
      // "*" means successful match
      return preg_match("/^[\*]/m", $r);
   }


   /**
    * non-standard, for emulation only
    *
    */
   function pspell_cmd($i, $insert="") {
      global $__pspell;
      
      # /usr/bin/aspell pipe check
      $cmd = $__pspell[$i]["_bin"] . " pipe $insert " . $__pspell[$i]["_insert"];

      # --lang= --ignore= --variety= --jargon= --personal= --repl= --extra-dicts= --dict-dir=
      foreach ($__pspell[$i] as $name=>$value) {
         if (strlen($value) && !strstr(",_bin,_mode",$name) && ($name[0]!="_")) {
            $cmd .= " --$name=$value";
         }
      }
      return $cmd;
   }   
   
   
   /**
    * If word does not exist in dictionary, returns list of alternatives.
    *
    */
   function pspell_suggest($i, $word) {
      
      // exec
      $cmd = pspell_cmd($i, "--suggest");
      $word = escapeshellarg($word);
      $r = `echo $word | $cmd`;
      
      // "&" multiple matches
      if (preg_match("/^[\&] (.+?) (\d+) (\d+): (.+)$/m", $r, $uu)) {
         return preg_split("/,\s*/", $uu[4]);
      }
      else {
         //return($word);    //@todo: native behaviour?
      }
   }


   /**
    * Set aspell options.
    *
    */
   function pspell_new($lang="en", $spelling="", $jargon="", $enc="utf-8", $mode=0) {
      global $__pspell;
      $i = count($__pspell);
      $__pspell[$i] = array_merge($__pspell[0], array(
         "lang" => $lang,
         "variety" => $spelling,
         "jargon" => $jargon,
         "encoding" => $enc,
      ));
      if ($mode) { 
         pspell_config_mode($i, $mode);
      }
      return($i);
   }


   /**
    * Various other dictionary options.
    * Just set $__pspell[][] cmdline --options array.
    *
    */
   function pspell_config_create($lang, $spelling=NULL, $jargon=NULL, $enc=NULL) {
      return pspell_new($lang, $spelling, $jargon, $enc);
   }
   function pspell_new_config($i) {
      return $i;  // dictionary and config are the same in this implementation
   }
   function pspell_config_mode($i, $mode) {
      global $__pspell;
      $__pspell[$i]["_mode"] = $mode;
      $modes = array(0x00=>"normal", PSPELL_NORMAL=>"normal", PSPELL_FAST=>"fast", PSPELL_ULTRA=>"ultra", PSPELL_BAD_SPELLERS=>"bad-spellers");
      $__pspell[$i]["sug-mode"] = $modes[$mode & 0x27];
      pspell_config_runtogether($i, $mode & PSPELL_RUN_TOGETHER);
   }
   function pspell_config_ignore($i, $minlength) {
      global $__pspell;
      $__pspell[$i]["ignore"] = (int)$minlength;
   }
   function pspell_config_personal($i, $file) {
      global $__pspell;
      $__pspell[$i]["personal"] = escapeshellarg($file);
   }
   function pspell_config_data_dir($i, $dir) {
      global $__pspell;
      $__pspell[$i]["data-dir"] = escapeshellarg($dir);
   }
   function pspell_config_dict_dir($i, $dir) {
      global $__pspell;
      $__pspell[$i]["dict-dir"] = escapeshellarg($dir);
   }
   function pspell_config_runtogether($i, $is) {
      global $__pspell;
      $__pspell[$i]["_insert"] = $is ? "--runtogether" : "";
   }

   
}


?>

Added ext/stubs/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"));
   }

}


?>

Added ext/stubs/zlib.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'd be 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);
    }

 }

?>

Added ext/uncommon_functions.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
<?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)
#   (you should use the PHP_Compat implementation of this preferably)
if (!function_exists("php_strip_whitespace")) {
   function php_strip_whitespace($fn) {
      // alternatives would be using te tokenizer or
      // some regexs to strip unwanted content parts
      // (PEAR::PHP_Compat simply calls the tokenizer)
      $fn = escapeshellcmd($fn);
      $text = `php -wqCf '$fn'`;
      if (!$text) {
         $text = implode("", file($fn));
      }
      return $text;
   }
}


#-- invocates PHP interpreter to do the syntax check (nothing else can do)
#   (you should use the PHP_Compat implementation of this preferably)
if (!function_exists("php_check_syntax")) {
   function php_check_syntax($fn) {
      $args = func_get_args();
      if (count($args)>1) {
         $result = & $args[1];
      }
      $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) . "  ";
         
         #-- function name
         if (isset($info["class"])) {
            echo "$info[class]::";
         }
         if (isset($info["object"])) {
            echo "\$$info[object]->";
         }
         echo "$info[function]";
         
         #-- args
         echo "(";
         foreach ($info["args"] as $a) {
            echo str_replace("\n", "", var_export($a, 1)) . ", ";
         }
         echo ")";
         
         #-- caller
         echo " called at [";
         if ($info["file"]) {
            echo $info["file"] . ":" . $info["line"];
         }
         else {
            echo "unknown_location";
         }
         echo "]\n";
      }
   }
}


?>

Added ext/unfinished/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
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
<?php
/**
 * @group 5_2_FILTER
 * @since 5.2
 *
 * filter_*() functions can probably be reimplemented for PHP5.0 and PHP4.x
 *
 *
 */




/**
 * Gets numeric filter index, from its textual name.
 *
 * @param  string
 * @return integer
 */
function filter_id($name) {
   $map = array(
      "int" => FILTER_VALIDATE_INT,
      "boolean" => FILTER_VALIDATE_BOOLEAN,
      "float" => FILTER_VALIDATE_FLOAT,
      "validate_regexp" => FILTER_VALIDATE_REGEXP,
      "validate_url" => FILTER_VALIDATE_URL,
      "validate_email" => FILTER_VALIDATE_EMAIL,
      "validate_ip" => FILTER_VALIDATE_IP,
      "string" => FILTER_SANITIZE_STRING,
      "stripped" => FILTER_SANITIZE_STRIPPED,
      "encoded" => FILTER_SANITIZE_ENCODED,
      "special_chars" => FILTER_SANITIZE_SPECIAL_CHARS,
      "unsafe_raw" => FILTER_UNSAFE_RAW,
      "email" => FILTER_SANITIZE_EMAIL,
      "url" => FILTER_SANITIZE_URL,
      "number_int" => FILTER_SANITIZE_NUMBER_INT,
      "number_float" => FILTER_SANITIZE_NUMBER_FLOAT,
      "magic_quotes" => FILTER_SANITIZE_MAGIC_QUOTES,
      "callback" => FILTER_CALLBACK,
   );
   if (isset($map[$name])) {
      return($map[$name]);
   }
   else {
      trigger_error(E_USER_ERROR, "no filter by name '".htmlentities($name)."'");
   }
}



/**
 * Returns list of filter names.
 *
 * @return array
 */
function filter_list() {
   return array(
      "int",
      "boolean",
      "float",
      "validate_regexp",
      "validate_url",
      "validate_email",
      "validate_ip",
      "string",
      "stripped",
      "encoded",
      "special_chars",
      "unsafe_raw",
      "email",
      "url",
      "number_int",
      "number_float",
      "magic_quotes",
      "callback",
   );
}



/**
 * filter id and flag constants,
 * may not match real values yet, just for testing
 *
 */
define("INPUT_POST", 1);
define("INPUT_GET", 2);
define("INPUT_COOKIE", 4);
define("INPUT_ENV", 8);
define("INPUT_SERVER", 16);
define("INPUT_SESSION", 32);
define("INPUT_REQUEST", 64);
define("FILTER_FLAG_NONE", 		0x0000000);
define("FILTER_REQUIRE_SCALAR",		0x0000001);
define("FILTER_REQUIRE_ARRAY",		0x0000002);
define("FILTER_FORCE_ARRAY",		0x0000006);
define("FILTER_NULL_ON_FAILURE",	0x0000080);
define("FILTER_VALIDATE_INT", 1083);
define("FILTER_VALIDATE_BOOLEAN", 1084);
define("FILTER_VALIDATE_FLOAT", 1085);
define("FILTER_VALIDATE_REGEXP", 1086);
define("FILTER_VALIDATE_URL", 1087);
define("FILTER_VALIDATE_EMAIL", 1088);
define("FILTER_VALIDATE_IP", 1089);
define("FILTER_DEFAULT", 1090);
define("FILTER_UNSAFE_RAW", 1091);
define("FILTER_SANITIZE_STRING", 1092);
define("FILTER_SANITIZE_STRIPPED", 1093);
define("FILTER_SANITIZE_ENCODED", 1094);
define("FILTER_SANITIZE_SPECIAL_CHARS", 1095);
define("FILTER_SANITIZE_EMAIL", 1096);
define("FILTER_SANITIZE_URL", 1097);
define("FILTER_SANITIZE_NUMBER_INT", 1098);
define("FILTER_SANITIZE_NUMBER_FLOAT", 1099);
define("FILTER_SANITIZE_MAGIC_QUOTES", 1100);
define("FILTER_CALLBACK", 1101);
define("FILTER_FLAG_ALLOW_OCTAL", 	0x0000100);
define("FILTER_FLAG_ALLOW_HEX", 	0x0000200);
define("FILTER_FLAG_STRIP_LOW", 	0x0000400);
define("FILTER_FLAG_STRIP_HIGH", 	0x0000800);
define("FILTER_FLAG_ENCODE_LOW", 	0x0001000);
define("FILTER_FLAG_ENCODE_HIGH",	0x0002000);
define("FILTER_FLAG_ENCODE_AMP",	0x0004000);
define("FILTER_FLAG_NO_ENCODE_QUOTES",	0x0008000);
define("FILTER_FLAG_EMPTY_STRING_NULL", 0x0010000);
define("FILTER_FLAG_ALLOW_FRACTION", 	0x0020000);
define("FILTER_FLAG_ALLOW_THOUSAND",	0x0040000);
define("FILTER_FLAG_ALLOW_SCIENTIFIC",	0x0080000);
define("FILTER_FLAG_SCHEME_REQUIRED",	0x0100000);
define("FILTER_FLAG_HOST_REQUIRED",	0x0200000);
define("FILTER_FLAG_PATH_REQUIRED",	0x0400000);
define("FILTER_FLAG_QUERY_REQUIRED",	0x0800000);
define("FILTER_FLAG_IPV4", 		0x1000000);
define("FILTER_FLAG_IPV6", 		0x2000000);
define("FILTER_FLAG_NO_RES_RANGE",	0x4000000);
define("FILTER_FLAG_NO_PRIV_RANGE", 	0x8000000);


/**
 * Get list of variables from _REQUEST, _GET, _POST, _COOKIE, _SERVER, _ENV
 * or _SESSION array, piped through some of the filters.
 *
 * @param integer  input array flag ids
 * @param mixed    mapping varname => filter_id or filter/flags hash
 * @global $_REQUEST,$_GET,$_POST,$_SERVER,$_ENV,$_SESSION,$_COOKIE
 */
function filter_input_array($GPCSESR, $def=array()) {
   $r = array();
   
   if ($GPCSESR & INPUT_REQUEST) {
      $r = array_merge($r, filter_var_array($_REQUEST, $def));
   }
   if ($GPCSESR & INPUT_POST) {
      $r = array_merge($r, filter_var_array($_POST, $def));
   }
   if ($GPCSESR & INPUT_GET) {
      $r = array_merge($r, filter_var_array($_GET, $def));
   }
   if ($GPCSESR & INPUT_COOKIE) {
      $r = array_merge($r, filter_var_array($_COOKIE, $def));
   }
   if ($GPCSESR & INPUT_SERVER) {
      $r = array_merge($r, filter_var_array($_SERVER, $def));
   }
   if ($GPCSESR & INPUT_ENV) {
      $r = array_merge($r, filter_var_array($_ENV, $def));
   }
   
   return($r);
}



/**
 * Get a single variable filtered from input arrays.
 *
 * @param bitmask
 * @param string
 * @param bitmask
 * @param bitmask
 * @return string
 */
function filter_input($_INPUT, $name, $filter=0, $flags=0) {
   return filter_input_array($_INPUT, array($name => array("filter"=>$filter, "flags"=>$flags)));
}




/**
 * Extract a list of variables from an array. Apply filters.
 *
 * @param array   source data
 * @param array   variable list
 * @return array  filtered vars
 */
function filter_var_array($hash, $def=array()) {
   $r = array();

   #-- variable names from list
   foreach($def as $varname=>$filt) {
   
      #-- do we have it?
      if (!isset($hash[$varname])) {
      }
      #-- filter id and flags
      elseif (is_array($filt)) {
         $r[$varname] = filter_var($hash[$name], $filt["filter"], $filt["flags"]);
      }
      #-- filter without args
      else {
         $r[$varname] = filter_var($hash[$name], $filt);
      }
   }
   
   return($r);
}


/**
 * isset() test in _GET,_POST,... arrays
 *
 */
function filter_has_var($_INPUT, $varname) {
   return false
   or ($_INPUT & INPUT_REQUEST) and isset($_REQUEST[$varname])
   or ($_INPUT & INPUT_SERVER) and isset($_SERVER[$varname])
   or ($_INPUT & INPUT_COOKIE) and isset($_COOKIE[$varname])
   or ($_INPUT & INPUT_POST) and isset($_POST[$varname])
   or ($_INPUT & INPUT_GET) and isset($_GET[$varname])
   or ($_INPUT & INPUT_ENV) and isset($_ENV[$varname]);
}



/**
 * Input filtering main function.
 *
 * @param mixed $var
 */
function filter_var($var, $filter=FILTER_SANITIZE_STRING, $options=array()) {

   #-- recursively call ourselves for array input
   if (is_array($var)) {
     array_walk_recursive($var, "filter_var__walk", array($filter, $options));
     return $var;
   }
   
   #-- extract options
   $flags = 0x0000000;
   $regexp = "//";
   $callback = "";
   $min_range = INT_MIN;
   $max_range = INT_MAX;
   if (is_array($options)) {
      extract($options);   // regexp, callback, min_range, max_range, flags
   }
   elseif (is_int($options)) {
      $flags = $options;
   }
   
   #-- clean up flags
   $FAILURE = $flags & FILTER_NULL_ON_FAILURE ? NULL : false;
   $flags = $flags & ~FILTER_NULL_ON_FAILURE;
   $flags = $flags & ~FILTER_REQUIRE_SCALAR;
   $flags = $flags & ~FILTER_REQUIRE_ARRAY;
   $flags = $flags & ~FILTER_FORCE_ARRAY;

   
   #-- regular expressions for simple filters
   $rx = array(
       "int" => "/^[-+]?(\d{1,9})$/",
       "oct" => "/^0([0-7]{1,12})$/",
       "hex" => => "/^(0x)?([0-0a-fA-F]{1,12})$/",
       "bool_true" => => "/^(true|yes|on|1)$/",
       "bool_false" => => "/^(false|no|off|0|)$/",
       "float" => => "/^([+-]?\d+(\.\d+)([eE]\d+))$/",
       "char_low" => => "[\000-\037]",
       "char_high" => => "[\177-\377]",
   );


   #-- generic string code
   if (1) {
      #-- rm ASCII <32
      if ($flags & FILTER_FLAG_STRIP_LOW) {
         $var = preg_replace("/$rx[char_low]+/", "", $var);
      }
      #-- rm ASCII >127
      if ($flags & FILTER_FLAG_STRIP_HIGH) {
         $var = preg_replace("/$rx[char_high]+/", "", $var);
      }
   }


   #-- integer
   if ($filter == FILTER_VALIDATE_INT) {

      #-- octal
      if ($flags & FILTER_FLAG_ALLOW_OCTAL) {
         if (preg_match($rx["oct"], $var)) {
            $var = octdec($var);
         }
         else {
            return $FAILURE;
         }
      }

      #-- hex
      elseif ($flags & FILTER_FLAG_ALLOW_HEX) {
         if (preg_match($rx["hex"], $var, $uu)) {
            $var = hexdec($uu[2]);
         }
         else {
            return $FAILURE;
         }
      }

      #-- plain int
      elseif (preg_match($rx["int"])) {
         $var = (int) $var;
      }
      else {
         return $FAILURE;
      }
      
      #-- range
      if (($var < $min_range) or ($var > $max_range)) {
         return $FAILURE;
      }
      else {
         return $var;
      }
   }

   
   #-- boolean
   elseif ($filter == FILTER_VALIDATE_BOOLEAN) {
      if (preg_match($rx["bool_true"], $var) {
         return TRUE;
      }
      elseif (preg_match($rx["bool_false"], $var) {
         return FALSE;
      }
      else {
         return $FAILURE;
      }
   }


   #-- float
   elseif ($filter = FILTER_VALIDATE_FLOAT) {
      return preg_match($rx["float"], $var) ? (float)$var : $FAILURE;
   }


   #-- regexp
   elseif ($filter = FILTER_VALIDATE_REGEXP) {
      if ($regexp) {
         return preg_match($regexp, $var) ? $var : $FAILURE;
      }
      else {
         trigger_error(E_USER_ERROR, "no regexp supplied for FILTER_VALIDATE_REGEXP");
      }
   }



// FILTER_VALIDATE_URL


// FILTER_VALIDATE_EMAIL


// FILTER_VALIDATE_IP






   #-- strip_tags
   elseif ($filter == FILTER_SANITIZE_STRING) {

      #-- remove angle brackets and everything in between
      $var = strip_tags($var);

      #-- quotes
      if ($flags & FILTER_FLAG_NO_ENCODE_QUOTES) {
         // nothing
      }
      else {
         $var = strtr(array("'", '"'), array("&#39;", "&#34;"), $var);
      }

      #-- encode ASCII <32
      if ($flags & FILTER_FLAG_ENCODE_LOW) {
         $var = preg_replace("/($rx[char_low]+)/e", "'&#'.ord('$1').';'", $var);
      }
      #-- encode ASCII >127
      if ($flags & FILTER_FLAG_ENCODE_HIGH) {
         $var = preg_replace("/($rx[char_high]+)/e", "'&#'.ord('$1').';'", $var);
      }


      #-- AMPERSAND
      if ($flags & FILTER_FLAG_ENCODE_AMP) {
         $var = str_replace("&", "&#38;", $var);
      }

      return $var;
   }


   #-- urlencoded
   elseif  ($filter == FILTER_SANITIZE_ENCODED) {
   
      $var = urlencode($var);

      #-- encode ASCII <32
      if ($flags & FILTER_FLAG_ENCODE_LOW) {
         $var = preg_replace("/($rx[char_low]+)/e", "rawurlencode('$1')", $var);
      }
      #-- encode ASCII >127
      if ($flags & FILTER_FLAG_ENCODE_HIGH) {
         $var = preg_replace("/($rx[char_high]+)/e", "rawurlencode('$1')", $var);
      }
       
      return $var;
   }


   #-- htmlspecialchars()
   elseif ($filter == FILTER_SANITIZE_SPECIAL_CHARS) {

      #-- encode rest
      $var = htmlspecialchars($var);

      #-- always encode ASCII<32
      if (1) {
         $var = preg_replace("/($rx[char_low]+)/e", "'&#'.ord('$1').';'", $var);
      }
      #-- encode ASCII >127
      if ($flags & FILTER_FLAG_ENCODE_HIGH) {
         $var = preg_replace("/($rx[char_high]+)/e", "'&#'.ord('$1').';'", $var);
      }

      return $var;
   }


   #-- binary
   elseif ($filter == FILTER_UNSAFE_RAW)) {
   
      #-- "raw": encode AMPERSAND
      if ($flags & FILTER_FLAG_ENCODE_AMP) {
         $var = str_replace("&", "%", $var);           // ???????????????
      }
   
      #-- rm ASCII <32
      if ($flags & FILTER_FLAG_STRIP_LOW) {
         $var = preg_replace("/$rx[char_low]+/", "", $var);
      }
      #-- rm ASCII >127
      if ($flags & FILTER_FLAG_STRIP_HIGH) {
         $var = preg_replace("/$rx[char_high]+/", "", $var);
      }
      #-- encode ASCII <32
      if ($flags & FILTER_FLAG_ENCODE_LOW) {
         $var = preg_replace("/($rx[char_low]+)/e", "rawurlencode('$1')", $var);
      }
      #-- encode ASCII >127
      if ($flags & FILTER_FLAG_ENCODE_HIGH) {
         $var = preg_replace("/($rx[char_high]+)/e", "rawurlencode('$1')", $var);
      }


      return $var;
   }


   #-- email
   elseif ($filter == FILTER_SANITIZE_EMAIL) {
      return preg_replace("/[^-\w\d!#\$%&'*+\/=?\^`{\|}~@\.\[\]]+/", "", $var);
   }


   #-- url
   elseif ($filter == FILTER_SANITIZE_URL) {
      return preg_replace("/[^-\w\d\$.+!*'(),{}\|\\~\^\[\]\`<>#%\";\/?:@&=]+/", "", $var);
   }


   #-- number_int
   elseif ($filter == FILTER_SANITIZE_NUMBER_INT) {
      return preg_replace("/(^[^-+\d]|[^\d]+)/", "", $var);
   }


   #-- number_float
   elseif ($filter == FILTER_SANITIZE_NUMBER_INT) {
      // FILTER_FLAG_ALLOW_FRACTION
      // FILTER_FLAG_ALLOW_THOUSAND
      // FILTER_FLAG_ALLOW_SCIENTIFIC
      return preg_replace("/(^[^-+\d]|[^\d.eE]+)/", "", $var);
   }


   #-- magic_quotes
   elseif ($filter == FILTER_SANITIZE_MAGIC_QUOTES) {
      return addslashes($var);
   }


   #-- callback function
   elseif ($filter == FILTER_CALLBACK) {
      return call_user_func($callback, $var);
   }

         
   #-- filter unknown         
   else {
      trigger_error(E_USER_ERROR, "Uh, oh. Unknown filter id #".$filter);
      return $FAILURE;
   }
   
}


/**
 * Callback wrapper; needed for array_walk_recursive().
 *
 */
function filter_var__walk(&$var, $key, $filter, $options) {
   $var = filter_var($var, $filter, $options);
}



/**
 * @tests
 
123 === filter_var("123", FILTER_VALIDATE_INT)
FALSE === filter_var("--123", FILTER_VALIDATE_INT)
123 == filter_var("+123", FILTER_VALIDATE_INT)
15 === filter_var("0xF", FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX)
FALSE === filter_var("-0xFFFF", FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX)
"12&#38;3" === filter_var("12&3", FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_AMP)
"1&#9;2'&5" === ("1\t2'3&<4>5", FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES|FILTER_FLAG_ENCODE_LOW)
 
 */

?>

Added ext/unfinished/mime.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
<?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) {

      static $mime_magic_data;

      #-- fallback
      $type = false;

      #-- read in first 3K of given file
      if (is_dir($fn)) {
         return("httpd/unix-directory");
      }
      elseif (is_resource($fn) || ($fn = @fopen($fn, "rb"))) {
         $bin = fread($fn, $maxlen=3072);
         fclose($fn);
      }
      elseif (!file_exists($fn)) {
         return false;
      }
      else {
         return("application/octet-stream");   // give up
      }
      
      #-- use the appropriate external tool
      /*
      if (function_exists("exec") && !ini_get("safe_mode")) {     
         $type = exec("file -iL " . escapeshellcmd($fn) . " 2>/dev/null");
         if ($type = trim(strtok(substr(strrchr($type, ":"), 1), ";"))) {
             return $type;
         }
      }
      */

      #-- use PECL::fileinfo when available
      if (function_exists("finfo_buffer")) {
         $fi = new finfo(FILEINFO_MIME_TYPE);
         $type = $fi->buffer($bin);
         return($type);
      }
      
      #-- read in magic data, when called for the very first time
      if (!isset($mime_content_type)) {
      
         if ((file_exists($fn = ini_get("mime_magic.magicfile")))
          or (file_exists($fn = "/usr/share/misc/magic.mime"))
          or (file_exists($fn = "/etc/mime-magic"))   )
         {
            $mime_magic_data = array();

            #-- read in file
            $f = fopen($fn, "r");
            $fd = fread($f, 1<<20);
            fclose($f);
            $fd = str_replace("       ", "\t", $fd);

            #-- look at each entry
            foreach (explode("\n", $fd) as $line) {

               #-- skip empty lines
               if (!strlen($line) or ($line[0] == "#") or ($line[0] == "\n")) {
                  continue;
               }

               #-- break into four fields at tabs
               $l = preg_split("/\t+/", $line);
               @list($pos, $typestr, $magic, $ct) = $l;
#print_r($l);

               #-- ignore >continuing lines
               if ($pos[0] == ">") {
                  continue;
               }
               #-- real mime type string?
               $ct = strtok($ct, " ");
               if (!strpos($ct, "/")) {
                  continue;
               }

               #-- mask given?
               $mask = 0;
               if (strpos($typestr, "&")) {
                  $typestr = strtok($typestr, "&");
                  $mask = strtok(" ");
                  if ($mask[0] == "0") {
                     $mask = ($mask[1] == "x") ? hexdec(substr($mask, 2)) : octdec($mask);
                  }
                  else {
                     $mask = (int)$mask;
                  }
               }

               #-- strip prefixes
               if ($magic[0] == "=") {
                  $magic = substr($magic, 1);
               }

               #-- convert type
               if ($typestr == "string") {
                  $magic = stripcslashes($magic);
                  $len = strlen($magic);
                  if ($mask) { 
                     continue;
                  }
               }
               #-- numeric values
               else {
                  $mask or $mask = 0xFFFFFFFF;

                  if ((ord($magic[0]) < 48) or (ord($magic[0]) > 57)) {
#echo "\nmagicnumspec=$line\n";
#var_dump($l);
                     continue;  #-- skip specials like  >, x, <, ^, &
                  }

                  #-- convert string representation into int
                  if ((strlen($magic) >= 4) && ($magic[1] == "x")) {
                     $magic = hexdec(substr($magic, 2));
                  }
                  elseif ($magic[0]) {
                     $magic = octdec($magic);
                  }
                  else {
                     $magic = (int) $magic;
                     if (!$magic) { continue; }   // zero is not a good magic value anyhow
                  }

                  #-- different types               
                  switch ($typestr) {

                     case "byte":
                        $len = 1;
                        break;
                        
                     case "beshort":
                        $magic = ($magic >> 8) | (($magic & 0xFF) << 8);
                     case "leshort":
                     case "short":
                        $len = 2;
                        break;
                     
                     case "belong":
                        $magic = (($magic >> 24) & 0xFF)
                               | (($magic >> 8) & 0xFF00)
                               | (($magic & 0xFF00) << 8)
                               | (($magic & 0xFF) << 24);
                     case "lelong":
                     case "long":
                        $len = 4;
                        break;

                     default:
                        // date, ldate, ledate, leldate, beldate, lebelbe...
                        continue;
                  }
               }
               
               #-- add to list
               $mime_magic_data[] = array($pos, $len, $mask, $magic, trim($ct));
            }
         }
#print_r($mime_magic_data);
      }
      
      
      #-- compare against each entry from the mime magic database
      foreach ($mime_magic_data as $def) {

         #-- entries are organized as follows
         list($pos, $len, $mask, $magic, $ct) = $def;
         
         #-- ignored entries (we only read first 3K of file for opt. speed)
         if ($pos >= $maxlen) {
            continue;
         }

         $slice = substr($bin, $pos, $len);
         #-- integer comparison value
         if ($mask) {
            $value = hexdec(bin2hex($slice));
            if (($value & $mask) == $magic) {
               $type = $ct;
               break;
            }
         }
         #-- string comparison
         else {
            if ($slice == $magic) {
               $type = $ct;
               break;
            }
         }
      }// foreach
      
      #-- built-in defaults
      if (!$type) {
      
         #-- some form of xml
         if (strpos($bin, "<"."?xml ") !== false) {
            return("text/xml");
         }
         #-- html
         elseif ((strpos($bin, "<html>") !== false) || (strpos($bin, "<HTML>") !== false)
         || strpos($bin, "<title>") || strpos($bin, "<TITLE>")
         || (strpos($bin, "<!--") !== false) || (strpos($bin, "<!DOCTYPE HTML ") !== false)) {
            $type = "text/html";
         }
         #-- mail msg
         elseif ((strpos($bin, "\nReceived: ") !== false) || strpos($bin, "\nSubject: ")
         || strpos($bin, "\nCc: ") || strpos($bin, "\nDate: ")) {
            $type = "message/rfc822";
         }
         #-- php scripts
         elseif (strpos($bin, "<"."?php") !== false) {
            return("application/x-httpd-php");
         }
         #-- plain text, C source or so
         elseif (strpos($bin, "function ") || strpos($bin, " and ")
         || strpos($bin, " the ") || strpos($bin, "The ")
         || (strpos($bin, "/*") !== false) || strpos($bin, "#include ")) {
            return("text/plain");
         }

         #-- final fallback
         else {
            $type = "application/octet-stream";
         }
      }
      
      

      #-- done
      return $type;
   }
}



#-- gives Media Type for the index numbers getimagesize() returned
if (!function_exists("image_type_to_mime_type")) {
   define("IMAGETYPE_GIF", 1);
   define("IMAGETYPE_JPEG", 2);
   define("IMAGETYPE_PNG", 3);
   define("IMAGETYPE_SWF", 4);
   define("IMAGETYPE_PSD", 5);  // post-4.3 from here ...
   define("IMAGETYPE_BMP", 6);
   define("IMAGETYPE_TIFF_II", 7);
   define("IMAGETYPE_TIFF_MM", 8);
   define("IMAGETYPE_JPC", 9);
   define("IMAGETYPE_JP2", 10);
   define("IMAGETYPE_JPX", 11);
   define("IMAGETYPE_JB2", 12);
   define("IMAGETYPE_SWC", 13);
   define("IMAGETYPE_IFF", 14);
   define("IMAGETYPE_WBMP", 15);
   define("IMAGETYPE_XBM", 16);
   define("IMAGETYPE_MNG", 77);
   define("IMAGETYPE_XPM", 88);
   define("IMAGETYPE_ZIF", 90);
   define("IMAGETYPE_PBM", 80);
   define("IMAGETYPE_PGM", 81);
   define("IMAGETYPE_PPM", 82);
   function image_type_to_mime_type($id) {
      static $mime = array(
         IMAGETYPE_GIF => "gif",
         IMAGETYPE_JPEG => "jpeg",
         IMAGETYPE_PNG => "png",
         IMAGETYPE_SWF => "application/x-shockwave-flash",
         IMAGETYPE_BMP => "bmp",
         IMAGETYPE_JP2 => "jp2",
         IMAGETYPE_WBMP => "vnd.wap.wbmp",
         IMAGETYPE_XBM => "xbm",
         IMAGETYPE_PSD => "x-photoshop",
         IMAGETYPE_TIFF_II => "tiff",
         IMAGETYPE_TIFF_MM => "tiff",
         IMAGETYPE_JPC => "application/octet-stream",
         IMAGETYPE_JP2 => "jp2",
//         IMAGETYPE_JPX => "",
//         IMAGETYPE_JB2 => "",
         IMAGETYPE_SWC => "application/x-shockwave-flash",
         IMAGETYPE_IFF => "iff",
         IMAGETYPE_XPM => "x-xpm",
         IMAGETYPE_ZIF => "unknown",
         IMAGETYPE_MNG => "video/mng",
         IMAGETYPE_PBM => "x-portable-bitmap",
         IMAGETYPE_PGM => "x-portable-greymap",
         IMAGETYPE_PPM => "x-portable-pixmap",
      );
      if (isset($mime[$id])) {
         $m = $mime[$id];
         strpos($m, "/") || ($m = "image/$m");
      }
      else {
         $m = "image/unknown";
      }
      return($m);
   }
}

#-- still in CVS
if (!function_exists("image_type_to_extension")) {
   function image_type_to_extension($id, $dot=true) {
      static $ext = array(
         0=>false,
         1=>"gif", 2=>"jpeg", 3=>"png",
         "swf", "psd", "bmp",
         "tiff", "tiff",
         "jpc", "jp2", "jpx", "jb2",
         "swc", "wbmp", "xbm",
         77=>"mng", 88=>"xpm", 90=>"zif",
         80=>"pbm", 81=>"pgm", 82=>"ppm",
      );
      $m = $ext[$id];
      if ($m && $dot) {
         $m = ".$m";
      }
      return($m);
   }
}



#-- we need this then, too
if (!function_exists("exif_imagetype")) {
   function exif_imagetype($fn) {
      $magic = array(
         "\211PNG" => IMAGETYPE_PNG,
         "\377\330" => IMAGETYPE_JPEG,
         "GIF89a" => IMAGETYPE_GIF,
         "GIF94z" => IMAGETYPE_ZIF,
         "FWS" => IMAGETYPE_SWF,
         "II" => IMAGETYPE_TIFF_II,
         "MM" => IMAGETYPE_TIFF_MM,
         "/* XPM" => IMAGETYPE_XPM,
         "BM" => IMAGETYPE_BMP,  // also for OS/2
         "\212MNG" => IMAGETYPE_MNG,
         "P1" => IMAGETYPE_PBM,
         "P4" => IMAGETYPE_PBM,
         "P2" => IMAGETYPE_PGM,
         "P5" => IMAGETYPE_PGM,
         "P3" => IMAGETYPE_PPM,
         "P6" => IMAGETYPE_PPM,
      );
      if ($f = fopen($fn, "rb")) {
         $bin = fread($f, 8);
         fclose($f);
         foreach ($magic as $scn=>$id) {
            if (!strncmp($bin, $scn, strlen($scn))) {
               return $id;
            }
         }
      }
   }
}

?>

Added ext/unfinished/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. Will not be completed. Use PDO instead.\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
   //...

   

}


?>

Added ext/unfinished/posix.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
<?php
/*
   POSIX subsystem functions are emulated using regular commandline
   utilities or by invoking Perl.  Of course not the full spectrum
   of features can be simulated this way. You shouldn't rely on the
   emulation here, and just abort on PHP version without POSIX ext.
*/

if (!function_exists("posix_mkfifo") && strlen($_ENV["SHELL"]) && !ini_get("safe_mode")) {

   function posix_mkfifo($pathname, $mode=0400) {
      $cmd = "/usr/bin/mkfifo -m 0" . decoct($mode) . " " . escape_shell_arg($pathname);
      exec($cmd, $uu, $error);
      return(!$error);
   }
   
   function posix_getcwd() {
      return realpath(getcwd());
   }
   
   function posix_kill($pid, $sig) {
      $cmd = "kill -" . ((int)$sig) . " " . ((int)$pid);
      exec($cmd, $uu, $error);
      return(!$error);
   }

   function posix_uname() {
      return array(
         "sysname" => `/bin/uname -s`,
         "nodename" => `/bin/uname -n`,
         "release" => `/bin/uname -r`,
         "version" => `/bin/uname -v`,
         "machine" => `/bin/uname -m`,
         "domainname" => `/bin/domainname`,
      );
   }
}


?>

Added ext/xmlentities.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
<?php
/**
 * api: php
 * title: future PHP functions
 * descriptions: functions, that are not yet in php.net releases
 *
 *
 *  
 */



/**
 * @nonstandard
 *
 * Encodes required named XML entities. It's like htmlentities().
 * Doesn't re-encode or fix numeric entities.
 *
 * @param string
 * @return string
 */
if (!function_exists("xmlentities")) {
   function xmlentities($str) {
      return strtr($str, array(
        "&#"=>"&#", "&"=>"&amp;", "'"=>"&apos;",
        "<"=>"&lt;", ">"=>"&gt;", "\""=>"&quot;", 
      ));
   }
}


?>

Deleted tests/_listemulated.

1
2
3
4
5
6
7
8
9
10
<?php

include("../upgrade.php");

$r = get_defined_functions();
$r = $r["user"];
echo "emulated functions are:\n";
print_r($r);

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




















Deleted tests/_runparts.

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
#!/bin/bash

#-- params
if [ -z "$1" ]
then
   echo "syntax:  _runparts [php412] [php501]  | more"
   echo "Runs all PHP scripts in the tests/ directory with two interpreter versions"
   echo "side by side, for comparison. If you don't have two of them installed, you"
   echo "could simply specify 'cat' or 'false' as the second argument."
else

   #-- go
   cd `dirname $0`
   OLD=$1
   NEW=$2
   [ -z "$NEW" ] && NEW="cat"
   for SCRIPT in *
   do
      $OLD $SCRIPT | tr -d "\r" | fmt -w 36 -s > /tmp/1
      $NEW $SCRIPT | tr -d "\r" | fmt -w 36 -s > /tmp/2
      echo "-----------------------------------------------------------------"
      echo "$SCRIPT"
      echo "-----------------------------------------------------------------"
      pr -m --columns=2 -t  /tmp/1 /tmp/2
      echo "--"
   done

fi   
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































Deleted tests/array_change_key_case.

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

include("../upgrade.php");

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

?>


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


























Deleted tests/array_chunk.

1
2
3
4
5
6
7
8
9
10
11
12
<?php

include("../upgrade.php");

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

?>


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
























Deleted tests/array_combine.

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

include("../upgrade.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);
?>

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






































Deleted tests/array_diff_assoc.

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

include("../upgrade.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);
?>

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




































Deleted tests/array_fill.

1
2
3
4
5
6
7
8
9
10
<?php

include("../upgrade.php");

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

?>

<
<
<
<
<
<
<
<
<
<




















Deleted tests/array_intersect_assoc.

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

include("../upgrade.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);
?>

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


































Deleted tests/array_udiff_uassoc.

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
<?php

include("../ext/array.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";
}

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












































































































Deleted tests/array_walk_recursive.

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
<?php

include("../upgrade.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);

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




















































Deleted tests/base16.

1
2
3
4
5
6
7
8
<?php
include "../ext/base64.php";

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

?>
<
<
<
<
<
<
<
<
















Deleted tests/bcmath.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

include("../ext/bcmath.php");

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

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

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




























Deleted tests/class_parents.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

include("../upgrade.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);

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






























Deleted tests/file_put_contents.

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

include("../upgrade.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);

?>


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


































Deleted tests/floatval.

1
2
3
4
5
6
7
8
floatval("1234.567abc") = <?php

include("../upgrade.php");

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

?>
<
<
<
<
<
<
<
<
















Deleted tests/fmod.

1
2
3
4
5
6
7
8
<?php

include("../upgrade.php");

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

?>
<
<
<
<
<
<
<
<
















Deleted tests/fnmatch.

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

include("../upgrade.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);

?>


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


































Deleted tests/get_headers.

1
2
3
4
5
6
7
8
<?php

include("../upgrade.php");

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

?>
<
<
<
<
<
<
<
<
















Deleted tests/gettext.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

include("../ext/gettext.php");

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

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

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






























Deleted tests/glob.

1
2
3
4
5
6
7
8
9
10
11
<?php

include("../upgrade.php");

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


?>

<
<
<
<
<
<
<
<
<
<
<






















Deleted tests/gzdecode.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

include("../upgrade.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";


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






























Deleted tests/headers_list.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

include("../upgrade.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);

?>


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
































Deleted tests/html_entity_decode.

1
2
3
4
5
6
7
8
9
10
<?php

include("../upgrade.php");

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

?>


<
<
<
<
<
<
<
<
<
<




















Deleted tests/http_build_query.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

include("../upgrade.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_");
?>


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






























Deleted tests/is_a.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

include("../upgrade.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";

?>


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






























Deleted tests/json.

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

include("../upgrade.php");

$a = array(
  "x" => "y",
  "text" => "Hallφchen
",
  "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";

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












































Deleted tests/json2.

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
<?php

include("../upgrade.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);

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




















































































Deleted tests/md5_file.

1
2
3
4
5
6
7
8
9
md5_file(__FILE__) = <?php

include("../upgrade.php");

echo md5_file(__FILE__);

?>


<
<
<
<
<
<
<
<
<


















Deleted tests/mhash.

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

include("../upgrade.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";



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






















































Deleted tests/mime_content_type.

1
2
3
4
5
6
7
8
9
<?php

include("../upgrade.php");
include("../ext/mime.php");

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

?>
<
<
<
<
<
<
<
<
<


















Deleted tests/scandir.

1
2
3
4
5
6
7
8
9
<?php

include("../upgrade.php");

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

?>
<
<
<
<
<
<
<
<
<


















Deleted tests/spl_classes.

1
2
3
4
5
6
7
8
9
<?php

include("../upgrade.php");

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

?>
<
<
<
<
<
<
<
<
<


















Deleted tests/str_ireplace.

1
2
3
4
5
6
7
8
9
10
11
12
<?php

include("../upgrade.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";

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
























Deleted tests/str_rot13.

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

include("../upgrade.php");

echo str_rot13('upgrade.php v4');

?>"


<
<
<
<
<
<
<
<
<


















Deleted tests/str_shuffle.

1
2
3
4
5
6
7
8
9
10
str_shuffle("ABCDEF") == "<?php

include("../upgrade.php");

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

?>"


<
<
<
<
<
<
<
<
<
<




















Deleted tests/str_split.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

include("../upgrade.php");


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

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






























Deleted tests/str_word_count.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

include("../upgrade.php");


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


?>



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




























Deleted tests/strftime.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

include("../upgrade.php");


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

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

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


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






























Deleted tests/stripos.

1
2
3
4
5
6
7
8
9
10
11
<?php

include("../upgrade.php");

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

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

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






















Deleted tests/strpbrk.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

include("../upgrade.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";
?>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























Deleted tests/strripos.

1
2
3
4
5
6
7
8
9
10
<?php

include("../upgrade.php");

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

?>


<
<
<
<
<
<
<
<
<
<




















Deleted tests/substr_compare.

1
2
3
4
5
6
7
8
9
10
11
12
<?php

include("../upgrade.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";
?>
<
<
<
<
<
<
<
<
<
<
<
<
























Deleted tests/uuencode.

1
2
3
4
5
6
7
8
9
10
11
<?php

include("../upgrade.php");

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

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

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






















Deleted tests/vprintf.

1
2
3
4
5
6
7
8
<?php

include("../upgrade.php");

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

?>

<
<
<
<
<
<
<
<
















Changes to upgrade.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
<?php
/**
 * api:		php
 * title:	upgrade.php
 * description:	backwards compatibility for older PHP interpreters
 * version:	14
 * license:	Public Domain
 * url:		http://freshmeat.net/p/upgradephp
 * type:	functions
 * category:	library
 * priority:	auto

 * sort:	-200
 * provides:	upgrade-php
 *
 *
 * You get PHP version independence by including() this script. It provides
 * downwards compatibility to older PHP installations by emulating missing
 * functions or constants using IDENTICAL NAMES. So this doesn't slow down
 * script execution on setups where the native functions already exist. It
 * is meant as quick drop-in solution, and to free you from rewriting or
 * cumbersome workarounds - instead of using the real & more powerful funcs.
 * 
 * It cannot mirror PHP5s extended OO-semantics and functionality into PHP4
 * however. A few features are added here that weren't part of PHP yet. And
 * some other function collections are separated out into the ext/ directory.


 * 
 * And further this is PUBLIC DOMAIN (no copyright, no license, no warranty)
 * so threrefore compatible to ALL open source licenses. You could rip this
 * paragraph out to republish this instead only under more restrictive terms
 * or your favorite license (GNU LGPL/GPL, BSDL, MPL/CDDL, Artist, PHPL, ...)
 *
 * Get update notes via "http://freshmeat.net/projects/upgradephp" or
 * google for it. Any contribution is appreciated. <milky*users·sf·net>






































































































 *




 */






















































































































































































































































/**



























































 *                                   ------------------------------ CVS ---
 * @group CVS
 * @since CVS
 *
 * planned, but as of yet unimplemented functions
 * - some of these might appear in 6.0 or ParrotPHP
 *
 * @emulated








 *    sys_get_temp_dir





 *


















 */



































































































































































































































/**
 * returns path of the system directory for temporary files

 *
 */
if (!function_exists("sys_get_temp_dir")) {



   function sys_get_temp_dir() {





      # check possible alternatives
      ($temp = ini_get("temp_dir"))
      or
      ($temp = $_SERVER["TEMP"])











      or
      ($temp = $_SERVER["TMP"])
      or
      ($temp = "/tmp");
      # fin
      return($temp);
   }
}





/**
 *                                   ------------------------------ 5.2 ---
 * @group 5_2
 * @since 5.2
 *
 * Additions of PHP 5.2.0
 * - some listed here, might have appeared earlier or in release candidates
 *
 * @emulated
 *    json_encode
 *    json_decode
 *    error_get_last
 *    preg_last_error
 *    lchown
 *    lchgrp
 *    E_RECOVERABLE_ERROR
 *    M_SQRTPI
 *    M_LNPI
 *    M_EULER
 *    M_SQRT3
 *

 * @missing
 *    sys_getloadavg
 *    inet_ntop
 *    inet_pton
 *    array_fill_keys
 *    array_intersect_key
 *    array_intersect_ukey
 *    array_diff_key
 *    array_diff_ukey

 *    array_product
 *    pdo_drivers
 *    ftp_ssl_connect
 *    XmlReader
 *    XmlWriter
 *    PDO*

 *
 * @unimplementable
 *    stream_*
 *
 */





/**
 * @since unknown
 */
if (!defined("E_RECOVERABLE_ERROR")) { define("E_RECOVERABLE_ERROR", 4096); }



/**
 * Converts PHP variable or array into "JSON" (a JavaScript value expression
 * or "object notation").
 *
 * @compat
 *    output seems identical to PECL versions
 * @bugs
 *    doesn't take care with unicode too much
 *


 */















if (!function_exists("json_encode")) {
   function json_encode($var, /*emu_args*/$obj=FALSE) {


   
      #-- prepare JSON string


      $json = "";




      
      #-- add array entries
      if (is_array($var) || ($obj=is_object($var))) {

         #-- check if array is associative
         if (!$obj) foreach ((array)$var as $i=>$v) {
            if (!is_int($i)) {
               $obj = 1;
               break;
            }
         }

         #-- concat invidual entries

         foreach ((array)$var as $i=>$v) {
            $json .= ($json ? "," : "")    // comma separators
                   . ($obj ? ("\"$i\":") : "")   // assoc prefix
                   . (json_encode($v));    // value
         }

         #-- enclose into braces or brackets
         $json = $obj ? "{".$json."}" : "[".$json."]";
      }

      #-- strings need some care
      elseif (is_string($var)) {

         if (!utf8_decode($var)) {

            $var = utf8_encode($var);
         }















         $var = str_replace(array("\"", "\\", "/", "\b", "\f", "\n", "\r", "\t"), array("\\\"", "\\\\", "\\/", "\\b", "\\f", "\\n", "\\r", "\\t"), $var);




         $json = '"' . $var . '"';
      }

      #-- basic types
      elseif (is_bool($var)) {
         $json = $var ? "true" : "false";
      }
      elseif ($var === NULL) {
         $json = "null";
      }
      elseif (is_int($var) || is_float($var)) {
         $json = "$var";









      }

      #-- something went wrong
      else {
         trigger_error("json_encode: don't know what a '" .gettype($var). "' is.", E_USER_ERROR);


      }
      
      #-- done
      return($json);
   }
}



/**
 * Parses JSON (JavaScript value expression) into PHP variable
 * (array or object).
 *
 * @compat
 *    behaves similiar to PECL version
 *    but is less quiet on errors

 *    might ignore some misformed representations
 * @bugs


 *    doesn't decode unicode \uXXXX string escapes



 *



 */
if (!function_exists("json_decode")) {





   function json_decode($json, $assoc=FALSE, /*emu_args*/$n=0,$state=0,$waitfor=0) {









      #-- result var
      $val = NULL;








      static $lang_eq = array("true" => TRUE, "false" => FALSE, "null" => NULL);
      static $str_eq = array("n"=>"\012", "r"=>"\015", "\\"=>"\\", '"'=>'"', "f"=>"\f", "b"=>"\b", "t"=>"\t", "/"=>"/");







      #-- flat char-wise parsing
      for (/*n*/; $n<strlen($json); /*n*/) {
         $c = $json[$n];

         #-= in-string
         if ($state==='"') {

            if ($c == '\\') {
               $c = $json[++$n];


               if (isset($str_eq[$c])) {
                  $val .= $str_eq[$c];
               }


               elseif ($c == "u") {























                  $val .= "\\u";
               }



               else {
                  $val .= "\\" . $c;



               }
            }


            elseif ($c == '"') {
               $state = 0;
            }
            else {







               $val .= $c;
            }
         }

         #-> end of sub-call (array/object)
         elseif ($waitfor && (strpos($waitfor, $c) !== false)) {
            return array($val, $n);  // return current value and state
         }
         
         #-= in-array
         elseif ($state===']') {
            list($v, $n) = json_decode($json, 0, $n, 0, ",]");
            $val[] = $v;
            if ($json[$n] == "]") { return array($val, $n); }
         }

         #-= in-object
         elseif ($state==='}') {






            list($i, $n) = json_decode($json, 0, $n, 0, ":");   // this allowed non-string indicies


            list($v, $n) = json_decode($json, 0, $n+1, 0, ",}");
            $val[$i] = $v;
            if ($json[$n] == "}") { return array($val, $n); }
         }

         #-- looking for next item (0)
         else {
         
            #-> whitesapce
            if (preg_match("/\s/", $c)) {
               // skip
            }

            #-> string begin
            elseif ($c == '"') {
               $state = '"';
            }

            #-> object
            elseif ($c == "{") {
               list($val, $n) = json_decode($json, $assoc, $n+1, '}', "}");

               if ($val && $n && !$assoc) {
                  $obj = new stdClass();
                  foreach ($val as $i=>$v) {
                     $obj->{$i} = $v;
                  }
                  $val = $obj;
                  unset($obj);
               }
            }
            #-> array
            elseif ($c == "[") {
               list($val, $n) = json_decode($json, $assoc, $n+1, ']', "]");
            }

            #-> comment
            elseif (($c == "/") && ($json[$n+1]=="*")) {
               // just find end, skip over
               ($n = strpos($json, "*/", $n+1)) or ($n = strlen($json));
            }

            #-> numbers
            elseif (preg_match("#^(-?\d+(?:\.\d+)?)(?:[eE](-?\d+))?#", substr($json, $n), $uu)) {
               $val = $uu[1];
               $n += strlen($uu[0]) - 1;
               $val = strpos($val, ".") ? (float)$val : (int)$val;


















               if (isset($uu[2])) {
                  $val *= pow(10, (int)$uu[2]);
               }
            }

            #-> boolean or null
            elseif (preg_match("#^(true|false|null)\b#", substr($json, $n), $uu)) {
               $val = $lang_eq[$uu[1]];
               $n += strlen($uu[1]) - 1;
            }












            #-- parsing error
            else {
               // PHPs native json_decode() breaks here usually and QUIETLY
              trigger_error("json_decode: error parsing '$c' at position $n", E_USER_WARNING);

               return $waitfor ? array(NULL, 1<<30) : NULL;
            }

         }//state
         
         #-- next char
         if ($n === NULL) { return NULL; }
         $n++;
      }//for

      #-- final result
      return ($val);
   }
}




























/**
 * @stub
 * @cannot-reimplement


 *
 */
if (!function_exists("preg_last_error")) {
   if (!defined("PREG_NO_ERROR")) { define("PREG_NO_ERROR", 0); }
   if (!defined("PREG_INTERNAL_ERROR")) { define("PREG_INTERNAL_ERROR", 1); }
   if (!defined("PREG_BACKTRACK_LIMIT_ERROR")) { define("PREG_BACKTRACK_LIMIT_ERROR", 2); }
   if (!defined("PREG_RECURSION_LIMIT_ERROR")) { define("PREG_RECURSION_LIMIT_ERROR", 3); }
   if (!defined("PREG_BAD_UTF8_ERROR")) { define("PREG_BAD_UTF8_ERROR", 4); }
   function preg_last_error() {
      return PREG_NO_ERROR;
   }
}




























/**
 * @stub
 *
 * Returns associative array with last error message.
 *
 */
if (!function_exists("error_get_last")) {
   function error_get_last() {
      return array(
         "type" => 0,
         "message" => $GLOBALS[php_errormsg],
         "file" => "unknonw",
         "line" => 0,
      );
   }
}




/**
 * @flag quirky, exec
 *
 * Change owner/group of a symlink filename.
 *
 */
if (!function_exists("lchown")) {
   function lchown($fn, $user) {
      if (PHP_OS != "Linux") {
         return false;
      }
      $user = escapeshellcmd($user);
      $fn = escapeshellcmd($fn);
      exec("chown -h '$user' '$fn'", $uu, $state);
      return($state);
   }
}









if (!function_exists("lchgrp")) {
   function lchgrp($fn, $group) {
      return lchown($fn, ":$group");
   }
}


































































































































































































/**
 *                                   ------------------------------ 5.1 ---
 * @group 5_1
 * @since 5.1
 *
 * Additions in PHP 5.1
 * - most functions here appeared in -rc1 already
 * - and were backported to 4.4 series?
 *
 * @emulated

 *    property_exists
 *    time_sleep_until
 *    fputcsv
 *    strptime
 *    ENT_COMPAT
 *    ENT_QUOTES
 *    ENT_NOQUOTES




|
|

|



>
|
|


|
|


|
|




>
>


|

|

<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|

|
<


>
>
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>


|
>
>
>
|
>
>
>
>
>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|











|













|
>
|
|


<


|
<
>
|
|




>





>
>











|
|


|

|

>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
|

>
>
|
>
>
>
>





|
|
|
<
|
|
<
|
>

|
|
|



|




>
|
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>










|

>
>
>
>
>
>
>
>
>




|
>
>








<

|



<
|
>
|

>
>
|
>
>
>

>
>
>


>
>
>
>
>
|
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>

|
|
>
>
>
>
>
>

|



|
>


>
>



>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>

|
>
>
>


>
>
|


|
>
>
>
>
>
>
>











|






>
>
>
>
>
>
|
>
>
|







|






|




|
>
|
<
|
<
|
<
<
|
|


|
<
<
<
<
<
<



|


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










>
>
>
>
>
>
>
>
>
>
>




|
>
|





|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




<
>
>















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|






|










|

|













>
>
>
>
>
>
>
>
>








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














>







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
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
<?php
/**
 * api:		php
 * title:	upgrade.php
 * description:	Emulates functions from new PHP versions on older interpreters.
 * version:	19.1
 * license:	Public Domain
 * url:		http://freshmeat.net/projects/upgradephp
 * type:	functions
 * category:	library
 * priority:	auto
 * load_if:     (PHP_VERSION<5.2)
 * sort:	-255
 * provides:	upgrade-php, api:php5, json
 *
 *
 * By loading this library you get PHP version independence. It provides
 * downwards compatibility to older PHP interpreters by emulating missing
 * functions or constants using IDENTICAL NAMES. So this doesn't slow down
 * script execution on setups where the native functions already exist. It
 * is meant as quick drop-in solution. It spares you from rewriting code or
 * using cumbersome workarounds instead of the more powerful v5 functions.
 * 
 * It cannot mirror PHP5s extended OO-semantics and functionality into PHP4
 * however. A few features are added here that weren't part of PHP yet. And
 * some other function collections are separated out into the ext/ directory.
 * It doesn't produce many custom error messages (YAGNI), and instead leaves
 * reporting to invoked functions or for native PHP execution.
 * 
 * And further this is PUBLIC DOMAIN (no copyright, no license, no warranty)
 * so therefore compatible to ALL open source licenses. You could rip this
 * paragraph out to republish this instead only under more restrictive terms
 * or your favorite license (GNU LGPL/GPL, BSDL, MPL/CDDL, Artistic/PHPL, ..)
 *

 * Any contribution is appreciated. <milky*users#sf#net>
 *
 */





/**
 *                                   -------------------------- FUTURE ---
 * @group SVN
 * @since future
 *
 * Following functions aren't implemented in current PHP versions, but
 * might already be in CVS/SVN.
 *
 * @removed
 *    setcookie2
 *
 */



/**
 *                                   ------------------------ OVERRIDE ---
 *
 */
if (defined("UPGRADEPHP_OVERRIDE") and function_exists("runkit_function_remove")) {
   ini_set("runkit.internal_override", 1);
   runkit_function_rename("json_encode", "php::json_encode");
   runkit_function_rename("json_decode", "php::json_encode");
 }

/**
 *                                   ----------------------------- 5.5 ---
 * @group 5_5
 * @since 5.5
 *
 * Extensions in PHP 5.5
 *
 * @emulated
 *    boolval
 *    array_column
 *    json_last_error_msg
 *
 * @missing
 *    date_create_immutable
 *    date_create_immutable_from_format
 *    openssl_pbkdf2
 *    hash_pbkdf2
 *
 */




/**
 * Creates a new array from excerpting columns from a list of arrays. Optionally
 * uses a key column from there for indexing.
 *
 * Full reimplementation at https://github.com/ramsey/array_column/blob/master/src/array_column.php
 *
 */
if (!function_exists("array_column")) {
   function array_column($array, $column, $key=NULL) {

      $result = array();
      assert('isset($column) /*array_column() expects two params*/')
      and assert('is_scalar($column) && is_scalar($key) /*array_column() key and column should be ints/strings*/')
      and assert('is_array($array) /*array_column() input array isn\'t one*/');

      // traverse array
      foreach ($array as $row) {
         if (isset($row[$column])) {
       
            // fetch as ordered list 
            if (($key === NULL) || !isset($row[$key]))  {   // this is odd in the native implementation, if the $key column is absent, it just appends
               $result[] = $row[$column];
            }   
           
            // or retain key value from another column for indexing
            else {
               //isset($result[$row[$key]]) and trigger_error("array_column(): a key occured twice, value was overwritten", E_USER_NOTICE);
               $result[ $row[$key] ] = $row[$column];
            }
         }
      }
      return $result;
   }
}


/**
 * That's basically just a typecast. Returns the PHP-interpreted booleanish equivalent of values.
 * Just exists for parity with intval/floatval/etc.
 *
 */
if (!function_exists("boolval")) {
   function boolval($var) {
      return (bool)$var;
   }
}



/**
 * Convert json_last_error() numbers into readable string:
 *
 */
if (!function_exists("json_last_error_msg")) {
   function json_last_error_msg($num) {
      $msgs = array(
         JSON_ERROR_NONE => "No error has occurred",
         JSON_ERROR_DEPTH => "The maximum stack depth has been exceeded",
         JSON_ERROR_STATE_MISMATCH => "Invalid or malformed JSON",
         JSON_ERROR_CTRL_CHAR => "Control character error, possibly incorrectly encoded",
         JSON_ERROR_SYNTAX => "Syntax error",
         JSON_ERROR_UTF8 => "Malformed UTF-8 characters, possibly incorrectly encoded",
         JSON_ERROR_RECURSION => "One or more recursive references in the value to be encoded",
         JSON_ERROR_INF_OR_NAN => "One or more NAN or INF values in the value to be encoded",
         JSON_ERROR_UNSUPPORTED_TYPE => "A value of a type that cannot be encoded was given",
      );
      return $msgs[$num];
   }
}






/**
 *                                   ----------------------------- 5.4 ---
 * @group 5_4
 * @since 5.4
 *
 * Extensions in PHP 5.4
 *
 * @emulated
 *    gzdecode
 *    hex2bin
 *    session_status -> basic probing
 *
 * @stub
 *    class_uses
 *    trait_exists
 *    get_declared_traits
 *
 * @missing
 *    libxml_set_external_entity_loader
 *    zlib_encode -> PHP_ZLIB_ENCODE_FUNC(zlib_encode, 0);
 *    zlib_decode -> PHP_ZLIB_DECODE_FUNC(zlib_decode, PHP_ZLIB_ENCODING_ANY);
 *    session_register_shutdown
 *    socket_import_stream
 *    getimagesizefromstring
 *    header_register_callback
 *    http_response_code
 *    stream_set_chunk_size
 *    CallbackFilterIterator
 *    RecursiveCallbackFilterIterator
 *    SessionHandler
 *    ReflectionZendExtension
 *
 * @unimplementable
 *    imageantialias
 *    imagelayereffect
 *
 */



/**
 * Simple convenience function for pack H*,
 * Converts a hextuplet string into its binary representation.
 *
 */
if (!function_exists("hex2bin")) {
   function hex2bin($hex) {
       return pack("H*", $hex);
   }
}



/**
 * Set or get HTTP status code.
 *
 */
if (!function_exists("http_response_code")) {
   function http_response_code($which=NULL) {

       $cgi = ini_get("cgi.rfc2616_headers");
       $headers = preg_grep("#^Status:|^HTTP/\d\.\d#i", headers_list());

       # override       
       if ($which >= 100 and $which <= 999) {
           if ($headers) {
               header_remove(current($headers));
           }
           # implicit notices for headers_sent()
           header($cgi ? "HTTP/1.0 $which n/a" : "Status: $which n/a");
       }
       # get current
       elseif ($which == NULL) {
           if (!$headers || !preg_match("/\d\d\d/", current($headers), $m)) {
               return 200; #default
           }
           return intval($m[0]);
       }
       else trigger_error("invalid status number", E_USER_WARNING);
   }
}



/**
 * Sends a Location: header. Unlike the PHP-builtin, it won't complete relative URLs.
 * So it's RFC6616 compliant, not anal about the original HTTP/1.1 revision RFC2616.
 * The <meta> fallback is also extraneous.
 * Belongs to http extensions actually. (Will be grouped out in later upgradephp revision.)
 *
 */
if (!function_exists("http_redirect")) {
   function http_redirect($url, $params=array(), $session=false, $status=0) {
       if ($session) {
           $params[session_name()] = session_id();
       }
       if ($params) {
           $url .= strstr($url, "?") ? "&" : "?";
           $url .= http_build_query($params);
       }
       header("Location: $url"); #, $status ? $status : 301);
       $url = htmlspecialchars($url, ENT_QUOTES, "UTF-8");
       print "Redirecting to <a href=\"$url\">$url</a>\n";
       print "<meta http-equiv=\"Location\" content=\"$url\" />\n";
       exit; // built-in exit
   }
}



/**
 * Sends a Content-Type: header
 * Belongs to http extensions actually. (Will be grouped out in later upgradephp revision.)
 *
 */
if (!function_exists("http_send_content_type")) {
   function http_send_content_type($content_type="application/x-octetstream") {
       return header("Content-Type: $content_type");
   }
}



/**
 * @stub
 * Traits (partial classes, elaborate syntactic and academic workaround, because MI is
 * hard to implement in *compiled* languages) cannot be emulated in older interpreters.
 *
 */
if (!function_exists("class_uses")) {
   function class_uses($trait) {
       return false;
   }
}
if (!function_exists("trait_exists")) {
   function trait_exists($trait) {
       return false;
   }
}
if (!function_exists("get_declared_traits")) {
   function get_declared_traits($trait) {
       return (array)NULL;
   }
}



/**
 * Long predicted, officially available @since 5.4.
 *
 * Inflates a string enriched with gzip headers. Counterpart to gzencode().
 *
 */
if (!function_exists("gzdecode")) {
   function gzdecode($gzdata, $maxlen=NULL) {

      #-- decode header
      $len = strlen($gzdata);
      if ($len < 20) {
         return;
      }
      $head = substr($gzdata, 0, 10);
      $head = unpack("n1id/C1cm/C1flg/V1mtime/C1xfl/C1os", $head);
      list($ID, $CM, $FLG, $MTIME, $XFL, $OS) = array_values($head);
      $FTEXT = 1<<0;
      $FHCRC = 1<<1;
      $FEXTRA = 1<<2;
      $FNAME = 1<<3;
      $FCOMMENT = 1<<4;
      $head = unpack("V1crc/V1isize", substr($gzdata, $len-8, 8));
      list($CRC32, $ISIZE) = array_values($head);

      #-- check gzip stream identifier
      if ($ID != 0x1f8b) {
         trigger_error("gzdecode: not in gzip format", E_USER_WARNING);
         return;
      }
      #-- check for deflate algorithm
      if ($CM != 8) {
         trigger_error("gzdecode: cannot decode anything but deflated streams", E_USER_WARNING);
         return;
      }

      #-- start of data, skip bonus fields
      $s = 10;
      if ($FLG & $FEXTRA) {
         $s += $XFL;
      }
      if ($FLG & $FNAME) {
         $s = strpos($gzdata, "\000", $s) + 1;
      }
      if ($FLG & $FCOMMENT) {
         $s = strpos($gzdata, "\000", $s) + 1;
      }
      if ($FLG & $FHCRC) {
         $s += 2;  // cannot check
      }
      
      #-- get data, uncompress
      $gzdata = substr($gzdata, $s, $len-$s);
      if ($maxlen) {
         $gzdata = gzinflate($gzdata, $maxlen);
         return($gzdata);  // no checks(?!)
      }
      else {
         $gzdata = gzinflate($gzdata);
      }
      
      #-- check+fin
      $chk = crc32($gzdata);
      if ($CRC32 != $chk) {
         trigger_error("gzdecode: checksum failed (real$chk != comp$CRC32)", E_USER_WARNING);
      }
      elseif ($ISIZE != strlen($gzdata)) {
         trigger_error("gzdecode: stream size mismatch", E_USER_WARNING);
      }
      else {
         return($gzdata);
      }
   }
}



/**
 * Probes for format(?) before decoding with one of the gz* functions.
 *
 */
if (!function_exists("zlib_decode")) {
   function zlib_decode($data) {
       if (!strncmp($data, "\x1F\x8B", 2)) {
           return gzdecode($data);
       }
       elseif (!strncmp($data, "\x78\x9C", 2)) {
           return gzuncompress($data);
       }
       else {
           return gzinflate($data);
       }
   }
}

/**
 * Weird constants, not documented in the manual yet, but that's how the function declaration looks.
 *
 */
if (!function_exists("zlib_encode")) {
   define("ZLIB_ENCODING_DEFLATE", 15);
   define("ZLIB_ENCODING_RAW", -15);
   define("ZLIB_ENCODING_GZIP", 31);
   function zlib_encode($data, $method) {
       if ($method == ZLIB_ENCODING_RAW) {
           return gzdeflate($data);
       }
       elseif ($method == ZLIB_ENCODING_DEFLATE) {
           return gzcompress($data);
       }
       elseif ($method == ZLIB_ENCODING_GZIP) {
           return gzencode($data);
       }
       else trigger_error("encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE", E_USER_WARNING);
   }
}


/**
 * @stub Tests whether a session is established.
 *
 */
if (!function_exists("session_status")) {
   define("PHP_SESSION_DISABLED", 0);
   define("PHP_SESSION_NONE", 1);
   define("PHP_SESSION_ACTIVE", 2);
   function session_status() {
       return (ini_get("session.name") != "") ? PHP_SESSION_DISABLED : 
           (isset($_SESSION) ? PHP_SESSION_ACTIVE : PHP_SESSION_NONE);
   }
}





/**
 *                                   ----------------------------- 5.3 ---
 * @group 5_3
 * @since 5.3
 *
 * Known additions of PHP 5.3

 *
 * @emulated
 *    ob_get_headers (stub)
 *    preg_filter
 *    lcfirst
 *    class_alias
 *    header_remove
 *    parse_ini_string
 *    array_replace
 *    array_replace_recursive
 *    str_getcsv
 *    forward_static_call
 *    forward_static_call_array
 *    quoted_printable_encode
 *    E_DEPRECATED
 *    E_USER_DEPRECATED
 *
 * @missing
 *    get_called_class
 *    stream_context_get_params
 *    stream_context_set_default
 *    stream_supports_lock
 *    hash_copy
 *    date_create_from_format
 *    date_parse_from_format
 *    date_get_last_errors
 *    date_add
 *    date_sub
 *    date_diff
 *    date_timestamp_set
 *    date_timestamp_get
 *    timezone_location_get
 *    date_interval_create_from_date_string
 *    date_interval_format
 *
 */



/**
 * @since PHP 5.3.0
 */
if (!defined('E_DEPRECATED')) { define('E_DEPRECATED', 8192); }
if (!defined('E_USER_DEPRECATED')) { define('E_USER_DEPRECATED', 16384); }


/**
 * preg_replace() variant, which filters out any unmatched $subject.
 *
 */
if (!function_exists("preg_filter")) {
   function preg_filter($pattern, $replacement, $subject, $limit=-1, $count=NULL) {

      // just do the replacing first, and eventually filter later
      $r = preg_replace($pattern, $replacement, $subject, $limit, $count);

      // look at subject lines one-by-one, remove from result per index
      foreach ((array)$subject as $si=>$s) {
         $any = 0;
         foreach ((array)$pattern as $p) {
            $any = $any ||preg_match($p, $s);
         }
         // remove if NONE of the patterns matched
         if (!$any) {
            if (is_array($r)) {
               unset($r[$si]);  // del from result array
            }
            else {
               return NULL;  // subject was a str
            }
         }
      }

      return $r;    // is already string if $subject was too
   }
}



/**
 * Lowercase first character.
 *
 * @param string
 * @return string
 */
if (!function_exists("lcfirst")) {
   function lcfirst($str) {
      return strlen($str) ? strtolower($str[0]) . substr($str, 1) : "";
   }
}



/**
 * @stub  cannot be emulated, because output buffering functions
 *        already swallow up any sent http header
 * @since 5.3.?
 *
 * get all ob_ soaked headers(),
 *
 */
if (!function_exists("ob_get_headers")) {
   function ob_get_headers() {
      return (array)NULL;
   }
}



/**
 * @stub  Cannot be emulated correctly, but let's try.
 *
 */
if (!function_exists("header_remove")) {
   function header_remove($name="") {
      if (strlen($name) and ($name = preg_replace("/[^-_.\w\d]+/", "", $name))) header("$name: \t");
      // Apache1.3? removed duplettes, empty header overrides previous.
      // ONLY if case was identical to previous header() call. (Very uncertain for applications which need to resort to such code smell.)
   }
}



/**
 * WTF?
 * At least an explaning reference was available on the php.net manual.
 * Why the parameters are supposed to be optional is a mystery.
 *
 */
if (!function_exists("class_alias")) {
   function class_alias($original, $alias) {
      $abstract = "";
      if (class_exists("ReflectionClass")) {
         $oc = new ReflectionClass($original);
         $abstract = $oc->isAbstract() ? "abstract" : "";
      }
      eval("$abstract class $alias extends $original { /* identical subclass */ }");
      return get_parent_class($alias) == $original;
   }
}




/**
 * Hey, reimplementin is fun.
 * (Could have used a data: wrapper for parse_ini_file, but that wouldn't work for php<5.2, and the data:// (!) wrapper is flaky anyway.)
 *
 */
if (!function_exists("parse_ini_string")) {
   function parse_ini_string($ini, $sectioned=false, $raw=0) {
      $r = array();
      $map = array("true"=>1, "yes"=>1, "1"=>1, "null"=>"", "false"=>"", "no"=>"", "0"=>0);
      $section = "";
      foreach (explode("\n", $ini) as $line) {
         if (!strlen($line)) {
         }
         // handle [sections]
         elseif (($line[0] == "[") and preg_match("/\[([-_\w ]+)\]/", $line, $uu)) {
            $section = $uu[1];
         }
         elseif (/*deprecated*/($line[0] != "#") && ($line[0] != ";") && ($i = strpos($line, "="))) {
            // key=value split
            $n = trim(substr($line, 0, $i));
            $v = trim(substr($line, $i+1));
            // replace special values
            if (!$raw) {
               $v=trim($v, '"');   // should actually use regex, to handle key="..\n.." multiline values
               $v=trim($v, "'");
               if (isset($map[$v])) {
                  $v=$map[$v];
               }
            }
            // special array[]= keys allowed
            if ($i = strpos($n, "[")) {
               $r[$section][substr($n, 0, $i)][] = $v;
            }
            else {
               $r[$section][$n] = $v;
            }
         }
      }
      return $sectioned ? $r : call_user_func_array("array_merge", $r);
   }
}




/**
 * Inject values from supplemental arrays into $target, according to its keys.
 *
 * @param array  $targt
 * @param+ array $supplements
 * @return array
 */
if (!function_exists("array_replace")) {
   function array_replace(/* & (?) */$target/*, $from, $from2, ...*/) {
      $merge = func_get_args();
      array_shift($merge);
      foreach ($merge as $add) {
         foreach ($add as $i=>$v) {
            $target[$i] = $v;
         }
      }
      return $target;
   }
}


/**
 * Descends into sub-arrays when replacing values by key in $target array.
 *
 */
if (!function_exists("array_replace_recursive")) {
   function array_replace_recursive($target/*, $from1, $from2, ...*/) {
      $merge = func_get_args();
      array_shift($merge);

      // loop through all merge arrays
      foreach ($merge as $from) {
         foreach ($from as $i=>$v) {
            // just add (wether array or scalar) if key does not exist yet
            if (!isset($target[$i])) {
               $target[$i] = $v;
            }
            // dive in
            elseif (is_array($v) && is_array($target[$i])) {
               $target[$i] = array_replace_recursive($target[$i], $v);
            }
            // replace
            else {
               $target[$i] = $v;
            }
         }
      }
      return $target;
   }
}




/**
 * Breaks up a SINGLE LINE in CSV format.
 * abc,123,"text with spaces",xy,"\""
 *
 */
if (!function_exists("str_getcsv")) {
   function str_getcsv($line, $del=",", $q='"', $esc="\\", $rm_spaces="\s*") {
      $line = rtrim($line, "\r\n");
      preg_match_all("/\G $rm_spaces ([^$q$del]*?) $rm_spaces $del | $q(( [$esc$esc][$q]|[^$q]* )+)$q \s* $del /xms", $line.$del, $r);
      foreach ($r[1] as $i=>$v) {  // merge both captures
         if (empty($v) && strlen($r[2][$i])) {
            $r[1][$i] = str_replace("$esc$q", "$q", $r[2][$i]);  // remove escape character
         }            # use stripcslashes to support standard CSV \r \n escapes
      }
      return($r[1]);
   }
}



/**
 * @stub: Basically aliases for function calls; just throw an error if called from main() and not from within a class.
 * The real implementations would behave on late static binding, though.
 *
 */
if (!function_exists("forward_static_call")) {
   function forward_static_call_array($callback, $args=NULL) {
      return call_user_func_array($callback, $args);
   }
   function forward_static_call($callback /*, ... */) {
      $args = func_get_args();
      array_shift($args);
      return call_user_func_array($callback, $args);
   }
}




/**
 * Encodes special chars as =0D=0A patterns. Soft-break at 76 characters.
 *
 */
if (!function_exists("quoted_printable_encode")) {
   function quoted_printable_encode($str) {
      $str = preg_replace("/([\\000-\\041=\\176-\\377])/e", "'='.strtoupper(dechex(ord('\$1')))", $str);
      $str = preg_replace("/(.{1,76})(?<=[^=][^=])/ims", "\$1=\r\n", $str); // QP-soft-break
      return $str;
   }
}













/**
 *                                   ------------------------------ 5.2 ---
 * @group 5_2
 * @since 5.2
 *
 * Additions of PHP 5.2.0
 * - some listed here might have appeared earlier or in release candidates
 *
 * @emulated
 *    json_encode
 *    json_decode
 *    error_get_last
 *    preg_last_error
 *    lchown
 *    lchgrp
 *    E_RECOVERABLE_ERROR
 *    M_SQRTPI
 *    M_LNPI
 *    M_EULER
 *    M_SQRT3
 *    array_fill_keys  (@doc: 4.2 or 5.2 ?)
 *    array_diff_key   (@doc: 5.1 or 5.2 ?)
 *    array_diff_ukey
 *    array_product
 *    inet_ntop
 *    inet_pton

 *    array_intersect_key
 *    array_intersect_ukey
 *    mysql_set_charset

 *
 * @missing
 *    sys_getloadavg
 *    ftp_ssl_connect
 *    XmlReader
 *    XmlWriter
 *    PDO*
 *    pdo_drivers     (should be in ext/pdo)
 *
 * @unimplementable
 *    stream_*
 *
 */





/**
 * @since unknown
 */
if (!defined("E_RECOVERABLE_ERROR")) { define("E_RECOVERABLE_ERROR", 4096); }



/**
 * Converts PHP variable or array into a "JSON" (JavaScript value expression
 * or "object notation") string.
 *
 * @compat
 *    Output seems identical to PECL versions. "Only" 20x slower than PECL version.
 * @bugs
 *    Doesn't take care with unicode too much - leaves UTF-8 sequences alone.
 *
 * @param  $var mixed  PHP variable/array/object
 * @return string      transformed into JSON equivalent
 */
if (!defined("JSON_HEX_TAG")) {
   define("JSON_HEX_TAG", 1);
   define("JSON_HEX_AMP", 2);
   define("JSON_HEX_APOS", 4);
   define("JSON_HEX_QUOT", 8);
   define("JSON_FORCE_OBJECT", 16);
 }
if (!defined("JSON_NUMERIC_CHECK")) {
   define("JSON_NUMERIC_CHECK", 32);      // 5.3.3
 }
if (!defined("JSON_UNESCAPED_SLASHES")) {
   define("JSON_UNESCAPED_SLASHES", 64);  // 5.4.0
   define("JSON_PRETTY_PRINT", 128);      // 5.4.0
   define("JSON_UNESCAPED_UNICODE", 256); // 5.4.0
 }
if (!function_exists("json_encode")) {
   function json_encode($var, $options=0, $_indent="") {
      global ${'.json_last_error'};
      ${'.json_last_error'} = JSON_ERROR_NONE;
            
      #-- prepare JSON string
      $obj = ($options & JSON_FORCE_OBJECT);
      list($_space, $_tab, $_nl) = ($options & JSON_PRETTY_PRINT) ? array(" ", "    $_indent", "\n") : array("", "", "");
      $json = "$_indent";
      
      if ($options & JSON_NUMERIC_CHECK and is_string($var) and is_numeric($var)) {
          $var = (strpos($var, ".") || strpos($var, "e")) ? floatval($var) : intval($var);
      }
      
      #-- add array entries
      if (is_array($var) || ($obj=is_object($var))) {

         #-- check if array is associative
         if (!$obj) {
            $keys = array_keys((array)$var);
            $obj = !($keys == array_keys($keys));   // keys must be in 0,1,2,3, ordering, but PHP treats integers==strings otherwise

         }


         #-- concat individual entries
         $empty = 0; $json = "";
         foreach ((array)$var as $i=>$v) {
            $json .= ($empty++ ? ",$_nl" : "")    // comma separators
                   . $_tab . ($obj ? (json_encode($i, $options & ~JSON_NUMERIC_CHECK, $_tab) . ":$_space") : "")   // assoc prefix
                   . (json_encode($v, $options, $_tab));    // value
         }

         #-- enclose into braces or brackets
         $json = $obj ? "{"."$_nl$json$_nl$_indent}" : "[$_nl$json$_nl$_indent]";
      }

      #-- strings need some care
      elseif (is_string($var)) {

         if (utf8_decode($var) != 0) {
            trigger_error("json_encode: invalid UTF-8 encoding in string, cannot proceed.", E_USER_WARNING);
            $var = NULL;
         }
         $rewrite = array(
             "\\" => "\\\\",
             "\"" => "\\\"",
           "\010" => "\\b",
             "\f" => "\\f",
             "\n" => "\\n",
             "\r" => "\\r", 
             "\t" => "\\t",
             "/"  => $options & JSON_UNESCAPED_SLASHES ? "/" : "\\/",
             "<"  => $options & JSON_HEX_TAG  ? "\\u003C" : "<",
             ">"  => $options & JSON_HEX_TAG  ? "\\u003E" : ">",
             "'"  => $options & JSON_HEX_APOS ? "\\u0027" : "'",
             "\"" => $options & JSON_HEX_QUOT ? "\\u0022" : "\\\"",
             "&"  => $options & JSON_HEX_AMP  ? "\\u0026" : "&",
         );
         $var = strtr($var, $rewrite);
         //@COMPAT control chars should probably be stripped beforehand, not escaped as here
         if (function_exists("iconv") && ($options & JSON_UNESCAPED_UNICODE) == 0) {
            $var = preg_replace("/[^\\x{0020}-\\x{007F}]/ue", "'\\u'.current(unpack('H*', iconv('UTF-8', 'UCS-2BE', '$0')))", $var);
         }
         $json = '"' . $var . '"';
      }

      #-- basic types
      elseif (is_bool($var)) {
         $json = $var ? "true" : "false";
      }
      elseif ($var === NULL) {
         $json = "null";
      }
      elseif (is_int($var)) {
         $json = "$var";
      }
      elseif (is_float($var)) {
         if (is_nan($var) || is_infinite($var)) {
            ${'.json_last_error'} = JSON_ERROR_INF_OR_NAN;
            return;
         }
         else {
            $json = "$var";
         }
      }

      #-- something went wrong
      else {
         trigger_error("json_encode: don't know what a '" .gettype($var). "' is.", E_USER_WARNING);
         ${'.json_last_error'} = JSON_ERROR_UNSUPPORTED_TYPE;
         return;
      }
      
      #-- done
      return($json);
   }
}



/**
 * Parses a JSON (JavaScript value expression) string into a PHP variable
 * (array or object).
 *
 * @compat

 *    Behaves similar to PECL version, but is less quiet on errors.
 *    Now even decodes unicode \uXXXX string escapes into UTF-8.
 *    "Only" 27 times slower than native function.
 * @bugs
 *    Might parse some misformed representations, when other implementations
 *    would scream error or explode.
 * @code
 *    This is state machine spaghetti code. Needs the extranous parameters to
 *    process subarrays, etc. When it recursively calls itself, $n is the
 *    current position, and $waitfor a string with possible end-tokens.
 *
 * @param   $json string   JSON encoded values
 * @param   $assoc bool    pack data into php array/hashes instead of objects
 * @return  mixed          parsed into PHP variable/array/object
 */
if (!function_exists("json_decode")) {

   define("JSON_OBJECT_AS_ARRAY", 1);     // undocumented
   define("JSON_BIGINT_AS_STRING", 2);    // 5.4.0
   define("JSON_PARSE_JAVASCRIPT", 4);    // unquoted object keys, and single quotes ' strings identical to double quoted, more relaxed parsing

   function json_decode($json, $assoc=FALSE, $limit=512, $options=0, /*emu_args*/$n=0,$state=0,$waitfor=0) {
      global ${'.json_last_error'};
      ${'.json_last_error'} = JSON_ERROR_NONE;

      #-- maximum nesting depth for decoding
      if ($limit < 0) {
          ${'.json_last_error'} = JSON_ERROR_DEPTH;
          return; // fall through
      }

      #-- result var
      $val = NULL;
      
      // shortcut state for parsing errors
      $FAILURE = array(
          NULL,   // result var
          1<<31   // tokenizer position
      );
      
      // transliterations from JSON to PHP values
      static $lang_eq = array("true" => TRUE, "false" => FALSE, "null" => NULL);
      static $str_eq = array("n"=>"\012", "r"=>"\015", "\\"=>"\\", '"'=>'"', "f"=>"\f", "b"=>"\010", "t"=>"\t", "/"=>"/");
      
      #-- strip UTF-8 BOM (the native version doesn't do this, but .. should)
      while (strncmp($json, "\xEF\xBB\xBF", 3) == 0) {
          trigger_error("UTF-8 BOM prefaces JSON, that's invalid for PHPs native json_decode", E_USER_ERROR);
          $json = substr($json, 3);
      }

      #-- flat char-wise parsing
      for (/*$n=0,*/ $len = strlen($json); $n<$len; /*$n++*/) {
         $c = $json[$n];

         #-= in-string
         if ($state==='"' or $state==="'") {

            if ($c == '\\') {
               $c = $json[++$n];
               
               // simple C escapes
               if (isset($str_eq[$c])) {
                  $val .= $str_eq[$c];
               }

               // here we transform \uXXXX Unicode (always 4 nibbles) references to UTF-8
               elseif ($c == "u") {
                  // read just 16bit (therefore value can't be negative)
                  $hex = hexdec( substr($json, $n+1, 4) );
                  $n += 4;
                  // Unicode ranges
                  if ($hex < 0x80) {    // plain ASCII character
                     $val .= chr($hex);
                  }
                  elseif ($hex < 0x800) {   // 110xxxxx 10xxxxxx 
                     $val .= chr(0xC0 + $hex>>6) . chr(0x80 + $hex&63);
                  }
                  elseif ($hex <= 0xFFFF) { // 1110xxxx 10xxxxxx 10xxxxxx 
                     $val .= chr(0xE0 + $hex>>12) . chr(0x80 + ($hex>>6)&63) . chr(0x80 + $hex&63);
                  }
                  // other ranges, like 0x1FFFFF=0xF0, 0x3FFFFFF=0xF8 and 0x7FFFFFFF=0xFC do not apply
               }

               // for JS (not JSON) the extraneous backslash just gets omitted
               elseif ($options & JSON_PARSE_JAVASCRIPT) {
                  if (is_numeric($c) and preg_match("/[0-3][0-7][0-7]|[0-7]{1,2}/", substr($json, $n), $m)) {
                     $val .= chr(octdec($m[0]));
                     $n += strlen($m[0]) - 1;
                  }
                  else {
                     $val .= $c;
                  }
               }
               
               // redundant backslashes disallowed in JSON
               else {
                  $val .= "\\$c";
                  ${'.json_last_error'} = JSON_ERROR_CTRL_CHAR; // not quite, but
                  trigger_error("Invalid backslash escape for JSON \\$c", E_USER_WARNING);
                  return $FAILURE;
               }
            }

            // end of string
            elseif ($c == $state) {
               $state = 0;
            }

            //@COMPAT: specialchars check - but native json doesn't do it?
            #elseif (ord($c) < 32) && !in_array($c, $str_eq)) {
            #   ${'.json_last_error'} = JSON_ERROR_CTRL_CHAR;
            #}
            
            // a single character was found
            else/*if (ord($c) >= 32)*/ {
               $val .= $c;
            }
         }

         #-> end of sub-call (array/object)
         elseif ($waitfor && (strpos($waitfor, $c) !== false)) {
            return array($val, $n);  // return current value and state
         }
         
         #-= in-array
         elseif ($state===']') {
            list($v, $n) = json_decode($json, $assoc, $limit, $options, $n, 0, ",]");
            $val[] = $v;
            if ($json[$n] == "]") { return array($val, $n); }
         }

         #-= in-object
         elseif ($state==='}') {
            // quick regex parsing cheat for unquoted JS object keys
            if ($options & JSON_PARSE_JAVASCRIPT and $c != '"' and preg_match("/^\s*(?!\d)(\w\pL*)\s*/u", substr($json, $n), $m)) {
                $i = $m[1];
                $n = $n + strlen($m[0]);
            }
            else {
                // this allowed non-string indicies
                list($i, $n) = json_decode($json, $assoc, $limit, $options, $n, 0, ":");
            }
            list($v, $n) = json_decode($json, $assoc, $limit, $options, $n+1, 0, ",}");
            $val[$i] = $v;
            if ($json[$n] == "}") { return array($val, $n); }
         }

         #-- looking for next item (0)
         else {
         
            #-> whitespace
            if (preg_match("/\s/", $c)) {
               // skip
            }

            #-> string begin
            elseif ($c == '"') {
               $state = $c;
            }

            #-> object
            elseif ($c == "{") {
               list($val, $n) = json_decode($json, $assoc, $limit-1, $options, $n+1, '}', "}");
               
               if ($val && $n) {

                  $val = $assoc ? (array)$val : (object)$val;

               }


            }

            #-> array
            elseif ($c == "[") {
               list($val, $n) = json_decode($json, $assoc, $limit-1, $options, $n+1, ']', "]");






            }

            #-> numbers
            elseif (preg_match("#^(-?\d+(?:\.\d+)?)(?:[eE]([-+]?\d+))?#", substr($json, $n), $uu)) {
               $val = $uu[1];
               $n += strlen($uu[0]) - 1;
               if (strpos($val, ".")) {  // float
                  $val = floatval($val);
               }
               elseif ($val[0] == "0") {  // oct
                  $val = octdec($val);
               }
               else {
                  $toobig = strval(intval($val)) !== strval($val);
                  if ($toobig and !isset($uu[2]) and ($options & JSON_BIGINT_AS_STRING)) {
                      $val = $val;  // keep lengthy numbers as string
                  }
                  elseif ($toobig or isset($uu[2])) {  // must become float anyway
                      $val = floatval($val);
                  }
                  else {  // int
                      $val = intval($val);
                  }
               }
               // exponent?
               if (isset($uu[2])) {
                  $val *= pow(10, (int)$uu[2]);
               }
            }

            #-> boolean or null
            elseif (preg_match("#^(true|false|null)\b#", substr($json, $n), $uu)) {
               $val = $lang_eq[$uu[1]];
               $n += strlen($uu[1]) - 1;
            }

            #-> JS-string begin
            elseif ($options & JSON_PARSE_JAVASCRIPT and $c == "'") {
               $state = $c;
            }

            #-> comment
            elseif ($options & JSON_PARSE_JAVASCRIPT and ($c == "/") and ($json[$n+1]=="*")) {
               // just find end, skip over
               ($n = strpos($json, "*/", $n+1)) or ($n = strlen($json));
            }

            #-- parsing error
            else {
               // PHPs native json_decode() breaks here usually and QUIETLY
               trigger_error("json_decode: error parsing '$c' at position $n", E_USER_WARNING);
               ${'.json_last_error'} = JSON_ERROR_SYNTAX;
               return $waitfor ? $FAILURE : NULL;
            }

         }//state
         
         #-- next char
         if ($n === NULL) { ${'.json_last_error'} = JSON_ERROR_STATE_MISMATCH; return NULL; }   // ooops, seems we have two failure modes
         $n++;
      }//for

      #-- final result
      return ($val);
   }
}


/**
 * @stub
 *
 * Should return last JSON decoding error.
 *
 */
if (!defined("JSON_ERROR_NONE")) {
   define("JSON_ERROR_NONE", 0);
   define("JSON_ERROR_DEPTH", 1);
   define("JSON_ERROR_STATE_MISMATCH", 2);
   define("JSON_ERROR_CTRL_CHAR", 3);
   define("JSON_ERROR_SYNTAX", 4);
   define("JSON_ERROR_UTF8", 5);
   define("JSON_ERROR_RECURSION", 6);
   define("JSON_ERROR_INF_OR_NAN", 7);
   define("JSON_ERROR_UNSUPPORTED_TYPE", 7);
 }
if (!function_exists("json_last_error")) {
   function json_last_error() {
       global ${'.json_last_error'}; 
       return ${'.json_last_error'}; // gives a notice if json_decode was never invoked before (no status constant for that)
   }
}



/**
 * @stub

 *
 * Should return last PCRE error.
 *
 */
if (!function_exists("preg_last_error")) {
   if (!defined("PREG_NO_ERROR")) { define("PREG_NO_ERROR", 0); }
   if (!defined("PREG_INTERNAL_ERROR")) { define("PREG_INTERNAL_ERROR", 1); }
   if (!defined("PREG_BACKTRACK_LIMIT_ERROR")) { define("PREG_BACKTRACK_LIMIT_ERROR", 2); }
   if (!defined("PREG_RECURSION_LIMIT_ERROR")) { define("PREG_RECURSION_LIMIT_ERROR", 3); }
   if (!defined("PREG_BAD_UTF8_ERROR")) { define("PREG_BAD_UTF8_ERROR", 4); }
   function preg_last_error() {
      return PREG_NO_ERROR;
   }
}




/**
 * returns path of the system directory for temporary files
 *
 * @since 5.2.1
 */
if (!function_exists("sys_get_temp_dir")) {
   function sys_get_temp_dir() {
      # check possible alternatives
      ($temp = ini_get("temp_dir"))
      or
      ($temp = @$_ENV["TMPDIR"])
      or
      ($temp = @$_ENV["TEMP"])
      or
      ($temp = @$_ENV["TMP"])
      or
      ($temp = "/tmp");
      # fin
      return($temp);
   }
}



/**
 * @stub
 *
 * Should return associative array with last error message.
 *
 */
if (!function_exists("error_get_last")) {
   function error_get_last() {
      return array(
         "type" => 0,
         "message" => $GLOBALS["php_errormsg"],
         "file" => "unknonw",
         "line" => 0,
      );
   }
}




/**
 * @flag quirky, exec, realmode
 *
 * Change owner of a symlink filename.
 *
 */
if (!function_exists("lchown")) {
   function lchown($fn, $user) {
      if (PHP_OS != "Linux") {
         return false;
      }
      $user = escapeshellcmd($user);
      $fn = escapeshellcmd($fn);
      exec("chown -h '$user' '$fn'", $uu, $state);
      return($state);
   }
}



/**
 * @flag quirky, exec, realmode
 *
 * Change group of a symlink filename.
 *
 */
if (!function_exists("lchgrp")) {
   function lchgrp($fn, $group) {
      return lchown($fn, ":$group");
   }
}



/**
 * @doc: Got this function new in PHP 5.2, but documentation says 4.2 ???
 * 
 * array_fill() with given $keys
 *
 */
if (!function_exists("array_fill_keys")) {
   function array_fill_keys($keys, $value) {
      return array_combine($keys, array_fill(0, count($keys), $value));
   }
}



/**
 * @doc: php manual says 5.1, but function appeared with 5.2
 *
 * Returns array entries, whose keys are not in any of the comparison arrays.
 *
 */
if (!function_exists("array_diff_key")) {
   function array_diff_key($base /*...*/) {
      $other = func_get_args();
      array_shift($other);

      $cmp = call_user_func_array("array_merge", array_map("array_keys", $other));

      foreach ($cmp as $key) {
            $key = (string) $key;
            if (array_key_exists($key, $base)) {
               // cannot compare if $key is actually a string in $base
               unset($base[$key]);
            }
      }
      return ($base);
   }
}




/**
 * @doc: php manual says 5.1, but function appeared with 5.2
 *
 * Uses callback function to compare array keys.
 * Callback returns -1, 0, +1, and then some keys are filtered???
 * Let's assume ==0 is meant for no difference --> and no difference => filter out
 *
 */
if (!function_exists("array_diff_ukey")) {
   function array_diff_ukey($base, $other_arrays/*...*/, $callback) {
      $other = func_get_args();
      array_shift($other);
      $callback = array_pop($other);
      
      $cmp = call_user_func_array("array_merge", array_map("array_keys", $other));

      foreach ($base as $key=>$value) {
         // compare against each key from $other arrays
         foreach ($cmp as $k) {
            if ($callback($key, $k) === 0) {
               unset($base[$key]);
            }
         }
      }
      return $base;      
   }
}



/**
 * @doc: 5.1 vs 5.2
 *
 * Keeps only array-entries, if key exists also in comparison arrays
 *
 */
if (!function_exists("array_intersect_key")) {
   function array_intersect_key($base /*...*/) {
      $all_arrays = array_map("array_keys", func_get_args());
      $keep = call_user_func_array("array_intersect", $all_arrays);
      
      $r = array();
      foreach ($keep as $k) {
         $r[$k] = $base[$k];
      }
      return ($r);
   }
}



/**
 * @doc: 5.1 vs 5.2
 *
 * array_uintersect on keys
 *
 */
if (!function_exists("array_intersect_ukey")) {
   function array_intersect_ukey(/*...*/) {
      $args = func_get_args();
      $base = $args[0];
      $callback = array_pop($other);

      $keys = array_map("array_values", $args);
      $intersect = call_user_func_array("array_uintersect", array_merge($keys, array($callback)));
      
      $r = array();
      foreach ($intersect as $key) {
         $r[$key] = $base[$key];
      }
      return $r;
   }
}







/**
 * Hmmm.
 *
 */
if (!function_exists("array_product")) {
   function array_product($multiply_us) {
      $r = count($multiply_us) ? 1 : NULL;
      foreach ($multiply_us as $m) {
         $r = $r * $m;
      }
      return $r;
   }
}



/**
 * Converts chr/bin/string-representation to human-readable IP text.
 *
 */
if (!function_exists("inet_ntop")) {
   function inet_ntop($bin) {
      if (strlen($bin) == 4) {   // IPv4
         return implode(".", array_map("ord", str_split($bin, 1)));
      }
      elseif (strlen($bin) == 16) {  // IPv6
         return preg_replace("/:?(0000:)+/", "::", implode(":", str_split(bin2hex($bin), 4)));
      }
      elseif (strlen($bin) == 6) {  // MAC
         return implode(":", str_split(bin2hex($bin), 2));
      }
   }
}


/**
 * Compact IPv4 1.2.3.4 or IPv6 ::FFFF:0001 addresses into binary string.
 *
 */
if (!function_exists("inet_pton")) {
   function inet_pton($str) {
      if (strpos($str, ".")) {  // IPv4
         return array_map("chr", explode(".", $str));
      }
      elseif (strstr($str, ":")) { // IPv6
         $str = str_replace("::", str_repeat(":", 2 + 7 - substr_count($str, ":")), $str);   // padding "::" can appear anywhere inside, replaces 7-x other :0000 colons and zeros
         $str = implode(array_map("inet_pton___ipv6_pad", explode(":", $str)));
         return pack("H32", $str);
      }
   }
   function inet_pton___ipv6_pad($s) {
      return str_pad($s, 4, "0", STR_PAD_LEFT);
   }
}


/**
 * @since 5.2.3
 * SET NAMES $charset
 *
 */
if (!function_exists("mysql_set_charset")) {
   function mysql_set_charset($charset, $link=NULL) {
      return mysqli_query("SET NAMES '$charset'", $link);
   }
}




/**
 *                                   ------------------------------ 5.1 ---
 * @group 5_1
 * @since 5.1
 *
 * Additions in PHP 5.1
 * - most functions here appeared in -rc1 already
 * - and were backported to 4.4 series?
 *
 * @emulated
 *    hash_hmac
 *    property_exists
 *    time_sleep_until
 *    fputcsv
 *    strptime
 *    ENT_COMPAT
 *    ENT_QUOTES
 *    ENT_NOQUOTES
440
441
442
443
444
445
446




































447
448
449
450
451
452
453
 *
 * @unimplementable
 *    ...
 *
 */







































/**
 * Constants for future 64-bit integer support.
 *
 */
if (!defined("PHP_INT_SIZE")) { define("PHP_INT_SIZE", 4); }
if (!defined("PHP_INT_MAX")) { define("PHP_INT_MAX", 2147483647); }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
 *
 * @unimplementable
 *    ...
 *
 */



/**
 * HMAC as per rfc2104,
 * only works with PHP-available "md5" and "sha1" algorithm backends
 *
 */
if (!function_exists("hash_hmac")) {
   function hash_hmac($H, $data, $key, $raw=0) {

       # algorithm parameters
       static $bitsize = array("sha1"=>160, "md5"=>128, "sha256"=>256, "sha512"=>512, "sha384"=>384, "sha224"=>224, "ripemd"=>160);
       $B = 64;

       # bring key to block size 64, hash it first if longer
       if (strlen($key) > $B) {
           $key = $H($key, 1);
       }
       $key .= str_repeat("\0", $B - strlen($key));

       # padding, XOR with key
       $inner_pad = "";
       $outer_pad = "";
       for ($i=0; $i<$B; $i++) {
           $inner_pad .= chr(0x36 ^ ord($key[$i]));
           $outer_pad .= chr(0x5C ^ ord($key[$i]));
       }

       # apply hash
       $data = $H($outer_pad . $H($inner_pad . $data, 1), 1);
       
       # bin2hex
       return $raw ? $data : bin2hex($data);
   }
}



/**
 * Constants for future 64-bit integer support.
 *
 */
if (!defined("PHP_INT_SIZE")) { define("PHP_INT_SIZE", 4); }
if (!defined("PHP_INT_MAX")) { define("PHP_INT_MAX", 2147483647); }
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
if (!defined("M_LNPI")) { define("M_LNPI", 1.1447298858494); }
if (!defined("M_EULER")) { define("M_EULER", 0.57721566490153); }
if (!defined("M_SQRT3")) { define("M_SQRT3", 1.7320508075689); }





#-- removes entities &lt; &gt; &amp; and &quot; eventually from HTML string


if (!function_exists("htmlspecialchars_decode")) {
   if (!defined("ENT_COMPAT")) { define("ENT_COMPAT", 2); }
   if (!defined("ENT_QUOTES")) { define("ENT_QUOTES", 3); }
   if (!defined("ENT_NOQUOTES")) { define("ENT_NOQUOTES", 0); }
   function htmlspecialchars_decode($string, $quotes=2) {
      $d = $quotes & ENT_COMPAT;
      $s = $quotes & ENT_QUOTES;
      return str_replace(
         array("&lt;", "&gt;", ($s ? "&quot;" : "&.-;"), ($d ? "&#039;" : "&.-;"), "&amp;"),
         array("<",    ">",    "'",                      "\"",                     "&"),
         $string
      );
   }
}



/**
 * @flag quirky, needs5
 *
 * Checks for existence of object property, should return TRUE even for NULL values.
 *
 * @compat
 *    uses (array) conversion to test, but that might not always work
 * @bugs
 *    probably can't handle static classes well
 */
# doesn't return true for NULL values, can't handle public/private
if (!function_exists("property_exists")) {
   function property_exists($obj, $prop) {
      if (!is_object($obj) && class_exists($obj)) {
         $obj = new $obj();
      }
      if (is_object($obj)) {
         return isset($obj->{$prop}) || in_array($prop, array_keys((array)$obj));
      }

   }
}




#-- halt execution, until given timestamp
// I wonder who always comes up with such useless function ideas


if (!function_exists("time_sleep_until")) {
   function time_sleep_until($t) {
      $delay = $t - time();
      if ($delay < 0) {
         trigger_error("time_sleep_until: timestamp in the past", E_USER_WARNING);
         return false;
      }
      else {
         sleep((int)$delay);
         usleep(($delay - floor($delay)) * 1000000);
         return true;
      }
   }
}










>
|
>
>
















>

|




<
<
|

<

|
|
|

|
|

>




>
>
|
<
>
>









|







1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621


1622
1623

1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
if (!defined("M_LNPI")) { define("M_LNPI", 1.1447298858494); }
if (!defined("M_EULER")) { define("M_EULER", 0.57721566490153); }
if (!defined("M_SQRT3")) { define("M_SQRT3", 1.7320508075689); }




/**
 * removes entities &lt; &gt; &amp; and eventually &quot; from HTML string
 *
 */
if (!function_exists("htmlspecialchars_decode")) {
   if (!defined("ENT_COMPAT")) { define("ENT_COMPAT", 2); }
   if (!defined("ENT_QUOTES")) { define("ENT_QUOTES", 3); }
   if (!defined("ENT_NOQUOTES")) { define("ENT_NOQUOTES", 0); }
   function htmlspecialchars_decode($string, $quotes=2) {
      $d = $quotes & ENT_COMPAT;
      $s = $quotes & ENT_QUOTES;
      return str_replace(
         array("&lt;", "&gt;", ($s ? "&quot;" : "&.-;"), ($d ? "&#039;" : "&.-;"), "&amp;"),
         array("<",    ">",    "'",                      "\"",                     "&"),
         $string
      );
   }
}



/**
 * @flag needs5
 *
 * Checks for existence of object property, should return TRUE even for NULL values.
 *
 * @compat


 *    no test for edge cases
 */

if (!function_exists("property_exists")) {
   function property_exists($obj, $propname) {
      if (is_object($obj)) {
         $props = array_keys(get_object_vars($obj));
      }
      elseif (class_exists($obj)) {
         $props = array_keys(get_class_vars($obj));
      }
      return !empty($props) and in_array($propname, $props);
   }
}



/**
 * halt execution, until given timestamp

 *
 */
if (!function_exists("time_sleep_until")) {
   function time_sleep_until($t) {
      $delay = $t - time();
      if ($delay < 0) {
         trigger_error("time_sleep_until: timestamp in the past", E_USER_WARNING);
         return false;
      }
      else {
         sleep((int)$delay);
         #usleep(($delay - floor($delay)) * 1000000);
         return true;
      }
   }
}



545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
      fwrite($fp, $line."\n");
   }
}



/**
 * @stub
 * @untested
 * @flag basic
 *
 * @compat
 *    only implements a few basic regular expression lookups
 *    no idea how to handle all of it
 */
if (!function_exists("strptime")) {
   function strptime($str, $format) {







|

<







1674
1675
1676
1677
1678
1679
1680
1681
1682

1683
1684
1685
1686
1687
1688
1689
      fwrite($fp, $line."\n");
   }
}



/**
 * @flag basic
 * @untested

 *
 * @compat
 *    only implements a few basic regular expression lookups
 *    no idea how to handle all of it
 */
if (!function_exists("strptime")) {
   function strptime($str, $format) {
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








/**
 *                                   --------------------------- FUTURE ---
 * @group FUTURE
 * @since unknown
 *
 * Following functions aren't implemented in current PHP versions allthough
 * they are logical and required counterparts to existing features or exist
 * in the according external library.
 *
 * @emulated
 *    gzdecode
 *    ob_get_headers
 *    xmlentities
 *
 * @missing
 *    ...
 *
 * @unimplementable
 *    ... 
 *
 */





#-- inflates a string enriched with gzip headers
#   (this is the logical counterpart to gzencode(), but don't tell anyone!)
if (!function_exists("gzdecode")) {
   function gzdecode($data, $maxlen=NULL) {

      #-- decode header
      $len = strlen($data);
      if ($len < 20) {
         return;
      }
      $head = substr($data, 0, 10);
      $head = unpack("n1id/C1cm/C1flg/V1mtime/C1xfl/C1os", $head);
      list($ID, $CM, $FLG, $MTIME, $XFL, $OS) = array_values($head);
      $FTEXT = 1<<0;
      $FHCRC = 1<<1;
      $FEXTRA = 1<<2;
      $FNAME = 1<<3;
      $FCOMMENT = 1<<4;
      $head = unpack("V1crc/V1isize", substr($data, $len-8, 8));
      list($CRC32, $ISIZE) = array_values($head);

      #-- check gzip stream identifier
      if ($ID != 0x1f8b) {
         trigger_error("gzdecode: not in gzip format", E_USER_WARNING);
         return;
      }
      #-- check for deflate algorithm
      if ($CM != 8) {
         trigger_error("gzdecode: cannot decode anything but deflated streams", E_USER_WARNING);
         return;
      }

      #-- start of data, skip bonus fields
      $s = 10;
      if ($FLG & $FEXTRA) {
         $s += $XFL;
      }
      if ($FLG & $FNAME) {
         $s = strpos($data, "\000", $s) + 1;
      }
      if ($FLG & $FCOMMENT) {
         $s = strpos($data, "\000", $s) + 1;
      }
      if ($FLG & $FHCRC) {
         $s += 2;  // cannot check
      }
      
      #-- get data, uncompress
      $data = substr($data, $s, $len-$s);
      if ($maxlen) {
         $data = gzinflate($data, $maxlen);
         return($data);  // no checks(?!)
      }
      else {
         $data = gzinflate($data);
      }
      
      #-- check+fin
      $chk = crc32($data);
      if ($CRC32 != $chk) {
         trigger_error("gzdecode: checksum failed (real$chk != comp$CRC32)", E_USER_WARNING);
      }
      elseif ($ISIZE != strlen($data)) {
         trigger_error("gzdecode: stream size mismatch", E_USER_WARNING);
      }
      else {
         return($data);
      }
   }
}


#-- get all already made headers(),
#   CANNOT be emulated, because output buffering functions
#   already swallow up any sent http header
if (!function_exists("ob_get_headers")) {
   function ob_get_headers() {
      return (array)NULL;
   }
}


#-- encodes required named XML entities, like htmlentities(),
#   but does not re-encode numeric &#xxxx; character references
#   - could screw up scripts which then implement this themselves
#   - doesn't fix bogus or invalid numeric entities
if (!function_exists("xmlentities")) {
   function xmlentities($str) {
      return strtr($str, array(
        "&#"=>"&#", "&"=>"&amp;", "'"=>"&apos;",
        "<"=>"&lt;", ">"=>"&gt;", "\""=>"&quot;", 
      ));
   }
}





/**
 *                                   ------------------------------ 5.0 ---
 * @group 5_0







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







1759
1760
1761
1762
1763
1764
1765


























































































































1766
1767
1768
1769
1770
1771
1772





































































































































/**
 *                                   ------------------------------ 5.0 ---
 * @group 5_0
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
 *    count_recursive
 *    FILE_USE_INCLUDE_PATH
 *    FILE_IGNORE_NEW_LINES
 *    FILE_SKIP_EMPTY_LINES
 *    FILE_APPEND
 *    FILE_NO_DEFAULT_CONTEXT
 *    E_STRICT

 *
 * @missing
 *    proc_nice
 *    dns_get_record
 *    date_sunrise - undoc.
 *    date_sunset - undoc.
 *    PHP_CONFIG_FILE_SCAN_DIR

 *
 * @unimplementable
 *    set_exception_handler
 *    restore_exception_handler
 *    debug_print_backtrace

 *    class_implements
 *    proc_terminate
 *    proc_get_status


 *
 */




#-- constant: end of line
if (!defined("PHP_EOL")) { define("PHP_EOL", ( (DIRECTORY_SEPARATOR == "\\") ? "\015\012" : (strncmp(PHP_OS, "D", 1) ? "\012" : "\015") )  ); } # "D" for Darwin




#-- case-insensitive string search function,
#   - finds position of first occourence of a string c-i
#   - parameters identical to strpos()

if (!function_exists("stripos")) {
   function stripos($haystack, $needle, $offset=NULL) {
   
      #-- simply lowercase args
      $haystack = strtolower($haystack);
      $needle = strtolower($needle);
      
      #-- search
      $pos = strpos($haystack, $needle, $offset);
      return($pos);
   }
}





#-- case-insensitive string search function
#   - but this one starts from the end of string (right to left)
#   - offset can be negative or positive


if (!function_exists("strripos")) {
   function strripos($haystack, $needle, $offset=NULL) {

      #-- lowercase incoming strings
      $haystack = strtolower($haystack);
      $needle = strtolower($needle);








>







>




|
>



>
>


|
>






>
>
|
|
|
>














>
>
>
|
|
|
>
>







1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
 *    count_recursive
 *    FILE_USE_INCLUDE_PATH
 *    FILE_IGNORE_NEW_LINES
 *    FILE_SKIP_EMPTY_LINES
 *    FILE_APPEND
 *    FILE_NO_DEFAULT_CONTEXT
 *    E_STRICT
 *    mysqli_set_charset
 *
 * @missing
 *    proc_nice
 *    dns_get_record
 *    date_sunrise - undoc.
 *    date_sunset - undoc.
 *    PHP_CONFIG_FILE_SCAN_DIR
 *    clone
 *
 * @unimplementable
 *    set_exception_handler
 *    restore_exception_handler
 *    debug_print_backtrace - in ext, needs4.3
 *    debug_backtrace       - stub
 *    class_implements
 *    proc_terminate
 *    proc_get_status
 *    range        - new param
 *    microtime    - new param
 *
 */
 
 


#-- constant: end of line
if (!defined("PHP_EOL")) { define("PHP_EOL", ( (DIRECTORY_SEPARATOR == "\\") ? "\015\012" : (strncmp(PHP_OS, "D", 1) ? "\012" : "\015") )  ); } # "D" for Darwin



/**
 * case-insensitive string search function,
 * - finds position of first occourence of a string c-i
 * - parameters identical to strpos()
 */
if (!function_exists("stripos")) {
   function stripos($haystack, $needle, $offset=NULL) {
   
      #-- simply lowercase args
      $haystack = strtolower($haystack);
      $needle = strtolower($needle);
      
      #-- search
      $pos = strpos($haystack, $needle, $offset);
      return($pos);
   }
}




/**
 * case-insensitive string search function
 * - but this one starts from the end of string (right to left)
 * - offset can be negative or positive
 * 
 */
if (!function_exists("strripos")) {
   function strripos($haystack, $needle, $offset=NULL) {

      #-- lowercase incoming strings
      $haystack = strtolower($haystack);
      $needle = strtolower($needle);

873
874
875
876
877
878
879

880


881
882
883
884
885
886
887

      #-- result      
      return($pos);
   }
}



#-- case-insensitive version of str_replace


if (!function_exists("str_ireplace")) {
   function str_ireplace($search, $replace, $subject, $count=NULL) {

      #-- call ourselves recursively, if parameters are arrays/lists 
      if (is_array($search)) {
         $replace = array_values($replace);
         foreach (array_values($search) as $i=>$srch) {







>
|
>
>







1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910

      #-- result      
      return($pos);
   }
}


/**
 * case-insensitive version of str_replace
 * 
 */
if (!function_exists("str_ireplace")) {
   function str_ireplace($search, $replace, $subject, $count=NULL) {

      #-- call ourselves recursively, if parameters are arrays/lists 
      if (is_array($search)) {
         $replace = array_values($replace);
         foreach (array_values($search) as $i=>$srch) {
899
900
901
902
903
904
905

906


907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922

      #-- result
      return($subject);
   }
}



#-- performs a http HEAD request


if (!function_exists("get_headers")) {
   function get_headers($url, $parse=0) {
   
      #-- extract URL parts ($host, $port, $path, ...)
      $c = parse_url($url);

      extract($c);
      if (!isset($port)) { 
         $port = 80;
      }
      
      #-- try to open TCP connection      
      $f = fsockopen($host, $port, $errno, $errstr, $timeout=15);
      if (!$f) {
         return;
      }








>
|
>
>





>

<
<
<







1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939



1940
1941
1942
1943
1944
1945
1946

      #-- result
      return($subject);
   }
}


/**
 * performs a http HEAD request
 * 
 */
if (!function_exists("get_headers")) {
   function get_headers($url, $parse=0) {
   
      #-- extract URL parts ($host, $port, $path, ...)
      $c = parse_url($url);
      $c = array_merge(array("port"=>"80", "path"=>"/"), $c);
      extract($c);



      
      #-- try to open TCP connection      
      $f = fsockopen($host, $port, $errno, $errstr, $timeout=15);
      if (!$f) {
         return;
      }

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
      #-- close TCP connection and give result
      fclose($f);
      return($ls);
   }
}




#-- list of already/potentially sent HTTP responsee headers(),
#   CANNOT be implemented (except for Apache module maybe)


if (!function_exists("headers_list")) {
   function headers_list() {
      trigger_error("headers_list(): not supported by this PHP version", E_USER_WARNING);
      return (array)NULL;
   }
}



#-- write formatted string to stream/file,
#   arbitrary numer of arguments


if (!function_exists("fprintf")) {
   function fprintf(/*...*/) {
      $args = func_get_args();
      $stream = array_shift($args);
      return fwrite($stream, call_user_func_array("sprintf", $args));
   }
}



#-- write formatted string to stream, args array


if (!function_exists("vfprintf")) {
   function vfprintf($stream, $format, $args=NULL) {
      return fwrite($stream, vsprintf($format, $args));
   }
}



#-- splits a string in evenly sized chunks

#   and returns this as array

if (!function_exists("str_split")) {
   function str_split($str, $chunk=1) {
      $r = array();
      
      #-- return back as one chunk completely, if size chosen too low
      if ($chunk < 1) {
         $r[] = $str;







>
>
|
|
>
>








>
|
|
>
>









>
|
>
>







>
|
>
|
>







1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
      #-- close TCP connection and give result
      fclose($f);
      return($ls);
   }
}


/**
 * @stub
 * list of already/potentially sent HTTP responsee headers(),
 * CANNOT be implemented (except for Apache module maybe)
 * 
 */
if (!function_exists("headers_list")) {
   function headers_list() {
      trigger_error("headers_list(): not supported by this PHP version", E_USER_WARNING);
      return (array)NULL;
   }
}


/**
 * write formatted string to stream/file,
 * arbitrary numer of arguments
 * 
 */
if (!function_exists("fprintf")) {
   function fprintf(/*...*/) {
      $args = func_get_args();
      $stream = array_shift($args);
      return fwrite($stream, call_user_func_array("sprintf", $args));
   }
}


/**
 * write formatted string to stream, args array
 * 
 */
if (!function_exists("vfprintf")) {
   function vfprintf($stream, $format, $args=NULL) {
      return fwrite($stream, vsprintf($format, $args));
   }
}


/**
 * splits a string in evenly sized chunks
 * 
 * @return array
 */
if (!function_exists("str_split")) {
   function str_split($str, $chunk=1) {
      $r = array();
      
      #-- return back as one chunk completely, if size chosen too low
      if ($chunk < 1) {
         $r[] = $str;
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
         }
      }
      return($r);
   }
}



#-- constructs a QUERY_STRING (application/x-www-form-urlencoded format, non-raw)
#   from a nested array/hash with name=>value pairs
#   - only first two args are part of the original API - rest used for recursion







if (!function_exists("http_build_query")) {
   function http_build_query($data, $int_prefix="", $subarray_pfix="", $level=0) {
   
      #-- empty starting string
      $s = "";
      ($SEP = ini_get("arg_separator.output")) or ($SEP = "&");
      
      #-- traverse hash/array/list entries 
      foreach ($data as $index=>$value) {
         
         #-- add sub_prefix for subarrays (happens for recursed innovocation)
         if ($subarray_pfix) {
            if ($level) {
               $index = "[" . $index . "]";
            }
            $index =  $subarray_pfix . $index;







>
|
|
|
>
>
>
>
>
>
>

|






|







2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
         }
      }
      return($r);
   }
}


/**
 * constructs a QUERY_STRING (application/x-www-form-urlencoded format, non-raw)
 * from a nested array/hash with name=>value pairs
 * - only first two args are part of the original API - rest used for recursion
 *
 * @param  mixed  $vars           variable data for query string
 * @param  string $int_prefix     (optional)
 * @param  string $subarray_pfix  (optional)
 * @param integer $level  
 * @return mixed
 */
if (!function_exists("http_build_query")) {
   function http_build_query($vars, $int_prefix="", $subarray_pfix="", $level=0) {
   
      #-- empty starting string
      $s = "";
      ($SEP = ini_get("arg_separator.output")) or ($SEP = "&");
      
      #-- traverse hash/array/list entries 
      foreach ($vars as $index=>$value) {
         
         #-- add sub_prefix for subarrays (happens for recursed innovocation)
         if ($subarray_pfix) {
            if ($level) {
               $index = "[" . $index . "]";
            }
            $index =  $subarray_pfix . $index;
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

      #-- return result / to previous array level and iteration
      return($s);
   }
}



#-- transform into 3to4 uuencode
#   - this is the bare encoding, not the uu file format




if (!function_exists("convert_uuencode")) {
   function convert_uuencode($data) {

      #-- init vars
      $out = "";
      $line = "";
      $len = strlen($data);
#      $data .= "\252\252\252";   // PHP and uuencode(1) use some special garbage??, looks like "\000"* and "`\n`" simply appended

      #-- canvass source string
      for ($n=0; $n<$len; ) {
      
         #-- make 24-bit integer from first three bytes
         $x = (ord($data[$n++]) << 16)
            + (ord($data[$n++]) <<  8)
            + (ord($data[$n++]) <<  0);
            
         #-- disperse that into 4 ascii characters
         $line .= chr( 32 + (($x >> 18) & 0x3f) )
                . chr( 32 + (($x >> 12) & 0x3f) )
                . chr( 32 + (($x >>  6) & 0x3f) )
                . chr( 32 + (($x >>  0) & 0x3f) );
                







>
|
|
>
>
>
>

|




|
|





|
|
|







2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139

      #-- return result / to previous array level and iteration
      return($s);
   }
}


/**
 * transform into 3to4 uuencode
 * - this is the bare encoding, not the uu file format
 * 
 * @param  string
 * @return string
 */
if (!function_exists("convert_uuencode")) {
   function convert_uuencode($bin) {

      #-- init vars
      $out = "";
      $line = "";
      $len = strlen($bin);
      $bin .= "\01\01\01";   // PHP and uuencode(1) use some special garbage??, looks like "\000"* and "`\n`" simply appended

      #-- canvass source string
      for ($n=0; $n<$len; ) {
      
         #-- make 24-bit integer from first three bytes
         $x = (ord($bin[$n++]) << 16)
            + (ord($bin[$n++]) <<  8)
            + (ord($bin[$n++]) <<  0);
            
         #-- disperse that into 4 ascii characters
         $line .= chr( 32 + (($x >> 18) & 0x3f) )
                . chr( 32 + (($x >> 12) & 0x3f) )
                . chr( 32 + (($x >>  6) & 0x3f) )
                . chr( 32 + (($x >>  0) & 0x3f) );
                
1102
1103
1104
1105
1106
1107
1108

1109




1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
      // uuencode(5) doesn't tell so, but spaces are replaced with the ` char in most implementations
      $out = strtr("$out \n", " ", "`");
      return($out);
   }
}



#-- decodes uuencoded() data again




if (!function_exists("convert_uudecode")) {
   function convert_uudecode($data) {

      #-- prepare
      $out = "";
      $data = strtr($data, "`", " ");
      
      #-- go through lines
      foreach(explode("\n", ltrim($data)) as $line) {
         if (!strlen($line)) {
            break;  // end reached
         }
         
         #-- current line length prefix
         unset($num);
         $num = ord($line{0}) - 32;







>
|
>
>
>
>

|



|


|







2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
      // uuencode(5) doesn't tell so, but spaces are replaced with the ` char in most implementations
      $out = strtr("$out \n", " ", "`");
      return($out);
   }
}


/**
 * decodes uuencoded() data again
 *
 * @param  string $from  
 * @return string
 */
if (!function_exists("convert_uudecode")) {
   function convert_uudecode($from) {

      #-- prepare
      $out = "";
      $from = strtr($from, "`", " ");
      
      #-- go through lines
      foreach(explode("\n", ltrim($from)) as $line) {
         if (!strlen($line)) {
            break;  // end reached
         }
         
         #-- current line length prefix
         unset($num);
         $num = ord($line{0}) - 32;
1150
1151
1152
1153
1154
1155
1156

1157
1158





1159
1160
1161
1162
1163
1164
1165
      }

      return($out);
   }
}



#-- return array of filenames in a given directory
#   (only works for local files)





if (!function_exists("scandir")) {
   function scandir($dirname, $desc=0) {
   
      #-- check for file:// protocol, others aren't handled
      if (strpos($dirname, "file://") === 0) {
         $dirname = substr($dirname, 7);
         if (strpos($dirname, "localh") === 0) {







>
|
|
>
>
>
>
>







2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
      }

      return($out);
   }
}


/**
 * return array of filenames in a given directory
 * (only works for local files)
 *
 * @param  string $dirname  
 * @param  bool   $desc  
 * @return array
 */
if (!function_exists("scandir")) {
   function scandir($dirname, $desc=0) {
   
      #-- check for file:// protocol, others aren't handled
      if (strpos($dirname, "file://") === 0) {
         $dirname = substr($dirname, 7);
         if (strpos($dirname, "localh") === 0) {
1187
1188
1189
1190
1191
1192
1193

1194





1195
1196
1197
1198
1199
1200
1201

      #-- failure
      return false;
   }
}



#-- like date(), but returns an integer for given one-letter format parameter





if (!function_exists("idate")) {
   function idate($formatchar, $timestamp=NULL) {
   
      #-- reject non-simple type parameters
      if (strlen($formatchar) != 1) {
         return false;
      }







>
|
>
>
>
>
>







2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268

      #-- failure
      return false;
   }
}


/**
 * like date(), but returns an integer for given one-letter format parameter
 *
 * @param  string  $formatchar
 * @param  integer $timestamp
 * @return integer
 */
if (!function_exists("idate")) {
   function idate($formatchar, $timestamp=NULL) {
   
      #-- reject non-simple type parameters
      if (strlen($formatchar) != 1) {
         return false;
      }
1209
1210
1211
1212
1213
1214
1215

1216


1217
1218
1219
1220
1221
1222
1223
1224
1225


1226
1227





1228
1229
1230
1231
1232
1233
1234
      $str = date($formatchar, $timestamp);
      return (int)$str;
   }
}




#-- combined sleep() and usleep() 


if (!function_exists("time_nanosleep")) {
   function time_nanosleep($sec, $nano) {
      sleep($sec);
      usleep($nano);
   }
}





#-- search first occourence of any of the given chars, returns rest of haystack
#   (char_list must be a string for compatibility with the real PHP func)





if (!function_exists("strpbrk")) {
   function strpbrk($haystack, $char_list) {
   
      #-- prepare
      $len = strlen($char_list);
      $min = strlen($haystack);
      







>
|
>
>









>
>
|
|
>
>
>
>
>







2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
      $str = date($formatchar, $timestamp);
      return (int)$str;
   }
}



/**
 * combined sleep() and usleep() 
 * 
 */
if (!function_exists("time_nanosleep")) {
   function time_nanosleep($sec, $nano) {
      sleep($sec);
      usleep($nano);
   }
}




/**
 * search first occourence of any of the given chars, returns rest of haystack
 * (char_list must be a string for compatibility with the real PHP func)
 *
 * @param  string $haystack  
 * @param  string $char_list  
 * @return integer
 */
if (!function_exists("strpbrk")) {
   function strpbrk($haystack, $char_list) {
   
      #-- prepare
      $len = strlen($char_list);
      $min = strlen($haystack);
      
1250
1251
1252
1253
1254
1255
1256

1257


1258
1259
1260
1261
1262
1263

1264
1265


1266
1267
1268
1269
1270
1271
1272
1273


1274
1275





1276
1277
1278
1279
1280
1281
1282
         return(false);
      }
   }
}




#-- logo image activation URL query strings (gaga feature)


if (!function_exists("php_real_logo_guid")) {
   function php_real_logo_guid() { return php_logo_guid(); }
   function php_egg_logo_guid() { return zend_logo_guid(); }
}



#-- no need to implement this
#   (there aren't interfaces in PHP4 anyhow)


if (!function_exists("get_declared_interfaces")) {
   function get_declared_interfaces() {
      trigger_error("get_declared_interfaces(): Current script won't run reliably with PHP4.", E_USER_WARNING);
      return( (array)NULL );
   }
}




#-- creates an array from lists of $keys and $values
#   (both should have same number of entries)





if (!function_exists("array_combine")) {
   function array_combine($keys, $values) {
   
      #-- convert input arrays into lists
      $keys = array_values($keys);
      $values = array_values($values);
      $r = array();







>
|
>
>






>
|
|
>
>








>
>
|
|
>
>
>
>
>







2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
         return(false);
      }
   }
}



/**
 * logo image activation URL query strings (gaga feature)
 * 
 */
if (!function_exists("php_real_logo_guid")) {
   function php_real_logo_guid() { return php_logo_guid(); }
   function php_egg_logo_guid() { return zend_logo_guid(); }
}


/**
 * no need to implement this
 * (there aren't interfaces in PHP4 anyhow)
 * 
 */
if (!function_exists("get_declared_interfaces")) {
   function get_declared_interfaces() {
      trigger_error("get_declared_interfaces(): Current script won't run reliably with PHP4.", E_USER_WARNING);
      return( (array)NULL );
   }
}



/**
 * creates an array from lists of $keys and $values
 * (both should have same number of entries)
 *
 * @param  array $keys  
 * @param  array $values  
 * @return array
 */
if (!function_exists("array_combine")) {
   function array_combine($keys, $values) {
   
      #-- convert input arrays into lists
      $keys = array_values($keys);
      $values = array_values($values);
      $r = array();
1291
1292
1293
1294
1295
1296
1297

1298
1299
1300






1301
1302
1303
1304
1305
1306
1307
         }
      }
      return($r);
   }
}



#-- apply userfunction to each array element (descending recursively)
#   use it like:  array_walk_recursive($_POST, "stripslashes");
#   - $callback can be static function name or object/method, class/method






if (!function_exists("array_walk_recursive")) {
   function array_walk_recursive(&$input, $callback, $userdata=NULL) {
      #-- each entry
      foreach ($input as $key=>$value) {

         #-- recurse for sub-arrays
         if (is_array($value)) {







>
|
|
|
>
>
>
>
>
>







2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
         }
      }
      return($r);
   }
}


/**
 * apply userfunction to each array element (descending recursively)
 * use it like:  array_walk_recursive($_POST, "stripslashes");
 * - $callback can be static function name or object/method, class/method
 *
 * @param  array  $input  
 * @param  string $callback  
 * @param  array  $userdata  (optional)
 * @return array
 */
if (!function_exists("array_walk_recursive")) {
   function array_walk_recursive(&$input, $callback, $userdata=NULL) {
      #-- each entry
      foreach ($input as $key=>$value) {

         #-- recurse for sub-arrays
         if (is_array($value)) {
1315
1316
1317
1318
1319
1320
1321

1322








1323
1324
1325
1326
1327
1328
1329
      }

      // no return value
   }
}



#-- complicated wrapper around substr() and and strncmp()








if (!function_exists("substr_compare")) {
   function substr_compare($haystack, $needle, $offset=0, $len=0, $ci=0) {

      #-- check params   
      if ($len <= 0) {   // not well documented
         $len = strlen($needle);
         if (!$len) { return(0); }







>
|
>
>
>
>
>
>
>
>







2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
      }

      // no return value
   }
}


/**
 * complicated wrapper around substr() and and strncmp()
 *
 * @param  string  $haystack  
 * @param  string  $needle  
 * @param  integer $offset  
 * @param  integer $len  
 * @param  integer $ci  
 * @return mixed
 */
if (!function_exists("substr_compare")) {
   function substr_compare($haystack, $needle, $offset=0, $len=0, $ci=0) {

      #-- check params   
      if ($len <= 0) {   // not well documented
         $len = strlen($needle);
         if (!$len) { return(0); }
1346
1347
1348
1349
1350
1351
1352

1353
1354


1355
1356
1357
1358
1359
1360
1361
1362
1363

1364




1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382

1383


1384
1385
1386
1387
1388
1389
1390
1391

1392





1393
1394
1395
1396
1397
1398
1399

      #-- do
      return(strncmp($haystack, $needle, $len));
   }
}



#-- stub, returns empty list as usual;
#   you must load "ext/spl.php" beforehand to get this


if (!function_exists("spl_classes")) {
   function spl_classes() {
      trigger_error("spl_classes(): not built into this PHP version");
      return (array)NULL;
   }
}




#-- gets you list of class names the given objects class was derived from, slow




if (!function_exists("class_parents")) {
   function class_parents($obj) {
   
      #-- first get full list
      $all = get_declared_classes();
      $r = array();
      
      #-- filter out
      foreach ($all as $potential_parent) {
         if (is_subclass_of($obj, $potential_parent)) {
            $r[$potential_parent] = $potential_parent;
         }
      }
      return($r);
   }
}



#-- an alias


if (!function_exists("session_commit") && function_exists("session_write_close")) {
   function session_commit() {
      // simple
      session_write_close();
   }
}



#-- aliases





if (!function_exists("dns_check_record")) {
   function dns_check_record($host, $type=NULL) {
      // synonym to
      return checkdnsrr($host, $type);
   }
}
if (!function_exists("dns_get_mx")) {







>
|
|
>
>









>
|
>
>
>
>


















>
|
>
>








>
|
>
>
>
>
>







2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522

      #-- do
      return(strncmp($haystack, $needle, $len));
   }
}


/**
 * stub, returns empty list as usual;
 * you must load "ext/spl.php" beforehand to get this
 * 
 */
if (!function_exists("spl_classes")) {
   function spl_classes() {
      trigger_error("spl_classes(): not built into this PHP version");
      return (array)NULL;
   }
}



/**
 * gets you list of class names the given objects class was derived from, slow
 *
 * @param  object $obj  
 * @return object
 */
if (!function_exists("class_parents")) {
   function class_parents($obj) {
   
      #-- first get full list
      $all = get_declared_classes();
      $r = array();
      
      #-- filter out
      foreach ($all as $potential_parent) {
         if (is_subclass_of($obj, $potential_parent)) {
            $r[$potential_parent] = $potential_parent;
         }
      }
      return($r);
   }
}


/**
 * an alias
 * 
 */
if (!function_exists("session_commit") && function_exists("session_write_close")) {
   function session_commit() {
      // simple
      session_write_close();
   }
}


/**
 * aliases
 *
 * @param  mixed $host  
 * @param  mixed $type  (optional)
 * @return mixed
 */
if (!function_exists("dns_check_record")) {
   function dns_check_record($host, $type=NULL) {
      // synonym to
      return checkdnsrr($host, $type);
   }
}
if (!function_exists("dns_get_mx")) {
1407
1408
1409
1410
1411
1412
1413

1414
1415









1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434

1435







1436
1437
1438
1439
1440
1441
1442






1443
1444
1445
1446







1447
1448
1449
1450
1451
1452
1453
1454
1455
1456

1457


1458
1459
1460
1461
1462
1463
1464

1465



1466
1467
1468


1469
1470
1471
1472
1473
1474





1475
1476





1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492


























1493
1494
1495
1496
1497
1498
1499
         $w = false;
      }
      return getmxrr($host, $mx, $w);
   }
}



#-- setrawcookie(),
#   can this be emulated 100% exactly?









if (!function_exists("setrawcookie")) {
   // we output everything directly as HTTP header(), PHP doesn't seem
   // to manage an internal cookie list anyhow
   function setrawcookie($name, $value=NULL, $expire=NULL, $path=NULL, $domain=NULL, $secure=0) {
      if (isset($value) && strpbrk($value, ",; \r\t\n\f\014\013")) {
         trigger_error("setrawcookie: value may not contain any of ',; \r\n' and some other control chars; thrown away", E_USER_WARNING);
      }
      else {
         $h = "Set-Cookie: $name=$value"
            . ($expire ? "; expires=" . gmstrftime("%a, %d-%b-%y %H:%M:%S %Z", $expire) : "")
            . ($path ? "; path=$path": "")
            . ($domain ? "; domain=$domain" : "")
            . ($secure ? "; secure" : "");
         header($h);
      }
   }
}



#-- write-at-once file access (counterpart to file_get_contents)







if (!function_exists("file_put_contents")) {
   function file_put_contents($filename, $data, $flags=0, $resource=NULL) {

      #-- prepare
      $mode = ($flags & FILE_APPEND ? "a" : "w" ) ."b";
      $incl = $flags & FILE_USE_INCLUDE_PATH;
      $length = strlen($data);







      #-- open for writing
      $f = fopen($filename, $mode, $incl);
      if ($f) {







         $written = fwrite($f, $data);
         fclose($f);
         
         #-- only report success, if completely saved
         return($length == $written);
      }
   }
}



#-- file-related constants


if (!defined("FILE_USE_INCLUDE_PATH")) { define("FILE_USE_INCLUDE_PATH", 1); }
if (!defined("FILE_IGNORE_NEW_LINES")) { define("FILE_IGNORE_NEW_LINES", 2); }
if (!defined("FILE_SKIP_EMPTY_LINES")) { define("FILE_SKIP_EMPTY_LINES", 4); }
if (!defined("FILE_APPEND")) { define("FILE_APPEND", 8); }
if (!defined("FILE_NO_DEFAULT_CONTEXT")) { define("FILE_NO_DEFAULT_CONTEXT", 16); }



#-- more new constants for 5.0



if (!defined("E_STRICT")) { define("E_STRICT", 2048); }  // _STRICT is a special case of _NOTICE (_DEBUG)
# PHP_CONFIG_FILE_SCAN_DIR




#-- array count_recursive()
if (!defined("COUNT_NORMAL")) { define("COUNT_NORMAL", 0); }      // count($array, 0);
if (!defined("COUNT_RECURSIVE")) { define("COUNT_RECURSIVE", 1); }    // not supported







#-- we introduce a new function, because we cannot emulate the
#   newly introduced second parameter to count()





if (!function_exists("count_recursive")) {
   function count_recursive($array, $mode=1) {
      if (!$mode) {
         return(count($array));
      }
      else {
         $c = count($array);
         foreach ($array as $sub) {
            if (is_array($sub)) {
               $c += count_recursive($sub);
            }
         }
         return($c);
      }
   }
}































/**
 *                                   ------------------------------ 4.4 ---







>
|
|
>
>
>
>
>
>
>
>
>



















>
|
>
>
>
>
>
>
>

|




|
>
>
>
>
>
>




>
>
>
>
>
>
>
|









>
|
>
>







>

>
>
>



>
>



|


>
>
>
>
>
|
|
>
>
>
>
>
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
         $w = false;
      }
      return getmxrr($host, $mx, $w);
   }
}


/**
 * setrawcookie(),
 * can this be emulated 100% exactly?
 *
 * @param  string $name 
 * @param  mixed  $value
 * @param  mixed  $expire
 * @param  mixed  $path
 * @param  mixed  $domain
 * @param integer $secure
 * @return string
 */
if (!function_exists("setrawcookie")) {
   // we output everything directly as HTTP header(), PHP doesn't seem
   // to manage an internal cookie list anyhow
   function setrawcookie($name, $value=NULL, $expire=NULL, $path=NULL, $domain=NULL, $secure=0) {
      if (isset($value) && strpbrk($value, ",; \r\t\n\f\014\013")) {
         trigger_error("setrawcookie: value may not contain any of ',; \r\n' and some other control chars; thrown away", E_USER_WARNING);
      }
      else {
         $h = "Set-Cookie: $name=$value"
            . ($expire ? "; expires=" . gmstrftime("%a, %d-%b-%y %H:%M:%S %Z", $expire) : "")
            . ($path ? "; path=$path": "")
            . ($domain ? "; domain=$domain" : "")
            . ($secure ? "; secure" : "");
         header($h);
      }
   }
}


/**
 * write-at-once file access (counterpart to file_get_contents)
 *
 * @param  integer $filename
 * @param  mixed   $content  
 * @param  integer $flags 
 * @param  mixed   $resource
 * @return integer
 */
if (!function_exists("file_put_contents")) {
   function file_put_contents($filename, $content, $flags=0, $resource=NULL) {

      #-- prepare
      $mode = ($flags & FILE_APPEND ? "a" : "w" ) ."b";
      $incl = $flags & FILE_USE_INCLUDE_PATH;
      $length = strlen($content);
//      $resource && trigger_error("EMULATED file_put_contents does not support \$resource parameter.", E_USER_ERROR);
      
      #-- write non-scalar?
      if (is_array($content) || is_object($content)) {
         $content = implode("", (array)$content);
      }

      #-- open for writing
      $f = fopen($filename, $mode, $incl);
      if ($f) {
      
         // locking
         if (($flags & LOCK_EX) && !flock($f, LOCK_EX)) {
            return fclose($f) && false;
         }

         // write
         $written = fwrite($f, $content);
         fclose($f);
         
         #-- only report success, if completely saved
         return($length == $written);
      }
   }
}


/**
 * file-related constants
 *
 */
if (!defined("FILE_USE_INCLUDE_PATH")) { define("FILE_USE_INCLUDE_PATH", 1); }
if (!defined("FILE_IGNORE_NEW_LINES")) { define("FILE_IGNORE_NEW_LINES", 2); }
if (!defined("FILE_SKIP_EMPTY_LINES")) { define("FILE_SKIP_EMPTY_LINES", 4); }
if (!defined("FILE_APPEND")) { define("FILE_APPEND", 8); }
if (!defined("FILE_NO_DEFAULT_CONTEXT")) { define("FILE_NO_DEFAULT_CONTEXT", 16); }



#-- more new constants for 5.0
/**
 * @since PHP 5
 */
if (!defined("E_STRICT")) { define("E_STRICT", 2048); }  // _STRICT is a special case of _NOTICE (_DEBUG)
# PHP_CONFIG_FILE_SCAN_DIR




#-- array count_recursive()
if (!defined("COUNT_NORMAL")) { define("COUNT_NORMAL", 0); }      // count($array, 0);
if (!defined("COUNT_RECURSIVE")) { define("COUNT_RECURSIVE", 1); }    // use count_recursive()



/**
 * @since never
 * @nonstandard
 * 
 * we introduce a new function, because we cannot emulate the
 * newly introduced second parameter to count()
 * 
 * @param  array $array 
 * @param  integer $mode
 * @return integer
 */
if (!function_exists("count_recursive")) {
   function count_recursive($array, $mode=1) {
      if (!$mode) {
         return(count($array));
      }
      else {
         $c = count($array);
         foreach ($array as $sub) {
            if (is_array($sub)) {
               $c += count_recursive($sub);
            }
         }
         return($c);
      }
   }
}



/**
 * Sets the default client character set.
 *
 * @compat
 *    Procedural style
 * @bugs
 *    PHP documentation says this function exists in PHP 5 >= 5.0.5,
 *    but it also depends on the versions of external libraries, e.g.,
 *    php_mysqli.dll and libmysql.dll.
 *
 * @param $link    mysqli MySQLi connection resource
 * @param $charset string Character set
 * @return bool           TRUE on success, FALSE on failure
 */
if (!function_exists("mysqli_set_charset") && function_exists("mysqli_query")) {
   function mysqli_set_charset($link, $charset) {
      return mysqli_query($link, "SET NAMES '$charset'");
   }
}









/**
 *                                   ------------------------------ 4.4 ---
1565
1566
1567
1568
1569
1570
1571

1572





1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588

1589






1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
 *
 * @unimplementable
 *    money_format
 *
 */



#-- simplified file read-at-once function





if (!function_exists("file_get_contents")) {
   function file_get_contents($filename, $use_include_path=1) {

      #-- open file, let fopen() report error
      $f = fopen($filename, "rb", $use_include_path);
      if (!$f) { return; }

      #-- read max 2MB
      $content = fread($f, 1<<21);
      fclose($f);
      return($content);
   }
}




#-- shell-like filename matching (* and ? globbing characters)






if (!function_exists("fnmatch")) {

   #-- associated constants
   if (!defined("FNM_PATHNAME")) { define("FNM_PATHNAME", 1<<0); }  // no wildcard ever matches a "/"
   if (!defined("FNM_NOESCAPE")) { define("FNM_NOESCAPE", 1<<1); }  // backslash can't escape meta chars
   if (!defined("FNM_PERIOD")) { define("FNM_PERIOD",   1<<2); }  // leading dot must be given explicit
   if (!defined("FNM_LEADING_DIR")) { define("FNM_LEADING_DIR", 1<<3); }  // not in PHP
   if (!defined("FNM_CASEFOLD")) { define("FNM_CASEFOLD", 0x50); }  // match case-insensitive
   if (!defined("FNM_EXTMATCH")) { define("FNM_EXTMATCH", 1<<5); }  // not in PHP
   
   #-- implementation
   function fnmatch($pattern, $str, $flags=0x0000) {
      
      #-- 'hidden' files
      if ($flags & FNM_PERIOD) {
         if (($str[0] == ".") && ($pattern[0] != ".")) {
            return(false);    // abort early
         }
      }

      #-- case-insensitivity
      $rxci = "";
      if ($flags & FNM_CASEFOLD) {







>
|
>
>
>
>
>
















>
|
>
>
>
>
>
>











|



|







2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
 *
 * @unimplementable
 *    money_format
 *
 */


/**
 * simplified file read-at-once function
 *
 * @param  string  $filename  
 * @param  integer $use_include_path  (optional)
 * @return string
 */
if (!function_exists("file_get_contents")) {
   function file_get_contents($filename, $use_include_path=1) {

      #-- open file, let fopen() report error
      $f = fopen($filename, "rb", $use_include_path);
      if (!$f) { return; }

      #-- read max 2MB
      $content = fread($f, 1<<21);
      fclose($f);
      return($content);
   }
}



/**
 * shell-like filename matching (* and ? globbing characters)
 *
 * @param  string $pattern  glob-pattern with *s and ?s
 * @param  string $fn       filename to match it against (without path)
 * @param integer $flags    (optional)
 * @return bool
 */
if (!function_exists("fnmatch")) {

   #-- associated constants
   if (!defined("FNM_PATHNAME")) { define("FNM_PATHNAME", 1<<0); }  // no wildcard ever matches a "/"
   if (!defined("FNM_NOESCAPE")) { define("FNM_NOESCAPE", 1<<1); }  // backslash can't escape meta chars
   if (!defined("FNM_PERIOD")) { define("FNM_PERIOD",   1<<2); }  // leading dot must be given explicit
   if (!defined("FNM_LEADING_DIR")) { define("FNM_LEADING_DIR", 1<<3); }  // not in PHP
   if (!defined("FNM_CASEFOLD")) { define("FNM_CASEFOLD", 0x50); }  // match case-insensitive
   if (!defined("FNM_EXTMATCH")) { define("FNM_EXTMATCH", 1<<5); }  // not in PHP
   
   #-- implementation
   function fnmatch($pattern, $fn, $flags=0x0000) {
      
      #-- 'hidden' files
      if ($flags & FNM_PERIOD) {
         if (($fn[0] == ".") && ($pattern[0] != ".")) {
            return(false);    // abort early
         }
      }

      #-- case-insensitivity
      $rxci = "";
      if ($flags & FNM_CASEFOLD) {
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647

1648





1649
1650
1651
1652
1653
1654
1655
         if (count($cmp) >= 50) {
            $cmp = array();   // free
         }
         $cmp["$pattern+$flags"] = $rx;
      }
      
      #-- compare
      return(preg_match($rx, $str));
   }
}



#-- file search and name matching (with shell patterns)





if (!function_exists("glob")) {

   #-- introduced constants
   if (!defined("GLOB_MARK")) { define("GLOB_MARK", 1<<0); }
   if (!defined("GLOB_NOSORT")) { define("GLOB_NOSORT", 1<<1); }
   if (!defined("GLOB_NOCHECK")) { define("GLOB_NOCHECK", 1<<2); }
   if (!defined("GLOB_NOESCAPE")) { define("GLOB_NOESCAPE", 1<<3); }







|




>
|
>
>
>
>
>







2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
         if (count($cmp) >= 50) {
            $cmp = array();   // free
         }
         $cmp["$pattern+$flags"] = $rx;
      }
      
      #-- compare
      return(preg_match($rx, $fn));
   }
}


/**
 * file search and name matching (with shell patterns)
 *
 * @param  string  $pattern   search pattern and path ../* string
 * @param  integer $flags (optional)
 * @return array
 */
if (!function_exists("glob")) {

   #-- introduced constants
   if (!defined("GLOB_MARK")) { define("GLOB_MARK", 1<<0); }
   if (!defined("GLOB_NOSORT")) { define("GLOB_NOSORT", 1<<1); }
   if (!defined("GLOB_NOCHECK")) { define("GLOB_NOCHECK", 1<<2); }
   if (!defined("GLOB_NOESCAPE")) { define("GLOB_NOESCAPE", 1<<3); }
1752
1753
1754
1755
1756
1757
1758


1759


1760
1761
1762
1763
1764
1765
1766

1767


1768
1769
1770
1771
1772
1773
1774
#print_r($ls);
#echo "<=\n";
      return($ls);
   }
} //@FIX: fully comment, remove debugging code (- as soon as it works ;)




#-- redundant alias for isset()


if (!function_exists("array_key_exists")) {
   function array_key_exists($key, $search) {
      return isset($search[$key]);
   }
}



#-- who could need that?


if (!function_exists("array_intersect_assoc")) {
   function array_intersect_assoc( /*array, array, array...*/ ) {

      #-- parameters, prepare
      $in = func_get_args();
      $cmax = count($in);
      $whatsleftover = array();







>
>
|
>
>







>
|
>
>







2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
#print_r($ls);
#echo "<=\n";
      return($ls);
   }
} //@FIX: fully comment, remove debugging code (- as soon as it works ;)



/**
 * redundant alias for isset()
 * 
 */
if (!function_exists("array_key_exists")) {
   function array_key_exists($key, $search) {
      return isset($search[$key]);
   }
}


/**
 * who could need that?
 * 
 */
if (!function_exists("array_intersect_assoc")) {
   function array_intersect_assoc( /*array, array, array...*/ ) {

      #-- parameters, prepare
      $in = func_get_args();
      $cmax = count($in);
      $whatsleftover = array();
1787
1788
1789
1790
1791
1792
1793

1794


1795
1796
1797
1798
1799
1800
1801
         $whatsleftover[$i] = $v;
      }
      return $whatsleftover;
   }
}



#-- the opposite of the above


if (!function_exists("array_diff_assoc")) {
   function array_diff_assoc( /*array, array, array...*/ ) {

      #-- params
      $in = func_get_args();
      $diff = array();
      







>
|
>
>







3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
         $whatsleftover[$i] = $v;
      }
      return $whatsleftover;
   }
}


/**
 * the opposite of the above
 * 
 */
if (!function_exists("array_diff_assoc")) {
   function array_diff_assoc( /*array, array, array...*/ ) {

      #-- params
      $in = func_get_args();
      $diff = array();
      
1811
1812
1813
1814
1815
1816
1817

1818


1819
1820
1821
1822
1823
1824
1825
1826
1827

1828


1829
1830
1831
1832
1833
1834
1835
         $diff[$i] = $v;
      }
      return $diff;
   }
}



#-- opposite of htmlentities


if (!function_exists("html_entity_decode")) {
   function html_entity_decode($string, $quote_style=ENT_COMPAT, $charset="ISO-8859-1") {
      //@FIX: we fall short on anything other than Latin-1
      $y = array_flip(get_html_translation_table(HTML_ENTITIES, $quote_style));
      return strtr($string, $y);
   }
}



#-- extracts single words from a string


if (!function_exists("str_word_count")) {
   function str_word_count($string, $result=0) {
   
      #-- let someone else do the work
      preg_match_all('/([\w](?:[-\'\w]?[\w]+)*)/', $string, $uu);

      #-- return full word list







>
|
>
>









>
|
>
>







3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
         $diff[$i] = $v;
      }
      return $diff;
   }
}


/**
 * opposite of htmlentities
 * 
 */
if (!function_exists("html_entity_decode")) {
   function html_entity_decode($string, $quote_style=ENT_COMPAT, $charset="ISO-8859-1") {
      //@FIX: we fall short on anything other than Latin-1
      $y = array_flip(get_html_translation_table(HTML_ENTITIES, $quote_style));
      return strtr($string, $y);
   }
}


/**
 * extracts single words from a string
 * 
 */
if (!function_exists("str_word_count")) {
   function str_word_count($string, $result=0) {
   
      #-- let someone else do the work
      preg_match_all('/([\w](?:[-\'\w]?[\w]+)*)/', $string, $uu);

      #-- return full word list
1853
1854
1855
1856
1857
1858
1859

1860
1861


1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881

1882


1883
1884
1885
1886
1887
1888
1889
      else {
         return(count($uu[1]));
      }
   }
}



#-- creates a permutation of the given strings characters
#   (let's hope the random number generator was alread initialized)


if (!function_exists("str_shuffle")) {
   function str_shuffle($str) {
      $r = "";

      #-- cut string down with every iteration
      while (strlen($str)) {
         $n = strlen($str) - 1;
         if ($n) {
            $n = rand(0, $n);   // glibcs` rand is ok since 2.1 at least
         }
         
         #-- cut out elected char, add to result string
         $r .= $str{$n};
         $str = substr($str, 0, $n) . substr($str, $n + 1);
      }
      return($r);
   }
}



#-- simple shorthands


if (!function_exists("get_include_path")) {
   function get_include_path() {
      return(get_cfg_var("include_path"));
   }
   function set_include_path($new) {
      return ini_set("include_path", $new);
   }







>
|
|
>
>




















>
|
>
>







3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
      else {
         return(count($uu[1]));
      }
   }
}


/**
 * creates a permutation of the given strings characters
 * (let's hope the random number generator was alread initialized)
 * 
 */
if (!function_exists("str_shuffle")) {
   function str_shuffle($str) {
      $r = "";

      #-- cut string down with every iteration
      while (strlen($str)) {
         $n = strlen($str) - 1;
         if ($n) {
            $n = rand(0, $n);   // glibcs` rand is ok since 2.1 at least
         }
         
         #-- cut out elected char, add to result string
         $r .= $str{$n};
         $str = substr($str, 0, $n) . substr($str, $n + 1);
      }
      return($r);
   }
}


/**
 * simple shorthands
 * 
 */
if (!function_exists("get_include_path")) {
   function get_include_path() {
      return(get_cfg_var("include_path"));
   }
   function set_include_path($new) {
      return ini_set("include_path", $new);
   }
1904
1905
1906
1907
1908
1909
1910

1911
























1912
1913
1914

1915



1916




1917
1918
1919
1920
1921
1922
1923
1924
1925
1926







1927
1928
1929
1930
1931
1932
1933
if (!defined("PHP_PREFIX") && isset($_ENV["_"])) { define("PHP_PREFIX", substr($_ENV["_"], 0, strpos($_ENV["_"], "bin/"))); }







#------------------------------------------------------------------ 4.2 ---
























# almost complete!?



#-- shy away from this one - it was broken in all real PHP4.2 versions, and



#   this function emulation script won't change that




if (!function_exists("str_rot13")) {
   function str_rot13($str) {
      static $from = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
      static $to = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm";
      return strtr($str, $from, $to);
   }
}


#-- well, if you need it







if (!function_exists("array_change_key_case")) {
   
   #-- introduced constants
   if (!defined("CASE_LOWER")) { define("CASE_LOWER", 0); }
   if (!defined("CASE_UPPER")) { define("CASE_UPPER", 1); }
   
   #-- implementation







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
|
>
>
>
|
>
>
>
>









<
>
>
>
>
>
>
>







3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198

3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
if (!defined("PHP_PREFIX") && isset($_ENV["_"])) { define("PHP_PREFIX", substr($_ENV["_"], 0, strpos($_ENV["_"], "bin/"))); }






/**
 *                                   ------------------------------ 4.2 ---
 * @group 4_2
 * @since 4.2
 *
 *
 *  Functions added in PHP 4.2 interpreters.
 *
 *
 * @emulated
 *   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
 * @missing
 *   ...
 *
 *   almost complete!?
 *
 *
 */


/**
 * shy away from this function - it was broken in all PHP4.2 releases,
 * and our emulation here won't change that
 *
 * @param  string $str  
 * @return string
 */
if (!function_exists("str_rot13")) {
   function str_rot13($str) {
      static $from = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
      static $to = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm";
      return strtr($str, $from, $to);
   }
}



/**
 * changes case of textual index keys
 *
 * @param  array $array  
 * @param  int   $case
 * @return array
 */
if (!function_exists("array_change_key_case")) {
   
   #-- introduced constants
   if (!defined("CASE_LOWER")) { define("CASE_LOWER", 0); }
   if (!defined("CASE_UPPER")) { define("CASE_UPPER", 1); }
   
   #-- implementation
1944
1945
1946
1947
1948
1949
1950

1951


1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969

1970


1971
1972
1973
1974
1975
1976
1977
         // non-recursive      
      }
      return($array);
   }
}



#-- create fixed-length array made up of $value data


if (!function_exists("array_fill")) {
   function array_fill($start_index, $num, $value) {

      #-- params
      $r = array();
      $i = $start_index;
      $end = $num + $start_index;
      
      #-- append
      for (; $i < $end; $i++)
      {
         $r[$i] = $value;
      }
      return($r);
   }
}



#-- split an array into evenly sized parts


if (!function_exists("array_chunk")) {
   function array_chunk($input, $size, $preserve_keys=false) {
   
      #-- array for chunked output
      $r = array();
      $n = -1;  // chunk index
      







>
|
>
>


















>
|
>
>







3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
         // non-recursive      
      }
      return($array);
   }
}


/**
 * create fixed-length array made up of $value data
 * 
 */
if (!function_exists("array_fill")) {
   function array_fill($start_index, $num, $value) {

      #-- params
      $r = array();
      $i = $start_index;
      $end = $num + $start_index;
      
      #-- append
      for (; $i < $end; $i++)
      {
         $r[$i] = $value;
      }
      return($r);
   }
}


/**
 * split an array into evenly sized parts
 * 
 */
if (!function_exists("array_chunk")) {
   function array_chunk($input, $size, $preserve_keys=false) {
   
      #-- array for chunked output
      $r = array();
      $n = -1;  // chunk index
      
1993
1994
1995
1996
1997
1998
1999

2000


2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017

2018


2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031

2032


2033
2034
2035
2036
2037
2038
2039
2040
2041
2042

2043




2044
2045
2046
2047
2048
2049
2050
2051

2052


2053
2054
2055
2056
2057
2058
2059
         }
      }
      return($r);
   }
}



#-- convenience wrapper


if (!function_exists("md5_file")) {
   function md5_file($filename, $raw_output=false) {

      #-- read file, apply hash function
      $data = file_get_contents($filename, "rb");
      $r = md5($data);
      $data = NULL;
         
      #-- transform? and return
      if ($raw_output) {
         $r = pack("H*", $r);
      }
      return $r;
   }
}



#-- object type checking


if (!function_exists("is_a")) {
   function is_a($obj, $classname) {
   
      #-- lowercase everything for comparison
      $classnaqme = strtolower($classname);
      $obj_class =  strtolower(get_class($obj));
      
      #-- two possible checks
      return ($obj_class == $classname) or is_subclass_of($obj, $classname);
   }
}



#-- floating point modulo


if (!function_exists("fmod")) {
   function fmod($x, $y) {
      $r = $x / $y;
      $r -= (int)$r;
      $r *= $y;
      return($r);
   }
}



#-- makes float variable from string




if (!function_exists("floatval")) {
   function floatval($str) {
      $str = ltrim($str);
      return (float)$str;
   }
}



#-- floats


if (!function_exists("is_infinite")) {

   #-- constants as-is
   if (!defined("NAN")) { define("NAN", "NAN"); }
   if (!defined("INF")) { define("INF", "INF"); }   // there is also "-INF"
   
   #-- simple checks







>
|
>
>




|
<
<










>
|
>
>













>
|
>
>










>
|
>
>
>
>








>
|
>
>







3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293


3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
         }
      }
      return($r);
   }
}


/**
 * convenience wrapper
 * 
 */
if (!function_exists("md5_file")) {
   function md5_file($filename, $raw_output=false) {

      #-- read file, apply hash function
      $r = md5(file_get_contents($filename, "rb"));


         
      #-- transform? and return
      if ($raw_output) {
         $r = pack("H*", $r);
      }
      return $r;
   }
}


/**
 * object type checking
 * 
 */
if (!function_exists("is_a")) {
   function is_a($obj, $classname) {
   
      #-- lowercase everything for comparison
      $classnaqme = strtolower($classname);
      $obj_class =  strtolower(get_class($obj));
      
      #-- two possible checks
      return ($obj_class == $classname) or is_subclass_of($obj, $classname);
   }
}


/**
 * floating point modulo
 * 
 */
if (!function_exists("fmod")) {
   function fmod($x, $y) {
      $r = $x / $y;
      $r -= (int)$r;
      $r *= $y;
      return($r);
   }
}


/**
 * makes float variable from string
 *
 * @param  string
 * @return float
 */
if (!function_exists("floatval")) {
   function floatval($str) {
      $str = ltrim($str);
      return (float)$str;
   }
}


/**
 * floats
 *
 */
if (!function_exists("is_infinite")) {

   #-- constants as-is
   if (!defined("NAN")) { define("NAN", "NAN"); }
   if (!defined("INF")) { define("INF", "INF"); }   // there is also "-INF"
   
   #-- simple checks
2068
2069
2070
2071
2072
2073
2074

2075


2076








2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
   function is_finite($f) {
      $s = (string)$f;
      return(  !strpos($s, "N")  );
   }
}



#-- throws value-instantiation PHP-code for given variable


#   (a bit different from the standard, was intentional for its orig use)








if (!function_exists("var_export")) {
   function var_export($var, $return=false, $indent="", $output="") {

      #-- output as in-class variable definitions
      if (is_object($var)) {
         $output = "class " . get_class($var) . " {\n";
         foreach (((array)$var) as $id=>$var) {
            $output .= "  var \$$id = " . var_export($var, true) . ";\n";
         }
         $output .= "}";
      }
      
      #-- array constructor
      elseif (is_array($var)) {
         foreach ($var as $id=>$next) {
            if ($output) $output .= ",\n";
                    else $output = "array(\n";







>
|
>
>
|
>
>
>
>
>
>
>
>





|

|

|







3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
   function is_finite($f) {
      $s = (string)$f;
      return(  !strpos($s, "N")  );
   }
}


/**
 * throws value-instantiation PHP-code for given variable
 *
 * @compat
 *    output differentiates from native PHP version,
 *    but functions identically
 *
 * @param  mixed $var  
 * @param  mixed $return  (optional) false
 * @param  string $indent  (optional) ""
 * @param  string $output  (optional) ""
 * @return mixed
 */
if (!function_exists("var_export")) {
   function var_export($var, $return=false, $indent="", $output="") {

      #-- output as in-class variable definitions
      if (is_object($var)) {
         $output = get_class($var) . "::_set_state(array(\n";
         foreach (((array)$var) as $id=>$var) {
            $output .= "  '\$$id' => " . var_export($var, true) . ",\n";
         }
         $output .= "));";
      }
      
      #-- array constructor
      elseif (is_array($var)) {
         foreach ($var as $id=>$next) {
            if ($output) $output .= ",\n";
                    else $output = "array(\n";
2118
2119
2120
2121
2122
2123
2124




2125
2126





2127
2128
2129
2130
2131
2132
2133
2134
2135
2136

2137



























2138
2139
2140


2141
2142
2143
2144
2145
2146
2147


2148
2149
2150
2151
2152
2153
2154
2155
2156
2157

2158





2159
2160
2161
2162
2163
2164
2165

2166





2167
2168
2169
2170
2171
2172
2173
2174



2175





2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186

2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
      else {
         print($output);
      }
   }
}






#-- strcmp() variant that respects locale setting,
#   existed since PHP 4.0.5, but under Win32 first since 4.3.2





if (!function_exists("strcoll")) {
   function strcoll($str1, $str2) {
      return strcmp($str1, $str2);
   }
}






#------------------------------------------------------------------ 4.1 ---



























# nl_langinfo - unimpl?
# getmygid
# version_compare


#
# See also "ext/math41.php" for some more (rarely used mathematical funcs).




#-- aliases (an earlier fallen attempt to unify PHP function names)


if (!function_exists("diskfreespace")) {
   function diskfreespace() {
      return disk_free_sapce();
   }
   function disktotalspace() {
      return disk_total_sapce();
   }
}



#-- variable count of arguments (in array list) printf variant





if (!function_exists("vprintf")) {
   function vprintf($format, $args=NULL) {
      call_user_func_array("fprintf", get_func_args());
   }
}



#-- same as above, but doesn't output directly and returns formatted string





if (!function_exists("vsprintf")) {
   function vsprintf($format, $args=NULL) {
      $args = array_merge(array($format), array_values((array)$args));
      return call_user_func_array("sprintf", $args);
   }
}





#-- can be used to simulate a register_globals=on environment





if (!function_exists("import_request_variables")) {
   function import_request_variables($types="GPC", $pfix="") {
      
      #-- associate abbreviations to global var names
      $alias = array(
         "G" => "_GET",
         "P" => "_POST",
         "C" => "_COOKIE",
         "S" => "_SERVER",   // non-standard
         "E" => "_ENV",      // non-standard
      );

      #-- alias long names (PHP < 4.0.6)
      if (!isset($_REQUEST)) {
         $_GET = & $HTTP_GET_VARS;
         $_POST = & $HTTP_POST_VARS;
         $_COOKIE = & $HTTP_COOKIE_VARS;
      }
      
      #-- copy
      for ($i=0; $i<strlen($types); $i++) {
         if ($FROM = $alias[strtoupper($c)]) {
            foreach ($$FROM as $key=>$val) {
               if (!isset($GLOBALS[$pfix.$key])) {
                  $GLOBALS[$pfix . $key] = $val;
               }
            }
         }







>
>
>
>
|
<
>
>
>
>
>










>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
|
<



|
|
>
>










>
|
>
>
>
>
>


|




>
|
>
>
>
>
>








>
>
>
|
>
>
>
>
>











>
|







|







3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440

3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490

3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
      else {
         print($output);
      }
   }
}


/**
 * @stub
 * @since existed since PHP 4.0.5, but under Win32 first since 4.3.2
 * 
 * strcmp() variant that respects locale setting,

 *
 * @param  string $str1  
 * @param  string $str2  
 * @return string
 */
if (!function_exists("strcoll")) {
   function strcoll($str1, $str2) {
      return strcmp($str1, $str2);
   }
}





/**
 *                                   ------------------------------ 4.1 ---
 * @group 4_1
 * @since 4.1
 *
 *
 * See also "ext/math41.php" for some more (rarely used mathematical funcs).
 *
 *
 * @emulated
 *   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
 * @missing
 *   nl_langinfo - unimpl?
 *   getmygid
 *   version_compare
 *
 */





/**
 * aliases (an earlier fallen attempt to unify PHP function names)
 * 
 */
if (!function_exists("diskfreespace")) {
   function diskfreespace() {
      return disk_free_sapce();
   }
   function disktotalspace() {
      return disk_total_sapce();
   }
}


/**
 * variable count of arguments (in array list) printf variant
 *
 * @param  string $format  
 * @param  mixed  $args
 * @output
 */
if (!function_exists("vprintf")) {
   function vprintf($format, $args=NULL) {
      call_user_func_array("fprintf", func_get_args());
   }
}


/**
 * same as above, but doesn't output directly and returns formatted string
 *
 * @param  string $format
 * @param  mixed  $args
 * @return string
 */
if (!function_exists("vsprintf")) {
   function vsprintf($format, $args=NULL) {
      $args = array_merge(array($format), array_values((array)$args));
      return call_user_func_array("sprintf", $args);
   }
}


/**
 * @extended
 *
 * can be used to simulate a register_globals=on environment
 *
 * @param  string $types   order of GET,POST,COOKIE variables
 * @param  string $pfix    prefix for imported variable names
 * @global $GLOBALS
 */
if (!function_exists("import_request_variables")) {
   function import_request_variables($types="GPC", $pfix="") {
      
      #-- associate abbreviations to global var names
      $alias = array(
         "G" => "_GET",
         "P" => "_POST",
         "C" => "_COOKIE",
         "S" => "_SERVER",   // non-standard
         "E" => "_ENV",      // non-standard
      );

      #-- alias long names (PHP < 4.0.6)    //@FIXME: does that belong here?
      if (!isset($_REQUEST)) {
         $_GET = & $HTTP_GET_VARS;
         $_POST = & $HTTP_POST_VARS;
         $_COOKIE = & $HTTP_COOKIE_VARS;
      }
      
      #-- copy
      foreach (str_split($types, 1) as $c) {
         if ($FROM = $alias[strtoupper($c)]) {
            foreach ($$FROM as $key=>$val) {
               if (!isset($GLOBALS[$pfix.$key])) {
                  $GLOBALS[$pfix . $key] = $val;
               }
            }
         }
2251
2252
2253
2254
2255
2256
2257



2258






2259
2260
2261
2262
2263
2264
2265
   }
   function atanh($x) {
      return(  log1p( 2*$x / (1-$x) ) / 2  );
   }
}





#-- HMAC from RFC2104, but see also PHP_Compat and Crypt_HMAC






if (!function_exists("mhash")) {

   #-- constants
   if (!defined("MHASH_CRC32")) { define("MHASH_CRC32", 0); }
   if (!defined("MHASH_MD5")) { define("MHASH_MD5", 1); }       // RFC1321
   if (!defined("MHASH_SHA1")) { define("MHASH_SHA1", 2); }      // RFC3174
   if (!defined("MHASH_TIGER")) { define("MHASH_TIGER", 7); }







>
>
>
|
>
>
>
>
>
>







3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
   }
   function atanh($x) {
      return(  log1p( 2*$x / (1-$x) ) / 2  );
   }
}




/**
 * HMAC from RFC2104, but see also PHP_Compat or Crypt_HMAC
 *
 * @param  string $hashtype  which encoding functions to use
 * @param  string $text      plaintext to hash
 * @param  string $key       key data
 * @return string            hash
 */
if (!function_exists("mhash")) {

   #-- constants
   if (!defined("MHASH_CRC32")) { define("MHASH_CRC32", 0); }
   if (!defined("MHASH_MD5")) { define("MHASH_MD5", 1); }       // RFC1321
   if (!defined("MHASH_SHA1")) { define("MHASH_SHA1", 2); }      // RFC3174
   if (!defined("MHASH_TIGER")) { define("MHASH_TIGER", 7); }
2317
2318
2319
2320
2321
2322
2323
2324

2325






2326



2327

2328
2329
2330
2331
2332












2333
2334

2335


2336
2337
2338
   function mhash_get_block_size($i) {
      return(64);
   }
}



#-- other stuff

/*






  removed funcs??



      [18] => leak

*/



#-- pre-4.1 -- end












// no need to implement anything below that, because such old versions
// will be incompatbile anyhow (- none of the newer superglobals known),

// but see also "ext/old"




?>







|
>
|
>
>
>
>
>
>
|
>
>
>
|
>
|



|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>



3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
   function mhash_get_block_size($i) {
      return(64);
   }
}





/**
 *
 * @group REMOVED_STUFF
 * @since unknown
 * @until unknown
 *
 *
 * @emulated
 *    ...
 *
 * @missing
 *    leak  - occupy a given amount of memory
 *
 */





/**
 *
 * group PRE_4_1
 * since 4.0
 * since 3.0
 *
 *
 * @emulated
 *    ...
 *
 *
 * No need to implement anything below that, because such old versions
 * will be incompatbile anyhow (- none of the newer superglobals known).
 *
 * but see also "ext/old"
 *
 */


?>