feat: add videodb media index with Docker stack

- Add videodb PHP/MySQL media collection manager (Blu-ray, DVD, CD)
- Dockerfile: PHP 8.1 + Apache with GD/mysqli/exif extensions
- docker-compose.yml: app on port 6761 + MySQL 8.0 with health checks
- docker-entrypoint.sh: auto-generates config.inc.php from env vars,
  waits for MySQL, initializes DB schema idempotently
- init-db.php: CLI schema installer using app's own prefix_query() logic
- Persistent volumes for DB, cache, and cover images

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-11 09:49:52 +02:00
commit f55c91276e
1230 changed files with 252321 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
# composer related
composer.lock
composer.phar
vendor
README.html
dist/

View File

@@ -0,0 +1,9 @@
language: php
php:
- 7
- 5.6
- 5.5
- 5.4
sudo: false
script:
- pear run-tests -r tests/

View File

@@ -0,0 +1,365 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
/**
* PHP Version 5
*
* Copyright (c) 2001-2015, The PEAR developers
*
* This source file is subject to the BSD-2-Clause license,
* that is bundled with this package in the file LICENSE, and is
* available through the world-wide-web at the following url:
* http://opensource.org/licenses/bsd-license.php.
*
* @category Console
* @package Console_Getopt
* @author Andrei Zmievski <andrei@php.net>
* @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_Getopt
*/
require_once 'PEAR.php';
/**
* Command-line options parsing class.
*
* @category Console
* @package Console_Getopt
* @author Andrei Zmievski <andrei@php.net>
* @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause
* @link http://pear.php.net/package/Console_Getopt
*/
class Console_Getopt
{
/**
* Parses the command-line options.
*
* The first parameter to this function should be the list of command-line
* arguments without the leading reference to the running program.
*
* The second parameter is a string of allowed short options. Each of the
* option letters can be followed by a colon ':' to specify that the option
* requires an argument, or a double colon '::' to specify that the option
* takes an optional argument.
*
* The third argument is an optional array of allowed long options. The
* leading '--' should not be included in the option name. Options that
* require an argument should be followed by '=', and options that take an
* option argument should be followed by '=='.
*
* The return value is an array of two elements: the list of parsed
* options and the list of non-option command-line arguments. Each entry in
* the list of parsed options is a pair of elements - the first one
* specifies the option, and the second one specifies the option argument,
* if there was one.
*
* Long and short options can be mixed.
*
* Most of the semantics of this function are based on GNU getopt_long().
*
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
* @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
*
* @return array two-element array containing the list of parsed options and
* the non-option arguments
*/
public static function getopt2($args, $short_options, $long_options = null, $skip_unknown = false)
{
return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown);
}
/**
* This function expects $args to start with the script name (POSIX-style).
* Preserved for backwards compatibility.
*
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
*
* @see getopt2()
* @return array two-element array containing the list of parsed options and
* the non-option arguments
*/
public static function getopt($args, $short_options, $long_options = null, $skip_unknown = false)
{
return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown);
}
/**
* The actual implementation of the argument parsing code.
*
* @param int $version Version to use
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
* @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
*
* @return array
*/
public static function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false)
{
// in case you pass directly readPHPArgv() as the first arg
if (PEAR::isError($args)) {
return $args;
}
if (empty($args)) {
return array(array(), array());
}
$non_opts = $opts = array();
settype($args, 'array');
if ($long_options) {
sort($long_options);
}
/*
* Preserve backwards compatibility with callers that relied on
* erroneous POSIX fix.
*/
if ($version < 2) {
if (isset($args[0][0]) && $args[0][0] != '-') {
array_shift($args);
}
}
for ($i = 0; $i < count($args); $i++) {
$arg = $args[$i];
/* The special element '--' means explicit end of
options. Treat the rest of the arguments as non-options
and end the loop. */
if ($arg == '--') {
$non_opts = array_merge($non_opts, array_slice($args, $i + 1));
break;
}
if ($arg[0] != '-' || (strlen($arg) > 1 && $arg[1] == '-' && !$long_options)) {
$non_opts = array_merge($non_opts, array_slice($args, $i));
break;
} elseif (strlen($arg) > 1 && $arg[1] == '-') {
$error = Console_Getopt::_parseLongOption(substr($arg, 2),
$long_options,
$opts,
$i,
$args,
$skip_unknown);
if (PEAR::isError($error)) {
return $error;
}
} elseif ($arg == '-') {
// - is stdin
$non_opts = array_merge($non_opts, array_slice($args, $i));
break;
} else {
$error = Console_Getopt::_parseShortOption(substr($arg, 1),
$short_options,
$opts,
$i,
$args,
$skip_unknown);
if (PEAR::isError($error)) {
return $error;
}
}
}
return array($opts, $non_opts);
}
/**
* Parse short option
*
* @param string $arg Argument
* @param string[] $short_options Available short options
* @param string[][] &$opts
* @param int &$argIdx
* @param string[] $args
* @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
*
* @return void
*/
protected static function _parseShortOption($arg, $short_options, &$opts, &$argIdx, $args, $skip_unknown)
{
for ($i = 0; $i < strlen($arg); $i++) {
$opt = $arg[$i];
$opt_arg = null;
/* Try to find the short option in the specifier string. */
if (($spec = strstr($short_options, $opt)) === false || $arg[$i] == ':') {
if ($skip_unknown === true) {
break;
}
$msg = "Console_Getopt: unrecognized option -- $opt";
return PEAR::raiseError($msg);
}
if (strlen($spec) > 1 && $spec[1] == ':') {
if (strlen($spec) > 2 && $spec[2] == ':') {
if ($i + 1 < strlen($arg)) {
/* Option takes an optional argument. Use the remainder of
the arg string if there is anything left. */
$opts[] = array($opt, substr($arg, $i + 1));
break;
}
} else {
/* Option requires an argument. Use the remainder of the arg
string if there is anything left. */
if ($i + 1 < strlen($arg)) {
$opts[] = array($opt, substr($arg, $i + 1));
break;
} else if (isset($args[++$argIdx])) {
$opt_arg = $args[$argIdx];
/* Else use the next argument. */;
if (Console_Getopt::_isShortOpt($opt_arg)
|| Console_Getopt::_isLongOpt($opt_arg)) {
$msg = "option requires an argument --$opt";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
} else {
$msg = "option requires an argument --$opt";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
}
}
$opts[] = array($opt, $opt_arg);
}
}
/**
* Checks if an argument is a short option
*
* @param string $arg Argument to check
*
* @return bool
*/
protected static function _isShortOpt($arg)
{
return strlen($arg) == 2 && $arg[0] == '-'
&& preg_match('/[a-zA-Z]/', $arg[1]);
}
/**
* Checks if an argument is a long option
*
* @param string $arg Argument to check
*
* @return bool
*/
protected static function _isLongOpt($arg)
{
return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
preg_match('/[a-zA-Z]+$/', substr($arg, 2));
}
/**
* Parse long option
*
* @param string $arg Argument
* @param string[] $long_options Available long options
* @param string[][] &$opts
* @param int &$argIdx
* @param string[] $args
*
* @return void|PEAR_Error
*/
protected static function _parseLongOption($arg, $long_options, &$opts, &$argIdx, $args, $skip_unknown)
{
@list($opt, $opt_arg) = explode('=', $arg, 2);
$opt_len = strlen($opt);
for ($i = 0; $i < count($long_options); $i++) {
$long_opt = $long_options[$i];
$opt_start = substr($long_opt, 0, $opt_len);
$long_opt_name = str_replace('=', '', $long_opt);
/* Option doesn't match. Go on to the next one. */
if ($long_opt_name != $opt) {
continue;
}
$opt_rest = substr($long_opt, $opt_len);
/* Check that the options uniquely matches one of the allowed
options. */
if ($i + 1 < count($long_options)) {
$next_option_rest = substr($long_options[$i + 1], $opt_len);
} else {
$next_option_rest = '';
}
if ($opt_rest != '' && $opt[0] != '=' &&
$i + 1 < count($long_options) &&
$opt == substr($long_options[$i+1], 0, $opt_len) &&
$next_option_rest != '' &&
$next_option_rest[0] != '=') {
$msg = "Console_Getopt: option --$opt is ambiguous";
return PEAR::raiseError($msg);
}
if (substr($long_opt, -1) == '=') {
if (substr($long_opt, -2) != '==') {
/* Long option requires an argument.
Take the next argument if one wasn't specified. */;
if (!strlen($opt_arg)) {
if (!isset($args[++$argIdx])) {
$msg = "Console_Getopt: option requires an argument --$opt";
return PEAR::raiseError($msg);
}
$opt_arg = $args[$argIdx];
}
if (Console_Getopt::_isShortOpt($opt_arg)
|| Console_Getopt::_isLongOpt($opt_arg)) {
$msg = "Console_Getopt: option requires an argument --$opt";
return PEAR::raiseError($msg);
}
}
} else if ($opt_arg) {
$msg = "Console_Getopt: option --$opt doesn't allow an argument";
return PEAR::raiseError($msg);
}
$opts[] = array('--' . $opt, $opt_arg);
return;
}
if ($skip_unknown === true) {
return;
}
return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
}
/**
* Safely read the $argv PHP array across different PHP configurations.
* Will take care on register_globals and register_argc_argv ini directives
*
* @return mixed the $argv PHP array or PEAR error if not registered
*/
public static function readPHPArgv()
{
global $argv;
if (!is_array($argv)) {
if (!@is_array($_SERVER['argv'])) {
if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
$msg = "Could not read cmd args (register_argc_argv=Off?)";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
return $GLOBALS['HTTP_SERVER_VARS']['argv'];
}
return $_SERVER['argv'];
}
return $argv;
}
}

View File

@@ -0,0 +1,25 @@
Copyright (c) 2001-2015, The PEAR developers
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,26 @@
*******************************************
Console_Getopt - Command-line option parser
*******************************************
This is a PHP implementation of "getopt" supporting both short and long options.
It helps parsing command line options in your PHP script.
Homepage: http://pear.php.net/package/Console_Getopt
.. image:: https://travis-ci.org/pear/Console_Getopt.svg?branch=master
:target: https://travis-ci.org/pear/Console_Getopt
Alternatives
============
* Console_CommandLine__ (recommended)
* Console_GetoptPlus__
__ http://pear.php.net/package/Console_CommandLine
__ http://pear.php.net/package/Console_GetoptPlus
License
=======
BSD-2-Clause

View File

@@ -0,0 +1,35 @@
{
"authors": [
{
"email": "andrei@php.net",
"name": "Andrei Zmievski",
"role": "Lead"
},
{
"email": "stig@php.net",
"name": "Stig Bakken",
"role": "Developer"
},
{
"email": "cellog@php.net",
"name": "Greg Beaver",
"role": "Helper"
}
],
"autoload": {
"psr-0": {
"Console": "./"
}
},
"description": "More info available on: http://pear.php.net/package/Console_Getopt",
"include-path": [
"./"
],
"license": "BSD-2-Clause",
"name": "pear/console_getopt",
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Console_Getopt",
"source": "https://github.com/pear/Console_Getopt"
},
"type": "library"
}

View File

@@ -0,0 +1,302 @@
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.2" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
<name>Console_Getopt</name>
<channel>pear.php.net</channel>
<summary>Command-line option parser</summary>
<description>This is a PHP implementation of &quot;getopt&quot; supporting both
short and long options.</description>
<lead>
<name>Andrei Zmievski</name>
<user>andrei</user>
<email>andrei@php.net</email>
<active>no</active>
</lead>
<developer>
<name>Stig Bakken</name>
<user>ssb</user>
<email>stig@php.net</email>
<active>no</active>
</developer>
<helper>
<name>Greg Beaver</name>
<user>cellog</user>
<email>cellog@php.net</email>
<active>no</active>
</helper>
<date>2019-11-20</date>
<version>
<release>1.4.3</release>
<api>1.4.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license>
<notes>
* PR #4: Fix PHP 7.4 deprecation: array/string curly braces access
* PR #5: fix phplint warnings
</notes>
<contents>
<dir name="/">
<dir name="Console">
<file name="Getopt.php" role="php" />
</dir>
<dir name="tests">
<file role="test" name="001-getopt.phpt" />
<file role="test" name="bug10557.phpt" />
<file role="test" name="bug11068.phpt" />
<file role="test" name="bug13140.phpt" />
</dir>
</dir>
</contents>
<compatible>
<name>PEAR</name>
<channel>pear.php.net</channel>
<min>1.4.0</min>
<max>1.999.999</max>
</compatible>
<dependencies>
<required>
<php>
<min>5.4.0</min>
</php>
<pearinstaller>
<min>1.8.0</min>
</pearinstaller>
</required>
</dependencies>
<phprelease />
<changelog>
<release>
<date>2019-11-20</date>
<version>
<release>1.4.3</release>
<api>1.4.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license>
<notes>
* PR #4: Fix PHP 7.4 deprecation: array/string curly braces access
* PR #5: fix phplint warnings
</notes>
</release>
<release>
<date>2019-02-06</date>
<version>
<release>1.4.2</release>
<api>1.4.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license>
<notes>
* Remove use of each(), which is removed in PHP 8
</notes>
</release>
<release>
<date>2015-07-20</date>
<version>
<release>1.4.1</release>
<api>1.4.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license>
<notes>
* Fix unit test on PHP 7 [cweiske]
</notes>
</release>
<release>
<date>2015-02-22</date>
<version>
<release>1.4.0</release>
<api>1.4.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license>
<notes>
* Change license to BSD-2-Clause
* Set minimum PHP version to 5.4.0
* Mark static methods with "static" keyword
</notes>
</release>
<release>
<date>2011-03-07</date>
<version>
<release>1.3.1</release>
<api>1.3.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
* Change the minimum PEAR installer dep to be lower
</notes>
</release>
<release>
<date>2010-12-11</date>
<time>20:20:13</time>
<version>
<release>1.3.0</release>
<api>1.3.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
* Implement Request #13140: [PATCH] to skip unknown parameters. [patch by rquadling, improved on by dufuz]
</notes>
</release>
<release>
<date>2007-06-12</date>
<version>
<release>1.2.3</release>
<api>1.2.1</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
* fix Bug #11068: No way to read plain &quot;-&quot; option [cardoe]
</notes>
</release>
<release>
<version>
<release>1.2.2</release>
<api>1.2.1</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2007-02-17</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
* fix Bug #4475: An ambiguous error occurred when specifying similar longoption name.
* fix Bug #10055: Not failing properly on short options missing required values
</notes>
</release>
<release>
<version>
<release>1.2.1</release>
<api>1.2.1</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2006-12-08</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
Fixed bugs #4448 (Long parameter values truncated with longoption parameter) and #7444 (Trailing spaces after php closing tag)
</notes>
</release>
<release>
<version>
<release>1.2</release>
<api>1.2</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2003-12-11</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
Fix to preserve BC with 1.0 and allow correct behaviour for new users
</notes>
</release>
<release>
<version>
<release>1.0</release>
<api>1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2002-09-13</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
Stable release
</notes>
</release>
<release>
<version>
<release>0.11</release>
<api>0.11</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2002-05-26</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
POSIX getopt compatibility fix: treat first element of args
array as command name
</notes>
</release>
<release>
<version>
<release>0.10</release>
<api>0.10</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2002-05-12</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
Packaging fix
</notes>
</release>
<release>
<version>
<release>0.9</release>
<api>0.9</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2002-05-12</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
Initial release
</notes>
</release>
</changelog>
</package>

View File

@@ -0,0 +1,63 @@
--TEST--
Console_Getopt
--FILE--
<?php
require_once 'Console/Getopt.php';
PEAR::setErrorHandling(PEAR_ERROR_PRINT, "%s\n\n");
function test($argstr, $optstr) {
$argv = preg_split('/[[:space:]]+/', $argstr);
if (PEAR::isError($options = Console_Getopt::getopt($argv, $optstr))) {
return;
}
$opts = $options[0];
$non_opts = $options[1];
$i = 0;
print "options: ";
foreach ($opts as $o => $d) {
if ($i++ > 0) {
print ", ";
}
print $d[0] . '=' . $d[1];
}
print "\n";
print "params: " . implode(", ", $non_opts) . "\n";
print "\n";
}
test("-abc", "abc");
test("-abc foo", "abc");
test("-abc foo", "abc:");
test("-abc foo bar gazonk", "abc");
test("-abc foo bar gazonk", "abc:");
test("-a -b -c", "abc");
test("-a -b -c", "abc:");
test("-abc", "ab:c");
test("-abc foo -bar gazonk", "abc");
?>
--EXPECT--
options: a=, b=, c=
params:
options: a=, b=, c=
params: foo
options: a=, b=, c=foo
params:
options: a=, b=, c=
params: foo, bar, gazonk
options: a=, b=, c=foo
params: bar, gazonk
options: a=, b=, c=
params:
Console_Getopt: option requires an argument --c
options: a=, b=c
params:
options: a=, b=, c=
params: foo, -bar, gazonk

View File

@@ -0,0 +1,22 @@
--TEST--
Console_Getopt [bug 10557]
--SKIPIF--
--FILE--
<?php
$_SERVER['argv'] =
$argv = array('hi', '-fjjohnston@mail.com', '--to', '--mailpack', '--debug');
require_once 'Console/Getopt.php';
$ret = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), 'f:t:',
array('from=','to=','mailpack=','direction=','verbose','debug'));
if(PEAR::isError($ret))
{
echo $ret->getMessage()."\n";
echo 'FATAL';
exit;
}
print_r($ret);
?>
--EXPECT--
Console_Getopt: option requires an argument --to
FATAL

View File

@@ -0,0 +1,44 @@
--TEST--
Console_Getopt [bug 11068]
--SKIPIF--
--FILE--
<?php
$_SERVER['argv'] =
$argv = array('hi', '-fjjohnston@mail.com', '--to', 'hi', '-');
require_once 'Console/Getopt.php';
$ret = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), 'f:t:',
array('from=','to=','mailpack=','direction=','verbose','debug'));
if(PEAR::isError($ret))
{
echo $ret->getMessage()."\n";
echo 'FATAL';
exit;
}
print_r($ret);
?>
--EXPECT--
Array
(
[0] => Array
(
[0] => Array
(
[0] => f
[1] => jjohnston@mail.com
)
[1] => Array
(
[0] => --to
[1] => hi
)
)
[1] => Array
(
[0] => -
)
)

View File

@@ -0,0 +1,75 @@
--TEST--
Console_Getopt [bug 13140]
--SKIPIF--
--FILE--
<?php
$_SERVER['argv'] = $argv =
array('--bob', '--foo' , '-bar', '--test', '-rq', 'thisshouldbehere');
require_once 'Console/Getopt.php';
$cg = new Console_GetOpt();
print_r($cg->getopt2($cg->readPHPArgv(), 't', array('test'), true));
print_r($cg->getopt2($cg->readPHPArgv(), 'bar', array('foo'), true));
?>
--EXPECT--
Array
(
[0] => Array
(
[0] => Array
(
[0] => --test
[1] =>
)
)
[1] => Array
(
[0] => thisshouldbehere
)
)
Array
(
[0] => Array
(
[0] => Array
(
[0] => --foo
[1] =>
)
[1] => Array
(
[0] => b
[1] =>
)
[2] => Array
(
[0] => a
[1] =>
)
[3] => Array
(
[0] => r
[1] =>
)
[4] => Array
(
[0] => r
[1] =>
)
)
[1] => Array
(
[0] => thisshouldbehere
)
)

View File

@@ -0,0 +1,3 @@
# Debug with: git archive --format=tar HEAD | tar t
/tests export-ignore

View File

@@ -0,0 +1,60 @@
# yamllint disable rule:line-length
# yamllint disable rule:braces
name: Continuous Integration
on:
pull_request:
push:
branches:
- main
- master
jobs:
tests:
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
operating-system: ['ubuntu-latest']
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
name: CI on ${{ matrix.operating-system }} with PHP ${{ matrix.php-version }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: composer:v2
coverage: none
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: composer-${{ runner.os }}-${{ matrix.php-version }}-${{ hashFiles('composer.*') }}-${{ matrix.composer-flags }}
restore-keys: |
composer-${{ runner.os }}-${{ matrix.php-version }}-${{ hashFiles('composer.*') }}-
composer-${{ runner.os }}-${{ matrix.php-version }}-
composer-${{ runner.os }}-
composer-
- name: Install dependencies
run: |
composer update --no-interaction --prefer-dist --no-progress ${{ matrix.composer-flags }}
- name: Run tests
run: |
vendor/bin/phpunit
- name: Lint code
run: |
find OLE* -type f -name \*.php | xargs -n1 php -l

View File

@@ -0,0 +1,38 @@
name: Coding Standards
on:
pull_request:
push:
branches:
- main
- master
jobs:
coding-standards:
name: Coding Standards
runs-on: ubuntu-latest
env:
PHP_CS_FIXER_VERSION: v2.17.3
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
coverage: none
tools: php-cs-fixer:${{ env.PHP_CS_FIXER_VERSION }}
- name: Restore PHP-CS-Fixer cache
uses: actions/cache@v2
with:
path: .php_cs.cache
key: "php-cs-fixer"
restore-keys: "php-cs-fixer"
- name: Run PHP-CS-Fixer, version ${{ env.PHP_CS_FIXER_VERSION }}
run: |
php-cs-fixer fix --diff --diff-format=udiff --dry-run --verbose

4
videodb/vendor/pear/ole/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# composer related
composer.lock
composer.phar
vendor

11
videodb/vendor/pear/ole/.php_cs.dist vendored Normal file
View File

@@ -0,0 +1,11 @@
<?php
return PhpCsFixer\Config::create()
->setRules([
'@PSR1' => true,
])
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__)
)
;

43
videodb/vendor/pear/ole/.travis.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
sudo: false
language: php
php:
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
- 7.4
- 8.0
- nightly
stages:
- analyze
- test
jobs:
fast_finish: true
allow_failures:
- php: nightly
include:
- stage: analyze
php: 7.4
install:
- composer install --prefer-dist
script:
- php vendor/bin/php-cs-fixer fix --dry-run --diff
- composer validate
- find OLE* -type f -name \*.php | xargs -n1 php -l
cache:
directories:
- $HOME/.composer/cache
- $HOME/.cache/cache
install:
- composer remove --no-update --dev
friendsofphp/php-cs-fixer
- composer install --prefer-dist
script:
- vendor/bin/phpunit --verbose

616
videodb/vendor/pear/ole/OLE.php vendored Normal file
View File

@@ -0,0 +1,616 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Xavier Noguer <xnoguer@php.net> |
// | Based on OLE::Storage_Lite by Kawai, Takanori |
// +----------------------------------------------------------------------+
//
// $Id$
/**
* Constants for OLE package
*/
define('OLE_PPS_TYPE_ROOT', 0x05);
define('OLE_PPS_TYPE_DIR', 0x01);
define('OLE_PPS_TYPE_FILE', 0x02);
define('OLE_DATA_SIZE_SMALL', 0x1000);
define('OLE_LONG_INT_SIZE', 4);
define('OLE_PPS_SIZE', 0x80);
define('OLE_DIFSECT', 0xFFFFFFFC);
define('OLE_FATSECT', 0xFFFFFFFD);
define('OLE_ENDOFCHAIN', 0xFFFFFFFE);
define('OLE_FREESECT', 0xFFFFFFFF);
define('OLE_LITTLE_ENDIAN', 0xFFFE);
define('OLE_VERSION_MAJOR_3', 0x0003);
define('OLE_VERSION_MINOR', 0x003E);
define('OLE_SECTOR_SHIFT_3', 0x0009);
define('OLE_MINI_SECTOR_SHIFT', 0x0006);
define('OLE_CFB_SIGNATURE', "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1");
if (!class_exists('PEAR')) {
require_once 'PEAR.php';
}
/**
* Array for storing OLE instances that are accessed from
* OLE_ChainedBlockStream::stream_open().
* @var array
*/
$GLOBALS['_OLE_INSTANCES'] = array();
/**
* OLE package base class.
*
* @category Structures
* @package OLE
* @author Xavier Noguer <xnoguer@php.net>
* @author Christian Schmidt <schmidt@php.net>
*/
class OLE extends PEAR
{
/**
* The file handle for reading an OLE container
* @var resource
*/
var $_file_handle;
/**
* Reference to the sbat stream
* @var resource
*/
var $_small_handle;
/**
* Array of PPS's found on the OLE container
* @var array
*/
var $_list;
/**
* Root directory of OLE container
* @var OLE_PPS_Root
*/
var $root;
/**
* Big Block Allocation Table
* @var array (blockId => nextBlockId)
*/
var $bbat;
/**
* Short Block Allocation Table
* @var array (blockId => nextBlockId)
*/
var $sbat;
/**
* Size of big blocks. This is usually 512.
* @var int number of octets per block.
*/
var $bigBlockSize;
/**
* Size of small blocks. This is usually 64.
* @var int number of octets per block
*/
var $smallBlockSize;
/**
* Creates a new OLE object
* @access public
*/
function __construct()
{
$this->_list = array();
}
/**
* Destructor (using PEAR)
* Just closes the file handle on the OLE file.
*
* @access private
*/
function _OLE()
{
fclose($this->_file_handle);
}
/**
* Reads an OLE container from the contents of the file given.
*
* @access public
* @param string $file
* @return mixed true on success, PEAR_Error on failure
*/
function read($file)
{
$fh = @fopen($file, "r");
if (!$fh) {
return $this->raiseError("Can't open file $file");
}
return $this->readStream($fh);
}
/**
* Reads an OLE container from the contents of the stream given.
*
* @access public
* @param resource $fh
* @return mixed true on success, PEAR_Error on failure
*/
function readStream($fh)
{
$this->_file_handle = $fh;
$signature = fread($fh, 8);
if (OLE_CFB_SIGNATURE != $signature) {
return $this->raiseError("File doesn't seem to be an OLE container.");
}
fseek($fh, 28);
if ($this->_readInt2($fh) != OLE_LITTLE_ENDIAN) {
// This shouldn't be a problem in practice
return $this->raiseError("Only Little-Endian encoding is supported.");
}
// Size of blocks and short blocks in bytes
$this->bigBlockSize = pow(2, $this->_readInt2($fh));
$this->smallBlockSize = pow(2, $this->_readInt2($fh));
// Skip UID, revision number and version number
fseek($fh, 44);
// Number of blocks in Big Block Allocation Table
$bbatBlockCount = $this->_readInt4($fh);
// Root chain 1st block
$directoryFirstBlockId = $this->_readInt4($fh);
// Skip unused bytes
fseek($fh, 56);
// Streams shorter than this are stored using small blocks
$this->bigBlockThreshold = $this->_readInt4($fh);
// Block id of first sector in Short Block Allocation Table
$sbatFirstBlockId = $this->_readInt4($fh);
// Number of blocks in Short Block Allocation Table
$sbbatBlockCount = $this->_readInt4($fh);
// Block id of first sector in Master Block Allocation Table
$mbatFirstBlockId = $this->_readInt4($fh);
// Number of blocks in Master Block Allocation Table
$mbbatBlockCount = $this->_readInt4($fh);
$this->bbat = array();
// Remaining 4 * 109 bytes of current block is beginning of Master
// Block Allocation Table
$mbatBlocks = array();
for ($i = 0; $i < 109; $i++) {
$mbatBlocks[] = $this->_readInt4($fh);
}
// Read rest of Master Block Allocation Table (if any is left)
$pos = $this->_getBlockOffset($mbatFirstBlockId);
for ($i = 0; $i < $mbbatBlockCount; $i++) {
fseek($fh, $pos);
for ($j = 0; $j < $this->bigBlockSize / 4 - 1; $j++) {
$mbatBlocks[] = $this->_readInt4($fh); // ffix - invalid block address check
}
// Last block id in each block points to next block
$chainBlock = $this->_readInt4($fh);
if ($chainBlock === OLE_ENDOFCHAIN) { // ENDOFCHAIN
break;
}
$pos = $this->_getBlockOffset($chainBlock);
}
// Read Big Block Allocation Table according to chain specified by
// $mbatBlocks
for ($i = 0; $i < $bbatBlockCount; $i++) {
$pos = $this->_getBlockOffset($mbatBlocks[$i]);
fseek($fh, $pos);
for ($j = 0 ; $j < $this->bigBlockSize / 4; $j++) {
$this->bbat[] = $this->_readInt4($fh);
}
}
// Read short block allocation table (SBAT)
$this->sbat = array();
$shortBlockCount = $sbbatBlockCount * $this->bigBlockSize / 4;
$sbatFh = $this->getStream($sbatFirstBlockId);
if (!$sbatFh) {
// Avoid an infinite loop if ChainedBlockStream.php somehow is
// missing
return false;
}
for ($blockId = 0; $blockId < $shortBlockCount; $blockId++) {
$this->sbat[$blockId] = $this->_readInt4($sbatFh);
}
fclose($sbatFh);
$this->_readPpsWks($directoryFirstBlockId);
return true;
}
/**
* @param int $blockId block id
* @return int byte offset from beginning of file
* @access private
*/
function _getBlockOffset($blockId)
{
return 512 + $blockId * $this->bigBlockSize;
}
/**
* Returns a stream for use with fread() etc. External callers should
* use OLE_PPS_File::getStream().
* @param int|PPS $blockIdOrPps block id or PPS
* @return resource read-only stream
*/
function getStream($blockIdOrPps)
{
include_once 'OLE/ChainedBlockStream.php';
static $isRegistered = false;
if (!$isRegistered) {
stream_wrapper_register('ole-chainedblockstream',
'OLE_ChainedBlockStream');
$isRegistered = true;
}
// Store current instance in global array, so that it can be accessed
// in OLE_ChainedBlockStream::stream_open().
// Object is removed from self::$instances in OLE_Stream::close().
$GLOBALS['_OLE_INSTANCES'][] = $this;
$keys = array_keys($GLOBALS['_OLE_INSTANCES']);
$instanceId = end($keys);
$path = 'ole-chainedblockstream://oleInstanceId=' . $instanceId;
if (is_a($blockIdOrPps, 'OLE_PPS')) {
$path .= '&blockId=' . $blockIdOrPps->_StartBlock;
$path .= '&size=' . $blockIdOrPps->Size;
} else {
$path .= '&blockId=' . $blockIdOrPps;
}
return fopen($path, 'r');
}
/**
* Reads a signed char.
* @param resource $fh file handle
* @return int
* @access private
*/
function _readInt1($fh)
{
list(, $tmp) = unpack("c", fread($fh, 1));
return $tmp;
}
/**
* Reads an unsigned short (2 octets).
* @param resource $fh file handle
* @return int
* @access private
*/
function _readInt2($fh)
{
list(, $tmp) = unpack("v", fread($fh, 2));
return $tmp;
}
/**
* Reads an unsigned long (4 octets).
* @param resource file handle
* @return int
* @access private
*/
function _readInt4($fh)
{
list(, $tmp) = unpack("V", fread($fh, 4));
return $tmp;
}
/**
* Gets information about all PPS's on the OLE container from the PPS WK's
* creates an OLE_PPS object for each one.
*
* @access private
* @param integer $blockId the block id of the first block
* @return mixed true on success, PEAR_Error on failure
*/
function _readPpsWks($blockId)
{
$fh = $this->getStream($blockId);
for ($pos = 0; ; $pos += 128) {
fseek($fh, $pos, SEEK_SET);
$nameUtf16 = fread($fh, 64);
$nameLength = $this->_readInt2($fh);
$nameUtf16 = substr($nameUtf16, 0, $nameLength - 2);
// Simple conversion from UTF-16LE to ISO-8859-1
$name = str_replace("\x00", "", $nameUtf16);
$type = $this->_readInt1($fh);
switch ($type) {
case OLE_PPS_TYPE_ROOT:
require_once 'OLE/PPS/Root.php';
$pps = new OLE_PPS_Root(null, null, array());
$this->root = $pps;
break;
case OLE_PPS_TYPE_DIR:
$pps = new OLE_PPS(null, null, null, null, null,
null, null, null, null, array());
break;
case OLE_PPS_TYPE_FILE:
require_once 'OLE/PPS/File.php';
$pps = new OLE_PPS_File($name);
break;
default:
continue 2;
}
fseek($fh, 1, SEEK_CUR); // skip Color Flag
$pps->Type = $type;
$pps->Name = $name;
$pps->PrevPps = $this->_readInt4($fh); // Left Sibling ID
$pps->NextPps = $this->_readInt4($fh); // Right Sibling ID
$pps->DirPps = $this->_readInt4($fh); // Child ID
fseek($fh, 20, SEEK_CUR); // skip CLSID (16 bytes) + State Bits
$pps->Time1st = OLE::OLE2LocalDate(fread($fh, 8));
$pps->Time2nd = OLE::OLE2LocalDate(fread($fh, 8));
$pps->_StartBlock = $this->_readInt4($fh);
$pps->Size = $this->_readInt4($fh);
$pps->No = count($this->_list);
$this->_list[] = $pps;
if ($type == OLE_PPS_TYPE_ROOT) {
$this->_small_handle = $this->getStream($pps->_StartBlock);
}
// check if the PPS tree (starting from root) is complete
if (isset($this->root) &&
$this->_ppsTreeComplete($this->root->No)) {
break;
}
}
fclose($fh);
// Initialize $pps->children on directories
foreach ($this->_list as $pps) {
if ($pps->Type == OLE_PPS_TYPE_DIR || $pps->Type == OLE_PPS_TYPE_ROOT) {
$nos = array($pps->DirPps);
$pps->children = array();
while ($nos) {
$no = array_pop($nos);
if ($no != OLE_FREESECT) {
$childPps = $this->_list[$no];
$nos[] = $childPps->PrevPps;
$nos[] = $childPps->NextPps;
$pps->children[] = $childPps;
}
}
}
}
return true;
}
/**
* It checks whether the PPS tree is complete (all PPS's read)
* starting with the given PPS (not necessarily root)
*
* @access private
* @param integer $index The index of the PPS from which we are checking
* @return boolean Whether the PPS tree for the given PPS is complete
*/
function _ppsTreeComplete($index)
{
return isset($this->_list[$index]) &&
($pps = $this->_list[$index]) &&
($pps->PrevPps == OLE_FREESECT ||
$this->_ppsTreeComplete($pps->PrevPps)) &&
($pps->NextPps == OLE_FREESECT ||
$this->_ppsTreeComplete($pps->NextPps)) &&
($pps->DirPps == OLE_FREESECT ||
$this->_ppsTreeComplete($pps->DirPps));
}
/**
* Checks whether a PPS is a File PPS or not.
* If there is no PPS for the index given, it will return false.
* @param integer $index The index for the PPS
* @return bool true if it's a File PPS, false otherwise
* @access public
*/
function isFile($index)
{
if (isset($this->_list[$index])) {
return ($this->_list[$index]->Type == OLE_PPS_TYPE_FILE);
}
return false;
}
/**
* Checks whether a PPS is a Root PPS or not.
* If there is no PPS for the index given, it will return false.
* @param integer $index The index for the PPS.
* @return bool true if it's a Root PPS, false otherwise
* @access public
*/
function isRoot($index)
{
if (isset($this->_list[$index])) {
return ($this->_list[$index]->Type == OLE_PPS_TYPE_ROOT);
}
return false;
}
/**
* Gives the total number of PPS's found in the OLE container.
* @return integer The total number of PPS's found in the OLE container
* @access public
*/
function ppsTotal()
{
return count($this->_list);
}
/**
* Gets data from a PPS
* If there is no PPS for the index given, it will return an empty string.
* @param integer $index The index for the PPS
* @param integer $position The position from which to start reading
* (relative to the PPS)
* @param integer $length The amount of bytes to read (at most)
* @return string The binary string containing the data requested
* @access public
* @see OLE_PPS_File::getStream()
*/
function getData($index, $position, $length)
{
// if position is not valid return empty string
if (!isset($this->_list[$index]) ||
$position >= $this->_list[$index]->Size ||
$position < 0) {
return '';
}
$fh = $this->getStream($this->_list[$index]);
$data = stream_get_contents($fh, $length, $position);
fclose($fh);
return $data;
}
/**
* Gets the data length from a PPS
* If there is no PPS for the index given, it will return 0.
* @param integer $index The index for the PPS
* @return integer The amount of bytes in data the PPS has
* @access public
*/
function getDataLength($index)
{
if (isset($this->_list[$index])) {
return $this->_list[$index]->Size;
}
return 0;
}
/**
* Utility function to transform ASCII text to Unicode
*
* @access public
* @static
* @param string $ascii The ASCII string to transform
* @return string The string in Unicode
*/
static function Asc2Ucs($ascii)
{
$rawname = '';
for ($i = 0; $i < strlen($ascii); $i++) {
$rawname .= $ascii[$i] . "\x00";
}
return $rawname;
}
/**
* Utility function
* Returns a string for the OLE container with the date given
*
* @access public
* @static
* @param integer $date A timestamp
* @return string The string for the OLE container
*/
static function LocalDate2OLE($date = null)
{
if (!isset($date)) {
return "\x00\x00\x00\x00\x00\x00\x00\x00";
}
// factor used for separating numbers into 4 bytes parts
$factor = pow(2, 32);
// days from 1-1-1601 until the beggining of UNIX era
$days = 134774;
// calculate seconds
$big_date = $days * 24 * 3600 +
gmmktime(date("H",$date),date("i",$date),date("s",$date),
date("m",$date),date("d",$date),date("Y",$date));
// multiply just to make MS happy
$big_date *= 10000000;
$high_part = floor($big_date / $factor);
// lower 4 bytes
$low_part = floor((($big_date / $factor) - $high_part) * $factor);
// Make HEX string
$res = '';
for ($i = 0; $i < 4; $i++) {
$hex = $low_part % 0x100;
$res .= pack('c', $hex);
$low_part /= 0x100;
}
for ($i = 0; $i < 4; $i++) {
$hex = $high_part % 0x100;
$res .= pack('c', $hex);
$high_part /= 0x100;
}
return $res;
}
/**
* Returns a timestamp from an OLE container's date
* @param integer $string A binary string with the encoded date
* @return string The timestamp corresponding to the string
* @access public
* @static
*/
static function OLE2LocalDate($string)
{
if (strlen($string) != 8) {
return new PEAR_Error("Expecting 8 byte string");
}
// factor used for separating numbers into 4 bytes parts
$factor = pow(2,32);
$high_part = 0;
for ($i = 0; $i < 4; $i++) {
list(, $high_part) = unpack('C', $string[(7 - $i)]);
if ($i < 3) {
$high_part *= 0x100;
}
}
$low_part = 0;
for ($i = 4; $i < 8; $i++) {
list(, $low_part) = unpack('C', $string[(7 - $i)]);
if ($i < 7) {
$low_part *= 0x100;
}
}
$big_date = ($high_part * $factor) + $low_part;
// translate to seconds
$big_date /= 10000000;
// days from 1-1-1601 until the beggining of UNIX era
$days = 134774;
// translate to seconds from beggining of UNIX era
$big_date -= $days * 24 * 3600;
return floor($big_date);
}
}

View File

@@ -0,0 +1,246 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Stream wrapper for reading data stored in an OLE file.
*
* 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 Structures
* @package OLE
* @author Christian Schmidt <schmidt@php.net>
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id$
* @link http://pear.php.net/package/OLE
* @since File available since Release 0.6.0
*/
if (!class_exists('PEAR')) {
require_once 'PEAR.php';
}
if (!class_exists('OLE')) {
require_once 'OLE.php';
}
/**
* Stream wrapper for reading data stored in an OLE file. Implements methods
* for PHP's stream_wrapper_register(). For creating streams using this
* wrapper, use OLE_PPS_File::getStream().
*
* @category Structures
* @package OLE
* @author Christian Schmidt <schmidt@php.net>
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: @package_version@
* @link http://pear.php.net/package/OLE
* @since Class available since Release 0.6.0
*/
class OLE_ChainedBlockStream extends PEAR
{
/**
* The OLE container of the file that is being read.
* @var OLE
*/
var $ole;
/**
* Parameters specified by fopen().
* @var array
*/
var $params;
/**
* The binary data of the file.
* @var string
*/
var $data;
/**
* The file pointer.
* @var int byte offset
*/
var $pos;
/**
* Implements support for fopen().
* For creating streams using this wrapper, use OLE_PPS_File::getStream().
* @param string resource name including scheme, e.g.
* ole-chainedblockstream://oleInstanceId=1
* @param string only "r" is supported
* @param int mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH
* @param string absolute path of the opened stream (out parameter)
* @return bool true on success
*/
function stream_open($path, $mode, $options, &$openedPath)
{
if ($mode != 'r') {
if ($options & STREAM_REPORT_ERRORS) {
trigger_error('Only reading is supported', E_USER_WARNING);
}
return false;
}
// 25 is length of "ole-chainedblockstream://"
parse_str(substr($path, 25), $this->params);
if (!isset($this->params['oleInstanceId'],
$this->params['blockId'],
$GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']])) {
if ($options & STREAM_REPORT_ERRORS) {
trigger_error('OLE stream not found', E_USER_WARNING);
}
return false;
}
$this->ole = $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']];
$blockId = $this->params['blockId'];
$this->data = '';
if (isset($this->params['size']) &&
$this->params['size'] < $this->ole->bigBlockThreshold &&
$blockId != $this->ole->root->_StartBlock) {
// Block id refers to small blocks
$rootPos = 0;
while ($blockId != OLE_ENDOFCHAIN) {
$pos = $rootPos + $blockId * $this->ole->smallBlockSize;
$blockId = $this->ole->sbat[$blockId];
fseek($this->ole->_small_handle, $pos);
$this->data .= fread($this->ole->_small_handle, $this->ole->smallBlockSize);
}
} else {
// Block id refers to big blocks
while ($blockId != OLE_ENDOFCHAIN) {
$pos = $this->ole->_getBlockOffset($blockId);
fseek($this->ole->_file_handle, $pos);
$this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize);
$blockId = $this->ole->bbat[$blockId];
}
}
if (isset($this->params['size'])) {
$this->data = substr($this->data, 0, $this->params['size']);
}
if ($options & STREAM_USE_PATH) {
$openedPath = $path;
}
return true;
}
/**
* Implements support for fclose().
*/
function stream_close()
{
$this->ole = null;
// $GLOBALS is not always defined in stream_close
if (isset($GLOBALS['_OLE_INSTANCES'])) {
unset($GLOBALS['_OLE_INSTANCES']);
}
}
/**
* Implements support for fread(), fgets() etc.
* @param int maximum number of bytes to read
* @return string
*/
function stream_read($count)
{
if ($this->stream_eof()) {
return false;
}
$s = substr($this->data, $this->pos, $count);
$this->pos += $count;
return $s;
}
/**
* Implements support for feof().
* @return bool TRUE if the file pointer is at EOF; otherwise FALSE
*/
function stream_eof()
{
$eof = $this->pos >= strlen($this->data);
// Workaround for bug in PHP 5.0.x: http://bugs.php.net/27508
if (version_compare(PHP_VERSION, '5.0', '>=') &&
version_compare(PHP_VERSION, '5.1', '<')) {
$eof = !$eof;
}
return $eof;
}
/**
* Returns the position of the file pointer, i.e. its offset into the file
* stream. Implements support for ftell().
* @return int
*/
function stream_tell()
{
return $this->pos;
}
/**
* Implements support for fseek().
* @param int byte offset
* @param int SEEK_SET, SEEK_CUR or SEEK_END
* @return bool
*/
function stream_seek($offset, $whence)
{
if ($whence == SEEK_SET && $offset >= 0) {
$this->pos = $offset;
} elseif ($whence == SEEK_CUR && -$offset <= $this->pos) {
$this->pos += $offset;
} elseif ($whence == SEEK_END && -$offset <= strlen($this->data)) {
$this->pos = strlen($this->data) + $offset;
} else {
return false;
}
return true;
}
/**
* Implements support for fstat(). Currently the only supported field is
* "size".
* @return array
*/
function stream_stat()
{
return array(
'size' => strlen($this->data),
);
}
/**
* PHP 5.6 for some reason wants this to be implemented. Currently returning false as if it wasn't implemented.
* @return boolean
*/
function stream_flush()
{
// If not implemented, FALSE is assumed as the return value.
return false;
}
// Methods used by stream_wrapper_register() that are not implemented:
// int stream_write ( string data )
// bool rename ( string path_from, string path_to )
// bool mkdir ( string path, int mode, int options )
// bool rmdir ( string path, int options )
// bool dir_opendir ( string path, int options )
// array url_stat ( string path, int flags )
// string dir_readdir ( void )
// bool dir_rewinddir ( void )
// bool dir_closedir ( void )
}

244
videodb/vendor/pear/ole/OLE/PPS.php vendored Normal file
View File

@@ -0,0 +1,244 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Xavier Noguer <xnoguer@php.net> |
// | Based on OLE::Storage_Lite by Kawai, Takanori |
// +----------------------------------------------------------------------+
//
// $Id$
if (!class_exists('PEAR')) {
require_once 'PEAR.php';
}
if (!class_exists('OLE')) {
require_once 'OLE.php';
}
/**
* Class for creating PPS's for OLE containers
*
* @author Xavier Noguer <xnoguer@php.net>
* @category Structures
* @package OLE
*/
class OLE_PPS extends PEAR
{
/**
* The PPS index
* @var integer
*/
var $No;
/**
* The PPS name (in Unicode)
* @var string
*/
var $Name;
/**
* The PPS type. Dir, Root or File
* @var integer
*/
var $Type;
/**
* The index of the previous PPS
* @var integer
*/
var $PrevPps;
/**
* The index of the next PPS
* @var integer
*/
var $NextPps;
/**
* The index of it's first child if this is a Dir or Root PPS
* @var integer
*/
var $DirPps;
/**
* A timestamp
* @var integer
*/
var $Time1st;
/**
* A timestamp
* @var integer
*/
var $Time2nd;
/**
* Starting block (small or big) for this PPS's data inside the container
* @var integer
*/
var $_StartBlock;
/**
* The size of the PPS's data (in bytes)
* @var integer
*/
var $Size;
/**
* The PPS's data (only used if it's not using a temporary file)
* @var string
*/
var $_data;
/**
* Array of child PPS's (only used by Root and Dir PPS's)
* @var array
*/
var $children = array();
/**
* Pointer to OLE container
* @var OLE
*/
var $ole;
/**
* The constructor
*
* @access public
* @param integer $No The PPS index
* @param string $name The PPS name
* @param integer $type The PPS type. Dir, Root or File
* @param integer $prev The index of the previous PPS
* @param integer $next The index of the next PPS
* @param integer $dir The index of it's first child if this is a Dir or Root PPS
* @param integer $time_1st A timestamp
* @param integer $time_2nd A timestamp
* @param string $data The (usually binary) source data of the PPS
* @param array $children Array containing children PPS for this PPS
*/
function __construct($No, $name, $type, $prev, $next, $dir, $time_1st, $time_2nd, $data, $children)
{
$this->No = $No;
$this->Name = $name;
$this->Type = $type;
$this->PrevPps = $prev;
$this->NextPps = $next;
$this->DirPps = $dir;
$this->Time1st = $time_1st;
$this->Time2nd = $time_2nd;
$this->_data = $data;
$this->children = $children;
if ($data != '') {
$this->Size = strlen($data);
} else {
$this->Size = 0;
}
}
/**
* Returns the amount of data saved for this PPS
*
* @access private
* @return integer The amount of data (in bytes)
*/
function _DataLen()
{
if (!isset($this->_data)) {
return 0;
}
if (isset($this->_PPS_FILE)) {
fseek($this->_PPS_FILE, 0);
$stats = fstat($this->_PPS_FILE);
return $stats[7];
} else {
return strlen($this->_data);
}
}
/**
* Returns a string with the PPS's WK (What is a WK?)
*
* @access private
* @return string The binary string
*/
function _getPpsWk()
{
$ret = $this->Name;
for ($i = 0; $i < (64 - strlen($this->Name)); $i++) {
$ret .= "\x00";
}
$ret .= pack("v", strlen($this->Name) + 2) // 66
. pack("c", $this->Type) // 67
. pack("c", 0x00) //UK // 68
. pack("V", $this->PrevPps) //Prev // 72
. pack("V", $this->NextPps) //Next // 76
. pack("V", $this->DirPps) //Dir // 80
. "\x00\x09\x02\x00" // 84
. "\x00\x00\x00\x00" // 88
. "\xc0\x00\x00\x00" // 92
. "\x00\x00\x00\x46" // 96 // Seems to be ok only for Root
. "\x00\x00\x00\x00" // 100
. OLE::LocalDate2OLE($this->Time1st) // 108
. OLE::LocalDate2OLE($this->Time2nd) // 116
. pack("V", isset($this->_StartBlock)?
$this->_StartBlock:0) // 120
. pack("V", $this->Size) // 124
. pack("V", 0); // 128
return $ret;
}
/**
* Updates index and pointers to previous, next and children PPS's for this
* PPS. I don't think it'll work with Dir PPS's.
*
* @access private
* @param array &$pps_array Reference to the array of PPS's for the whole OLE
* container
* @return integer The index for this PPS
*/
static function _savePpsSetPnt(&$raList, $to_save, $depth = 0)
{
if ( !is_array($to_save) || (count($to_save) == 0) ) {
return OLE_FREESECT;
}
elseif( count($to_save) == 1 ) {
$cnt = count($raList);
// If the first entry, it's the root... Don't clone it!
$raList[$cnt] = ( $depth == 0 ) ? $to_save[0] : clone $to_save[0];
$raList[$cnt]->No = $cnt;
$raList[$cnt]->PrevPps = OLE_FREESECT;
$raList[$cnt]->NextPps = OLE_FREESECT;
$raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++);
return $cnt;
}
else {
$iPos = floor(count($to_save) / 2);
$aPrev = array_slice($to_save, 0, $iPos);
$aNext = array_slice($to_save, $iPos + 1);
$cnt = count($raList);
// If the first entry, it's the root... Don't clone it!
$raList[$cnt] = ( $depth == 0 ) ? $to_save[$iPos] : clone $to_save[$iPos];
$raList[$cnt]->No = $cnt;
$raList[$cnt]->PrevPps = self::_savePpsSetPnt($raList, $aPrev, $depth++);
$raList[$cnt]->NextPps = self::_savePpsSetPnt($raList, $aNext, $depth++);
$raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++);
return $cnt;
}
}
}

130
videodb/vendor/pear/ole/OLE/PPS/File.php vendored Normal file
View File

@@ -0,0 +1,130 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Xavier Noguer <xnoguer@php.net> |
// | Based on OLE::Storage_Lite by Kawai, Takanori |
// +----------------------------------------------------------------------+
//
// $Id$
if (!class_exists('OLE_PPS')) {
require_once 'OLE/PPS.php';
}
if (!class_exists('System')) {
require_once 'System.php';
}
/**
* Class for creating File PPS's for OLE containers
*
* @author Xavier Noguer <xnoguer@php.net>
* @category Structures
* @package OLE
*/
class OLE_PPS_File extends OLE_PPS
{
/**
* The temporary dir for storing the OLE file
* @var string
*/
var $_tmp_dir;
/**
* The constructor
*
* @access public
* @param string $name The name of the file (in Unicode)
* @see OLE::Asc2Ucs()
*/
function __construct($name)
{
$system = new System();
$this->_tmp_dir = $system->tmpdir();
parent::__construct(
null,
$name,
OLE_PPS_TYPE_FILE,
null,
null,
null,
null,
null,
'',
array());
}
/**
* Sets the temp dir used for storing the OLE file
*
* @access public
* @param string $dir The dir to be used as temp dir
* @return boolean true if given dir is valid, false otherwise
*/
function setTempDir($dir)
{
if (is_dir($dir)) {
$this->_tmp_dir = $dir;
return true;
}
return false;
}
/**
* Initialization method. Has to be called right after OLE_PPS_File().
*
* @access public
* @return mixed true on success. PEAR_Error on failure
*/
function init()
{
$this->_tmp_filename = tempnam($this->_tmp_dir, "OLE_PPS_File");
$fh = @fopen($this->_tmp_filename, "w+b");
if ($fh == false) {
return $this->raiseError("Can't create temporary file");
}
$this->_PPS_FILE = $fh;
if ($this->_PPS_FILE) {
fseek($this->_PPS_FILE, 0);
}
return true;
}
/**
* Append data to PPS
*
* @access public
* @param string $data The data to append
*/
function append($data)
{
if ($this->_PPS_FILE) {
fwrite($this->_PPS_FILE, $data);
} else {
$this->_data .= $data;
}
}
/**
* Returns a stream for reading this file using fread() etc.
* @return resource a read-only stream
*/
function getStream()
{
$this->ole->getStream($this);
}
}

724
videodb/vendor/pear/ole/OLE/PPS/Root.php vendored Normal file
View File

@@ -0,0 +1,724 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Xavier Noguer <xnoguer@php.net> |
// | Based on OLE::Storage_Lite by Kawai, Takanori |
// +----------------------------------------------------------------------+
//
// $Id$
if (!class_exists('OLE_PPS')) {
require_once 'OLE/PPS.php';
}
if (!class_exists('System')) {
require_once 'System.php';
}
/**
* Class for creating Root PPS's for OLE containers
*
* @author Xavier Noguer <xnoguer@php.net>
* @category Structures
* @package OLE
*/
class OLE_PPS_Root extends OLE_PPS
{
/**
* Flag to enable new logic
* @var bool
*/
var $new_func = true;
/**
* The temporary dir for storing the OLE file
* @var string
*/
var $_tmp_dir;
/**
* Constructor
*
* @access public
* @param integer $time_1st A timestamp
* @param integer $time_2nd A timestamp
*/
function __construct($time_1st, $time_2nd, $raChild)
{
$system = new System();
$this->_tmp_dir = $system->tmpdir();
parent::__construct(
null,
OLE::Asc2Ucs('Root Entry'),
OLE_PPS_TYPE_ROOT,
null,
null,
null,
$time_1st,
$time_2nd,
null,
$raChild);
}
/**
* Sets the temp dir used for storing the OLE file
*
* @access public
* @param string $dir The dir to be used as temp dir
* @return true if given dir is valid, false otherwise
*/
function setTempDir($dir)
{
if (is_dir($dir)) {
$this->_tmp_dir = $dir;
return true;
}
return false;
}
/**
* Method for saving the whole OLE container (including files).
* In fact, if called with an empty argument (or '-'), it saves to a
* temporary file and then outputs it's contents to stdout.
*
* @param string $filename The name of the file where to save the OLE container
* @access public
* @return mixed true on success, PEAR_Error on failure
*/
function save($filename)
{
// Initial Setting for saving
$this->_BIG_BLOCK_SIZE = pow(2,
((isset($this->_BIG_BLOCK_SIZE))? $this->_adjust2($this->_BIG_BLOCK_SIZE) : 9));
$this->_SMALL_BLOCK_SIZE= pow(2,
((isset($this->_SMALL_BLOCK_SIZE))? $this->_adjust2($this->_SMALL_BLOCK_SIZE): 6));
// Open temp file if we are sending output to stdout
if (($filename == '-') || ($filename == '')) {
$this->_tmp_filename = tempnam($this->_tmp_dir, "OLE_PPS_Root");
$this->_FILEH_ = @fopen($this->_tmp_filename,"w+b");
if ($this->_FILEH_ == false) {
return $this->raiseError("Can't create temporary file.");
}
} else {
$this->_FILEH_ = @fopen($filename, "wb");
if ($this->_FILEH_ == false) {
return $this->raiseError("Can't open $filename. It may be in use or protected.");
}
}
// Make an array of PPS's (for Save)
$aList = array();
OLE_PPS_Root::_savePpsSetPnt($aList, array($this));
// calculate values for header
list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo);
// Save Header
$this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
// Make Small Data string (write SBD)
$this->_data = $this->_makeSmallData($aList);
// Write BB
$this->_saveBigData($iSBDcnt, $aList);
// Write PPS
$this->_savePps($aList);
// Write Big Block Depot and BDList and Adding Header informations
$this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt);
// Close File, send it to stdout if necessary
if (($filename == '-') || ($filename == '')) {
fseek($this->_FILEH_, 0);
fpassthru($this->_FILEH_);
@fclose($this->_FILEH_);
// Delete the temporary file.
@unlink($this->_tmp_filename);
} else {
@fclose($this->_FILEH_);
}
return true;
}
/**
* Calculate some numbers
*
* @access private
* @param array $raList Reference to an array of PPS's
* @return array The array of numbers
*/
function _calcSize(&$raList)
{
// Calculate Basic Setting
$iBBcnt = 0;
$iSBcnt = 0;
for ($i = 0; $i < count($raList); $i++) {
if ($raList[$i]->Type == OLE_PPS_TYPE_FILE) {
$raList[$i]->Size = $raList[$i]->_DataLen();
if ($raList[$i]->Size < OLE_DATA_SIZE_SMALL) {
$iSBcnt += floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE)
+ (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0);
} else {
$iBBcnt += (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) +
(($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0));
}
}
}
$iSmallLen = $iSBcnt * $this->_SMALL_BLOCK_SIZE;
$iSlCnt = floor($this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE);
$iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt)? 1:0);
$iBBcnt += (floor($iSmallLen / $this->_BIG_BLOCK_SIZE) +
(( $iSmallLen % $this->_BIG_BLOCK_SIZE)? 1: 0));
$iCnt = count($raList);
$iBdCnt = $this->_BIG_BLOCK_SIZE / OLE_PPS_SIZE;
$iPPScnt = (floor($iCnt/$iBdCnt) + (($iCnt % $iBdCnt)? 1: 0));
return array($iSBDcnt, $iBBcnt, $iPPScnt);
}
/**
* Helper function for caculating a magic value for block sizes
*
* @access private
* @param integer $i2 The argument
* @see save()
* @return integer
*/
function _adjust2($i2)
{
$iWk = log($i2)/log(2);
return ($iWk > floor($iWk))? floor($iWk)+1:$iWk;
}
/**
* Save OLE header
*
* @access private
* @param integer $iSBDcnt
* @param integer $iBBcnt
* @param integer $iPPScnt
*/
function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt)
{
$FILE = $this->_FILEH_;
if($this->new_func)
return $this->_create_header($iSBDcnt, $iBBcnt, $iPPScnt);
// Calculate Basic Setting
$iBlCnt = $this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE;
$i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / OLE_LONG_INT_SIZE;
$iBdExL = 0;
$iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
$iAllW = $iAll;
$iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0);
$iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0);
// Calculate BD count
if ($iBdCnt > $i1stBdL) {
while (1) {
$iBdExL++;
$iAllW++;
$iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0);
$iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0);
if ($iBdCnt <= ($iBdExL*$iBlCnt+ $i1stBdL)) {
break;
}
}
}
// Save Header
fwrite($FILE,
OLE_CFB_SIGNATURE // Header Signature (8 bytes)
. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // Header CLSID (16 bytes)
. pack("v", OLE_VERSION_MINOR) // Minor Version (2 bytes)
. pack("v", OLE_VERSION_MAJOR_3) // Major Version (2 bytes)
. pack("v", OLE_LITTLE_ENDIAN) // Byte Order (2 bytes)
. pack("v", OLE_SECTOR_SHIFT_3) // Sector Shift (2 bytes)
. pack("v", OLE_MINI_SECTOR_SHIFT) // Mini Sector Shift (2 bytes)
. "\x00\x00\x00\x00\x00\x00" // Reserved (6 bytes)
. "\x00\x00\x00\x00" // Number of Directory Sectors (4 bytes)
. pack("V", $iBdCnt) // Number of FAT Sectors (4 bytes)
. pack("V", $iBBcnt+$iSBDcnt) //ROOT START, First Directory Sector Location (4 bytes)
. pack("V", 0) // Transaction Signature Number (4 bytes)
. pack("V", 0x00001000) // Mini Stream Cutoff Size (4 bytes)
. pack("V", $iSBDcnt ? 0 : OLE_ENDOFCHAIN) // First Mini FAT Sector Location (4 bytes)
. pack("V", $iSBDcnt) // Number of Mini FAT Sectors (4 bytes)
);
// Extra BDList Start, Count
if ($iBdCnt < $i1stBdL) {
fwrite($FILE,
pack("V", OLE_ENDOFCHAIN). // Extra BDList Start
pack("V", 0) // Extra BDList Count
);
} else {
fwrite($FILE, pack("V", $iAll+$iBdCnt) . pack("V", $iBdExL));
}
// BDList
for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; $i++) {
fwrite($FILE, pack("V", $iAll+$i));
}
if ($i < $i1stBdL) { // free sectors
for ($j = 0; $j < ($i1stBdL-$i); $j++) {
fwrite($FILE, (pack("V", OLE_FREESECT)));
}
}
}
/**
* Saving big data (PPS's with data bigger than OLE_DATA_SIZE_SMALL)
*
* @access private
* @param integer $iStBlk
* @param array &$raList Reference to array of PPS's
*/
function _saveBigData($iStBlk, &$raList)
{
$FILE = $this->_FILEH_;
// cycle through PPS's
for ($i = 0; $i < count($raList); $i++) {
if ($raList[$i]->Type != OLE_PPS_TYPE_DIR) {
$raList[$i]->Size = $raList[$i]->_DataLen();
if (($raList[$i]->Size >= OLE_DATA_SIZE_SMALL) ||
(($raList[$i]->Type == OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data)))
{
// Write Data
if (isset($raList[$i]->_PPS_FILE)) {
$iLen = 0;
fseek($raList[$i]->_PPS_FILE, 0); // To The Top
while($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) {
$iLen += strlen($sBuff);
fwrite($FILE, $sBuff);
}
} else {
fwrite($FILE, $raList[$i]->_data);
}
if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE) {
for ($j = 0; $j < ($this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)); $j++) {
fwrite($FILE, "\x00");
}
}
// Set For PPS
$raList[$i]->_StartBlock = $iStBlk;
$iStBlk +=
(floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) +
(($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0));
}
// Close file for each PPS, and unlink it
if (isset($raList[$i]->_PPS_FILE)) {
@fclose($raList[$i]->_PPS_FILE);
$raList[$i]->_PPS_FILE = null;
@unlink($raList[$i]->_tmp_filename);
}
}
}
}
/**
* get small data (PPS's with data smaller than OLE_DATA_SIZE_SMALL)
*
* @access private
* @param array &$raList Reference to array of PPS's
*/
function _makeSmallData(&$raList)
{
$sRes = '';
$FILE = $this->_FILEH_;
$iSmBlk = 0;
for ($i = 0; $i < count($raList); $i++) {
// Make SBD, small data string
if ($raList[$i]->Type == OLE_PPS_TYPE_FILE) {
if ($raList[$i]->Size <= 0) {
continue;
}
if ($raList[$i]->Size < OLE_DATA_SIZE_SMALL) {
$iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE)
+ (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0);
// Add to SBD
for ($j = 0; $j < ($iSmbCnt-1); $j++) {
fwrite($FILE, pack("V", $j+$iSmBlk+1));
}
fwrite($FILE, pack("V", OLE_ENDOFCHAIN));
// Add to Data String(this will be written for RootEntry)
if ($raList[$i]->_PPS_FILE) {
fseek($raList[$i]->_PPS_FILE, 0); // To The Top
while ($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) {
$sRes .= $sBuff;
}
} else {
$sRes .= $raList[$i]->_data;
}
if ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE) {
for ($j = 0; $j < ($this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)); $j++) {
$sRes .= "\x00";
}
}
// Set for PPS
$raList[$i]->_StartBlock = $iSmBlk;
$iSmBlk += $iSmbCnt;
}
}
}
$iSbCnt = floor($this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE);
if ($iSmBlk % $iSbCnt) {
for ($i = 0; $i < ($iSbCnt - ($iSmBlk % $iSbCnt)); $i++) {
fwrite($FILE, pack("V", OLE_FREESECT));
}
}
return $sRes;
}
/**
* Saves all the PPS's WKs
*
* @access private
* @param array $raList Reference to an array with all PPS's
*/
function _savePps(&$raList)
{
// Save each PPS WK
for ($i = 0; $i < count($raList); $i++) {
fwrite($this->_FILEH_, $raList[$i]->_getPpsWk());
}
// Adjust for Block
$iCnt = count($raList);
$iBCnt = $this->_BIG_BLOCK_SIZE / OLE_PPS_SIZE;
if ($iCnt % $iBCnt) {
for ($i = 0; $i < (($iBCnt - ($iCnt % $iBCnt)) * OLE_PPS_SIZE); $i++) {
fwrite($this->_FILEH_, "\x00");
}
}
}
/**
* Saving Big Block Depot
*
* @access private
* @param integer $iSbdSize
* @param integer $iBsize
* @param integer $iPpsCnt
*/
function _saveBbd($iSbdSize, $iBsize, $iPpsCnt)
{
if($this->new_func)
return $this->_create_big_block_chain($iSbdSize, $iBsize, $iPpsCnt);
$FILE = $this->_FILEH_;
// Calculate Basic Setting
$iBbCnt = $this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE;
$i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / OLE_LONG_INT_SIZE;
$iBdExL = 0;
$iAll = $iBsize + $iPpsCnt + $iSbdSize;
$iAllW = $iAll;
$iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0);
$iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
// Calculate BD count
if ($iBdCnt >$i1stBdL) {
while (1) {
$iBdExL++;
$iAllW++;
$iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0);
$iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
if ($iBdCnt <= ($iBdExL*$iBbCnt+ $i1stBdL)) {
break;
}
}
}
// Making BD
// Set for SBD
if ($iSbdSize > 0) {
for ($i = 0; $i < ($iSbdSize - 1); $i++) {
fwrite($FILE, pack("V", $i+1));
}
fwrite($FILE, pack("V", OLE_ENDOFCHAIN));
}
// Set for B
for ($i = 0; $i < ($iBsize - 1); $i++) {
fwrite($FILE, pack("V", $i+$iSbdSize+1));
}
fwrite($FILE, pack("V", OLE_ENDOFCHAIN));
// Set for PPS
for ($i = 0; $i < ($iPpsCnt - 1); $i++) {
fwrite($FILE, pack("V", $i+$iSbdSize+$iBsize+1));
}
fwrite($FILE, pack("V", OLE_ENDOFCHAIN));
// Set for BBD itself ( 0xFFFFFFFD : BBD)
for ($i = 0; $i < $iBdCnt; $i++) {
fwrite($FILE, pack("V", OLE_FATSECT));
}
// Set for ExtraBDList
for ($i = 0; $i < $iBdExL; $i++) {
fwrite($FILE, pack("V", OLE_DIFSECT));
}
// Adjust for Block
if (($iAllW + $iBdCnt) % $iBbCnt) {
for ($i = 0; $i < ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); $i++) {
fwrite($FILE, pack("V", OLE_FREESECT));
}
}
// Extra BDList
if ($iBdCnt > $i1stBdL) {
$iN=0;
$iNb=0;
for ($i = $i1stBdL;$i < $iBdCnt; $i++, $iN++) {
if ($iN >= ($iBbCnt - 1)) {
$iN = 0;
$iNb++;
fwrite($FILE, pack("V", $iAll+$iBdCnt+$iNb));
}
fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i));
}
if (($iBdCnt-$i1stBdL) % ($iBbCnt-1)) {
for ($i = 0; $i < (($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1))); $i++) {
fwrite($FILE, pack("V", OLE_FREESECT));
}
}
fwrite($FILE, pack("V", OLE_ENDOFCHAIN));
}
}
/**
* New method to store Bigblock chain
*
* @access private
* @param integer $num_sb_blocks - number of Smallblock depot blocks
* @param integer $num_bb_blocks - number of Bigblock depot blocks
* @param integer $num_pps_blocks - number of PropertySetStorage blocks
*/
function _create_big_block_chain($num_sb_blocks, $num_bb_blocks, $num_pps_blocks)
{
$FILE = $this->_FILEH_;
$bbd_info = $this->_calculate_big_block_chain($num_sb_blocks, $num_bb_blocks, $num_pps_blocks);
$data = "";
if($num_sb_blocks > 0)
{
for($i = 0; $i<($num_sb_blocks-1); $i++)
$data .= pack("V", $i+1);
$data .= pack("V", OLE_ENDOFCHAIN);
}
for($i = 0; $i<($num_bb_blocks-1); $i++)
$data .= pack("V", $i + $num_sb_blocks + 1);
$data .= pack("V", OLE_ENDOFCHAIN);
for($i = 0; $i<($num_pps_blocks-1); $i++)
$data .= pack("V", $i + $num_sb_blocks + $num_bb_blocks + 1);
$data .= pack("V", OLE_ENDOFCHAIN);
for($i = 0; $i < $bbd_info["0xFFFFFFFD_blockchain_entries"]; $i++)
$data .= pack("V", OLE_FATSECT);
for($i = 0; $i < $bbd_info["0xFFFFFFFC_blockchain_entries"]; $i++)
$data .= pack("V", OLE_DIFSECT);
// Adjust for Block
$all_entries = $num_sb_blocks + $num_bb_blocks + $num_pps_blocks + $bbd_info["0xFFFFFFFD_blockchain_entries"] + $bbd_info["0xFFFFFFFC_blockchain_entries"];
if($all_entries % $bbd_info["entries_per_block"])
{
$rest = $bbd_info["entries_per_block"] - ($all_entries % $bbd_info["entries_per_block"]);
for($i = 0; $i < $rest; $i++)
$data .= pack("V", OLE_FREESECT);
}
// Extra BDList
if($bbd_info["blockchain_list_entries"] > $bbd_info["header_blockchain_list_entries"])
{
$iN=0;
$iNb=0;
for($i = $bbd_info["header_blockchain_list_entries"]; $i < $bbd_info["blockchain_list_entries"]; $i++, $iN++)
{
if($iN >= ($bbd_info["entries_per_block"]-1))
{
$iN = 0;
$iNb++;
$data .= pack("V", $num_sb_blocks + $num_bb_blocks + $num_pps_blocks + $bbd_info["0xFFFFFFFD_blockchain_entries"] + $iNb);
}
$data .= pack("V", $num_bb_blocks + $num_sb_blocks + $num_pps_blocks + $i);
}
$all_entries = $bbd_info["blockchain_list_entries"] - $bbd_info["header_blockchain_list_entries"];
if(($all_entries % ($bbd_info["entries_per_block"] - 1)))
{
$rest = ($bbd_info["entries_per_block"] - 1) - ($all_entries % ($bbd_info["entries_per_block"] - 1));
for($i = 0; $i < $rest; $i++)
$data .= pack("V", OLE_FREESECT);
}
$data .= pack("V", OLE_ENDOFCHAIN);
}
/*
$this->dump($data, 0, strlen($data));
die;
*/
fwrite($FILE, $data);
}
/**
* New method to store Header
*
* @access private
* @param integer $num_sb_blocks - number of Smallblock depot blocks
* @param integer $num_bb_blocks - number of Bigblock depot blocks
* @param integer $num_pps_blocks - number of PropertySetStorage blocks
*/
function _create_header($num_sb_blocks, $num_bb_blocks, $num_pps_blocks)
{
$FILE = $this->_FILEH_;
$bbd_info = $this->_calculate_big_block_chain($num_sb_blocks, $num_bb_blocks, $num_pps_blocks);
// Save Header
fwrite($FILE,
OLE_CFB_SIGNATURE // Header Signature (8 bytes)
. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // Header CLSID (16 bytes)
. pack("v", OLE_VERSION_MINOR) // Minor Version (2 bytes)
. pack("v", OLE_VERSION_MAJOR_3) // Major Version (2 bytes)
. pack("v", OLE_LITTLE_ENDIAN) // Byte Order (2 bytes)
. pack("v", OLE_SECTOR_SHIFT_3) // Sector Shift (2 bytes)
. pack("v", OLE_MINI_SECTOR_SHIFT) // Mini Sector Shift (2 bytes)
. "\x00\x00\x00\x00\x00\x00" // Reserved (6 bytes)
. "\x00\x00\x00\x00" // Number of Directory Sectors (4 bytes)
. pack("V", $bbd_info["blockchain_list_entries"]) // Number of FAT Sectors (4 bytes)
. pack("V", $num_sb_blocks + $num_bb_blocks) //ROOT START, First Directory Sector Location (4 bytes)
. pack("V", 0) // Transaction Signature Number (4 bytes)
. pack("V", 0x00001000) // Mini Stream Cutoff Size (4 bytes)
. pack("V", $num_sb_blocks > 0 ? 0 : OLE_ENDOFCHAIN) // First Mini FAT Sector Location (4 bytes)
. pack("V", $num_sb_blocks) // Number of Mini FAT Sectors (4 bytes)
);
// Extra BDList Start, Count
if($bbd_info["blockchain_list_entries"] < $bbd_info["header_blockchain_list_entries"])
{
fwrite($FILE,
pack("V", OLE_ENDOFCHAIN). // Extra BDList Start
pack("V", 0) // Extra BDList Count
);
}
else
{
fwrite($FILE, pack("V", $num_sb_blocks + $num_bb_blocks + $num_pps_blocks + $bbd_info["0xFFFFFFFD_blockchain_entries"]) . pack("V", $bbd_info["0xFFFFFFFC_blockchain_entries"]));
}
// BDList
for ($i=0; $i < $bbd_info["header_blockchain_list_entries"] and $i < $bbd_info["blockchain_list_entries"]; $i++)
{
fwrite($FILE, pack("V", $num_bb_blocks + $num_sb_blocks + $num_pps_blocks + $i));
}
if($i < $bbd_info["header_blockchain_list_entries"])
{
for($j = 0; $j < ($bbd_info["header_blockchain_list_entries"]-$i); $j++)
{
fwrite($FILE, (pack("V", OLE_FREESECT)));
}
}
}
/**
* New method to calculate Bigblock chain
*
* @access private
* @param integer $num_sb_blocks - number of Smallblock depot blocks
* @param integer $num_bb_blocks - number of Bigblock depot blocks
* @param integer $num_pps_blocks - number of PropertySetStorage blocks
*/
function _calculate_big_block_chain($num_sb_blocks, $num_bb_blocks, $num_pps_blocks)
{
$bbd_info["entries_per_block"] = $this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE;
$bbd_info["header_blockchain_list_entries"] = ($this->_BIG_BLOCK_SIZE - 0x4C) / OLE_LONG_INT_SIZE;
$bbd_info["blockchain_entries"] = $num_sb_blocks + $num_bb_blocks + $num_pps_blocks;
$bbd_info["0xFFFFFFFD_blockchain_entries"] = $this->get_number_of_pointer_blocks($bbd_info["blockchain_entries"]);
$bbd_info["blockchain_list_entries"] = $this->get_number_of_pointer_blocks($bbd_info["blockchain_entries"] + $bbd_info["0xFFFFFFFD_blockchain_entries"]);
// do some magic
$bbd_info["ext_blockchain_list_entries"] = 0;
$bbd_info["0xFFFFFFFC_blockchain_entries"] = 0;
if($bbd_info["blockchain_list_entries"] > $bbd_info["header_blockchain_list_entries"])
{
do
{
$bbd_info["blockchain_list_entries"] = $this->get_number_of_pointer_blocks($bbd_info["blockchain_entries"] + $bbd_info["0xFFFFFFFD_blockchain_entries"] + $bbd_info["0xFFFFFFFC_blockchain_entries"]);
$bbd_info["ext_blockchain_list_entries"] = $bbd_info["blockchain_list_entries"] - $bbd_info["header_blockchain_list_entries"];
$bbd_info["0xFFFFFFFC_blockchain_entries"] = $this->get_number_of_pointer_blocks($bbd_info["ext_blockchain_list_entries"]);
$bbd_info["0xFFFFFFFD_blockchain_entries"] = $this->get_number_of_pointer_blocks($num_sb_blocks + $num_bb_blocks + $num_pps_blocks + $bbd_info["0xFFFFFFFD_blockchain_entries"] + $bbd_info["0xFFFFFFFC_blockchain_entries"]);
}
while($bbd_info["blockchain_list_entries"] < $this->get_number_of_pointer_blocks($bbd_info["blockchain_entries"] + $bbd_info["0xFFFFFFFD_blockchain_entries"] + $bbd_info["0xFFFFFFFC_blockchain_entries"]));
}
return $bbd_info;
}
/**
* Calculates number of pointer blocks
*
* @access public
* @param integer $num_pointers - number of pointers
*/
function get_number_of_pointer_blocks($num_pointers)
{
$pointers_per_block = $this->_BIG_BLOCK_SIZE / OLE_LONG_INT_SIZE;
return floor($num_pointers / $pointers_per_block) + (($num_pointers % $pointers_per_block)? 1: 0);
}
/**
* Support method for some hexdumping
*
* @access public
* @param string $data - Binary data
* @param integer $from - Start offset of data to dump
* @param integer $to - Target offset of data to dump
*/
function dump($data, $from, $to)
{
$chars = array();
for($i = $from; $i < $to; $i++)
{
if(sizeof($chars) == 16)
{
printf("%08X (% 12d) |", $i-16, $i-16);
foreach($chars as $char)
printf(" %02X", $char);
print " |\n";
$chars = array();
}
$chars[] = ord($data[$i]);
}
if(sizeof($chars))
{
printf("%08X (% 12d) |", $i-sizeof($chars), $i-sizeof($chars));
foreach($chars as $char)
printf(" %02X", $char);
print " |\n";
}
}
}

25
videodb/vendor/pear/ole/README.md vendored Normal file
View File

@@ -0,0 +1,25 @@
[![Build Status](https://travis-ci.org/pear/OLE.svg?branch=master)](https://travis-ci.org/pear/OLE)
[![Latest Stable Version](https://poser.pugx.org/pear/ole/v/stable)](https://packagist.org/packages/pear/ole)
This package is http://pear.php.net/package/OLE and has been migrated from https://svn.php.net/repository/pear/packages/OLE
Please report all new issues via the PEAR bug tracker.
If this package is marked as unmaintained and you have fixes, please submit your pull requests and start discussion on the pear-qa mailing list.
To test, run
$ composer install
$ vendor/bin/phpunit
To build, simply
$ pear package
To install from scratch
$ pear install package.xml
To upgrade
$ pear upgrade -f package.xml

45
videodb/vendor/pear/ole/composer.json vendored Normal file
View File

@@ -0,0 +1,45 @@
{
"name": "pear/ole",
"type": "library",
"description": "This package allows reading and writing of OLE (Object Linking and Embedding) compound documents. This format is used as container for Excel (.xls), Word (.doc) and other Microsoft file formats.",
"license": "PHP-3.01",
"authors": [
{
"name": "Christian Schmidt",
"email": "schmidt@php.net",
"role": "Lead"
},
{
"name": "Xavier Noguer",
"email": "xnoguer@php.net",
"role": "Lead"
}
],
"require": {
"php": ">=5.6",
"pear/pear_exception": "^1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2",
"pear/pear-core-minimal": "^1.10",
"phpunit/phpunit": ">=5 <10",
"sanmai/phpunit-legacy-adapter": "^6 || ^8"
},
"autoload": {
"psr-0": {
"OLE": "./"
}
},
"autoload-dev": {
"psr-0": {
"OLE": "tests/"
}
},
"include-path": [
"./"
],
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=OLE",
"source": "https://github.com/pear/OLE"
}
}

212
videodb/vendor/pear/ole/package.xml vendored Normal file
View File

@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
<name>OLE</name>
<channel>pear.php.net</channel>
<summary>Package for reading and writing OLE containers</summary>
<description>This package allows reading and writing of OLE (Object Linking and Embedding) compound documents. This format is used as container for Excel (.xls), Word (.doc) and other Microsoft file formats.</description>
<lead>
<name>Christian Schmidt</name>
<user>schmidt</user>
<email>schmidt@php.net</email>
<active>yes</active>
</lead>
<lead>
<name>Xavier Noguer</name>
<user>xnoguer</user>
<email>xnoguer@php.net</email>
<active>no</active>
</lead>
<date>2017-06-20</date>
<version>
<release>1.0.0RC3</release>
<api>1.0.0RC3</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<license uri="http://www.php.net/license">PHP</license>
<notes>
Bug #19284: RC2 breaks header in excel files from Spreadsheet_Excel_Writer
Bug #21216: Call to undefined method PEAR::OLE_PPS()
</notes>
<contents>
<dir baseinstalldir="/" name="/">
<file baseinstalldir="/" name="OLE/ChainedBlockStream.php" role="php" />
<file baseinstalldir="/" name="OLE/PPS.php" role="php" />
<file baseinstalldir="/" name="OLE/PPS/File.php" role="php" />
<file baseinstalldir="/" name="OLE/PPS/Root.php" role="php" />
<file baseinstalldir="/" name="OLE.php" role="php" />
</dir>
</contents>
<dependencies>
<required>
<php>
<min>5.0.0</min>
</php>
<pearinstaller>
<min>1.4.0b1</min>
</pearinstaller>
</required>
</dependencies>
<phprelease />
<changelog>
<release>
<version>
<release>0.2.1</release>
<api>0.2.1</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2003-05-12</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
Fixing install dir
</notes>
</release>
<release>
<version>
<release>0.3</release>
<api>0.3</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2003-08-21</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
-added OLE_PPS_File::init() initialization method.
-better error handling.
</notes>
</release>
<release>
<version>
<release>0.4</release>
<api>0.4</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2003-09-25</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
-deleting tmp files (Herman Kuiper).
-fixed hardcoded tmp dir (Herman Kuiper).
-fixed pass by reference warning (Herman Kuiper).
</notes>
</release>
<release>
<version>
<release>0.5</release>
<api>0.5</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2003-12-14</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
- BC break!!! OLE/OLE.php file moved to OLE.php to comply with PEAR
standards. You will have to change your require(&apos;OLE/OLE.php&apos;)&apos;s
for require(&apos;OLE.php&apos;)&apos;s
- If you are using Spreadsheet_Excel_Writer, do not upgrade to this
version yet. A new version of Spreadsheet_Excel_Writer will be
released soon so the BC break won&apos;t affect you.
- allowing setting of temp dir for OLE_PPS_File and OLE_PPS_Root objects
- fixed problem when reading files (not reading the whole OLE tree)
</notes>
</release>
<release>
<version>
<release>0.6.0</release>
<api>0.6.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2007-12-09</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
Rewrite of parser (no change to writer):
- Files inside OLE container are now saved in directory structure.
- Parser now properly uses Big Block, Small Block and Master Block Allocation Tables.
- Added stream interface for reading files inside OLE container.
- Bug #6516. Fix &quot;PPS at 1 has unknown type&quot; errors. (Christian Schmidt)
- Coding Standard cleanups (by helgi)
- Bug #3951 OLE_PPS_File::init() does not return true on success (by helgi)
- Bug #3955 OLE::_readPpsWks() does not return true on success (by helgi)
</notes>
</release>
<release>
<version>
<release>0.6.1</release>
<api>0.6.1</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2007-12-18</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
- fixed bug #12693: wrong order of require_once
- added missing file to package: ChainedBlockStream.php
</notes>
</release>
<release>
<version>
<release>0.6.2</release>
<api>0.6.2</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2012-01-26</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
- fixed bug #12944: Incompatibility open_basedir restriction.
</notes>
</release>
<release>
<version>
<release>1.0.0RC2</release>
<api>1.0.0RC2</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2012-01-26</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
QA release
Bug #15904 Invalid Bigblock chain with files &gt; 200MB
Bug #17685 OLE doesn&apos;t save multistreams
</notes>
</release>
<release>
<version>
<release>1.0.0RC3</release>
<api>1.0.0RC3</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2017-06-20</date>
<license uri="http://www.php.net/license">PHP</license>
<notes>
Bug #19284: RC2 breaks header in excel files from Spreadsheet_Excel_Writer
Bug #21216: Call to undefined method PEAR::OLE_PPS()
</notes>
</release>
</changelog>
</package>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" verbose="true" colors="true"
convertNoticesToExceptions="true"
>
<testsuites>
<testsuite>
<directory>tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">OLE/</directory>
<file>OLE.php</file>
</whitelist>
</filter>
<logging>
<log type="coverage-clover" target="build/logs/clover.xml"/>
<log type="coverage-text" target="php://stdout"/>
</logging>
</phpunit>

View File

@@ -0,0 +1,26 @@
******************************
Minimal set of PEAR core files
******************************
This repository provides a set of files from ``pear-core``
that are often used in PEAR packages.
It follows the `pear-core`__ repository and gets updated whenever a new
PEAR version is released.
It's meant to be used as dependency for composer packages.
__ https://github.com/pear/pear-core
==============
Included files
==============
- ``OS/Guess.php``
- ``PEAR.php``
- ``PEAR/Error.php``
- ``PEAR/ErrorStack.php``
- ``System.php``
``PEAR/Error.php`` is a dummy file that only includes ``PEAR.php``,
to make autoloaders work without problems.

View File

@@ -0,0 +1,32 @@
{
"name": "pear/pear-core-minimal",
"description": "Minimal set of PEAR core files to be used as composer dependency",
"license": "BSD-3-Clause",
"authors": [
{
"email": "cweiske@php.net",
"name": "Christian Weiske",
"role": "Lead"
}
],
"autoload": {
"psr-0": {
"": "src/"
}
},
"include-path": [
"src/"
],
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR",
"source": "https://github.com/pear/pear-core-minimal"
},
"type": "library",
"require": {
"pear/console_getopt": "~1.4",
"pear/pear_exception": "~1.0"
},
"replace": {
"rsky/pear-core-min": "self.version"
}
}

View File

@@ -0,0 +1,395 @@
<?php
/**
* The OS_Guess class
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since PEAR 0.1
*/
// {{{ uname examples
// php_uname() without args returns the same as 'uname -a', or a PHP-custom
// string for Windows.
// PHP versions prior to 4.3 return the uname of the host where PHP was built,
// as of 4.3 it returns the uname of the host running the PHP code.
//
// PC RedHat Linux 7.1:
// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
//
// PC Debian Potato:
// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
//
// PC FreeBSD 3.3:
// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386
//
// PC FreeBSD 4.3:
// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386
//
// PC FreeBSD 4.5:
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386
//
// PC FreeBSD 4.5 w/uname from GNU shellutils:
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown
//
// HP 9000/712 HP-UX 10:
// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
//
// HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
// HP-UX host B.10.10 A 9000/712 unknown
//
// IBM RS6000/550 AIX 4.3:
// AIX host 3 4 000003531C00
//
// AIX 4.3 w/uname from GNU shellutils:
// AIX host 3 4 000003531C00 unknown
//
// SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
// IRIX64 host 6.5 01091820 IP19 mips
//
// SGI Onyx IRIX 6.5:
// IRIX64 host 6.5 01091820 IP19
//
// SparcStation 20 Solaris 8 w/uname from GNU shellutils:
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
//
// SparcStation 20 Solaris 8:
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
//
// Mac OS X (Darwin)
// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh
//
// Mac OS X early versions
//
// }}}
/* TODO:
* - define endianness, to allow matchSignature("bigend") etc.
*/
/**
* Retrieves information about the current operating system
*
* This class uses php_uname() to grok information about the current OS
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2020 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class OS_Guess
{
var $sysname;
var $nodename;
var $cpu;
var $release;
var $extra;
function __construct($uname = null)
{
list($this->sysname,
$this->release,
$this->cpu,
$this->extra,
$this->nodename) = $this->parseSignature($uname);
}
function parseSignature($uname = null)
{
static $sysmap = array(
'HP-UX' => 'hpux',
'IRIX64' => 'irix',
);
static $cpumap = array(
'i586' => 'i386',
'i686' => 'i386',
'ppc' => 'powerpc',
);
if ($uname === null) {
$uname = php_uname();
}
$parts = preg_split('/\s+/', trim($uname));
$n = count($parts);
$release = $machine = $cpu = '';
$sysname = $parts[0];
$nodename = $parts[1];
$cpu = $parts[$n-1];
$extra = '';
if ($cpu == 'unknown') {
$cpu = $parts[$n - 2];
}
switch ($sysname) {
case 'AIX' :
$release = "$parts[3].$parts[2]";
break;
case 'Windows' :
$release = $parts[1];
if ($release == '95/98') {
$release = '9x';
}
$cpu = 'i386';
break;
case 'Linux' :
$extra = $this->_detectGlibcVersion();
// use only the first two digits from the kernel version
$release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
break;
case 'Mac' :
$sysname = 'darwin';
$nodename = $parts[2];
$release = $parts[3];
$cpu = $this->_determineIfPowerpc($cpu, $parts);
break;
case 'Darwin' :
$cpu = $this->_determineIfPowerpc($cpu, $parts);
$release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
break;
default:
$release = preg_replace('/-.*/', '', $parts[2]);
break;
}
if (isset($sysmap[$sysname])) {
$sysname = $sysmap[$sysname];
} else {
$sysname = strtolower($sysname);
}
if (isset($cpumap[$cpu])) {
$cpu = $cpumap[$cpu];
}
return array($sysname, $release, $cpu, $extra, $nodename);
}
function _determineIfPowerpc($cpu, $parts)
{
$n = count($parts);
if ($cpu == 'Macintosh' && $parts[$n - 2] == 'Power') {
$cpu = 'powerpc';
}
return $cpu;
}
function _detectGlibcVersion()
{
static $glibc = false;
if ($glibc !== false) {
return $glibc; // no need to run this multiple times
}
$major = $minor = 0;
include_once "System.php";
// Let's try reading possible libc.so.6 symlinks
$libcs = array(
'/lib64/libc.so.6',
'/lib/libc.so.6',
'/lib/i386-linux-gnu/libc.so.6'
);
$versions = array();
foreach ($libcs as $file) {
$versions = $this->_readGlibCVersionFromSymlink($file);
if ($versions != []) {
list($major, $minor) = $versions;
break;
}
}
// Use glibc's <features.h> header file to
// get major and minor version number:
if (!($major && $minor)) {
$versions = $this->_readGlibCVersionFromFeaturesHeaderFile();
}
if (is_array($versions) && $versions != []) {
list($major, $minor) = $versions;
}
if (!($major && $minor)) {
return $glibc = '';
}
return $glibc = "glibc{$major}.{$minor}";
}
function _readGlibCVersionFromSymlink($file)
{
$versions = array();
if (@is_link($file)
&& (preg_match('/^libc-(.*)\.so$/', basename(readlink($file)), $matches))
) {
$versions = explode('.', $matches[1]);
}
return $versions;
}
function _readGlibCVersionFromFeaturesHeaderFile()
{
$features_header_file = '/usr/include/features.h';
if (!(@file_exists($features_header_file)
&& @is_readable($features_header_file))
) {
return array();
}
if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
return $this-_parseFeaturesHeaderFile($features_header_file);
} // no cpp
return $this->_fromGlibCTest();
}
function _parseFeaturesHeaderFile($features_header_file)
{
$features_file = fopen($features_header_file, 'rb');
while (!feof($features_file)) {
$line = fgets($features_file, 8192);
if (!$this->_IsADefinition($line)) {
continue;
}
if (strpos($line, '__GLIBC__')) {
// major version number #define __GLIBC__ version
$line = preg_split('/\s+/', $line);
$glibc_major = trim($line[2]);
if (isset($glibc_minor)) {
break;
}
continue;
}
if (strpos($line, '__GLIBC_MINOR__')) {
// got the minor version number
// #define __GLIBC_MINOR__ version
$line = preg_split('/\s+/', $line);
$glibc_minor = trim($line[2]);
if (isset($glibc_major)) {
break;
}
}
}
fclose($features_file);
if (!isset($glibc_major) || !isset($glibc_minor)) {
return array();
}
return array(trim($glibc_major), trim($glibc_minor));
}
function _IsADefinition($line)
{
if ($line === false) {
return false;
}
return strpos(trim($line), '#define') !== false;
}
function _fromGlibCTest()
{
$major = null;
$minor = null;
$tmpfile = System::mktemp("glibctest");
$fp = fopen($tmpfile, "w");
fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
fclose($fp);
$cpp = popen("/usr/bin/cpp $tmpfile", "r");
while ($line = fgets($cpp, 1024)) {
if ($line[0] == '#' || trim($line) == '') {
continue;
}
if (list($major, $minor) = explode(' ', trim($line))) {
break;
}
}
pclose($cpp);
unlink($tmpfile);
if ($major !== null && $minor !== null) {
return [$major, $minor];
}
}
function getSignature()
{
if (empty($this->extra)) {
return "{$this->sysname}-{$this->release}-{$this->cpu}";
}
return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
}
function getSysname()
{
return $this->sysname;
}
function getNodename()
{
return $this->nodename;
}
function getCpu()
{
return $this->cpu;
}
function getRelease()
{
return $this->release;
}
function getExtra()
{
return $this->extra;
}
function matchSignature($match)
{
$fragments = is_array($match) ? $match : explode('-', $match);
$n = count($fragments);
$matches = 0;
if ($n > 0) {
$matches += $this->_matchFragment($fragments[0], $this->sysname);
}
if ($n > 1) {
$matches += $this->_matchFragment($fragments[1], $this->release);
}
if ($n > 2) {
$matches += $this->_matchFragment($fragments[2], $this->cpu);
}
if ($n > 3) {
$matches += $this->_matchFragment($fragments[3], $this->extra);
}
return ($matches == $n);
}
function _matchFragment($fragment, $value)
{
if (strcspn($fragment, '*?') < strlen($fragment)) {
$expression = str_replace(
array('*', '?', '/'),
array('.*', '.', '\\/'),
$fragment
);
$reg = '/^' . $expression . '\\z/';
return preg_match($reg, $value);
}
return ($fragment == '*' || !strcasecmp($fragment, $value));
}
}
/*
* Local Variables:
* indent-tabs-mode: nil
* c-basic-offset: 4
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
<?php
/**
* Dummy file to make autoloaders work
*
* PHP version 5
*
* @category PEAR
* @package PEAR
* @author Christian Weiske <cweiske@php.net>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
*/
require_once __DIR__ . '/../PEAR.php';
?>

View File

@@ -0,0 +1,979 @@
<?php
/**
* Error Stack Implementation
*
* This is an incredibly simple implementation of a very complex error handling
* facility. It contains the ability
* to track multiple errors from multiple packages simultaneously. In addition,
* it can track errors of many levels, save data along with the error, context
* information such as the exact file, line number, class and function that
* generated the error, and if necessary, it can raise a traditional PEAR_Error.
* It has built-in support for PEAR::Log, to log errors as they occur
*
* Since version 0.2alpha, it is also possible to selectively ignore errors,
* through the use of an error callback, see {@link pushCallback()}
*
* Since version 0.3alpha, it is possible to specify the exception class
* returned from {@link push()}
*
* Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can
* still be done quite handily in an error callback or by manipulating the returned array
* @category Debugging
* @package PEAR_ErrorStack
* @author Greg Beaver <cellog@php.net>
* @copyright 2004-2008 Greg Beaver
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR_ErrorStack
*/
/**
* Singleton storage
*
* Format:
* <pre>
* array(
* 'package1' => PEAR_ErrorStack object,
* 'package2' => PEAR_ErrorStack object,
* ...
* )
* </pre>
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
*/
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
/**
* Global error callback (default)
*
* This is only used if set to non-false. * is the default callback for
* all packages, whereas specific packages may set a default callback
* for all instances, regardless of whether they are a singleton or not.
*
* To exclude non-singletons, only set the local callback for the singleton
* @see PEAR_ErrorStack::setDefaultCallback()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
*/
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
'*' => false,
);
/**
* Global Log object (default)
*
* This is only used if set to non-false. Use to set a default log object for
* all stacks, regardless of instantiation order or location
* @see PEAR_ErrorStack::setDefaultLogger()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
*/
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
/**
* Global Overriding Callback
*
* This callback will override any error callbacks that specific loggers have set.
* Use with EXTREME caution
* @see PEAR_ErrorStack::staticPushCallback()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
*/
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
/**#@+
* One of four possible return values from the error Callback
* @see PEAR_ErrorStack::_errorCallback()
*/
/**
* If this is returned, then the error will be both pushed onto the stack
* and logged.
*/
define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
/**
* If this is returned, then the error will only be pushed onto the stack,
* and not logged.
*/
define('PEAR_ERRORSTACK_PUSH', 2);
/**
* If this is returned, then the error will only be logged, but not pushed
* onto the error stack.
*/
define('PEAR_ERRORSTACK_LOG', 3);
/**
* If this is returned, then the error is completely ignored.
*/
define('PEAR_ERRORSTACK_IGNORE', 4);
/**
* If this is returned, then the error is logged and die() is called.
*/
define('PEAR_ERRORSTACK_DIE', 5);
/**#@-*/
/**
* Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
* the singleton method.
*/
define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
/**
* Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
* that has no __toString() method
*/
define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
/**
* Error Stack Implementation
*
* Usage:
* <code>
* // global error stack
* $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
* // local error stack
* $local_stack = new PEAR_ErrorStack('MyPackage');
* </code>
* @author Greg Beaver <cellog@php.net>
* @version @package_version@
* @package PEAR_ErrorStack
* @category Debugging
* @copyright 2004-2008 Greg Beaver
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR_ErrorStack
*/
class PEAR_ErrorStack {
/**
* Errors are stored in the order that they are pushed on the stack.
* @since 0.4alpha Errors are no longer organized by error level.
* This renders pop() nearly unusable, and levels could be more easily
* handled in a callback anyway
* @var array
* @access private
*/
var $_errors = array();
/**
* Storage of errors by level.
*
* Allows easy retrieval and deletion of only errors from a particular level
* @since PEAR 1.4.0dev
* @var array
* @access private
*/
var $_errorsByLevel = array();
/**
* Package name this error stack represents
* @var string
* @access protected
*/
var $_package;
/**
* Determines whether a PEAR_Error is thrown upon every error addition
* @var boolean
* @access private
*/
var $_compat = false;
/**
* If set to a valid callback, this will be used to generate the error
* message from the error code, otherwise the message passed in will be
* used
* @var false|string|array
* @access private
*/
var $_msgCallback = false;
/**
* If set to a valid callback, this will be used to generate the error
* context for an error. For PHP-related errors, this will be a file
* and line number as retrieved from debug_backtrace(), but can be
* customized for other purposes. The error might actually be in a separate
* configuration file, or in a database query.
* @var false|string|array
* @access protected
*/
var $_contextCallback = false;
/**
* If set to a valid callback, this will be called every time an error
* is pushed onto the stack. The return value will be used to determine
* whether to allow an error to be pushed or logged.
*
* The return value must be one an PEAR_ERRORSTACK_* constant
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @var false|string|array
* @access protected
*/
var $_errorCallback = array();
/**
* PEAR::Log object for logging errors
* @var false|Log
* @access protected
*/
var $_logger = false;
/**
* Error messages - designed to be overridden
* @var array
* @abstract
*/
var $_errorMsgs = array();
/**
* Set up a new error stack
*
* @param string $package name of the package this error stack represents
* @param callback $msgCallback callback used for error message generation
* @param callback $contextCallback callback used for context generation,
* defaults to {@link getFileLine()}
* @param boolean $throwPEAR_Error
*/
function __construct($package, $msgCallback = false, $contextCallback = false,
$throwPEAR_Error = false)
{
$this->_package = $package;
$this->setMessageCallback($msgCallback);
$this->setContextCallback($contextCallback);
$this->_compat = $throwPEAR_Error;
}
/**
* Return a single error stack for this package.
*
* Note that all parameters are ignored if the stack for package $package
* has already been instantiated
* @param string $package name of the package this error stack represents
* @param callback $msgCallback callback used for error message generation
* @param callback $contextCallback callback used for context generation,
* defaults to {@link getFileLine()}
* @param boolean $throwPEAR_Error
* @param string $stackClass class to instantiate
*
* @return PEAR_ErrorStack
*/
public static function &singleton(
$package, $msgCallback = false, $contextCallback = false,
$throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack'
) {
if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
}
if (!class_exists($stackClass)) {
if (function_exists('debug_backtrace')) {
$trace = debug_backtrace();
}
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
'exception', array('stackclass' => $stackClass),
'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
false, $trace);
}
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
}
/**
* Internal error handler for PEAR_ErrorStack class
*
* Dies if the error is an exception (and would have died anyway)
* @access private
*/
function _handleError($err)
{
if ($err['level'] == 'exception') {
$message = $err['message'];
if (isset($_SERVER['REQUEST_URI'])) {
echo '<br />';
} else {
echo "\n";
}
var_dump($err['context']);
die($message);
}
}
/**
* Set up a PEAR::Log object for all error stacks that don't have one
* @param Log $log
*/
public static function setDefaultLogger(&$log)
{
if (is_object($log) && method_exists($log, 'log') ) {
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
} elseif (is_callable($log)) {
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
}
}
/**
* Set up a PEAR::Log object for this error stack
* @param Log $log
*/
function setLogger(&$log)
{
if (is_object($log) && method_exists($log, 'log') ) {
$this->_logger = &$log;
} elseif (is_callable($log)) {
$this->_logger = &$log;
}
}
/**
* Set an error code => error message mapping callback
*
* This method sets the callback that can be used to generate error
* messages for any instance
* @param array|string Callback function/method
*/
function setMessageCallback($msgCallback)
{
if (!$msgCallback) {
$this->_msgCallback = array(&$this, 'getErrorMessage');
} else {
if (is_callable($msgCallback)) {
$this->_msgCallback = $msgCallback;
}
}
}
/**
* Get an error code => error message mapping callback
*
* This method returns the current callback that can be used to generate error
* messages
* @return array|string|false Callback function/method or false if none
*/
function getMessageCallback()
{
return $this->_msgCallback;
}
/**
* Sets a default callback to be used by all error stacks
*
* This method sets the callback that can be used to generate error
* messages for a singleton
* @param array|string Callback function/method
* @param string Package name, or false for all packages
*/
public static function setDefaultCallback($callback = false, $package = false)
{
if (!is_callable($callback)) {
$callback = false;
}
$package = $package ? $package : '*';
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
}
/**
* Set a callback that generates context information (location of error) for an error stack
*
* This method sets the callback that can be used to generate context
* information for an error. Passing in NULL will disable context generation
* and remove the expensive call to debug_backtrace()
* @param array|string|null Callback function/method
*/
function setContextCallback($contextCallback)
{
if ($contextCallback === null) {
return $this->_contextCallback = false;
}
if (!$contextCallback) {
$this->_contextCallback = array(&$this, 'getFileLine');
} else {
if (is_callable($contextCallback)) {
$this->_contextCallback = $contextCallback;
}
}
}
/**
* Set an error Callback
* If set to a valid callback, this will be called every time an error
* is pushed onto the stack. The return value will be used to determine
* whether to allow an error to be pushed or logged.
*
* The return value must be one of the ERRORSTACK_* constants.
*
* This functionality can be used to emulate PEAR's pushErrorHandling, and
* the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
* the error stack or logging
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @see popCallback()
* @param string|array $cb
*/
function pushCallback($cb)
{
array_push($this->_errorCallback, $cb);
}
/**
* Remove a callback from the error callback stack
* @see pushCallback()
* @return array|string|false
*/
function popCallback()
{
if (!count($this->_errorCallback)) {
return false;
}
return array_pop($this->_errorCallback);
}
/**
* Set a temporary overriding error callback for every package error stack
*
* Use this to temporarily disable all existing callbacks (can be used
* to emulate the @ operator, for instance)
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @see staticPopCallback(), pushCallback()
* @param string|array $cb
*/
public static function staticPushCallback($cb)
{
array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
}
/**
* Remove a temporary overriding error callback
* @see staticPushCallback()
* @return array|string|false
*/
public static function staticPopCallback()
{
$ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
}
return $ret;
}
/**
* Add an error to the stack
*
* If the message generator exists, it is called with 2 parameters.
* - the current Error Stack object
* - an array that is in the same format as an error. Available indices
* are 'code', 'package', 'time', 'params', 'level', and 'context'
*
* Next, if the error should contain context information, this is
* handled by the context grabbing method.
* Finally, the error is pushed onto the proper error stack
* @param int $code Package-specific error code
* @param string $level Error level. This is NOT spell-checked
* @param array $params associative array of error parameters
* @param string $msg Error message, or a portion of it if the message
* is to be generated
* @param array $repackage If this error re-packages an error pushed by
* another package, place the array returned from
* {@link pop()} in this parameter
* @param array $backtrace Protected parameter: use this to pass in the
* {@link debug_backtrace()} that should be used
* to find error context
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
* thrown. If a PEAR_Error is returned, the userinfo
* property is set to the following array:
*
* <code>
* array(
* 'code' => $code,
* 'params' => $params,
* 'package' => $this->_package,
* 'level' => $level,
* 'time' => time(),
* 'context' => $context,
* 'message' => $msg,
* //['repackage' => $err] repackaged error array/Exception class
* );
* </code>
*
* Normally, the previous array is returned.
*/
function push($code, $level = 'error', $params = array(), $msg = false,
$repackage = false, $backtrace = false)
{
$context = false;
// grab error context
if ($this->_contextCallback) {
if (!$backtrace) {
$backtrace = debug_backtrace();
}
$context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
}
// save error
$time = explode(' ', microtime());
$time = $time[1] + $time[0];
$err = array(
'code' => $code,
'params' => $params,
'package' => $this->_package,
'level' => $level,
'time' => $time,
'context' => $context,
'message' => $msg,
);
if ($repackage) {
$err['repackage'] = $repackage;
}
// set up the error message, if necessary
if ($this->_msgCallback) {
$msg = call_user_func_array($this->_msgCallback,
array(&$this, $err));
$err['message'] = $msg;
}
$push = $log = true;
$die = false;
// try the overriding callback first
$callback = $this->staticPopCallback();
if ($callback) {
$this->staticPushCallback($callback);
}
if (!is_callable($callback)) {
// try the local callback next
$callback = $this->popCallback();
if (is_callable($callback)) {
$this->pushCallback($callback);
} else {
// try the default callback
$callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
}
}
if (is_callable($callback)) {
switch(call_user_func($callback, $err)){
case PEAR_ERRORSTACK_IGNORE:
return $err;
break;
case PEAR_ERRORSTACK_PUSH:
$log = false;
break;
case PEAR_ERRORSTACK_LOG:
$push = false;
break;
case PEAR_ERRORSTACK_DIE:
$die = true;
break;
// anything else returned has the same effect as pushandlog
}
}
if ($push) {
array_unshift($this->_errors, $err);
if (!isset($this->_errorsByLevel[$err['level']])) {
$this->_errorsByLevel[$err['level']] = array();
}
$this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
}
if ($log) {
if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
$this->_log($err);
}
}
if ($die) {
die();
}
if ($this->_compat && $push) {
return $this->raiseError($msg, $code, null, null, $err);
}
return $err;
}
/**
* Static version of {@link push()}
*
* @param string $package Package name this error belongs to
* @param int $code Package-specific error code
* @param string $level Error level. This is NOT spell-checked
* @param array $params associative array of error parameters
* @param string $msg Error message, or a portion of it if the message
* is to be generated
* @param array $repackage If this error re-packages an error pushed by
* another package, place the array returned from
* {@link pop()} in this parameter
* @param array $backtrace Protected parameter: use this to pass in the
* {@link debug_backtrace()} that should be used
* to find error context
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
* thrown. see docs for {@link push()}
*/
public static function staticPush(
$package, $code, $level = 'error', $params = array(),
$msg = false, $repackage = false, $backtrace = false
) {
$s = &PEAR_ErrorStack::singleton($package);
if ($s->_contextCallback) {
if (!$backtrace) {
if (function_exists('debug_backtrace')) {
$backtrace = debug_backtrace();
}
}
}
return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
}
/**
* Log an error using PEAR::Log
* @param array $err Error array
* @param array $levels Error level => Log constant map
* @access protected
*/
function _log($err)
{
if ($this->_logger) {
$logger = &$this->_logger;
} else {
$logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
}
if (is_a($logger, 'Log')) {
$levels = array(
'exception' => PEAR_LOG_CRIT,
'alert' => PEAR_LOG_ALERT,
'critical' => PEAR_LOG_CRIT,
'error' => PEAR_LOG_ERR,
'warning' => PEAR_LOG_WARNING,
'notice' => PEAR_LOG_NOTICE,
'info' => PEAR_LOG_INFO,
'debug' => PEAR_LOG_DEBUG);
if (isset($levels[$err['level']])) {
$level = $levels[$err['level']];
} else {
$level = PEAR_LOG_INFO;
}
$logger->log($err['message'], $level, $err);
} else { // support non-standard logs
call_user_func($logger, $err);
}
}
/**
* Pop an error off of the error stack
*
* @return false|array
* @since 0.4alpha it is no longer possible to specify a specific error
* level to return - the last error pushed will be returned, instead
*/
function pop()
{
$err = @array_shift($this->_errors);
if (!is_null($err)) {
@array_pop($this->_errorsByLevel[$err['level']]);
if (!count($this->_errorsByLevel[$err['level']])) {
unset($this->_errorsByLevel[$err['level']]);
}
}
return $err;
}
/**
* Pop an error off of the error stack, static method
*
* @param string package name
* @return boolean
* @since PEAR1.5.0a1
*/
static function staticPop($package)
{
if ($package) {
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return false;
}
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
}
}
/**
* Determine whether there are any errors on the stack
* @param string|array Level name. Use to determine if any errors
* of level (string), or levels (array) have been pushed
* @return boolean
*/
function hasErrors($level = false)
{
if ($level) {
return isset($this->_errorsByLevel[$level]);
}
return count($this->_errors);
}
/**
* Retrieve all errors since last purge
*
* @param boolean set in order to empty the error stack
* @param string level name, to return only errors of a particular severity
* @return array
*/
function getErrors($purge = false, $level = false)
{
if (!$purge) {
if ($level) {
if (!isset($this->_errorsByLevel[$level])) {
return array();
} else {
return $this->_errorsByLevel[$level];
}
} else {
return $this->_errors;
}
}
if ($level) {
$ret = $this->_errorsByLevel[$level];
foreach ($this->_errorsByLevel[$level] as $i => $unused) {
// entries are references to the $_errors array
$this->_errorsByLevel[$level][$i] = false;
}
// array_filter removes all entries === false
$this->_errors = array_filter($this->_errors);
unset($this->_errorsByLevel[$level]);
return $ret;
}
$ret = $this->_errors;
$this->_errors = array();
$this->_errorsByLevel = array();
return $ret;
}
/**
* Determine whether there are any errors on a single error stack, or on any error stack
*
* The optional parameter can be used to test the existence of any errors without the need of
* singleton instantiation
* @param string|false Package name to check for errors
* @param string Level name to check for a particular severity
* @return boolean
*/
public static function staticHasErrors($package = false, $level = false)
{
if ($package) {
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return false;
}
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
}
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
if ($obj->hasErrors($level)) {
return true;
}
}
return false;
}
/**
* Get a list of all errors since last purge, organized by package
* @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
* @param boolean $purge Set to purge the error stack of existing errors
* @param string $level Set to a level name in order to retrieve only errors of a particular level
* @param boolean $merge Set to return a flat array, not organized by package
* @param array $sortfunc Function used to sort a merged array - default
* sorts by time, and should be good for most cases
*
* @return array
*/
public static function staticGetErrors(
$purge = false, $level = false, $merge = false,
$sortfunc = array('PEAR_ErrorStack', '_sortErrors')
) {
$ret = array();
if (!is_callable($sortfunc)) {
$sortfunc = array('PEAR_ErrorStack', '_sortErrors');
}
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
$test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
if ($test) {
if ($merge) {
$ret = array_merge($ret, $test);
} else {
$ret[$package] = $test;
}
}
}
if ($merge) {
usort($ret, $sortfunc);
}
return $ret;
}
/**
* Error sorting function, sorts by time
* @access private
*/
public static function _sortErrors($a, $b)
{
if ($a['time'] == $b['time']) {
return 0;
}
if ($a['time'] < $b['time']) {
return 1;
}
return -1;
}
/**
* Standard file/line number/function/class context callback
*
* This function uses a backtrace generated from {@link debug_backtrace()}
* and so will not work at all in PHP < 4.3.0. The frame should
* reference the frame that contains the source of the error.
* @return array|false either array('file' => file, 'line' => line,
* 'function' => function name, 'class' => class name) or
* if this doesn't work, then false
* @param unused
* @param integer backtrace frame.
* @param array Results of debug_backtrace()
*/
public static function getFileLine($code, $params, $backtrace = null)
{
if ($backtrace === null) {
return false;
}
$frame = 0;
$functionframe = 1;
if (!isset($backtrace[1])) {
$functionframe = 0;
} else {
while (isset($backtrace[$functionframe]['function']) &&
$backtrace[$functionframe]['function'] == 'eval' &&
isset($backtrace[$functionframe + 1])) {
$functionframe++;
}
}
if (isset($backtrace[$frame])) {
if (!isset($backtrace[$frame]['file'])) {
$frame++;
}
$funcbacktrace = $backtrace[$functionframe];
$filebacktrace = $backtrace[$frame];
$ret = array('file' => $filebacktrace['file'],
'line' => $filebacktrace['line']);
// rearrange for eval'd code or create function errors
if (strpos($filebacktrace['file'], '(') &&
preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
$matches)) {
$ret['file'] = $matches[1];
$ret['line'] = $matches[2] + 0;
}
if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
if ($funcbacktrace['function'] != 'eval') {
if ($funcbacktrace['function'] == '__lambda_func') {
$ret['function'] = 'create_function() code';
} else {
$ret['function'] = $funcbacktrace['function'];
}
}
}
if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
$ret['class'] = $funcbacktrace['class'];
}
return $ret;
}
return false;
}
/**
* Standard error message generation callback
*
* This method may also be called by a custom error message generator
* to fill in template values from the params array, simply
* set the third parameter to the error message template string to use
*
* The special variable %__msg% is reserved: use it only to specify
* where a message passed in by the user should be placed in the template,
* like so:
*
* Error message: %msg% - internal error
*
* If the message passed like so:
*
* <code>
* $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
* </code>
*
* The returned error message will be "Error message: server error 500 -
* internal error"
* @param PEAR_ErrorStack
* @param array
* @param string|false Pre-generated error message template
*
* @return string
*/
public static function getErrorMessage(&$stack, $err, $template = false)
{
if ($template) {
$mainmsg = $template;
} else {
$mainmsg = $stack->getErrorMessageTemplate($err['code']);
}
$mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
if (is_array($err['params']) && count($err['params'])) {
foreach ($err['params'] as $name => $val) {
if (is_array($val)) {
// @ is needed in case $val is a multi-dimensional array
$val = @implode(', ', $val);
}
if (is_object($val)) {
if (method_exists($val, '__toString')) {
$val = $val->__toString();
} else {
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
'warning', array('obj' => get_class($val)),
'object %obj% passed into getErrorMessage, but has no __toString() method');
$val = 'Object';
}
}
$mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
}
}
return $mainmsg;
}
/**
* Standard Error Message Template generator from code
* @return string
*/
function getErrorMessageTemplate($code)
{
if (!isset($this->_errorMsgs[$code])) {
return '%__msg%';
}
return $this->_errorMsgs[$code];
}
/**
* Set the Error Message Template array
*
* The array format must be:
* <pre>
* array(error code => 'message template',...)
* </pre>
*
* Error message parameters passed into {@link push()} will be used as input
* for the error message. If the template is 'message %foo% was %bar%', and the
* parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
* be 'message one was six'
* @return string
*/
function setErrorMessageTemplate($template)
{
$this->_errorMsgs = $template;
}
/**
* emulate PEAR::raiseError()
*
* @return PEAR_Error
*/
function raiseError()
{
require_once 'PEAR.php';
$args = func_get_args();
return call_user_func_array(array('PEAR', 'raiseError'), $args);
}
}
$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
$stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
?>

View File

@@ -0,0 +1,630 @@
<?php
/**
* File/Directory manipulation
*
* PHP versions 4 and 5
*
* @category pear
* @package System
* @author Tomas V.V.Cox <cox@idecnet.com>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR.php';
require_once 'Console/Getopt.php';
$GLOBALS['_System_temp_files'] = array();
/**
* System offers cross platform compatible system functions
*
* Static functions for different operations. Should work under
* Unix and Windows. The names and usage has been taken from its respectively
* GNU commands. The functions will return (bool) false on error and will
* trigger the error with the PHP trigger_error() function (you can silence
* the error by prefixing a '@' sign after the function call, but this
* is not recommended practice. Instead use an error handler with
* {@link set_error_handler()}).
*
* Documentation on this class you can find in:
* http://pear.php.net/manual/
*
* Example usage:
* if (!@System::rm('-r file1 dir1')) {
* print "could not delete file1 or dir1";
* }
*
* In case you need to to pass file names with spaces,
* pass the params as an array:
*
* System::rm(array('-r', $file1, $dir1));
*
* @category pear
* @package System
* @author Tomas V.V. Cox <cox@idecnet.com>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
* @static
*/
class System
{
/**
* returns the commandline arguments of a function
*
* @param string $argv the commandline
* @param string $short_options the allowed option short-tags
* @param string $long_options the allowed option long-tags
* @return array the given options and there values
*/
public static function _parseArgs($argv, $short_options, $long_options = null)
{
if (!is_array($argv) && $argv !== null) {
/*
// Quote all items that are a short option
$av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
$offset = 0;
foreach ($av as $a) {
$b = trim($a[0]);
if ($b[0] == '"' || $b[0] == "'") {
continue;
}
$escape = escapeshellarg($b);
$pos = $a[1] + $offset;
$argv = substr_replace($argv, $escape, $pos, strlen($b));
$offset += 2;
}
*/
// Find all items, quoted or otherwise
preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
$argv = $av[1];
foreach ($av[2] as $k => $a) {
if (empty($a)) {
continue;
}
$argv[$k] = trim($a) ;
}
}
return Console_Getopt::getopt2($argv, $short_options, $long_options);
}
/**
* Output errors with PHP trigger_error(). You can silence the errors
* with prefixing a "@" sign to the function call: @System::mkdir(..);
*
* @param mixed $error a PEAR error or a string with the error message
* @return bool false
*/
protected static function raiseError($error)
{
if (PEAR::isError($error)) {
$error = $error->getMessage();
}
trigger_error($error, E_USER_WARNING);
return false;
}
/**
* Creates a nested array representing the structure of a directory
*
* System::_dirToStruct('dir1', 0) =>
* Array
* (
* [dirs] => Array
* (
* [0] => dir1
* )
*
* [files] => Array
* (
* [0] => dir1/file2
* [1] => dir1/file3
* )
* )
* @param string $sPath Name of the directory
* @param integer $maxinst max. deep of the lookup
* @param integer $aktinst starting deep of the lookup
* @param bool $silent if true, do not emit errors.
* @return array the structure of the dir
*/
protected static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
{
$struct = array('dirs' => array(), 'files' => array());
if (($dir = @opendir($sPath)) === false) {
if (!$silent) {
System::raiseError("Could not open dir $sPath");
}
return $struct; // XXX could not open error
}
$struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
$list = array();
while (false !== ($file = readdir($dir))) {
if ($file != '.' && $file != '..') {
$list[] = $file;
}
}
closedir($dir);
natsort($list);
if ($aktinst < $maxinst || $maxinst == 0) {
foreach ($list as $val) {
$path = $sPath . DIRECTORY_SEPARATOR . $val;
if (is_dir($path) && !is_link($path)) {
$tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent);
$struct = array_merge_recursive($struct, $tmp);
} else {
$struct['files'][] = $path;
}
}
}
return $struct;
}
/**
* Creates a nested array representing the structure of a directory and files
*
* @param array $files Array listing files and dirs
* @return array
* @static
* @see System::_dirToStruct()
*/
protected static function _multipleToStruct($files)
{
$struct = array('dirs' => array(), 'files' => array());
settype($files, 'array');
foreach ($files as $file) {
if (is_dir($file) && !is_link($file)) {
$tmp = System::_dirToStruct($file, 0);
$struct = array_merge_recursive($tmp, $struct);
} else {
if (!in_array($file, $struct['files'])) {
$struct['files'][] = $file;
}
}
}
return $struct;
}
/**
* The rm command for removing files.
* Supports multiple files and dirs and also recursive deletes
*
* @param string $args the arguments for rm
* @return mixed PEAR_Error or true for success
* @static
* @access public
*/
public static function rm($args)
{
$opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
if (PEAR::isError($opts)) {
return System::raiseError($opts);
}
foreach ($opts[0] as $opt) {
if ($opt[0] == 'r') {
$do_recursive = true;
}
}
$ret = true;
if (isset($do_recursive)) {
$struct = System::_multipleToStruct($opts[1]);
foreach ($struct['files'] as $file) {
if (!@unlink($file)) {
$ret = false;
}
}
rsort($struct['dirs']);
foreach ($struct['dirs'] as $dir) {
if (!@rmdir($dir)) {
$ret = false;
}
}
} else {
foreach ($opts[1] as $file) {
$delete = (is_dir($file)) ? 'rmdir' : 'unlink';
if (!@$delete($file)) {
$ret = false;
}
}
}
return $ret;
}
/**
* Make directories.
*
* The -p option will create parent directories
* @param string $args the name of the director(y|ies) to create
* @return bool True for success
*/
public static function mkDir($args)
{
$opts = System::_parseArgs($args, 'pm:');
if (PEAR::isError($opts)) {
return System::raiseError($opts);
}
$mode = 0777; // default mode
foreach ($opts[0] as $opt) {
if ($opt[0] == 'p') {
$create_parents = true;
} elseif ($opt[0] == 'm') {
// if the mode is clearly an octal number (starts with 0)
// convert it to decimal
if (strlen($opt[1]) && $opt[1][0] == '0') {
$opt[1] = octdec($opt[1]);
} else {
// convert to int
$opt[1] += 0;
}
$mode = $opt[1];
}
}
$ret = true;
if (isset($create_parents)) {
foreach ($opts[1] as $dir) {
$dirstack = array();
while ((!file_exists($dir) || !is_dir($dir)) &&
$dir != DIRECTORY_SEPARATOR) {
array_unshift($dirstack, $dir);
$dir = dirname($dir);
}
while ($newdir = array_shift($dirstack)) {
if (!is_writeable(dirname($newdir))) {
$ret = false;
break;
}
if (!mkdir($newdir, $mode)) {
$ret = false;
}
}
}
} else {
foreach($opts[1] as $dir) {
if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
$ret = false;
}
}
}
return $ret;
}
/**
* Concatenate files
*
* Usage:
* 1) $var = System::cat('sample.txt test.txt');
* 2) System::cat('sample.txt test.txt > final.txt');
* 3) System::cat('sample.txt test.txt >> final.txt');
*
* Note: as the class use fopen, urls should work also
*
* @param string $args the arguments
* @return boolean true on success
*/
public static function &cat($args)
{
$ret = null;
$files = array();
if (!is_array($args)) {
$args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
}
$count_args = count($args);
for ($i = 0; $i < $count_args; $i++) {
if ($args[$i] == '>') {
$mode = 'wb';
$outputfile = $args[$i+1];
break;
} elseif ($args[$i] == '>>') {
$mode = 'ab+';
$outputfile = $args[$i+1];
break;
} else {
$files[] = $args[$i];
}
}
$outputfd = false;
if (isset($mode)) {
if (!$outputfd = fopen($outputfile, $mode)) {
$err = System::raiseError("Could not open $outputfile");
return $err;
}
$ret = true;
}
foreach ($files as $file) {
if (!$fd = fopen($file, 'r')) {
System::raiseError("Could not open $file");
continue;
}
while ($cont = fread($fd, 2048)) {
if (is_resource($outputfd)) {
fwrite($outputfd, $cont);
} else {
$ret .= $cont;
}
}
fclose($fd);
}
if (is_resource($outputfd)) {
fclose($outputfd);
}
return $ret;
}
/**
* Creates temporary files or directories. This function will remove
* the created files when the scripts finish its execution.
*
* Usage:
* 1) $tempfile = System::mktemp("prefix");
* 2) $tempdir = System::mktemp("-d prefix");
* 3) $tempfile = System::mktemp();
* 4) $tempfile = System::mktemp("-t /var/tmp prefix");
*
* prefix -> The string that will be prepended to the temp name
* (defaults to "tmp").
* -d -> A temporary dir will be created instead of a file.
* -t -> The target dir where the temporary (file|dir) will be created. If
* this param is missing by default the env vars TMP on Windows or
* TMPDIR in Unix will be used. If these vars are also missing
* c:\windows\temp or /tmp will be used.
*
* @param string $args The arguments
* @return mixed the full path of the created (file|dir) or false
* @see System::tmpdir()
*/
public static function mktemp($args = null)
{
static $first_time = true;
$opts = System::_parseArgs($args, 't:d');
if (PEAR::isError($opts)) {
return System::raiseError($opts);
}
foreach ($opts[0] as $opt) {
if ($opt[0] == 'd') {
$tmp_is_dir = true;
} elseif ($opt[0] == 't') {
$tmpdir = $opt[1];
}
}
$prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
if (!isset($tmpdir)) {
$tmpdir = System::tmpdir();
}
if (!System::mkDir(array('-p', $tmpdir))) {
return false;
}
$tmp = tempnam($tmpdir, $prefix);
if (isset($tmp_is_dir)) {
unlink($tmp); // be careful possible race condition here
if (!mkdir($tmp, 0700)) {
return System::raiseError("Unable to create temporary directory $tmpdir");
}
}
$GLOBALS['_System_temp_files'][] = $tmp;
if (isset($tmp_is_dir)) {
//$GLOBALS['_System_temp_files'][] = dirname($tmp);
}
if ($first_time) {
PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
$first_time = false;
}
return $tmp;
}
/**
* Remove temporary files created my mkTemp. This function is executed
* at script shutdown time
*/
public static function _removeTmpFiles()
{
if (count($GLOBALS['_System_temp_files'])) {
$delete = $GLOBALS['_System_temp_files'];
array_unshift($delete, '-r');
System::rm($delete);
$GLOBALS['_System_temp_files'] = array();
}
}
/**
* Get the path of the temporal directory set in the system
* by looking in its environments variables.
* Note: php.ini-recommended removes the "E" from the variables_order setting,
* making unavaible the $_ENV array, that s why we do tests with _ENV
*
* @return string The temporary directory on the system
*/
public static function tmpdir()
{
if (OS_WINDOWS) {
if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
return $var;
}
if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
return $var;
}
if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) {
return $var;
}
if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
return $var;
}
return getenv('SystemRoot') . '\temp';
}
if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
return $var;
}
return realpath(function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '/tmp');
}
/**
* The "which" command (show the full path of a command)
*
* @param string $program The command to search for
* @param mixed $fallback Value to return if $program is not found
*
* @return mixed A string with the full path or false if not found
* @author Stig Bakken <ssb@php.net>
*/
public static function which($program, $fallback = false)
{
// enforce API
if (!is_string($program) || '' == $program) {
return $fallback;
}
// full path given
if (basename($program) != $program) {
$path_elements[] = dirname($program);
$program = basename($program);
} else {
$path = getenv('PATH');
if (!$path) {
$path = getenv('Path'); // some OSes are just stupid enough to do this
}
$path_elements = explode(PATH_SEPARATOR, $path);
}
if (OS_WINDOWS) {
$exe_suffixes = getenv('PATHEXT')
? explode(PATH_SEPARATOR, getenv('PATHEXT'))
: array('.exe','.bat','.cmd','.com');
// allow passing a command.exe param
if (strpos($program, '.') !== false) {
array_unshift($exe_suffixes, '');
}
} else {
$exe_suffixes = array('');
}
foreach ($exe_suffixes as $suff) {
foreach ($path_elements as $dir) {
$file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
// It's possible to run a .bat on Windows that is_executable
// would return false for. The is_executable check is meaningless...
if (OS_WINDOWS) {
if (file_exists($file)) {
return $file;
}
} else {
if (is_executable($file)) {
return $file;
}
}
}
}
return $fallback;
}
/**
* The "find" command
*
* Usage:
*
* System::find($dir);
* System::find("$dir -type d");
* System::find("$dir -type f");
* System::find("$dir -name *.php");
* System::find("$dir -name *.php -name *.htm*");
* System::find("$dir -maxdepth 1");
*
* Params implemented:
* $dir -> Start the search at this directory
* -type d -> return only directories
* -type f -> return only files
* -maxdepth <n> -> max depth of recursion
* -name <pattern> -> search pattern (bash style). Multiple -name param allowed
*
* @param mixed Either array or string with the command line
* @return array Array of found files
*/
public static function find($args)
{
if (!is_array($args)) {
$args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
}
$dir = realpath(array_shift($args));
if (!$dir) {
return array();
}
$patterns = array();
$depth = 0;
$do_files = $do_dirs = true;
$args_count = count($args);
for ($i = 0; $i < $args_count; $i++) {
switch ($args[$i]) {
case '-type':
if (in_array($args[$i+1], array('d', 'f'))) {
if ($args[$i+1] == 'd') {
$do_files = false;
} else {
$do_dirs = false;
}
}
$i++;
break;
case '-name':
$name = preg_quote($args[$i+1], '#');
// our magic characters ? and * have just been escaped,
// so now we change the escaped versions to PCRE operators
$name = strtr($name, array('\?' => '.', '\*' => '.*'));
$patterns[] = '('.$name.')';
$i++;
break;
case '-maxdepth':
$depth = $args[$i+1];
break;
}
}
$path = System::_dirToStruct($dir, $depth, 0, true);
if ($do_files && $do_dirs) {
$files = array_merge($path['files'], $path['dirs']);
} elseif ($do_dirs) {
$files = $path['dirs'];
} else {
$files = $path['files'];
}
if (count($patterns)) {
$dsq = preg_quote(DIRECTORY_SEPARATOR, '#');
$pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#';
$ret = array();
$files_count = count($files);
for ($i = 0; $i < $files_count; $i++) {
// only search in the part of the file below the current directory
$filepart = basename($files[$i]);
if (preg_match($pattern, $filepart)) {
$ret[] = $files[$i];
}
}
return $ret;
}
return $files;
}
}

View File

@@ -0,0 +1,27 @@
Copyright (c) 1997-2009,
Stig Bakken <ssb@php.net>,
Gregory Beaver <cellog@php.net>,
Helgi Þormar Þorbjörnsson <helgi@php.net>,
Tomas V.V.Cox <cox@idecnet.com>,
Martin Jansen <mj@php.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,456 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
/**
* PEAR_Exception
*
* PHP version 5
*
* @category PEAR
* @package PEAR_Exception
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR_Exception
* @since File available since Release 1.0.0
*/
/**
* Base PEAR_Exception Class
*
* 1) Features:
*
* - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
* - Definable triggers, shot when exceptions occur
* - Pretty and informative error messages
* - Added more context info available (like class, method or cause)
* - cause can be a PEAR_Exception or an array of mixed
* PEAR_Exceptions/PEAR_ErrorStack warnings
* - callbacks for specific exception classes and their children
*
* 2) Ideas:
*
* - Maybe a way to define a 'template' for the output
*
* 3) Inherited properties from PHP Exception Class:
*
* protected $message
* protected $code
* protected $line
* protected $file
* private $trace
*
* 4) Inherited methods from PHP Exception Class:
*
* __clone
* __construct
* getMessage
* getCode
* getFile
* getLine
* getTraceSafe
* getTraceSafeAsString
* __toString
*
* 5) Usage example
*
* <code>
* require_once 'PEAR/Exception.php';
*
* class Test {
* function foo() {
* throw new PEAR_Exception('Error Message', ERROR_CODE);
* }
* }
*
* function myLogger($pear_exception) {
* echo $pear_exception->getMessage();
* }
* // each time a exception is thrown the 'myLogger' will be called
* // (its use is completely optional)
* PEAR_Exception::addObserver('myLogger');
* $test = new Test;
* try {
* $test->foo();
* } catch (PEAR_Exception $e) {
* print $e;
* }
* </code>
*
* @category PEAR
* @package PEAR_Exception
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PEAR_Exception
* @since Class available since Release 1.0.0
*/
class PEAR_Exception extends Exception
{
const OBSERVER_PRINT = -2;
const OBSERVER_TRIGGER = -4;
const OBSERVER_DIE = -8;
protected $cause;
private static $_observers = array();
private static $_uniqueid = 0;
private $_trace;
/**
* Supported signatures:
* - PEAR_Exception(string $message);
* - PEAR_Exception(string $message, int $code);
* - PEAR_Exception(string $message, Exception $cause);
* - PEAR_Exception(string $message, Exception $cause, int $code);
* - PEAR_Exception(string $message, PEAR_Error $cause);
* - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
* - PEAR_Exception(string $message, array $causes);
* - PEAR_Exception(string $message, array $causes, int $code);
*
* @param string $message exception message
* @param int|Exception|PEAR_Error|array|null $p2 exception cause
* @param int|null $p3 exception code or null
*/
public function __construct($message, $p2 = null, $p3 = null)
{
if (is_int($p2)) {
$code = $p2;
$this->cause = null;
} elseif (is_object($p2) || is_array($p2)) {
// using is_object allows both Exception and PEAR_Error
if (is_object($p2) && !($p2 instanceof Exception)) {
if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) {
throw new PEAR_Exception(
'exception cause must be Exception, ' .
'array, or PEAR_Error'
);
}
}
$code = $p3;
if (is_array($p2) && isset($p2['message'])) {
// fix potential problem of passing in a single warning
$p2 = array($p2);
}
$this->cause = $p2;
} else {
$code = null;
$this->cause = null;
}
parent::__construct($message, (int) $code);
$this->signal();
}
/**
* Add an exception observer
*
* @param mixed $callback - A valid php callback, see php func is_callable()
* - A PEAR_Exception::OBSERVER_* constant
* - An array(const PEAR_Exception::OBSERVER_*,
* mixed $options)
* @param string $label The name of the observer. Use this if you want
* to remove it later with removeObserver()
*
* @return void
*/
public static function addObserver($callback, $label = 'default')
{
self::$_observers[$label] = $callback;
}
/**
* Remove an exception observer
*
* @param string $label Name of the observer
*
* @return void
*/
public static function removeObserver($label = 'default')
{
unset(self::$_observers[$label]);
}
/**
* Generate a unique ID for an observer
*
* @return int unique identifier for an observer
*/
public static function getUniqueId()
{
return self::$_uniqueid++;
}
/**
* Send a signal to all observers
*
* @return void
*/
protected function signal()
{
foreach (self::$_observers as $func) {
if (is_callable($func)) {
call_user_func($func, $this);
continue;
}
settype($func, 'array');
switch ($func[0]) {
case self::OBSERVER_PRINT :
$f = (isset($func[1])) ? $func[1] : '%s';
printf($f, $this->getMessage());
break;
case self::OBSERVER_TRIGGER :
$f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
trigger_error($this->getMessage(), $f);
break;
case self::OBSERVER_DIE :
$f = (isset($func[1])) ? $func[1] : '%s';
die(printf($f, $this->getMessage()));
break;
default:
trigger_error('invalid observer type', E_USER_WARNING);
}
}
}
/**
* Return specific error information that can be used for more detailed
* error messages or translation.
*
* This method may be overridden in child exception classes in order
* to add functionality not present in PEAR_Exception and is a placeholder
* to define API
*
* The returned array must be an associative array of parameter => value like so:
* <pre>
* array('name' => $name, 'context' => array(...))
* </pre>
*
* @return array
*/
public function getErrorData()
{
return array();
}
/**
* Returns the exception that caused this exception to be thrown
*
* @return Exception|array The context of the exception
*/
public function getCause()
{
return $this->cause;
}
/**
* Function must be public to call on caused exceptions
*
* @param array $causes Array that gets filled.
*
* @return void
*/
public function getCauseMessage(&$causes)
{
$trace = $this->getTraceSafe();
$cause = array('class' => get_class($this),
'message' => $this->message,
'file' => 'unknown',
'line' => 'unknown');
if (isset($trace[0])) {
if (isset($trace[0]['file'])) {
$cause['file'] = $trace[0]['file'];
$cause['line'] = $trace[0]['line'];
}
}
$causes[] = $cause;
if ($this->cause instanceof PEAR_Exception) {
$this->cause->getCauseMessage($causes);
} elseif ($this->cause instanceof Exception) {
$causes[] = array('class' => get_class($this->cause),
'message' => $this->cause->getMessage(),
'file' => $this->cause->getFile(),
'line' => $this->cause->getLine());
} elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) {
$causes[] = array('class' => get_class($this->cause),
'message' => $this->cause->getMessage(),
'file' => 'unknown',
'line' => 'unknown');
} elseif (is_array($this->cause)) {
foreach ($this->cause as $cause) {
if ($cause instanceof PEAR_Exception) {
$cause->getCauseMessage($causes);
} elseif ($cause instanceof Exception) {
$causes[] = array('class' => get_class($cause),
'message' => $cause->getMessage(),
'file' => $cause->getFile(),
'line' => $cause->getLine());
} elseif (class_exists('PEAR_Error')
&& $cause instanceof PEAR_Error
) {
$causes[] = array('class' => get_class($cause),
'message' => $cause->getMessage(),
'file' => 'unknown',
'line' => 'unknown');
} elseif (is_array($cause) && isset($cause['message'])) {
// PEAR_ErrorStack warning
$causes[] = array(
'class' => $cause['package'],
'message' => $cause['message'],
'file' => isset($cause['context']['file']) ?
$cause['context']['file'] :
'unknown',
'line' => isset($cause['context']['line']) ?
$cause['context']['line'] :
'unknown',
);
}
}
}
}
/**
* Build a backtrace and return it
*
* @return array Backtrace
*/
public function getTraceSafe()
{
if (!isset($this->_trace)) {
$this->_trace = $this->getTrace();
if (empty($this->_trace)) {
$backtrace = debug_backtrace();
$this->_trace = array($backtrace[count($backtrace)-1]);
}
}
return $this->_trace;
}
/**
* Gets the first class of the backtrace
*
* @return string Class name
*/
public function getErrorClass()
{
$trace = $this->getTraceSafe();
return $trace[0]['class'];
}
/**
* Gets the first method of the backtrace
*
* @return string Method/function name
*/
public function getErrorMethod()
{
$trace = $this->getTraceSafe();
return $trace[0]['function'];
}
/**
* Converts the exception to a string (HTML or plain text)
*
* @return string String representation
*
* @see toHtml()
* @see toText()
*/
public function __toString()
{
if (isset($_SERVER['REQUEST_URI'])) {
return $this->toHtml();
}
return $this->toText();
}
/**
* Generates a HTML representation of the exception
*
* @return string HTML code
*/
public function toHtml()
{
$trace = $this->getTraceSafe();
$causes = array();
$this->getCauseMessage($causes);
$html = '<table style="border: 1px" cellspacing="0">' . "\n";
foreach ($causes as $i => $cause) {
$html .= '<tr><td colspan="3" style="background: #ff9999">'
. str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
. htmlspecialchars($cause['message'])
. ' in <b>' . $cause['file'] . '</b> '
. 'on line <b>' . $cause['line'] . '</b>'
. "</td></tr>\n";
}
$html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n"
. '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>'
. '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>'
. '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n";
foreach ($trace as $k => $v) {
$html .= '<tr><td style="text-align: center;">' . $k . '</td>'
. '<td>';
if (!empty($v['class'])) {
$html .= $v['class'] . $v['type'];
}
$html .= $v['function'];
$args = array();
if (!empty($v['args'])) {
foreach ($v['args'] as $arg) {
if (is_null($arg)) {
$args[] = 'null';
} else if (is_array($arg)) {
$args[] = 'Array';
} else if (is_object($arg)) {
$args[] = 'Object('.get_class($arg).')';
} else if (is_bool($arg)) {
$args[] = $arg ? 'true' : 'false';
} else if (is_int($arg) || is_double($arg)) {
$args[] = $arg;
} else {
$arg = (string)$arg;
$str = htmlspecialchars(substr($arg, 0, 16));
if (strlen($arg) > 16) {
$str .= '&hellip;';
}
$args[] = "'" . $str . "'";
}
}
}
$html .= '(' . implode(', ', $args) . ')'
. '</td>'
. '<td>' . (isset($v['file']) ? $v['file'] : 'unknown')
. ':' . (isset($v['line']) ? $v['line'] : 'unknown')
. '</td></tr>' . "\n";
}
$html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>'
. '<td>{main}</td>'
. '<td>&nbsp;</td></tr>' . "\n"
. '</table>';
return $html;
}
/**
* Generates text representation of the exception and stack trace
*
* @return string
*/
public function toText()
{
$causes = array();
$this->getCauseMessage($causes);
$causeMsg = '';
foreach ($causes as $i => $cause) {
$causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
. $cause['message'] . ' in ' . $cause['file']
. ' on line ' . $cause['line'] . "\n";
}
return $causeMsg . $this->getTraceAsString();
}
}
?>

View File

@@ -0,0 +1,41 @@
{
"name": "pear/pear_exception",
"description": "The PEAR Exception base class.",
"type": "class",
"keywords": [
"exception"
],
"homepage": "https://github.com/pear/PEAR_Exception",
"license": "BSD-2-Clause",
"authors": [
{
"name": "Helgi Thormar",
"email": "dufuz@php.net"
},
{
"name": "Greg Beaver",
"email": "cellog@php.net"
}
],
"require": {
"php": ">=5.2.0"
},
"autoload": {
"classmap": ["PEAR/"]
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"include-path": [
"."
],
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR_Exception",
"source": "https://github.com/pear/PEAR_Exception"
},
"require-dev": {
"phpunit/phpunit": "<9"
}
}

View File

@@ -0,0 +1,60 @@
# yamllint disable rule:line-length
# yamllint disable rule:braces
name: Continuous Integration
on:
pull_request:
push:
branches:
- main
- master
jobs:
tests:
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
operating-system: ['ubuntu-latest']
php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
name: CI on ${{ matrix.operating-system }} with PHP ${{ matrix.php-version }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: composer:v2
coverage: none
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: composer-${{ runner.os }}-${{ matrix.php-version }}-${{ hashFiles('composer.*') }}-${{ matrix.composer-flags }}
restore-keys: |
composer-${{ runner.os }}-${{ matrix.php-version }}-${{ hashFiles('composer.*') }}-
composer-${{ runner.os }}-${{ matrix.php-version }}-
composer-${{ runner.os }}-
composer-
- name: Install dependencies
run: |
composer update --no-interaction --prefer-dist --no-progress ${{ matrix.composer-flags }}
- name: Run tests
run: |
vendor/bin/phpunit
- name: Lint code
run: |
find Spreadsheet/ -type f -name \*.php | xargs -n1 php -l

View File

@@ -0,0 +1,38 @@
name: Coding Standards
on:
pull_request:
push:
branches:
- main
- master
jobs:
coding-standards:
name: Coding Standards
runs-on: ubuntu-latest
env:
PHP_CS_FIXER_VERSION: v2.17.3
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
coverage: none
tools: php-cs-fixer:${{ env.PHP_CS_FIXER_VERSION }}
- name: Restore PHP-CS-Fixer cache
uses: actions/cache@v2
with:
path: .php_cs.cache
key: "php-cs-fixer"
restore-keys: "php-cs-fixer"
- name: Run PHP-CS-Fixer, version ${{ env.PHP_CS_FIXER_VERSION }}
run: |
php-cs-fixer fix --diff --diff-format=udiff --dry-run --verbose

View File

@@ -0,0 +1,7 @@
# composer related
composer.lock
composer.phar
vendor
# build logs
build

View File

@@ -0,0 +1,11 @@
<?php
return PhpCsFixer\Config::create()
->setRules([
'native_function_invocation' => null,
])
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__)
)
;

View File

@@ -0,0 +1,25 @@
language: php
php:
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
- 7.4
cache:
directories:
- $HOME/.composer/cache
- $HOME/.cache/cache
- build/cache
install:
- composer install --prefer-dist
- mkdir -p build/cache
script:
- php vendor/bin/phpunit --coverage-clover build/logs/clover.xml
- vendor/bin/php-cs-fixer --cache-file=build/cache/.php_cs.cache --diff --dry-run --stop-on-violation --verbose fix
after_success:
- travis_retry php vendor/bin/php-coveralls

View File

@@ -0,0 +1,166 @@
[![Build Status](https://travis-ci.org/pear/Spreadsheet_Excel_Writer.svg?branch=master)](https://travis-ci.org/pear/Spreadsheet_Excel_Writer)
[![Latest Stable Version](https://poser.pugx.org/pear/spreadsheet_excel_writer/v/stable)](https://packagist.org/packages/pear/spreadsheet_excel_writer)
[![Coverage Status](https://coveralls.io/repos/github/pear/Spreadsheet_Excel_Writer/badge.svg?branch=master)](https://coveralls.io/github/pear/Spreadsheet_Excel_Writer?branch=master)
# Spreadsheet_Excel_Writer
This package is [Spreadsheet_Excel_Writer](http://pear.php.net/package/Spreadsheet_Excel_Writer) and has been migrated from [svn.php.net](https://svn.php.net/repository/pear/packages/Spreadsheet_Excel_Writer).
Please report all new issues [via the PEAR bug tracker](http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Spreadsheet_Excel_Writer&order_by=ts1&direction=DESC&status=Open).
If this package is marked as unmaintained and you have fixes, please submit your pull requests and start discussion on the pear-qa mailing list.
# Installation
## Pear
To test, run
$ phpunit
To build, simply
$ pear package
To install from scratch
$ pear install package.xml
To upgrade
$ pear upgrade -f package.xml
## Composer
This package comes with support for Composer.
To install from Composer
$ composer require pear/spreadsheet_excel_writer
To install the latest development version
$ composer require pear/spreadsheet_excel_writer:dev-master
# Features
- writing Excel (.XLS) spreadsheets
- support: strings (with formatting for text and cells), formulas, images (BMP)
# Limitations
Library support only 2 types of format for writing XLS, also known as Binary Interchange File Format ([BIFF](https://www.openoffice.org/sc/excelfileformat.pdf)):
- BIFF5 (Excel 5.0 - Excel 95)
- BIFF8 (Excel 98 - Excel 2003)
**Some important limitations:**
| Limit | BIFF5 | BIFF8 |
| --- | --- | --- |
| Maximum number of rows | 16384 | 65535 |
| Maximum number of columns | 255 | 255 |
| Maximum data size of a record | 2080 bytes | 8224 bytes |
| Unicode support | CodePage based character encoding | UTF-16LE |
Explanation of formats and specifications you can find [here](https://www.loc.gov/preservation/digital/formats/fdd/fdd000510.shtml) (section "Useful references")
Correct output only guaranteed with `mbstring.func_overload = 0` otherwise, you should use workround `mb_internal_encoding('latin1');`
# Usage
## Basic usage
```php
use Spreadsheet_Excel_Writer;
$filePath = __DIR__ . '/output/out.xls';
$xls = new Spreadsheet_Excel_Writer($filePath);
// 8 = BIFF8
$xls->setVersion(8);
$sheet = $xls->addWorksheet('info');
// only available with BIFF8
$sheet->setInputEncoding('UTF-8');
$headers = [
'id',
'name',
'email',
'code',
'address'
];
$row = $col = 0;
foreach ($headers as $header) {
$sheet->write($row, $col, $header);
$col++;
}
for ($id = 1; $id < 100; $id++) {
$data = [
'id' => $id,
'name' => 'Name Surname',
'email' => 'mail@gmail.com',
'password' => 'cfcd208495d565ef66e7dff9f98764da',
'address' => '00000 North Tantau Avenue. Cupertino, CA 12345. (000) 1234567'
];
$sheet->writeRow($id, 0, $data);
}
$xls->close();
```
## Format usage
```php
$xls = new Spreadsheet_Excel_Writer();
$titleFormat = $xls->addFormat();
$titleFormat->setFontFamily('Helvetica');
$titleFormat->setBold();
$titleFormat->setSize(10);
$titleFormat->setColor('orange');
$titleFormat->setBorder(1);
$titleFormat->setBottom(2);
$titleFormat->setBottomColor(44);
$titleFormat->setAlign('center');
$sheet = $xls->addWorksheet('info');
$sheet->write(0, 0, 'Text 123', $titleFormat);
```
## Header usage (Sending HTTP header for download dialog)
```php
$xls = new Spreadsheet_Excel_Writer();
$xls->send('excel_'.date("Y-m-d__H:i:s").'.xls');
```
# Performance
**Platform:**
Intel(R) Core(TM) i5-4670 CPU @ 3.40GHz
PHP 7.4
**Test case:**
Write xls (BIFF8 format, UTF-8), by 5 cells (1x number, 4x string without format/styles, average line length = 120 char) in each row
**Estimated performance:**
| Number of rows | Time (seconds) | Peak memory usage (MB) |
| --- | --- | --- |
| 10000 | 0.2 | 4 |
| 20000 | 0.4 | 4 |
| 30000 | 0.6 | 6 |
| 40000 | 0.8 | 6 |
| 50000 | 1.0 | 8 |
| 65534 | 1.2 | 8 |
# Alternative solutions
- [PHPOffice/PhpSpreadsheet](https://github.com/PHPOffice/PhpSpreadsheet)
File formats supported: https://phpspreadsheet.readthedocs.io/en/latest/
- [box/spout](https://github.com/box/spout)
File formats supported: https://opensource.box.com/spout/

View File

@@ -0,0 +1,105 @@
<?php
/*
* Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
*
* PERL Spreadsheet::WriteExcel module.
*
* The author of the Spreadsheet::WriteExcel module is John McNamara
* <jmcnamara@cpan.org>
*
* I _DO_ maintain this code, and John McNamara has nothing to do with the
* porting of this code to PHP. Any questions directly related to this
* class library should be directed to me.
*
* License Information:
*
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
if (!class_exists('Spreadsheet_Excel_Writer_Workbook')) {
require_once 'Spreadsheet/Excel/Writer/Workbook.php';
}
/**
* Class for writing Excel Spreadsheets. This class should change COMPLETELY.
*
* @author Xavier Noguer <xnoguer@rezebra.com>
* @category FileFormats
* @package Spreadsheet_Excel_Writer
*/
class Spreadsheet_Excel_Writer extends Spreadsheet_Excel_Writer_Workbook
{
/**
* The constructor. It just creates a Workbook
*
* @param string $filename The optional filename for the Workbook.
* @return Spreadsheet_Excel_Writer_Workbook The Workbook created
*/
public function __construct($filename = '')
{
$this->_filename = $filename;
parent::__construct($filename);
}
/**
* Send HTTP headers for the Excel file.
*
* @param string $filename The filename to use for HTTP headers
* @access public
*/
public function send($filename)
{
$filename = addslashes($filename);
header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0,pre-check=0");
header("Pragma: public");
}
/**
* Utility function for writing formulas
* Converts a cell's coordinates to the A1 format.
*
* @access public
* @static
* @param integer $row Row for the cell to convert (0-indexed).
* @param integer $col Column for the cell to convert (0-indexed).
* @return string The cell identifier in A1 format
*/
function rowcolToCell($row, $col)
{
if ($col > 255) { //maximum column value exceeded
return new PEAR_Error("Maximum column value exceeded: $col");
}
$int = (int)($col / 26);
$frac = $col % 26;
$chr1 = '';
if ($int > 0) {
$chr1 = chr(ord('A') + $int - 1);
}
$chr2 = chr(ord('A') + $frac);
$row++;
return $chr1 . $chr2 . $row;
}
}

View File

@@ -0,0 +1,268 @@
<?php
/*
* Module written/ported by Xavier Noguer <xnoguer@php.net>
*
* The majority of this is _NOT_ my code. I simply ported it from the
* PERL Spreadsheet::WriteExcel module.
*
* The author of the Spreadsheet::WriteExcel module is John McNamara
* <jmcnamara@cpan.org>
*
* I _DO_ maintain this code, and John McNamara has nothing to do with the
* porting of this code to PHP. Any questions directly related to this
* class library should be directed to me.
*
* License Information:
*
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@php.net
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
if (!class_exists('PEAR')) {
require_once 'PEAR.php';
}
/**
* Class for writing Excel BIFF records.
*
* From "MICROSOFT EXCEL BINARY FILE FORMAT" by Mark O'Brien (Microsoft Corporation):
*
* BIFF (BInary File Format) is the file format in which Excel documents are
* saved on disk. A BIFF file is a complete description of an Excel document.
* BIFF files consist of sequences of variable-length records. There are many
* different types of BIFF records. For example, one record type describes a
* formula entered into a cell; one describes the size and location of a
* window into a document; another describes a picture format.
*
* @author Xavier Noguer <xnoguer@php.net>
* @category FileFormats
* @package Spreadsheet_Excel_Writer
*/
class Spreadsheet_Excel_Writer_BIFFwriter extends PEAR
{
/**
* The BIFF/Excel version (5).
* @var integer
*/
public $_BIFF_version = 0x0500;
/**
* The byte order of this architecture. 0 => little endian, 1 => big endian
* @var integer
*/
public $_byte_order;
/**
* The string containing the data of the BIFF stream
* @var string
*/
public $_data;
/**
* The size of the data in bytes. Should be the same as strlen($this->_data)
* @var integer
*/
public $_datasize;
/**
* The maximun length for a BIFF record. See _addContinue()
* @var integer
* @see _addContinue()
*/
public $_limit;
/**
* The temporary dir for storing the OLE file
* @var string
*/
public $_tmp_dir;
/**
* The temporary file for storing the OLE file
* @var string
*/
public $_tmp_file;
/**
* Constructor
*
* @access public
*/
public function __construct()
{
$this->_byte_order = '';
$this->_data = '';
$this->_datasize = 0;
$this->_limit = 2080;
$this->_tmp_dir = '';
// Set the byte order
$this->_setByteOrder();
}
/**
* Determine the byte order and store it as class data to avoid
* recalculating it for each call to new().
*
* @access private
*/
protected function _setByteOrder()
{
// Check if "pack" gives the required IEEE 64bit float
$teststr = pack("d", 1.2345);
$number = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F);
if ($number == $teststr) {
$byte_order = 0; // Little Endian
} elseif ($number == strrev($teststr)){
$byte_order = 1; // Big Endian
} else {
// Give up. I'll fix this in a later version.
return $this->raiseError("Required floating point format ".
"not supported on this platform.");
}
$this->_byte_order = $byte_order;
}
/**
* General storage public function
*
* @param string $data binary data to prepend
* @access private
*/
protected function _prepend($data)
{
if (strlen($data) > $this->_limit) {
$data = $this->_addContinue($data);
}
$this->_data = $data.$this->_data;
$this->_datasize += strlen($data);
}
/**
* General storage public function
*
* @param string $data binary data to append
* @access private
*/
protected function _append($data)
{
if (strlen($data) > $this->_limit) {
$data = $this->_addContinue($data);
}
$this->_data .= $data;
$this->_datasize += strlen($data);
}
/**
* Writes Excel BOF record to indicate the beginning of a stream or
* sub-stream in the BIFF file.
*
* @param integer $type Type of BIFF file to write: 0x0005 Workbook,
* 0x0010 Worksheet.
* @access private
*/
protected function _storeBof($type)
{
$record = 0x0809; // Record identifier
// According to the SDK $build and $year should be set to zero.
// However, this throws a warning in Excel 5. So, use magic numbers.
if ($this->_BIFF_version == 0x0500) {
$length = 0x0008;
$unknown = '';
$build = 0x096C;
$year = 0x07C9;
} elseif ($this->_BIFF_version == 0x0600) {
$length = 0x0010;
$unknown = pack("VV", 0x00000041, 0x00000006); //unknown last 8 bytes for BIFF8
$build = 0x0DBB;
$year = 0x07CC;
}
$version = $this->_BIFF_version;
$header = pack("vv", $record, $length);
$data = pack("vvvv", $version, $type, $build, $year);
$this->_prepend($header . $data . $unknown);
}
/**
* Writes Excel EOF record to indicate the end of a BIFF stream.
*
* @access private
*/
protected function _storeEof()
{
$record = 0x000A; // Record identifier
$length = 0x0000; // Number of bytes to follow
$header = pack("vv", $record, $length);
$this->_append($header);
}
/**
* Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In
* Excel 97 the limit is 8228 bytes. Records that are longer than these limits
* must be split up into CONTINUE blocks.
*
* This public function takes a long BIFF record and inserts CONTINUE records as
* necessary.
*
* @param string $data The original binary data to be written
* @return string A very convenient string of continue blocks
* @access private
*/
protected function _addContinue($data)
{
$limit = $this->_limit;
$record = 0x003C; // Record identifier
// The first 2080/8224 bytes remain intact. However, we have to change
// the length field of the record.
$tmp = substr($data, 0, 2).pack("v", $limit-4).substr($data, 4, $limit - 4);
$header = pack("vv", $record, $limit); // Headers for continue records
// Retrieve chunks of 2080/8224 bytes +4 for the header.
$data_length = strlen($data);
for ($i = $limit; $i < ($data_length - $limit); $i += $limit) {
$tmp .= $header;
$tmp .= substr($data, $i, $limit);
}
// Retrieve the last chunk of data
$header = pack("vv", $record, strlen($data) - $i);
$tmp .= $header;
$tmp .= substr($data, $i, strlen($data) - $i);
return $tmp;
}
/**
* Sets the temp dir used for storing the OLE file
*
* @access public
* @param string $dir The dir to be used as temp dir
* @return true if given dir is valid, false otherwise
*/
public function setTempDir($dir)
{
if (is_dir($dir)) {
$this->_tmp_dir = $dir;
return true;
}
return false;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,228 @@
<?php
/*
* Module written by Herman Kuiper <herman@ozuzo.net>
*
* License Information:
*
* Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets
* Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//require_once('PEAR.php');
// Possible operator types
/*
FIXME: change prefixes
*/
define("OP_BETWEEN", 0x00);
define("OP_NOTBETWEEN", 0x01);
define("OP_EQUAL", 0x02);
define("OP_NOTEQUAL", 0x03);
define("OP_GT", 0x04);
define("OP_LT", 0x05);
define("OP_GTE", 0x06);
define("OP_LTE", 0x07);
/**
* Baseclass for generating Excel DV records (validations)
*
* @author Herman Kuiper
* @category FileFormats
* @package Spreadsheet_Excel_Writer
*/
class Spreadsheet_Excel_Writer_Validator
{
public $_type;
public $_style;
public $_fixedList;
public $_blank;
public $_incell;
public $_showprompt;
public $_showerror;
public $_title_prompt;
public $_descr_prompt;
public $_title_error;
public $_descr_error;
public $_operator;
public $_formula1;
public $_formula2;
/**
* The parser from the workbook. Used to parse validation formulas also
* @var Spreadsheet_Excel_Writer_Parser
*/
public $_parser;
public function __construct($parser)
{
$this->_parser = $parser;
$this->_type = 0x01; // FIXME: add method for setting datatype
$this->_style = 0x00;
$this->_fixedList = false;
$this->_blank = false;
$this->_incell = false;
$this->_showprompt = false;
$this->_showerror = true;
$this->_title_prompt = "\x00";
$this->_descr_prompt = "\x00";
$this->_title_error = "\x00";
$this->_descr_error = "\x00";
$this->_operator = 0x00; // default is equal
$this->_formula1 = '';
$this->_formula2 = '';
}
public function setPrompt($promptTitle = "\x00", $promptDescription = "\x00", $showPrompt = true)
{
$this->_showprompt = $showPrompt;
$this->_title_prompt = $promptTitle;
$this->_descr_prompt = $promptDescription;
}
public function setError($errorTitle = "\x00", $errorDescription = "\x00", $showError = true)
{
$this->_showerror = $showError;
$this->_title_error = $errorTitle;
$this->_descr_error = $errorDescription;
}
public function allowBlank()
{
$this->_blank = true;
}
public function onInvalidStop()
{
$this->_style = 0x00;
}
public function onInvalidWarn()
{
$this->_style = 0x01;
}
public function onInvalidInfo()
{
$this->_style = 0x02;
}
public function setFormula1($formula)
{
// Parse the formula using the parser in Parser.php
$error = $this->_parser->parse($formula);
if (PEAR::isError($error)) {
return $this->_formula1;
}
$this->_formula1 = $this->_parser->toReversePolish();
if (PEAR::isError($this->_formula1)) {
return $this->_formula1;
}
return true;
}
public function setFormula2($formula)
{
// Parse the formula using the parser in Parser.php
$error = $this->_parser->parse($formula);
if (PEAR::isError($error)) {
return $this->_formula2;
}
$this->_formula2 = $this->_parser->toReversePolish();
if (PEAR::isError($this->_formula2)) {
return $this->_formula2;
}
return true;
}
protected function _getOptions()
{
$options = $this->_type;
$options |= $this->_style << 3;
if ($this->_fixedList) {
$options |= 0x80;
}
if ($this->_blank) {
$options |= 0x100;
}
if (!$this->_incell) {
$options |= 0x200;
}
if ($this->_showprompt) {
$options |= 0x40000;
}
if ($this->_showerror) {
$options |= 0x80000;
}
$options |= $this->_operator << 20;
return $options;
}
protected function _getData()
{
$title_prompt_len = strlen($this->_title_prompt);
$descr_prompt_len = strlen($this->_descr_prompt);
$title_error_len = strlen($this->_title_error);
$descr_error_len = strlen($this->_descr_error);
$formula1_size = strlen($this->_formula1);
$formula2_size = strlen($this->_formula2);
$data = pack("V", $this->_getOptions());
$data .= pack("vC", $title_prompt_len, 0x00) . $this->_title_prompt;
$data .= pack("vC", $title_error_len, 0x00) . $this->_title_error;
$data .= pack("vC", $descr_prompt_len, 0x00) . $this->_descr_prompt;
$data .= pack("vC", $descr_error_len, 0x00) . $this->_descr_error;
$data .= pack("vv", $formula1_size, 0x0000) . $this->_formula1;
$data .= pack("vv", $formula2_size, 0x0000) . $this->_formula2;
return $data;
}
}
/*class Spreadsheet_Excel_Writer_Validation_List extends Spreadsheet_Excel_Writer_Validation
{
public function Spreadsheet_Excel_Writer_Validation_list()
{
parent::Spreadsheet_Excel_Writer_Validation();
$this->_type = 0x03;
}
public function setList($source, $incell = true)
{
$this->_incell = $incell;
$this->_fixedList = true;
$source = implode("\x00", $source);
$this->_formula1 = pack("CCC", 0x17, strlen($source), 0x0c) . $source;
}
public function setRow($row, $col1, $col2, $incell = true)
{
$this->_incell = $incell;
//$this->_formula1 = ...;
}
public function setCol($col, $row1, $row2, $incell = true)
{
$this->_incell = $incell;
//$this->_formula1 = ...;
}
}*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
{
"name": "pear/spreadsheet_excel_writer",
"type": "library",
"description": "Allows writing of Excel spreadsheets without the need for COM objects. Supports formulas, images (BMP) and all kinds of formatting for text and cells.",
"license": "LGPL-2.1-or-later",
"authors": [
{
"name": "Carsten Schmitz",
"email": "cschmitz@limesurvey.org",
"role": "Lead"
},
{
"name": "Xavier Noguer",
"email": "xnoguer@php.net",
"role": "Lead"
},
{
"name": "Franck Lefevre",
"email": "progi1984@gmail.com",
"role": "Developer"
},
{
"name": "Mika Tuupola",
"email": "tuupola@appelsiini.net",
"role": "Developer"
},
{
"name": "Alexey Kopytko",
"email": "alexey@kopytko.com",
"role": "Lead"
}
],
"require": {
"php": ">=5.6",
"pear/ole": ">=1.0.0RC4",
"pear/pear-core-minimal": "^1.10"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2",
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": ">=5 <10",
"sanmai/phpunit-legacy-adapter": "^6 || ^8"
},
"autoload": {
"psr-0": {
"Spreadsheet": ""
}
},
"autoload-dev": {
"psr-0": {
"Test": "test"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"include-path": [
"./"
],
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Spreadsheet_Excel_Writer",
"source": "https://github.com/pear/Spreadsheet_Excel_Writer"
}
}

View File

@@ -0,0 +1,357 @@
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
<name>Spreadsheet_Excel_Writer</name>
<channel>pear.php.net</channel>
<summary>Package for generating Excel spreadsheets</summary>
<description>Spreadsheet_Excel_Writer was born as a porting of the Spreadsheet::WriteExcel Perl module to PHP.
It allows writing of Excel spreadsheets without the need for COM objects.
It supports formulas, images (BMP) and all kinds of formatting for text and cells.
It currently supports the BIFF5 format (Excel 5.0), so functionality appeared in the latest Excel versions is not yet available.</description>
<lead>
<name>Carsten Schmitz</name>
<user>cschmitz</user>
<email>cschmitz@limesurvey.org</email>
<active>yes</active>
</lead>
<lead>
<name>Xavier Noguer</name>
<user>xnoguer</user>
<email>xnoguer@php.net</email>
<active>no</active>
</lead>
<lead>
<name>Alexey Kopytko</name>
<user>sanmai</user>
<email>alexey@kopytko.com</email>
<active>yes</active>
</lead>
<developer>
<name>Franck Lefevre</name>
<user>progi1984</user>
<email>progi1984@gmail.com</email>
<active>yes</active>
</developer>
<developer>
<name>Mika Tuupola</name>
<user>tuupola</user>
<email>tuupola@appelsiini.net</email>
<active>no</active>
</developer>
<date>2017-05-24</date>
<time>11:31:45</time>
<version>
<release>0.9.4</release>
<api>0.9.4</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
QA release. Comes with support for newer PHP versions. Fixed irritating "pass by reference" errors.
</notes>
<contents>
<dir name="/">
<dir name="Spreadsheet">
<dir name="Excel">
<dir name="Writer">
<file name="BIFFwriter.php" role="php" />
<file name="Format.php" role="php" />
<file name="Parser.php" role="php" />
<file name="Validator.php" role="php" />
<file name="Workbook.php" role="php" />
<file name="Worksheet.php" role="php" />
</dir>
<file name="Writer.php" role="php" />
</dir>
</dir>
</dir>
</contents>
<dependencies>
<required>
<php>
<min>5.3.3</min>
</php>
<pearinstaller>
<min>1.4.0b1</min>
</pearinstaller>
<package>
<name>OLE</name>
<channel>pear.php.net</channel>
<min>1.0.0RC2</min>
</package>
</required>
</dependencies>
<phprelease />
<changelog>
<release>
<version>
<release>0.9.3</release>
<api>0.9.3</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2012-01-26</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
QA release
Bug #18590 Impossible to work from IIS7
Bug #18024 deprecated line 180, 186 with php 5.3.2
Bug #16025 MERGEDCELLS record split by CONTINUE record
Bug #17766 Patch: Avoid deprecated split
Bug #17572 Temporary files are not removed
Bug #16938 open_basedir check is wrong in Spreadsheet_Excel_Writer_Worksheet::_initialize
Bug #14585 open_basedir workaround doesn&apos;t work
Bug #12362 named worksheets &amp; utf-8
Bug #14515 writeUrl only uses writeString, never writeNumber
Bug #14281 Using a row &gt; 16,384 reports error
Request #13486 Set the worksheet direction to right-to-left (RTL)
Bug #12720 Notice thrown when using setColumn (undefined colFirst and colLast)
Bug #12053 With SetVersion(8) setting bottom border color to 0 gives cross borders (!)
</notes>
</release>
<release>
<version>
<release>0.2</release>
<api>0.2</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2003-03-17</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
-added several formatting methods: setTextRotation(), setStrikeOut(),
setOutLine(), setShadow(), setScript().
-fixed bug in Workbook::sheets() (Bjoern Schotte).
-fixed range for references in formulas (Edward).
-added support for external references in formulas.
-added support for comparisons in formulas.
-added support for strings in formulas.
</notes>
</release>
<release>
<version>
<release>0.3</release>
<api>0.3</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2003-05-02</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
New features:
-added support for row ranges (JT Hughes)
-added method method Format::setUnLocked() (Ajit Dixit)
-added Worksheet::writeRow() and Worksheet::writeCol()
Bug fixes:
-fixed problem with unparenthesized expresions in formulas (Brent Laminack)
-fixed problems with non ISO-8859-1 characters (KUBO Atsuhiro)
-fixed swapping of columns in formulas (JT Hughes)
-fixed assorted bugs in tokenizing formulas (JT Hughes)
-fixed Worksheet::activate() (JT Hughes)
</notes>
</release>
<release>
<version>
<release>0.4</release>
<api>0.4</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2003-08-21</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
New features:
-using OLE package (&gt;= 0.3) to generate files bigger than 7MB
-changed setFgColor() and setBgColor()&apos;s behavior to something more intuitive.
Bug fixes:
-fixed bug #25133, lowercase cell references (jkwiat03 at hotmail dot com)
-fixed Bug #23730, worksheet names containing spaces in formulas (Robin Ericsson)
-fixed Bug #24147, formulas ended in &apos;0&apos; (paul at classical dot com)
-fixed swapping of arguments in variable arguments functions (JT Hughes)
</notes>
</release>
<release>
<version>
<release>0.5</release>
<api>0.5</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2003-10-01</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
New features:
-added rowcolToCell() utility method for easy writing of formula&apos;s cell references (JT Hughes).
-added Worksheet::setOutline() method (Herman Kuiper)
-added Format::setFontFamily() method (Donnie Miller)
Bug fixes:
-fixed bug #21, cyrillic characters in sheet references (arhip at goldentele dot com)
</notes>
</release>
<release>
<version>
<release>0.6</release>
<api>0.6</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2003-11-15</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
New features:
- allow semicolon as argument separator (Axel Pratzner)
- added experimental Excel97 generation. You can test it with setVersion():
Beware! this method will be deprecated in a future release (when
Excel97 becomes the default). It is only available for testing
purposes. Use it at your own risk.
- strings longer than 255 bytes are now available using the experimental
Excel97 generation. But not all Excel97 features are available yet!
Bug fixes:
- Fixed bug #225, error in writeUrl() (jamesn at tocquigny dot com)
- Fixed bug #59, retval undefined for writeRow() (Bertrand)
</notes>
</release>
<release>
<version>
<release>0.7</release>
<api>0.7</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2004-02-27</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
New features:
- allow setting temp dir other than default using setTempDir() (using OLE 5.0 for this).
- added setMerge() for merging (only for experimental Excel97 generation)
- added setCountry() method.
- added setLocked() method.
Bug fixes:
- Fixed bug #415, typo in BIFF8 code (papercrane at reversefold dot com)
</notes>
</release>
<release>
<version>
<release>0.8</release>
<api>0.8</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2004-06-22</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
New features:
- added hideScreenGridlines() (Paul Osman)
Bug fixes:
- Fixed SST table (long strings) (Bernd Jaenichen)
- Fixed bug #1218, SST table (boucher dot stephane at free dot fr)
- Fixed bug #781, insertBitmap ignores row height
- Fixed bug #578, setVPageBreaks doesn&apos;t handle multiple value arrays (natel at tocquigny dot com)
</notes>
</release>
<release>
<version>
<release>0.9.0</release>
<api>0.9.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2005-11-21</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
New features:
- adding new methods Format::setVAlign() and Format::setHAlign()
- adding support for uncapitalized functions in formulas (ej: &quot;=sum(B27:B31)&quot;)
- adding support for different charsets with method Worksheet::setInputEncoding()
- adding support for sheetnames longer than 31 chars when using setVersion(8).
Bug fixes:
- Fixed Bug #1796, wrong regular expression in _writeUrlInternal
- Fixed Bug #2363, wrong export filename with spaces
- Fixed Bug #2425, Error using writeFormula with Now() and TODAY()
- Fixed Bug #2876, German Umlauts destroy sheet references
- Fixed Bug #1706, Formulas refer to other Worksheets with &quot;spezial&quot; names don&apos;t work
- Fixed Bug #2748, setMargins(), setHeader() and setFooter() work in excel but not in openoffice.
- Fixed Bug #5698, preg_replace in _writeUrlInternal
- Fixed Bug #2823, Inpropper results from writeUrl() method
</notes>
</release>
<release>
<version>
<release>0.9.1</release>
<api>0.9.1</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2006-09-26</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
</notes>
</release>
<release>
<version>
<release>0.9.2</release>
<api>0.9.2</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<date>2009-11-28</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
</notes>
</release>
<release>
<version>
<release>0.9.3</release>
<api>0.9.3</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2012-01-26</date>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
<notes>
QA release
Bug #18590 Impossible to work from IIS7
Bug #18024 deprecated line 180, 186 with php 5.3.2
Bug #16025 MERGEDCELLS record split by CONTINUE record
Bug #17766 Patch: Avoid deprecated split
Bug #17572 Temporary files are not removed
Bug #16938 open_basedir check is wrong in Spreadsheet_Excel_Writer_Worksheet::_initialize
Bug #14585 open_basedir workaround doesn&apos;t work
Bug #12362 named worksheets &amp; utf-8
Bug #14515 writeUrl only uses writeString, never writeNumber
Bug #14281 Using a row &gt; 16,384 reports error
Request #13486 Set the worksheet direction to right-to-left (RTL)
Bug #12720 Notice thrown when using setColumn (undefined colFirst and colLast)
Bug #12053 With SetVersion(8) setting bottom border color to 0 gives cross borders (!)
</notes>
</release>
</changelog>
</package>

View File

@@ -0,0 +1,28 @@
<phpunit bootstrap="vendor/autoload.php"
cacheTokens="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false">
<testsuites>
<testsuite name="Test Suite">
<directory>test/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">Spreadsheet/</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-clover" target="build/logs/clover.xml"/>
<log type="coverage-text" target="php://stdout"/>
</logging>
</phpunit>

View File

@@ -0,0 +1,81 @@
<?php
/**
* @author stev leibelt <artodeto@bazzline.net>
* @since 2016-01-17
*/
class Test_Spreadsheet_Excel_Writer_WorkbookTest extends Test_Spreadsheet_Excel_WriterTestCase
{
public static function doSetUpBeforeClass()
{
// Preload constants from OLE
@class_exists(OLE::class);
}
public function testSetVersion()
{
$workbook = $this->getNewWorkbook();
$before = get_object_vars($workbook);
$workbook->setVersion(1);
$this->assertEquals($before, get_object_vars($workbook), "Version 1 should not change internal state");
$workbook->setVersion(8);
$this->assertNotEquals($before, get_object_vars($workbook), "Version 8 should change internal state");
return $workbook;
}
/**
* @depends testSetVersion
*/
public function testWriteSingleCell(Spreadsheet_Excel_Writer $workbook)
{
$sheet = $workbook->addWorksheet("Example");
$sheet->write(0, 0, "Example");
$this->assertSameAsInFixture('example.xls', $workbook);
}
public function testWriteWithFormat()
{
$workbook = $this->getNewWorkbook();
$workbook->setVersion(8);
$format = $workbook->addFormat();
$format->setFontFamily('Helvetica');
$format->setSize(16);
$format->setVAlign('vcenter');
$format->setBorder(1);
$sheet = $workbook->addWorksheet('Example report');
$sheet->setInputEncoding('utf-8');
$sheet->setColumn(0, 10, 35);
$sheet->writeString(0, 0, "Test string", $format);
$sheet->setRow(0, 40);
$sheet->writeString(1, 0, "こんにちわ");
$this->assertSameAsInFixture('with_format.xls', $workbook);
}
public function testWithDefaultVersion()
{
$workbook = $this->getNewWorkbook();
$sheet = $workbook->addWorksheet("Example");
for ($i = 0; $i < 10; $i++) {
for ($j = 0; $j < 10; $j++) {
$sheet->write($i, $j, "Row $i $j");
}
}
$this->assertSameAsInFixture('example2.xls', $workbook);
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* @author stev leibelt <artodeto@bazzline.net>
* @since 2016-01-17
*/
class Test_Spreadsheet_Excel_WriterTestCase extends \LegacyPHPUnit\TestCase
{
const FIXTURES_PATH = 'test/fixture/';
/**
* @param string $filename
* @return Spreadsheet_Excel_Writer
*/
protected function getNewWorkbook($filename = '')
{
// we're writing to the standard output by defaulr
return new Spreadsheet_Excel_Writer($filename);
}
protected function assertSameAsInFixture($filename, Spreadsheet_Excel_Writer $workbook)
{
$this->assertEmpty($workbook->_filename, "Testing with fixtures works only for standard output");
// we have to fix timestamp for fixtures to work
$workbook->_timestamp = 1000000000; // somewhere in 2001
ob_start();
$workbook->close();
$data = ob_get_clean();
$fullPath = self::FIXTURES_PATH.$filename;
if ($this->shouldUpdateFixtures()) {
file_put_contents($fullPath, $data);
}
if (!is_file($fullPath)) {
$this->fail("Fixture $filename not found");
}
// TODO: should we save data for future analysis?
//file_put_contents("{$fullPath}.work", $data);
$this->assertEquals(file_get_contents($fullPath), $data, "Output differs for $filename");
}
/**
* We should update golden files
*/
private function shouldUpdateFixtures()
{
return isset($_SERVER['GOLDEN']);
}
}