Add script 'get-openssl-version.sh'.
This commit is contained in:
9
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/.gitignore
vendored
Normal file
9
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
*.iml
|
||||
.idea/
|
||||
composer.phar
|
||||
vendor/
|
||||
composer.lock
|
||||
apigen.phar
|
||||
docs/
|
||||
nbproject/
|
||||
.phpunit.result.cache
|
19
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/LICENSE
vendored
Normal file
19
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015 Andreas Gohr <gohr@cosmocode.de>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
68
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/README.md
vendored
Normal file
68
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/README.md
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
PHPArchive - Pure PHP ZIP and TAR handling
|
||||
==========================================
|
||||
|
||||
This library allows to handle new ZIP and TAR archives without the need for any special PHP extensions (gz and bzip are
|
||||
needed for compression). It can create new files or extract existing ones.
|
||||
|
||||
To keep things simple, the modification (adding or removing files) of existing archives is not supported.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Use composer:
|
||||
|
||||
```php composer.phar require splitbrain/php-archive```
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The usage for the Zip and Tar classes are basically the same. Here are some
|
||||
examples for working with TARs to get you started.
|
||||
|
||||
Check the [API docs](https://splitbrain.github.io/php-archive/) for more
|
||||
info.
|
||||
|
||||
|
||||
```php
|
||||
require_once 'vendor/autoload.php';
|
||||
use splitbrain\PHPArchive\Tar;
|
||||
|
||||
// To list the contents of an existing TAR archive, open() it and use
|
||||
// contents() on it:
|
||||
$tar = new Tar();
|
||||
$tar->open('myfile.tgz');
|
||||
$toc = $tar->contents();
|
||||
print_r($toc); // array of FileInfo objects
|
||||
|
||||
// To extract the contents of an existing TAR archive, open() it and use
|
||||
// extract() on it:
|
||||
$tar = new Tar();
|
||||
$tar->open('myfile.tgz');
|
||||
$tar->extract('/tmp');
|
||||
|
||||
// To create a new TAR archive directly on the filesystem (low memory
|
||||
// requirements), create() it:
|
||||
$tar = new Tar();
|
||||
$tar->create('myfile.tgz');
|
||||
$tar->addFile(...);
|
||||
$tar->addData(...);
|
||||
...
|
||||
$tar->close();
|
||||
|
||||
// To create a TAR archive directly in memory, create() it, add*()
|
||||
// files and then either save() or getArchive() it:
|
||||
$tar = new Tar();
|
||||
$tar->setCompression(9, Archive::COMPRESS_BZIP);
|
||||
$tar->create();
|
||||
$tar->addFile(...);
|
||||
$tar->addData(...);
|
||||
...
|
||||
$tar->save('myfile.tbz'); // compresses and saves it
|
||||
echo $tar->getArchive(); // compresses and returns it
|
||||
```
|
||||
|
||||
Differences between Tar and Zip: Tars are compressed as a whole, while Zips compress each file individually. Therefore
|
||||
you can call ```setCompression``` before each ```addFile()``` and ```addData()``` function call.
|
||||
|
||||
The FileInfo class can be used to specify additional info like ownership or permissions when adding a file to
|
||||
an archive.
|
42
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/composer.json
vendored
Normal file
42
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/composer.json
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "splitbrain/php-archive",
|
||||
"description": "Pure-PHP implementation to read and write TAR and ZIP archives",
|
||||
"keywords": ["zip", "tar", "archive", "unpack", "extract", "unzip"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andreas Gohr",
|
||||
"email": "andi@splitbrain.org"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
|
||||
"require": {
|
||||
"php": ">=7.0"
|
||||
},
|
||||
|
||||
"suggest": {
|
||||
"ext-iconv": "Used for proper filename encode handling",
|
||||
"ext-mbstring": "Can be used alternatively for handling filename encoding",
|
||||
"ext-bz2": "For bz2 compression",
|
||||
"ext-zlib": "For zlib compression"
|
||||
},
|
||||
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"ext-zip": "*",
|
||||
"ext-bz2": "*"
|
||||
},
|
||||
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"splitbrain\\PHPArchive\\": "src"
|
||||
}
|
||||
},
|
||||
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"splitbrain\\PHPArchive\\": "tests"
|
||||
}
|
||||
}
|
||||
}
|
21
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/phpunit.xml
vendored
Normal file
21
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/phpunit.xml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false">
|
||||
<testsuites>
|
||||
<testsuite name="Test Suite">
|
||||
<directory suffix=".php">./tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="false">
|
||||
<directory suffix=".php">src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
135
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/Archive.php
vendored
Normal file
135
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/Archive.php
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\PHPArchive;
|
||||
|
||||
abstract class Archive
|
||||
{
|
||||
|
||||
const COMPRESS_AUTO = -1;
|
||||
const COMPRESS_NONE = 0;
|
||||
const COMPRESS_GZIP = 1;
|
||||
const COMPRESS_BZIP = 2;
|
||||
|
||||
/** @var callable */
|
||||
protected $callback;
|
||||
|
||||
/**
|
||||
* Set the compression level and type
|
||||
*
|
||||
* @param int $level Compression level (0 to 9)
|
||||
* @param int $type Type of compression to use (use COMPRESS_* constants)
|
||||
* @throws ArchiveIllegalCompressionException
|
||||
*/
|
||||
abstract public function setCompression($level = 9, $type = Archive::COMPRESS_AUTO);
|
||||
|
||||
/**
|
||||
* Open an existing archive file for reading
|
||||
*
|
||||
* @param string $file
|
||||
* @throws ArchiveIOException
|
||||
*/
|
||||
abstract public function open($file);
|
||||
|
||||
/**
|
||||
* Read the contents of an archive
|
||||
*
|
||||
* This function lists the files stored in the archive, and returns an indexed array of FileInfo objects
|
||||
*
|
||||
* The archive is closed afer reading the contents, because rewinding is not possible in bzip2 streams.
|
||||
* Reopen the file with open() again if you want to do additional operations
|
||||
*
|
||||
* @return FileInfo[]
|
||||
*/
|
||||
abstract public function contents();
|
||||
|
||||
/**
|
||||
* Extract an existing archive
|
||||
*
|
||||
* The $strip parameter allows you to strip a certain number of path components from the filenames
|
||||
* found in the archive file, similar to the --strip-components feature of GNU tar. This is triggered when
|
||||
* an integer is passed as $strip.
|
||||
* Alternatively a fixed string prefix may be passed in $strip. If the filename matches this prefix,
|
||||
* the prefix will be stripped. It is recommended to give prefixes with a trailing slash.
|
||||
*
|
||||
* By default this will extract all files found in the archive. You can restrict the output using the $include
|
||||
* and $exclude parameter. Both expect a full regular expression (including delimiters and modifiers). If
|
||||
* $include is set, only files that match this expression will be extracted. Files that match the $exclude
|
||||
* expression will never be extracted. Both parameters can be used in combination. Expressions are matched against
|
||||
* stripped filenames as described above.
|
||||
*
|
||||
* The archive is closed afterwards. Reopen the file with open() again if you want to do additional operations
|
||||
*
|
||||
* @param string $outdir the target directory for extracting
|
||||
* @param int|string $strip either the number of path components or a fixed prefix to strip
|
||||
* @param string $exclude a regular expression of files to exclude
|
||||
* @param string $include a regular expression of files to include
|
||||
* @throws ArchiveIOException
|
||||
* @return array
|
||||
*/
|
||||
abstract public function extract($outdir, $strip = '', $exclude = '', $include = '');
|
||||
|
||||
/**
|
||||
* Create a new archive file
|
||||
*
|
||||
* If $file is empty, the archive file will be created in memory
|
||||
*
|
||||
* @param string $file
|
||||
*/
|
||||
abstract public function create($file = '');
|
||||
|
||||
/**
|
||||
* Add a file to the current archive using an existing file in the filesystem
|
||||
*
|
||||
* @param string $file path to the original file
|
||||
* @param string|FileInfo $fileinfo either the name to us in archive (string) or a FileInfo oject with all meta data, empty to take from original
|
||||
* @throws ArchiveIOException
|
||||
*/
|
||||
abstract public function addFile($file, $fileinfo = '');
|
||||
|
||||
/**
|
||||
* Add a file to the current archive using the given $data as content
|
||||
*
|
||||
* @param string|FileInfo $fileinfo either the name to us in archive (string) or a FileInfo oject with all meta data
|
||||
* @param string $data binary content of the file to add
|
||||
* @throws ArchiveIOException
|
||||
*/
|
||||
abstract public function addData($fileinfo, $data);
|
||||
|
||||
/**
|
||||
* Close the archive, close all file handles
|
||||
*
|
||||
* After a call to this function no more data can be added to the archive, for
|
||||
* read access no reading is allowed anymore
|
||||
*/
|
||||
abstract public function close();
|
||||
|
||||
/**
|
||||
* Returns the created in-memory archive data
|
||||
*
|
||||
* This implicitly calls close() on the Archive
|
||||
*/
|
||||
abstract public function getArchive();
|
||||
|
||||
/**
|
||||
* Save the created in-memory archive data
|
||||
*
|
||||
* Note: It is more memory effective to specify the filename in the create() function and
|
||||
* let the library work on the new file directly.
|
||||
*
|
||||
* @param string $file
|
||||
*/
|
||||
abstract public function save($file);
|
||||
|
||||
/**
|
||||
* Set a callback function to be called whenever a file is added or extracted.
|
||||
*
|
||||
* The callback is called with a FileInfo object as parameter. You can use this to show progress
|
||||
* info during an operation.
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function setCallback($callback)
|
||||
{
|
||||
$this->callback = $callback;
|
||||
}
|
||||
}
|
10
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/ArchiveCorruptedException.php
vendored
Normal file
10
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/ArchiveCorruptedException.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\PHPArchive;
|
||||
|
||||
/**
|
||||
* The archive is unreadable
|
||||
*/
|
||||
class ArchiveCorruptedException extends \Exception
|
||||
{
|
||||
}
|
10
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/ArchiveIOException.php
vendored
Normal file
10
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/ArchiveIOException.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\PHPArchive;
|
||||
|
||||
/**
|
||||
* Read/Write Errors
|
||||
*/
|
||||
class ArchiveIOException extends \Exception
|
||||
{
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\PHPArchive;
|
||||
|
||||
/**
|
||||
* Bad or unsupported compression settings requested
|
||||
*/
|
||||
class ArchiveIllegalCompressionException extends \Exception
|
||||
{
|
||||
}
|
358
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/FileInfo.php
vendored
Normal file
358
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/FileInfo.php
vendored
Normal file
@ -0,0 +1,358 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\PHPArchive;
|
||||
|
||||
/**
|
||||
* Class FileInfo
|
||||
*
|
||||
* stores meta data about a file in an Archive
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @package splitbrain\PHPArchive
|
||||
* @license MIT
|
||||
*/
|
||||
class FileInfo
|
||||
{
|
||||
|
||||
protected $isdir = false;
|
||||
protected $path = '';
|
||||
protected $size = 0;
|
||||
protected $csize = 0;
|
||||
protected $mtime = 0;
|
||||
protected $mode = 0664;
|
||||
protected $owner = '';
|
||||
protected $group = '';
|
||||
protected $uid = 0;
|
||||
protected $gid = 0;
|
||||
protected $comment = '';
|
||||
|
||||
/**
|
||||
* initialize dynamic defaults
|
||||
*
|
||||
* @param string $path The path of the file, can also be set later through setPath()
|
||||
*/
|
||||
public function __construct($path = '')
|
||||
{
|
||||
$this->mtime = time();
|
||||
$this->setPath($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle calls to deprecated methods
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
if($name === 'match') {
|
||||
trigger_error('FileInfo::match() is deprecated, use FileInfo::matchExpression() instead.', E_USER_NOTICE);
|
||||
return call_user_func_array([$this, $name], $arguments);
|
||||
}
|
||||
|
||||
trigger_error('Call to undefined method FileInfo::'.$name.'()', E_USER_ERROR);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to build FileInfo from existing file or directory
|
||||
*
|
||||
* @param string $path path to a file on the local file system
|
||||
* @param string $as optional path to use inside the archive
|
||||
* @throws FileInfoException
|
||||
* @return FileInfo
|
||||
*/
|
||||
public static function fromPath($path, $as = '')
|
||||
{
|
||||
clearstatcache(false, $path);
|
||||
|
||||
if (!file_exists($path)) {
|
||||
throw new FileInfoException("$path does not exist");
|
||||
}
|
||||
|
||||
$stat = stat($path);
|
||||
$file = new FileInfo();
|
||||
|
||||
$file->setPath($path);
|
||||
$file->setIsdir(is_dir($path));
|
||||
$file->setMode(fileperms($path));
|
||||
$file->setOwner(fileowner($path));
|
||||
$file->setGroup(filegroup($path));
|
||||
$file->setSize(filesize($path));
|
||||
$file->setUid($stat['uid']);
|
||||
$file->setGid($stat['gid']);
|
||||
$file->setMtime($stat['mtime']);
|
||||
|
||||
if ($as) {
|
||||
$file->setPath($as);
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int the filesize. always 0 for directories
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
if($this->isdir) return 0;
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $size
|
||||
*/
|
||||
public function setSize($size)
|
||||
{
|
||||
$this->size = $size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCompressedSize()
|
||||
{
|
||||
return $this->csize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $csize
|
||||
*/
|
||||
public function setCompressedSize($csize)
|
||||
{
|
||||
$this->csize = $csize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getMtime()
|
||||
{
|
||||
return $this->mtime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $mtime
|
||||
*/
|
||||
public function setMtime($mtime)
|
||||
{
|
||||
$this->mtime = $mtime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getGid()
|
||||
{
|
||||
return $this->gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $gid
|
||||
*/
|
||||
public function setGid($gid)
|
||||
{
|
||||
$this->gid = $gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getUid()
|
||||
{
|
||||
return $this->uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
*/
|
||||
public function setUid($uid)
|
||||
{
|
||||
$this->uid = $uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getComment()
|
||||
{
|
||||
return $this->comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $comment
|
||||
*/
|
||||
public function setComment($comment)
|
||||
{
|
||||
$this->comment = $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getGroup()
|
||||
{
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $group
|
||||
*/
|
||||
public function setGroup($group)
|
||||
{
|
||||
$this->group = $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsdir()
|
||||
{
|
||||
return $this->isdir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $isdir
|
||||
*/
|
||||
public function setIsdir($isdir)
|
||||
{
|
||||
// default mode for directories
|
||||
if ($isdir && $this->mode === 0664) {
|
||||
$this->mode = 0775;
|
||||
}
|
||||
$this->isdir = $isdir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getMode()
|
||||
{
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $mode
|
||||
*/
|
||||
public function setMode($mode)
|
||||
{
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOwner()
|
||||
{
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $owner
|
||||
*/
|
||||
public function setOwner($owner)
|
||||
{
|
||||
$this->owner = $owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPath()
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*/
|
||||
public function setPath($path)
|
||||
{
|
||||
$this->path = $this->cleanPath($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up a path and removes relative parts, also strips leading slashes
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
protected function cleanPath($path)
|
||||
{
|
||||
$path = str_replace('\\', '/', $path);
|
||||
$path = explode('/', $path);
|
||||
$newpath = array();
|
||||
foreach ($path as $p) {
|
||||
if ($p === '' || $p === '.') {
|
||||
continue;
|
||||
}
|
||||
if ($p === '..') {
|
||||
array_pop($newpath);
|
||||
continue;
|
||||
}
|
||||
array_push($newpath, $p);
|
||||
}
|
||||
return trim(implode('/', $newpath), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip given prefix or number of path segments from the filename
|
||||
*
|
||||
* The $strip parameter allows you to strip a certain number of path components from the filenames
|
||||
* found in the tar file, similar to the --strip-components feature of GNU tar. This is triggered when
|
||||
* an integer is passed as $strip.
|
||||
* Alternatively a fixed string prefix may be passed in $strip. If the filename matches this prefix,
|
||||
* the prefix will be stripped. It is recommended to give prefixes with a trailing slash.
|
||||
*
|
||||
* @param int|string $strip
|
||||
*/
|
||||
public function strip($strip)
|
||||
{
|
||||
$filename = $this->getPath();
|
||||
$striplen = strlen($strip);
|
||||
if (is_int($strip)) {
|
||||
// if $strip is an integer we strip this many path components
|
||||
$parts = explode('/', $filename);
|
||||
if (!$this->getIsdir()) {
|
||||
$base = array_pop($parts); // keep filename itself
|
||||
} else {
|
||||
$base = '';
|
||||
}
|
||||
$filename = join('/', array_slice($parts, $strip));
|
||||
if ($base) {
|
||||
$filename .= "/$base";
|
||||
}
|
||||
} else {
|
||||
// if strip is a string, we strip a prefix here
|
||||
if (substr($filename, 0, $striplen) == $strip) {
|
||||
$filename = substr($filename, $striplen);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setPath($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the file match the given include and exclude expressions?
|
||||
*
|
||||
* Exclude rules take precedence over include rules
|
||||
*
|
||||
* @param string $include Regular expression of files to include
|
||||
* @param string $exclude Regular expression of files to exclude
|
||||
* @return bool
|
||||
*/
|
||||
public function matchExpression($include = '', $exclude = '')
|
||||
{
|
||||
$extract = true;
|
||||
if ($include && !preg_match($include, $this->getPath())) {
|
||||
$extract = false;
|
||||
}
|
||||
if ($exclude && preg_match($exclude, $this->getPath())) {
|
||||
$extract = false;
|
||||
}
|
||||
|
||||
return $extract;
|
||||
}
|
||||
}
|
||||
|
10
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/FileInfoException.php
vendored
Normal file
10
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/FileInfoException.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\PHPArchive;
|
||||
|
||||
/**
|
||||
* File meta data problems
|
||||
*/
|
||||
class FileInfoException extends \Exception
|
||||
{
|
||||
}
|
716
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/Tar.php
vendored
Normal file
716
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/Tar.php
vendored
Normal file
@ -0,0 +1,716 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\PHPArchive;
|
||||
|
||||
/**
|
||||
* Class Tar
|
||||
*
|
||||
* Creates or extracts Tar archives. Supports gz and bzip compression
|
||||
*
|
||||
* Long pathnames (>100 chars) are supported in POSIX ustar and GNU longlink formats.
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @package splitbrain\PHPArchive
|
||||
* @license MIT
|
||||
*/
|
||||
class Tar extends Archive
|
||||
{
|
||||
|
||||
protected $file = '';
|
||||
protected $comptype = Archive::COMPRESS_AUTO;
|
||||
protected $complevel = 9;
|
||||
protected $fh;
|
||||
protected $memory = '';
|
||||
protected $closed = true;
|
||||
protected $writeaccess = false;
|
||||
|
||||
/**
|
||||
* Sets the compression to use
|
||||
*
|
||||
* @param int $level Compression level (0 to 9)
|
||||
* @param int $type Type of compression to use (use COMPRESS_* constants)
|
||||
* @throws ArchiveIllegalCompressionException
|
||||
*/
|
||||
public function setCompression($level = 9, $type = Archive::COMPRESS_AUTO)
|
||||
{
|
||||
$this->compressioncheck($type);
|
||||
if ($level < -1 || $level > 9) {
|
||||
throw new ArchiveIllegalCompressionException('Compression level should be between -1 and 9');
|
||||
}
|
||||
$this->comptype = $type;
|
||||
$this->complevel = $level;
|
||||
if($level == 0) $this->comptype = Archive::COMPRESS_NONE;
|
||||
if($type == Archive::COMPRESS_NONE) $this->complevel = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an existing TAR file for reading
|
||||
*
|
||||
* @param string $file
|
||||
* @throws ArchiveIOException
|
||||
* @throws ArchiveIllegalCompressionException
|
||||
*/
|
||||
public function open($file)
|
||||
{
|
||||
$this->file = $file;
|
||||
|
||||
// update compression to mach file
|
||||
if ($this->comptype == Tar::COMPRESS_AUTO) {
|
||||
$this->setCompression($this->complevel, $this->filetype($file));
|
||||
}
|
||||
|
||||
// open file handles
|
||||
if ($this->comptype === Archive::COMPRESS_GZIP) {
|
||||
$this->fh = @gzopen($this->file, 'rb');
|
||||
} elseif ($this->comptype === Archive::COMPRESS_BZIP) {
|
||||
$this->fh = @bzopen($this->file, 'r');
|
||||
} else {
|
||||
$this->fh = @fopen($this->file, 'rb');
|
||||
}
|
||||
|
||||
if (!$this->fh) {
|
||||
throw new ArchiveIOException('Could not open file for reading: '.$this->file);
|
||||
}
|
||||
$this->closed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the contents of a TAR archive
|
||||
*
|
||||
* This function lists the files stored in the archive
|
||||
*
|
||||
* The archive is closed afer reading the contents, because rewinding is not possible in bzip2 streams.
|
||||
* Reopen the file with open() again if you want to do additional operations
|
||||
*
|
||||
* @throws ArchiveIOException
|
||||
* @throws ArchiveCorruptedException
|
||||
* @returns FileInfo[]
|
||||
*/
|
||||
public function contents()
|
||||
{
|
||||
$result = array();
|
||||
|
||||
foreach ($this->yieldContents() as $fileinfo) {
|
||||
$result[] = $fileinfo;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the contents of a TAR archive and return each entry using yield
|
||||
* for memory efficiency.
|
||||
*
|
||||
* @see contents()
|
||||
* @throws ArchiveIOException
|
||||
* @throws ArchiveCorruptedException
|
||||
* @returns FileInfo[]
|
||||
*/
|
||||
public function yieldContents()
|
||||
{
|
||||
if ($this->closed || !$this->file) {
|
||||
throw new ArchiveIOException('Can not read from a closed archive');
|
||||
}
|
||||
|
||||
while ($read = $this->readbytes(512)) {
|
||||
$header = $this->parseHeader($read);
|
||||
if (!is_array($header)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->skipbytes(ceil($header['size'] / 512) * 512);
|
||||
yield $this->header2fileinfo($header);
|
||||
}
|
||||
|
||||
$this->close();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract an existing TAR archive
|
||||
*
|
||||
* The $strip parameter allows you to strip a certain number of path components from the filenames
|
||||
* found in the tar file, similar to the --strip-components feature of GNU tar. This is triggered when
|
||||
* an integer is passed as $strip.
|
||||
* Alternatively a fixed string prefix may be passed in $strip. If the filename matches this prefix,
|
||||
* the prefix will be stripped. It is recommended to give prefixes with a trailing slash.
|
||||
*
|
||||
* By default this will extract all files found in the archive. You can restrict the output using the $include
|
||||
* and $exclude parameter. Both expect a full regular expression (including delimiters and modifiers). If
|
||||
* $include is set only files that match this expression will be extracted. Files that match the $exclude
|
||||
* expression will never be extracted. Both parameters can be used in combination. Expressions are matched against
|
||||
* stripped filenames as described above.
|
||||
*
|
||||
* The archive is closed afer reading the contents, because rewinding is not possible in bzip2 streams.
|
||||
* Reopen the file with open() again if you want to do additional operations
|
||||
*
|
||||
* @param string $outdir the target directory for extracting
|
||||
* @param int|string $strip either the number of path components or a fixed prefix to strip
|
||||
* @param string $exclude a regular expression of files to exclude
|
||||
* @param string $include a regular expression of files to include
|
||||
* @throws ArchiveIOException
|
||||
* @throws ArchiveCorruptedException
|
||||
* @return FileInfo[]
|
||||
*/
|
||||
public function extract($outdir, $strip = '', $exclude = '', $include = '')
|
||||
{
|
||||
if ($this->closed || !$this->file) {
|
||||
throw new ArchiveIOException('Can not read from a closed archive');
|
||||
}
|
||||
|
||||
$outdir = rtrim($outdir, '/');
|
||||
@mkdir($outdir, 0777, true);
|
||||
if (!is_dir($outdir)) {
|
||||
throw new ArchiveIOException("Could not create directory '$outdir'");
|
||||
}
|
||||
|
||||
$extracted = array();
|
||||
while ($dat = $this->readbytes(512)) {
|
||||
// read the file header
|
||||
$header = $this->parseHeader($dat);
|
||||
if (!is_array($header)) {
|
||||
continue;
|
||||
}
|
||||
$fileinfo = $this->header2fileinfo($header);
|
||||
|
||||
// apply strip rules
|
||||
$fileinfo->strip($strip);
|
||||
|
||||
// skip unwanted files
|
||||
if (!strlen($fileinfo->getPath()) || !$fileinfo->matchExpression($include, $exclude)) {
|
||||
$this->skipbytes(ceil($header['size'] / 512) * 512);
|
||||
continue;
|
||||
}
|
||||
|
||||
// create output directory
|
||||
$output = $outdir.'/'.$fileinfo->getPath();
|
||||
$directory = ($fileinfo->getIsdir()) ? $output : dirname($output);
|
||||
if (!file_exists($directory)) {
|
||||
mkdir($directory, 0777, true);
|
||||
}
|
||||
|
||||
// extract data
|
||||
if (!$fileinfo->getIsdir()) {
|
||||
$fp = @fopen($output, "wb");
|
||||
if (!$fp) {
|
||||
throw new ArchiveIOException('Could not open file for writing: '.$output);
|
||||
}
|
||||
|
||||
$size = floor($header['size'] / 512);
|
||||
for ($i = 0; $i < $size; $i++) {
|
||||
fwrite($fp, $this->readbytes(512), 512);
|
||||
}
|
||||
if (($header['size'] % 512) != 0) {
|
||||
fwrite($fp, $this->readbytes(512), $header['size'] % 512);
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
@touch($output, $fileinfo->getMtime());
|
||||
@chmod($output, $fileinfo->getMode());
|
||||
} else {
|
||||
$this->skipbytes(ceil($header['size'] / 512) * 512); // the size is usually 0 for directories
|
||||
}
|
||||
|
||||
if(is_callable($this->callback)) {
|
||||
call_user_func($this->callback, $fileinfo);
|
||||
}
|
||||
$extracted[] = $fileinfo;
|
||||
}
|
||||
|
||||
$this->close();
|
||||
return $extracted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TAR file
|
||||
*
|
||||
* If $file is empty, the tar file will be created in memory
|
||||
*
|
||||
* @param string $file
|
||||
* @throws ArchiveIOException
|
||||
* @throws ArchiveIllegalCompressionException
|
||||
*/
|
||||
public function create($file = '')
|
||||
{
|
||||
$this->file = $file;
|
||||
$this->memory = '';
|
||||
$this->fh = 0;
|
||||
|
||||
if ($this->file) {
|
||||
// determine compression
|
||||
if ($this->comptype == Archive::COMPRESS_AUTO) {
|
||||
$this->setCompression($this->complevel, $this->filetype($file));
|
||||
}
|
||||
|
||||
if ($this->comptype === Archive::COMPRESS_GZIP) {
|
||||
$this->fh = @gzopen($this->file, 'wb'.$this->complevel);
|
||||
} elseif ($this->comptype === Archive::COMPRESS_BZIP) {
|
||||
$this->fh = @bzopen($this->file, 'w');
|
||||
} else {
|
||||
$this->fh = @fopen($this->file, 'wb');
|
||||
}
|
||||
|
||||
if (!$this->fh) {
|
||||
throw new ArchiveIOException('Could not open file for writing: '.$this->file);
|
||||
}
|
||||
}
|
||||
$this->writeaccess = true;
|
||||
$this->closed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a file to the current TAR archive using an existing file in the filesystem
|
||||
*
|
||||
* @param string $file path to the original file
|
||||
* @param string|FileInfo $fileinfo either the name to us in archive (string) or a FileInfo oject with all meta data, empty to take from original
|
||||
* @throws ArchiveCorruptedException when the file changes while reading it, the archive will be corrupt and should be deleted
|
||||
* @throws ArchiveIOException there was trouble reading the given file, it was not added
|
||||
* @throws FileInfoException trouble reading file info, it was not added
|
||||
*/
|
||||
public function addFile($file, $fileinfo = '')
|
||||
{
|
||||
if (is_string($fileinfo)) {
|
||||
$fileinfo = FileInfo::fromPath($file, $fileinfo);
|
||||
}
|
||||
|
||||
if ($this->closed) {
|
||||
throw new ArchiveIOException('Archive has been closed, files can no longer be added');
|
||||
}
|
||||
|
||||
// create file header
|
||||
$this->writeFileHeader($fileinfo);
|
||||
|
||||
// write data, but only if we have data to write.
|
||||
// note: on Windows fopen() on a directory will fail, so we prevent
|
||||
// errors on Windows by testing if we have data to write.
|
||||
if (!$fileinfo->getIsdir() && $fileinfo->getSize() > 0) {
|
||||
$read = 0;
|
||||
$fp = @fopen($file, 'rb');
|
||||
if (!$fp) {
|
||||
throw new ArchiveIOException('Could not open file for reading: ' . $file);
|
||||
}
|
||||
while (!feof($fp)) {
|
||||
$data = fread($fp, 512);
|
||||
$read += strlen($data);
|
||||
if ($data === false) {
|
||||
break;
|
||||
}
|
||||
if ($data === '') {
|
||||
break;
|
||||
}
|
||||
$packed = pack("a512", $data);
|
||||
$this->writebytes($packed);
|
||||
}
|
||||
fclose($fp);
|
||||
|
||||
if ($read != $fileinfo->getSize()) {
|
||||
$this->close();
|
||||
throw new ArchiveCorruptedException("The size of $file changed while reading, archive corrupted. read $read expected ".$fileinfo->getSize());
|
||||
}
|
||||
}
|
||||
|
||||
if(is_callable($this->callback)) {
|
||||
call_user_func($this->callback, $fileinfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a file to the current TAR archive using the given $data as content
|
||||
*
|
||||
* @param string|FileInfo $fileinfo either the name to us in archive (string) or a FileInfo oject with all meta data
|
||||
* @param string $data binary content of the file to add
|
||||
* @throws ArchiveIOException
|
||||
*/
|
||||
public function addData($fileinfo, $data)
|
||||
{
|
||||
if (is_string($fileinfo)) {
|
||||
$fileinfo = new FileInfo($fileinfo);
|
||||
}
|
||||
|
||||
if ($this->closed) {
|
||||
throw new ArchiveIOException('Archive has been closed, files can no longer be added');
|
||||
}
|
||||
|
||||
$len = strlen($data);
|
||||
$fileinfo->setSize($len);
|
||||
$this->writeFileHeader($fileinfo);
|
||||
|
||||
for ($s = 0; $s < $len; $s += 512) {
|
||||
$this->writebytes(pack("a512", substr($data, $s, 512)));
|
||||
}
|
||||
|
||||
if (is_callable($this->callback)) {
|
||||
call_user_func($this->callback, $fileinfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the closing footer to the archive if in write mode, close all file handles
|
||||
*
|
||||
* After a call to this function no more data can be added to the archive, for
|
||||
* read access no reading is allowed anymore
|
||||
*
|
||||
* "Physically, an archive consists of a series of file entries terminated by an end-of-archive entry, which
|
||||
* consists of two 512 blocks of zero bytes"
|
||||
*
|
||||
* @link http://www.gnu.org/software/tar/manual/html_chapter/tar_8.html#SEC134
|
||||
* @throws ArchiveIOException
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if ($this->closed) {
|
||||
return;
|
||||
} // we did this already
|
||||
|
||||
// write footer
|
||||
if ($this->writeaccess) {
|
||||
$this->writebytes(pack("a512", ""));
|
||||
$this->writebytes(pack("a512", ""));
|
||||
}
|
||||
|
||||
// close file handles
|
||||
if ($this->file) {
|
||||
if ($this->comptype === Archive::COMPRESS_GZIP) {
|
||||
gzclose($this->fh);
|
||||
} elseif ($this->comptype === Archive::COMPRESS_BZIP) {
|
||||
bzclose($this->fh);
|
||||
} else {
|
||||
fclose($this->fh);
|
||||
}
|
||||
|
||||
$this->file = '';
|
||||
$this->fh = 0;
|
||||
}
|
||||
|
||||
$this->writeaccess = false;
|
||||
$this->closed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the created in-memory archive data
|
||||
*
|
||||
* This implicitly calls close() on the Archive
|
||||
* @throws ArchiveIOException
|
||||
*/
|
||||
public function getArchive()
|
||||
{
|
||||
$this->close();
|
||||
|
||||
if ($this->comptype === Archive::COMPRESS_AUTO) {
|
||||
$this->comptype = Archive::COMPRESS_NONE;
|
||||
}
|
||||
|
||||
if ($this->comptype === Archive::COMPRESS_GZIP) {
|
||||
return gzencode($this->memory, $this->complevel);
|
||||
}
|
||||
if ($this->comptype === Archive::COMPRESS_BZIP) {
|
||||
return bzcompress($this->memory);
|
||||
}
|
||||
return $this->memory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the created in-memory archive data
|
||||
*
|
||||
* Note: It more memory effective to specify the filename in the create() function and
|
||||
* let the library work on the new file directly.
|
||||
*
|
||||
* @param string $file
|
||||
* @throws ArchiveIOException
|
||||
* @throws ArchiveIllegalCompressionException
|
||||
*/
|
||||
public function save($file)
|
||||
{
|
||||
if ($this->comptype === Archive::COMPRESS_AUTO) {
|
||||
$this->setCompression($this->complevel, $this->filetype($file));
|
||||
}
|
||||
|
||||
if (!@file_put_contents($file, $this->getArchive())) {
|
||||
throw new ArchiveIOException('Could not write to file: '.$file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from the open file pointer
|
||||
*
|
||||
* @param int $length bytes to read
|
||||
* @return string
|
||||
*/
|
||||
protected function readbytes($length)
|
||||
{
|
||||
if ($this->comptype === Archive::COMPRESS_GZIP) {
|
||||
return @gzread($this->fh, $length);
|
||||
} elseif ($this->comptype === Archive::COMPRESS_BZIP) {
|
||||
return @bzread($this->fh, $length);
|
||||
} else {
|
||||
return @fread($this->fh, $length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to the open filepointer or memory
|
||||
*
|
||||
* @param string $data
|
||||
* @throws ArchiveIOException
|
||||
* @return int number of bytes written
|
||||
*/
|
||||
protected function writebytes($data)
|
||||
{
|
||||
if (!$this->file) {
|
||||
$this->memory .= $data;
|
||||
$written = strlen($data);
|
||||
} elseif ($this->comptype === Archive::COMPRESS_GZIP) {
|
||||
$written = @gzwrite($this->fh, $data);
|
||||
} elseif ($this->comptype === Archive::COMPRESS_BZIP) {
|
||||
$written = @bzwrite($this->fh, $data);
|
||||
} else {
|
||||
$written = @fwrite($this->fh, $data);
|
||||
}
|
||||
if ($written === false) {
|
||||
throw new ArchiveIOException('Failed to write to archive stream');
|
||||
}
|
||||
return $written;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip forward in the open file pointer
|
||||
*
|
||||
* This is basically a wrapper around seek() (and a workaround for bzip2)
|
||||
*
|
||||
* @param int $bytes seek to this position
|
||||
*/
|
||||
protected function skipbytes($bytes)
|
||||
{
|
||||
if ($this->comptype === Archive::COMPRESS_GZIP) {
|
||||
@gzseek($this->fh, $bytes, SEEK_CUR);
|
||||
} elseif ($this->comptype === Archive::COMPRESS_BZIP) {
|
||||
// there is no seek in bzip2, we simply read on
|
||||
// bzread allows to read a max of 8kb at once
|
||||
while($bytes) {
|
||||
$toread = min(8192, $bytes);
|
||||
@bzread($this->fh, $toread);
|
||||
$bytes -= $toread;
|
||||
}
|
||||
} else {
|
||||
@fseek($this->fh, $bytes, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the given file meta data as header
|
||||
*
|
||||
* @param FileInfo $fileinfo
|
||||
* @throws ArchiveIOException
|
||||
*/
|
||||
protected function writeFileHeader(FileInfo $fileinfo)
|
||||
{
|
||||
$this->writeRawFileHeader(
|
||||
$fileinfo->getPath(),
|
||||
$fileinfo->getUid(),
|
||||
$fileinfo->getGid(),
|
||||
$fileinfo->getMode(),
|
||||
$fileinfo->getSize(),
|
||||
$fileinfo->getMtime(),
|
||||
$fileinfo->getIsdir() ? '5' : '0'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a file header to the stream
|
||||
*
|
||||
* @param string $name
|
||||
* @param int $uid
|
||||
* @param int $gid
|
||||
* @param int $perm
|
||||
* @param int $size
|
||||
* @param int $mtime
|
||||
* @param string $typeflag Set to '5' for directories
|
||||
* @throws ArchiveIOException
|
||||
*/
|
||||
protected function writeRawFileHeader($name, $uid, $gid, $perm, $size, $mtime, $typeflag = '')
|
||||
{
|
||||
// handle filename length restrictions
|
||||
$prefix = '';
|
||||
$namelen = strlen($name);
|
||||
if ($namelen > 100) {
|
||||
$file = basename($name);
|
||||
$dir = dirname($name);
|
||||
if (strlen($file) > 100 || strlen($dir) > 155) {
|
||||
// we're still too large, let's use GNU longlink
|
||||
$this->writeRawFileHeader('././@LongLink', 0, 0, 0, $namelen, 0, 'L');
|
||||
for ($s = 0; $s < $namelen; $s += 512) {
|
||||
$this->writebytes(pack("a512", substr($name, $s, 512)));
|
||||
}
|
||||
$name = substr($name, 0, 100); // cut off name
|
||||
} else {
|
||||
// we're fine when splitting, use POSIX ustar
|
||||
$prefix = $dir;
|
||||
$name = $file;
|
||||
}
|
||||
}
|
||||
|
||||
// values are needed in octal
|
||||
$uid = sprintf("%6s ", decoct($uid));
|
||||
$gid = sprintf("%6s ", decoct($gid));
|
||||
$perm = sprintf("%6s ", decoct($perm));
|
||||
$size = sprintf("%11s ", decoct($size));
|
||||
$mtime = sprintf("%11s", decoct($mtime));
|
||||
|
||||
$data_first = pack("a100a8a8a8a12A12", $name, $perm, $uid, $gid, $size, $mtime);
|
||||
$data_last = pack("a1a100a6a2a32a32a8a8a155a12", $typeflag, '', 'ustar', '', '', '', '', '', $prefix, "");
|
||||
|
||||
for ($i = 0, $chks = 0; $i < 148; $i++) {
|
||||
$chks += ord($data_first[$i]);
|
||||
}
|
||||
|
||||
for ($i = 156, $chks += 256, $j = 0; $i < 512; $i++, $j++) {
|
||||
$chks += ord($data_last[$j]);
|
||||
}
|
||||
|
||||
$this->writebytes($data_first);
|
||||
|
||||
$chks = pack("a8", sprintf("%6s ", decoct($chks)));
|
||||
$this->writebytes($chks.$data_last);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the given tar file header
|
||||
*
|
||||
* @param string $block a 512 byte block containing the header data
|
||||
* @return array|false returns false when this was a null block
|
||||
* @throws ArchiveCorruptedException
|
||||
*/
|
||||
protected function parseHeader($block)
|
||||
{
|
||||
if (!$block || strlen($block) != 512) {
|
||||
throw new ArchiveCorruptedException('Unexpected length of header');
|
||||
}
|
||||
|
||||
// null byte blocks are ignored
|
||||
if(trim($block) === '') return false;
|
||||
|
||||
for ($i = 0, $chks = 0; $i < 148; $i++) {
|
||||
$chks += ord($block[$i]);
|
||||
}
|
||||
|
||||
for ($i = 156, $chks += 256; $i < 512; $i++) {
|
||||
$chks += ord($block[$i]);
|
||||
}
|
||||
|
||||
$header = @unpack(
|
||||
"a100filename/a8perm/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix",
|
||||
$block
|
||||
);
|
||||
if (!$header) {
|
||||
throw new ArchiveCorruptedException('Failed to parse header');
|
||||
}
|
||||
|
||||
$return['checksum'] = OctDec(trim($header['checksum']));
|
||||
if ($return['checksum'] != $chks) {
|
||||
throw new ArchiveCorruptedException('Header does not match its checksum');
|
||||
}
|
||||
|
||||
$return['filename'] = trim($header['filename']);
|
||||
$return['perm'] = OctDec(trim($header['perm']));
|
||||
$return['uid'] = OctDec(trim($header['uid']));
|
||||
$return['gid'] = OctDec(trim($header['gid']));
|
||||
$return['size'] = OctDec(trim($header['size']));
|
||||
$return['mtime'] = OctDec(trim($header['mtime']));
|
||||
$return['typeflag'] = $header['typeflag'];
|
||||
$return['link'] = trim($header['link']);
|
||||
$return['uname'] = trim($header['uname']);
|
||||
$return['gname'] = trim($header['gname']);
|
||||
|
||||
// Handle ustar Posix compliant path prefixes
|
||||
if (trim($header['prefix'])) {
|
||||
$return['filename'] = trim($header['prefix']).'/'.$return['filename'];
|
||||
}
|
||||
|
||||
// Handle Long-Link entries from GNU Tar
|
||||
if ($return['typeflag'] == 'L') {
|
||||
// following data block(s) is the filename
|
||||
$filename = trim($this->readbytes(ceil($return['size'] / 512) * 512));
|
||||
// next block is the real header
|
||||
$block = $this->readbytes(512);
|
||||
$return = $this->parseHeader($block);
|
||||
// overwrite the filename
|
||||
$return['filename'] = $filename;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a FileInfo object from the given parsed header
|
||||
*
|
||||
* @param $header
|
||||
* @return FileInfo
|
||||
*/
|
||||
protected function header2fileinfo($header)
|
||||
{
|
||||
$fileinfo = new FileInfo();
|
||||
$fileinfo->setPath($header['filename']);
|
||||
$fileinfo->setMode($header['perm']);
|
||||
$fileinfo->setUid($header['uid']);
|
||||
$fileinfo->setGid($header['gid']);
|
||||
$fileinfo->setSize($header['size']);
|
||||
$fileinfo->setMtime($header['mtime']);
|
||||
$fileinfo->setOwner($header['uname']);
|
||||
$fileinfo->setGroup($header['gname']);
|
||||
$fileinfo->setIsdir((bool) $header['typeflag']);
|
||||
|
||||
return $fileinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given compression type is available and throws an exception if not
|
||||
*
|
||||
* @param $comptype
|
||||
* @throws ArchiveIllegalCompressionException
|
||||
*/
|
||||
protected function compressioncheck($comptype)
|
||||
{
|
||||
if ($comptype === Archive::COMPRESS_GZIP && !function_exists('gzopen')) {
|
||||
throw new ArchiveIllegalCompressionException('No gzip support available');
|
||||
}
|
||||
|
||||
if ($comptype === Archive::COMPRESS_BZIP && !function_exists('bzopen')) {
|
||||
throw new ArchiveIllegalCompressionException('No bzip2 support available');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses the wanted compression from the given file
|
||||
*
|
||||
* Uses magic bytes for existing files, the file extension otherwise
|
||||
*
|
||||
* You don't need to call this yourself. It's used when you pass Archive::COMPRESS_AUTO somewhere
|
||||
*
|
||||
* @param string $file
|
||||
* @return int
|
||||
*/
|
||||
public function filetype($file)
|
||||
{
|
||||
// for existing files, try to read the magic bytes
|
||||
if(file_exists($file) && is_readable($file) && filesize($file) > 5) {
|
||||
$fh = @fopen($file, 'rb');
|
||||
if(!$fh) return false;
|
||||
$magic = fread($fh, 5);
|
||||
fclose($fh);
|
||||
|
||||
if(strpos($magic, "\x42\x5a") === 0) return Archive::COMPRESS_BZIP;
|
||||
if(strpos($magic, "\x1f\x8b") === 0) return Archive::COMPRESS_GZIP;
|
||||
}
|
||||
|
||||
// otherwise rely on file name
|
||||
$file = strtolower($file);
|
||||
if (substr($file, -3) == '.gz' || substr($file, -4) == '.tgz') {
|
||||
return Archive::COMPRESS_GZIP;
|
||||
} elseif (substr($file, -4) == '.bz2' || substr($file, -4) == '.tbz') {
|
||||
return Archive::COMPRESS_BZIP;
|
||||
}
|
||||
|
||||
return Archive::COMPRESS_NONE;
|
||||
}
|
||||
|
||||
}
|
1026
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/Zip.php
vendored
Normal file
1026
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-archive/src/Zip.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/.gitignore
vendored
Normal file
8
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
*.iml
|
||||
.idea/
|
||||
composer.phar
|
||||
vendor/
|
||||
composer.lock
|
||||
apigen.phar
|
||||
docs/
|
||||
.phpunit.result.cache
|
21
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/LICENSE
vendored
Normal file
21
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Andreas Gohr
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
164
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/README.md
vendored
Normal file
164
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/README.md
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
# PHP-CLI
|
||||
|
||||
PHP-CLI is a simple library that helps with creating nice looking command line scripts.
|
||||
|
||||
It takes care of
|
||||
|
||||
- **option parsing**
|
||||
- **help page generation**
|
||||
- **automatic width adjustment**
|
||||
- **colored output**
|
||||
- **optional PSR3 compatibility**
|
||||
|
||||
It is lightweight and has **no 3rd party dependencies**. Note: this is for non-interactive scripts only. It has no readline or similar support.
|
||||
|
||||
## Installation
|
||||
|
||||
Use composer:
|
||||
|
||||
```php composer.phar require splitbrain/php-cli```
|
||||
|
||||
## Usage and Examples
|
||||
|
||||
Minimal example:
|
||||
|
||||
```php
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
use splitbrain\phpcli\CLI;
|
||||
use splitbrain\phpcli\Options;
|
||||
|
||||
class Minimal extends CLI
|
||||
{
|
||||
// register options and arguments
|
||||
protected function setup(Options $options)
|
||||
{
|
||||
$options->setHelp('A very minimal example that does nothing but print a version');
|
||||
$options->registerOption('version', 'print version', 'v');
|
||||
}
|
||||
|
||||
// implement your code
|
||||
protected function main(Options $options)
|
||||
{
|
||||
if ($options->getOpt('version')) {
|
||||
$this->info('1.0.0');
|
||||
} else {
|
||||
echo $options->help();
|
||||
}
|
||||
}
|
||||
}
|
||||
// execute it
|
||||
$cli = new Minimal();
|
||||
$cli->run();
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
The basic usage is simple:
|
||||
|
||||
- create a class and ``extend splitbrain\phpcli\CLI``
|
||||
- implement the ```setup($options)``` method and register options, arguments, commands and set help texts
|
||||
- ``$options->setHelp()`` adds a general description
|
||||
- ``$options->registerOption()`` adds an option
|
||||
- ``$options->registerArgument()`` adds an argument
|
||||
- ``$options->registerCommand()`` adds a sub command
|
||||
- implement the ```main($options)``` method and do your business logic there
|
||||
- ``$options->getOpts`` lets you access set options
|
||||
- ``$options->getArgs()`` returns the remaining arguments after removing the options
|
||||
- ``$options->getCmd()`` returns the sub command the user used
|
||||
- instantiate your class and call ```run()``` on it
|
||||
|
||||
More examples can be found in the examples directory. Please refer to the [API docs](https://splitbrain.github.io/php-cli/)
|
||||
for further info.
|
||||
|
||||
## Exceptions
|
||||
|
||||
By default, the CLI class registers an exception handler and will print the exception's message to the end user and
|
||||
exit the programm with a non-zero exit code. You can disable this behaviour and catch all exceptions yourself by
|
||||
passing false to the constructor.
|
||||
|
||||
You can use the provided ``splitbrain\phpcli\Exception`` to signal any problems within your main code yourself. The
|
||||
exception's code will be used as the exit code then.
|
||||
|
||||
Stacktraces will be printed on log level `debug`.
|
||||
|
||||
## Colored output
|
||||
|
||||
Colored output is handled through the ``Colors`` class. It tries to detect if a color terminal is available and only
|
||||
then uses terminal colors. You can always suppress colored output by passing ``--no-colors`` to your scripts.
|
||||
Disabling colors will also disable the emoticon prefixes.
|
||||
|
||||
Simple colored log messages can be printed by you using the convinence methods ``success()`` (green), ``info()`` (cyan),
|
||||
``error()`` (red) or ``fatal()`` (red). The latter will also exit the programm with a non-zero exit code.
|
||||
|
||||
For more complex coloring you can access the color class through ``$this->colors`` in your script. The ``wrap()`` method
|
||||
is probably what you want to use.
|
||||
|
||||
The table formatter allows coloring full columns. To use that mechanism pass an array of colors as third parameter to
|
||||
its ``format()`` method. Please note that you can not pass colored texts in the second parameters (text length calculation
|
||||
and wrapping will fail, breaking your texts).
|
||||
|
||||
## Table Formatter
|
||||
|
||||
The ``TableFormatter`` class allows you to align texts in multiple columns. It tries to figure out the available
|
||||
terminal width on its own. It can be overwritten by setting a ``COLUMNS`` environment variable.
|
||||
|
||||
The formatter is used through the ``format()`` method which expects at least two arrays: The first defines the column
|
||||
widths, the second contains the texts to fill into the columns. Between each column a border is printed (a single space
|
||||
by default).
|
||||
|
||||
See the ``example/table.php`` for sample usage.
|
||||
|
||||
Columns width can be given in three forms:
|
||||
|
||||
- fixed width in characters by providing an integer (eg. ``15``)
|
||||
- precentages by provifing an integer and a percent sign (eg. ``25%``)
|
||||
- a single fluid "rest" column marked with an asterisk (eg. ``*``)
|
||||
|
||||
When mixing fixed and percentage widths, percentages refer to the remaining space after all fixed columns have been
|
||||
assigned.
|
||||
|
||||
Space for borders is automatically calculated. It is recommended to always have some relative (percentage) or a fluid
|
||||
column to adjust for different terminal widths.
|
||||
|
||||
The table formatter is used for the automatic help screen accessible when calling your script with ``-h`` or ``--help``.
|
||||
|
||||
## PSR-3 Logging
|
||||
|
||||
The CLI class is a fully PSR-3 compatible logger (printing colored log data to STDOUT and STDERR). This is useful when
|
||||
you call backend code from your CLI that expects a Logger instance to produce any sensible status output while running.
|
||||
|
||||
If you need to pass a class implementing the `Psr\Log\LoggerInterface` you can do so by inheriting from one of the two provided classes implementing this interface instead of `splitbrain\phpcli\CLI`.
|
||||
|
||||
* Use `splitbrain\phpcli\PSR3CLI` if you're using version 2 of PSR3 (PHP < 8.0)
|
||||
* Use `splitbrain\phpcli\PSR3CLIv3` if you're using version 3 of PSR3 (PHP >= 8.0)
|
||||
|
||||
The resulting object then can be passed as the logger instance. The difference between the two is in adjusted method signatures (with appropriate type hinting) only. Be sure you have the suggested `psr/log` composer package installed when using these classes.
|
||||
|
||||
Note: if your backend code calls for a PSR-3 logger but does not actually type check for the interface (AKA being LoggerAware only) you can also just pass an instance of `splitbrain\phpcli\CLI`.
|
||||
|
||||
## Log Levels
|
||||
|
||||
You can adjust the verbosity of your CLI tool using the `--loglevel` parameter. Supported loglevels are the PSR-3
|
||||
loglevels and our own `success` level:
|
||||
|
||||
* debug
|
||||
* info
|
||||
* notice
|
||||
* success (this is not defined in PSR-3)
|
||||
* warning
|
||||
* error
|
||||
* critical
|
||||
* alert
|
||||
* emergency
|
||||
|
||||

|
||||
|
||||
Convenience methods for all log levels are available. Placeholder interpolation as described in PSR-3 is available, too.
|
||||
Messages from `warning` level onwards are printed to `STDERR` all below are printed to `STDOUT`.
|
||||
|
||||
The default log level of your script can be set by overwriting the `$logdefault` member.
|
||||
|
||||
See `example/logging.php` for an example.
|
34
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/composer.json
vendored
Normal file
34
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/composer.json
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "splitbrain/php-cli",
|
||||
"description": "Easy command line scripts for PHP with opt parsing and color output. No dependencies",
|
||||
"keywords": [
|
||||
"cli",
|
||||
"console",
|
||||
"terminal",
|
||||
"command line",
|
||||
"getopt",
|
||||
"optparse",
|
||||
"argparse"
|
||||
],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andreas Gohr",
|
||||
"email": "andi@splitbrain.org"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "Allows you to make the CLI available as PSR-3 logger"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"splitbrain\\phpcli\\": "src"
|
||||
}
|
||||
}
|
||||
}
|
261
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/Base.php
vendored
Normal file
261
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/Base.php
vendored
Normal file
@ -0,0 +1,261 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\phpcli;
|
||||
|
||||
/**
|
||||
* Class CLIBase
|
||||
*
|
||||
* All base functionality is implemented here.
|
||||
*
|
||||
* Your commandline should not inherit from this class, but from one of the *CLI* classes
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @license MIT
|
||||
*/
|
||||
abstract class Base
|
||||
{
|
||||
/** @var string the executed script itself */
|
||||
protected $bin;
|
||||
/** @var Options the option parser */
|
||||
protected $options;
|
||||
/** @var Colors */
|
||||
public $colors;
|
||||
|
||||
/** @var array PSR-3 compatible loglevels and their prefix, color, output channel */
|
||||
protected $loglevel = array(
|
||||
'debug' => array('', Colors::C_RESET, STDOUT),
|
||||
'info' => array('ℹ ', Colors::C_CYAN, STDOUT),
|
||||
'notice' => array('☛ ', Colors::C_CYAN, STDOUT),
|
||||
'success' => array('✓ ', Colors::C_GREEN, STDOUT),
|
||||
'warning' => array('⚠ ', Colors::C_BROWN, STDERR),
|
||||
'error' => array('✗ ', Colors::C_RED, STDERR),
|
||||
'critical' => array('☠ ', Colors::C_LIGHTRED, STDERR),
|
||||
'alert' => array('✖ ', Colors::C_LIGHTRED, STDERR),
|
||||
'emergency' => array('✘ ', Colors::C_LIGHTRED, STDERR),
|
||||
);
|
||||
|
||||
protected $logdefault = 'info';
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
* Initialize the arguments, set up helper classes and set up the CLI environment
|
||||
*
|
||||
* @param bool $autocatch should exceptions be catched and handled automatically?
|
||||
*/
|
||||
public function __construct($autocatch = true)
|
||||
{
|
||||
if ($autocatch) {
|
||||
set_exception_handler(array($this, 'fatal'));
|
||||
}
|
||||
|
||||
$this->colors = new Colors();
|
||||
$this->options = new Options($this->colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register options and arguments on the given $options object
|
||||
*
|
||||
* @param Options $options
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
abstract protected function setup(Options $options);
|
||||
|
||||
/**
|
||||
* Your main program
|
||||
*
|
||||
* Arguments and options have been parsed when this is run
|
||||
*
|
||||
* @param Options $options
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
abstract protected function main(Options $options);
|
||||
|
||||
/**
|
||||
* Execute the CLI program
|
||||
*
|
||||
* Executes the setup() routine, adds default options, initiate the options parsing and argument checking
|
||||
* and finally executes main() - Each part is split into their own protected function below, so behaviour
|
||||
* can easily be overwritten
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if ('cli' != php_sapi_name()) {
|
||||
throw new Exception('This has to be run from the command line');
|
||||
}
|
||||
|
||||
$this->setup($this->options);
|
||||
$this->registerDefaultOptions();
|
||||
$this->parseOptions();
|
||||
$this->handleDefaultOptions();
|
||||
$this->setupLogging();
|
||||
$this->checkArguments();
|
||||
$this->execute();
|
||||
}
|
||||
|
||||
// region run handlers - for easier overriding
|
||||
|
||||
/**
|
||||
* Add the default help, color and log options
|
||||
*/
|
||||
protected function registerDefaultOptions()
|
||||
{
|
||||
$this->options->registerOption(
|
||||
'help',
|
||||
'Display this help screen and exit immediately.',
|
||||
'h'
|
||||
);
|
||||
$this->options->registerOption(
|
||||
'no-colors',
|
||||
'Do not use any colors in output. Useful when piping output to other tools or files.'
|
||||
);
|
||||
$this->options->registerOption(
|
||||
'loglevel',
|
||||
'Minimum level of messages to display. Default is ' . $this->colors->wrap($this->logdefault, Colors::C_CYAN) . '. ' .
|
||||
'Valid levels are: debug, info, notice, success, warning, error, critical, alert, emergency.',
|
||||
null,
|
||||
'level'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the default options
|
||||
*/
|
||||
protected function handleDefaultOptions()
|
||||
{
|
||||
if ($this->options->getOpt('no-colors')) {
|
||||
$this->colors->disable();
|
||||
}
|
||||
if ($this->options->getOpt('help')) {
|
||||
echo $this->options->help();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the logging options
|
||||
*/
|
||||
protected function setupLogging()
|
||||
{
|
||||
$level = $this->options->getOpt('loglevel', $this->logdefault);
|
||||
if (!isset($this->loglevel[$level])) $this->fatal('Unknown log level');
|
||||
foreach (array_keys($this->loglevel) as $l) {
|
||||
if ($l == $level) break;
|
||||
unset($this->loglevel[$l]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around the option parsing
|
||||
*/
|
||||
protected function parseOptions()
|
||||
{
|
||||
$this->options->parseOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around the argument checking
|
||||
*/
|
||||
protected function checkArguments()
|
||||
{
|
||||
$this->options->checkArguments();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around main
|
||||
*/
|
||||
protected function execute()
|
||||
{
|
||||
$this->main($this->options);
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region logging
|
||||
|
||||
/**
|
||||
* Exits the program on a fatal error
|
||||
*
|
||||
* @param \Exception|string $error either an exception or an error message
|
||||
* @param array $context
|
||||
*/
|
||||
public function fatal($error, array $context = array())
|
||||
{
|
||||
$code = 0;
|
||||
if (is_object($error) && is_a($error, 'Exception')) {
|
||||
/** @var Exception $error */
|
||||
$this->logMessage('debug', get_class($error) . ' caught in ' . $error->getFile() . ':' . $error->getLine());
|
||||
$this->logMessage('debug', $error->getTraceAsString());
|
||||
$code = $error->getCode();
|
||||
$error = $error->getMessage();
|
||||
|
||||
}
|
||||
if (!$code) {
|
||||
$code = Exception::E_ANY;
|
||||
}
|
||||
|
||||
$this->logMessage('critical', $error, $context);
|
||||
exit($code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal, positive outcome (This is not a PSR-3 level)
|
||||
*
|
||||
* @param string $string
|
||||
* @param array $context
|
||||
*/
|
||||
public function success($string, array $context = array())
|
||||
{
|
||||
$this->logMessage('success', $string, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $level
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
protected function logMessage($level, $message, array $context = array())
|
||||
{
|
||||
// is this log level wanted?
|
||||
if (!isset($this->loglevel[$level])) return;
|
||||
|
||||
/** @var string $prefix */
|
||||
/** @var string $color */
|
||||
/** @var resource $channel */
|
||||
list($prefix, $color, $channel) = $this->loglevel[$level];
|
||||
if (!$this->colors->isEnabled()) $prefix = '';
|
||||
|
||||
$message = $this->interpolate($message, $context);
|
||||
$this->colors->ptln($prefix . $message, $color, $channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolates context values into the message placeholders.
|
||||
*
|
||||
* @param $message
|
||||
* @param array $context
|
||||
* @return string
|
||||
*/
|
||||
protected function interpolate($message, array $context = array())
|
||||
{
|
||||
// build a replacement array with braces around the context keys
|
||||
$replace = array();
|
||||
foreach ($context as $key => $val) {
|
||||
// check that the value can be casted to string
|
||||
if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
|
||||
$replace['{' . $key . '}'] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
// interpolate replacement values into the message and return
|
||||
return strtr((string)$message, $replace);
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
127
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/CLI.php
vendored
Normal file
127
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/CLI.php
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\phpcli;
|
||||
|
||||
/**
|
||||
* Class CLI
|
||||
*
|
||||
* Your commandline script should inherit from this class and implement the abstract methods.
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @license MIT
|
||||
*/
|
||||
abstract class CLI extends Base
|
||||
{
|
||||
/**
|
||||
* System is unusable.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function emergency($message, array $context = array())
|
||||
{
|
||||
$this->log('emergency', $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Action must be taken immediately.
|
||||
*
|
||||
* Example: Entire website down, database unavailable, etc. This should
|
||||
* trigger the SMS alerts and wake you up.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
public function alert($message, array $context = array())
|
||||
{
|
||||
$this->log('alert', $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Critical conditions.
|
||||
*
|
||||
* Example: Application component unavailable, unexpected exception.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
public function critical($message, array $context = array())
|
||||
{
|
||||
$this->log('critical', $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime errors that do not require immediate action but should typically
|
||||
* be logged and monitored.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
public function error($message, array $context = array())
|
||||
{
|
||||
$this->log('error', $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceptional occurrences that are not errors.
|
||||
*
|
||||
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
||||
* that are not necessarily wrong.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
public function warning($message, array $context = array())
|
||||
{
|
||||
$this->log('warning', $message, $context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Normal but significant events.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
public function notice($message, array $context = array())
|
||||
{
|
||||
$this->log('notice', $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interesting events.
|
||||
*
|
||||
* Example: User logs in, SQL logs.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
public function info($message, array $context = array())
|
||||
{
|
||||
$this->log('info', $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detailed debug information.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
public function debug($message, array $context = array())
|
||||
{
|
||||
$this->log('debug', $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $level
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
public function log($level, $message, array $context = array())
|
||||
{
|
||||
$this->logMessage($level, $message, $context);
|
||||
}
|
||||
}
|
170
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/Colors.php
vendored
Normal file
170
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/Colors.php
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\phpcli;
|
||||
|
||||
/**
|
||||
* Class Colors
|
||||
*
|
||||
* Handles color output on (Linux) terminals
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @license MIT
|
||||
*/
|
||||
class Colors
|
||||
{
|
||||
// these constants make IDE autocompletion easier, but color names can also be passed as strings
|
||||
const C_RESET = 'reset';
|
||||
const C_BLACK = 'black';
|
||||
const C_DARKGRAY = 'darkgray';
|
||||
const C_BLUE = 'blue';
|
||||
const C_LIGHTBLUE = 'lightblue';
|
||||
const C_GREEN = 'green';
|
||||
const C_LIGHTGREEN = 'lightgreen';
|
||||
const C_CYAN = 'cyan';
|
||||
const C_LIGHTCYAN = 'lightcyan';
|
||||
const C_RED = 'red';
|
||||
const C_LIGHTRED = 'lightred';
|
||||
const C_PURPLE = 'purple';
|
||||
const C_LIGHTPURPLE = 'lightpurple';
|
||||
const C_BROWN = 'brown';
|
||||
const C_YELLOW = 'yellow';
|
||||
const C_LIGHTGRAY = 'lightgray';
|
||||
const C_WHITE = 'white';
|
||||
|
||||
/** @var array known color names */
|
||||
protected $colors = array(
|
||||
self::C_RESET => "\33[0m",
|
||||
self::C_BLACK => "\33[0;30m",
|
||||
self::C_DARKGRAY => "\33[1;30m",
|
||||
self::C_BLUE => "\33[0;34m",
|
||||
self::C_LIGHTBLUE => "\33[1;34m",
|
||||
self::C_GREEN => "\33[0;32m",
|
||||
self::C_LIGHTGREEN => "\33[1;32m",
|
||||
self::C_CYAN => "\33[0;36m",
|
||||
self::C_LIGHTCYAN => "\33[1;36m",
|
||||
self::C_RED => "\33[0;31m",
|
||||
self::C_LIGHTRED => "\33[1;31m",
|
||||
self::C_PURPLE => "\33[0;35m",
|
||||
self::C_LIGHTPURPLE => "\33[1;35m",
|
||||
self::C_BROWN => "\33[0;33m",
|
||||
self::C_YELLOW => "\33[1;33m",
|
||||
self::C_LIGHTGRAY => "\33[0;37m",
|
||||
self::C_WHITE => "\33[1;37m",
|
||||
);
|
||||
|
||||
/** @var bool should colors be used? */
|
||||
protected $enabled = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Tries to disable colors for non-terminals
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) {
|
||||
$this->enabled = false;
|
||||
return;
|
||||
}
|
||||
if (!getenv('TERM')) {
|
||||
$this->enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* enable color output
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
$this->enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* disable color output
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
$this->enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool is color support enabled?
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to print a line in a given color
|
||||
*
|
||||
* @param string $line the line to print, a new line is added automatically
|
||||
* @param string $color one of the available color names
|
||||
* @param resource $channel file descriptor to write to
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function ptln($line, $color, $channel = STDOUT)
|
||||
{
|
||||
$this->set($color, $channel);
|
||||
fwrite($channel, rtrim($line) . "\n");
|
||||
$this->reset($channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given text wrapped in the appropriate color and reset code
|
||||
*
|
||||
* @param string $text string to wrap
|
||||
* @param string $color one of the available color names
|
||||
* @return string the wrapped string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function wrap($text, $color)
|
||||
{
|
||||
return $this->getColorCode($color) . $text . $this->getColorCode('reset');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the appropriate terminal code for the given color
|
||||
*
|
||||
* @param string $color one of the available color names
|
||||
* @return string color code
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getColorCode($color)
|
||||
{
|
||||
if (!$this->enabled) {
|
||||
return '';
|
||||
}
|
||||
if (!isset($this->colors[$color])) {
|
||||
throw new Exception("No such color $color");
|
||||
}
|
||||
|
||||
return $this->colors[$color];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given color for consecutive output
|
||||
*
|
||||
* @param string $color one of the supported color names
|
||||
* @param resource $channel file descriptor to write to
|
||||
* @throws Exception
|
||||
*/
|
||||
public function set($color, $channel = STDOUT)
|
||||
{
|
||||
fwrite($channel, $this->getColorCode($color));
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the terminal color
|
||||
*
|
||||
* @param resource $channel file descriptor to write to
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function reset($channel = STDOUT)
|
||||
{
|
||||
$this->set('reset', $channel);
|
||||
}
|
||||
}
|
35
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/Exception.php
vendored
Normal file
35
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/Exception.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\phpcli;
|
||||
|
||||
/**
|
||||
* Class Exception
|
||||
*
|
||||
* The code is used as exit code for the CLI tool. This should probably be extended. Many cases just fall back to the
|
||||
* E_ANY code.
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @license MIT
|
||||
*/
|
||||
class Exception extends \RuntimeException
|
||||
{
|
||||
const E_ANY = -1; // no error code specified
|
||||
const E_UNKNOWN_OPT = 1; //Unrecognized option
|
||||
const E_OPT_ARG_REQUIRED = 2; //Option requires argument
|
||||
const E_OPT_ARG_DENIED = 3; //Option not allowed argument
|
||||
const E_OPT_ABIGUOUS = 4; //Option abiguous
|
||||
const E_ARG_READ = 5; //Could not read argv
|
||||
|
||||
/**
|
||||
* @param string $message The Exception message to throw.
|
||||
* @param int $code The Exception code
|
||||
* @param \Exception $previous The previous exception used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = "", $code = 0, \Exception $previous = null)
|
||||
{
|
||||
if (!$code) {
|
||||
$code = self::E_ANY;
|
||||
}
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
504
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/Options.php
vendored
Normal file
504
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/Options.php
vendored
Normal file
@ -0,0 +1,504 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\phpcli;
|
||||
|
||||
/**
|
||||
* Class Options
|
||||
*
|
||||
* Parses command line options passed to the CLI script. Allows CLI scripts to easily register all accepted options and
|
||||
* commands and even generates a help text from this setup.
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @license MIT
|
||||
*/
|
||||
class Options
|
||||
{
|
||||
/** @var array keeps the list of options to parse */
|
||||
protected $setup;
|
||||
|
||||
/** @var array store parsed options */
|
||||
protected $options = array();
|
||||
|
||||
/** @var string current parsed command if any */
|
||||
protected $command = '';
|
||||
|
||||
/** @var array passed non-option arguments */
|
||||
protected $args = array();
|
||||
|
||||
/** @var string the executed script */
|
||||
protected $bin;
|
||||
|
||||
/** @var Colors for colored help output */
|
||||
protected $colors;
|
||||
|
||||
/** @var string newline used for spacing help texts */
|
||||
protected $newline = "\n";
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Colors $colors optional configured color object
|
||||
* @throws Exception when arguments can't be read
|
||||
*/
|
||||
public function __construct(Colors $colors = null)
|
||||
{
|
||||
if (!is_null($colors)) {
|
||||
$this->colors = $colors;
|
||||
} else {
|
||||
$this->colors = new Colors();
|
||||
}
|
||||
|
||||
$this->setup = array(
|
||||
'' => array(
|
||||
'opts' => array(),
|
||||
'args' => array(),
|
||||
'help' => '',
|
||||
'commandhelp' => 'This tool accepts a command as first parameter as outlined below:'
|
||||
)
|
||||
); // default command
|
||||
|
||||
$this->args = $this->readPHPArgv();
|
||||
$this->bin = basename(array_shift($this->args));
|
||||
|
||||
$this->options = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bin value
|
||||
*/
|
||||
public function getBin()
|
||||
{
|
||||
return $this->bin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the help text for the tool itself
|
||||
*
|
||||
* @param string $help
|
||||
*/
|
||||
public function setHelp($help)
|
||||
{
|
||||
$this->setup['']['help'] = $help;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the help text for the tools commands itself
|
||||
*
|
||||
* @param string $help
|
||||
*/
|
||||
public function setCommandHelp($help)
|
||||
{
|
||||
$this->setup['']['commandhelp'] = $help;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a more compact help screen with less new lines
|
||||
*
|
||||
* @param bool $set
|
||||
*/
|
||||
public function useCompactHelp($set = true)
|
||||
{
|
||||
$this->newline = $set ? '' : "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the names of arguments for help generation and number checking
|
||||
*
|
||||
* This has to be called in the order arguments are expected
|
||||
*
|
||||
* @param string $arg argument name (just for help)
|
||||
* @param string $help help text
|
||||
* @param bool $required is this a required argument
|
||||
* @param string $command if theses apply to a sub command only
|
||||
* @throws Exception
|
||||
*/
|
||||
public function registerArgument($arg, $help, $required = true, $command = '')
|
||||
{
|
||||
if (!isset($this->setup[$command])) {
|
||||
throw new Exception("Command $command not registered");
|
||||
}
|
||||
|
||||
$this->setup[$command]['args'][] = array(
|
||||
'name' => $arg,
|
||||
'help' => $help,
|
||||
'required' => $required
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This registers a sub command
|
||||
*
|
||||
* Sub commands have their own options and use their own function (not main()).
|
||||
*
|
||||
* @param string $command
|
||||
* @param string $help
|
||||
* @throws Exception
|
||||
*/
|
||||
public function registerCommand($command, $help)
|
||||
{
|
||||
if (isset($this->setup[$command])) {
|
||||
throw new Exception("Command $command already registered");
|
||||
}
|
||||
|
||||
$this->setup[$command] = array(
|
||||
'opts' => array(),
|
||||
'args' => array(),
|
||||
'help' => $help
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an option for option parsing and help generation
|
||||
*
|
||||
* @param string $long multi character option (specified with --)
|
||||
* @param string $help help text for this option
|
||||
* @param string|null $short one character option (specified with -)
|
||||
* @param bool|string $needsarg does this option require an argument? give it a name here
|
||||
* @param string $command what command does this option apply to
|
||||
* @throws Exception
|
||||
*/
|
||||
public function registerOption($long, $help, $short = null, $needsarg = false, $command = '')
|
||||
{
|
||||
if (!isset($this->setup[$command])) {
|
||||
throw new Exception("Command $command not registered");
|
||||
}
|
||||
|
||||
$this->setup[$command]['opts'][$long] = array(
|
||||
'needsarg' => $needsarg,
|
||||
'help' => $help,
|
||||
'short' => $short
|
||||
);
|
||||
|
||||
if ($short) {
|
||||
if (strlen($short) > 1) {
|
||||
throw new Exception("Short options should be exactly one ASCII character");
|
||||
}
|
||||
|
||||
$this->setup[$command]['short'][$short] = $long;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the actual number of arguments against the required number
|
||||
*
|
||||
* Throws an exception if arguments are missing.
|
||||
*
|
||||
* This is run from CLI automatically and usually does not need to be called directly
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function checkArguments()
|
||||
{
|
||||
$argc = count($this->args);
|
||||
|
||||
$req = 0;
|
||||
foreach ($this->setup[$this->command]['args'] as $arg) {
|
||||
if (!$arg['required']) {
|
||||
break;
|
||||
} // last required arguments seen
|
||||
$req++;
|
||||
}
|
||||
|
||||
if ($req > $argc) {
|
||||
throw new Exception("Not enough arguments", Exception::E_OPT_ARG_REQUIRED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given arguments for known options and command
|
||||
*
|
||||
* The given $args array should NOT contain the executed file as first item anymore! The $args
|
||||
* array is stripped from any options and possible command. All found otions can be accessed via the
|
||||
* getOpt() function
|
||||
*
|
||||
* Note that command options will overwrite any global options with the same name
|
||||
*
|
||||
* This is run from CLI automatically and usually does not need to be called directly
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function parseOptions()
|
||||
{
|
||||
$non_opts = array();
|
||||
|
||||
$argc = count($this->args);
|
||||
for ($i = 0; $i < $argc; $i++) {
|
||||
$arg = $this->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($this->args, $i + 1));
|
||||
break;
|
||||
}
|
||||
|
||||
// '-' is stdin - a normal argument
|
||||
if ($arg == '-') {
|
||||
$non_opts = array_merge($non_opts, array_slice($this->args, $i));
|
||||
break;
|
||||
}
|
||||
|
||||
// first non-option
|
||||
if ($arg[0] != '-') {
|
||||
$non_opts = array_merge($non_opts, array_slice($this->args, $i));
|
||||
break;
|
||||
}
|
||||
|
||||
// long option
|
||||
if (strlen($arg) > 1 && $arg[1] === '-') {
|
||||
$arg = explode('=', substr($arg, 2), 2);
|
||||
$opt = array_shift($arg);
|
||||
$val = array_shift($arg);
|
||||
|
||||
if (!isset($this->setup[$this->command]['opts'][$opt])) {
|
||||
throw new Exception("No such option '$opt'", Exception::E_UNKNOWN_OPT);
|
||||
}
|
||||
|
||||
// argument required?
|
||||
if ($this->setup[$this->command]['opts'][$opt]['needsarg']) {
|
||||
if (is_null($val) && $i + 1 < $argc && !preg_match('/^--?[\w]/', $this->args[$i + 1])) {
|
||||
$val = $this->args[++$i];
|
||||
}
|
||||
if (is_null($val)) {
|
||||
throw new Exception("Option $opt requires an argument",
|
||||
Exception::E_OPT_ARG_REQUIRED);
|
||||
}
|
||||
$this->options[$opt] = $val;
|
||||
} else {
|
||||
$this->options[$opt] = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// short option
|
||||
$opt = substr($arg, 1);
|
||||
if (!isset($this->setup[$this->command]['short'][$opt])) {
|
||||
throw new Exception("No such option $arg", Exception::E_UNKNOWN_OPT);
|
||||
} else {
|
||||
$opt = $this->setup[$this->command]['short'][$opt]; // store it under long name
|
||||
}
|
||||
|
||||
// argument required?
|
||||
if ($this->setup[$this->command]['opts'][$opt]['needsarg']) {
|
||||
$val = null;
|
||||
if ($i + 1 < $argc && !preg_match('/^--?[\w]/', $this->args[$i + 1])) {
|
||||
$val = $this->args[++$i];
|
||||
}
|
||||
if (is_null($val)) {
|
||||
throw new Exception("Option $arg requires an argument",
|
||||
Exception::E_OPT_ARG_REQUIRED);
|
||||
}
|
||||
$this->options[$opt] = $val;
|
||||
} else {
|
||||
$this->options[$opt] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// parsing is now done, update args array
|
||||
$this->args = $non_opts;
|
||||
|
||||
// if not done yet, check if first argument is a command and reexecute argument parsing if it is
|
||||
if (!$this->command && $this->args && isset($this->setup[$this->args[0]])) {
|
||||
// it is a command!
|
||||
$this->command = array_shift($this->args);
|
||||
$this->parseOptions(); // second pass
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the given option
|
||||
*
|
||||
* Please note that all options are accessed by their long option names regardless of how they were
|
||||
* specified on commandline.
|
||||
*
|
||||
* Can only be used after parseOptions() has been run
|
||||
*
|
||||
* @param mixed $option
|
||||
* @param bool|string $default what to return if the option was not set
|
||||
* @return bool|string|string[]
|
||||
*/
|
||||
public function getOpt($option = null, $default = false)
|
||||
{
|
||||
if ($option === null) {
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
if (isset($this->options[$option])) {
|
||||
return $this->options[$option];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the found command if any
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCmd()
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the arguments passed to the script
|
||||
*
|
||||
* This will not contain any recognized options or the script name itself
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getArgs()
|
||||
{
|
||||
return $this->args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a help screen from the available options. You may want to call it from -h or on error
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function help()
|
||||
{
|
||||
$tf = new TableFormatter($this->colors);
|
||||
$text = '';
|
||||
|
||||
$hascommands = (count($this->setup) > 1);
|
||||
$commandhelp = $this->setup['']["commandhelp"];
|
||||
|
||||
foreach ($this->setup as $command => $config) {
|
||||
$hasopts = (bool)$this->setup[$command]['opts'];
|
||||
$hasargs = (bool)$this->setup[$command]['args'];
|
||||
|
||||
// usage or command syntax line
|
||||
if (!$command) {
|
||||
$text .= $this->colors->wrap('USAGE:', Colors::C_BROWN);
|
||||
$text .= "\n";
|
||||
$text .= ' ' . $this->bin;
|
||||
$mv = 2;
|
||||
} else {
|
||||
$text .= $this->newline;
|
||||
$text .= $this->colors->wrap(' ' . $command, Colors::C_PURPLE);
|
||||
$mv = 4;
|
||||
}
|
||||
|
||||
if ($hasopts) {
|
||||
$text .= ' ' . $this->colors->wrap('<OPTIONS>', Colors::C_GREEN);
|
||||
}
|
||||
|
||||
if (!$command && $hascommands) {
|
||||
$text .= ' ' . $this->colors->wrap('<COMMAND> ...', Colors::C_PURPLE);
|
||||
}
|
||||
|
||||
foreach ($this->setup[$command]['args'] as $arg) {
|
||||
$out = $this->colors->wrap('<' . $arg['name'] . '>', Colors::C_CYAN);
|
||||
|
||||
if (!$arg['required']) {
|
||||
$out = '[' . $out . ']';
|
||||
}
|
||||
$text .= ' ' . $out;
|
||||
}
|
||||
$text .= $this->newline;
|
||||
|
||||
// usage or command intro
|
||||
if ($this->setup[$command]['help']) {
|
||||
$text .= "\n";
|
||||
$text .= $tf->format(
|
||||
array($mv, '*'),
|
||||
array('', $this->setup[$command]['help'] . $this->newline)
|
||||
);
|
||||
}
|
||||
|
||||
// option description
|
||||
if ($hasopts) {
|
||||
if (!$command) {
|
||||
$text .= "\n";
|
||||
$text .= $this->colors->wrap('OPTIONS:', Colors::C_BROWN);
|
||||
}
|
||||
$text .= "\n";
|
||||
foreach ($this->setup[$command]['opts'] as $long => $opt) {
|
||||
|
||||
$name = '';
|
||||
if ($opt['short']) {
|
||||
$name .= '-' . $opt['short'];
|
||||
if ($opt['needsarg']) {
|
||||
$name .= ' <' . $opt['needsarg'] . '>';
|
||||
}
|
||||
$name .= ', ';
|
||||
}
|
||||
$name .= "--$long";
|
||||
if ($opt['needsarg']) {
|
||||
$name .= ' <' . $opt['needsarg'] . '>';
|
||||
}
|
||||
|
||||
$text .= $tf->format(
|
||||
array($mv, '30%', '*'),
|
||||
array('', $name, $opt['help']),
|
||||
array('', 'green', '')
|
||||
);
|
||||
$text .= $this->newline;
|
||||
}
|
||||
}
|
||||
|
||||
// argument description
|
||||
if ($hasargs) {
|
||||
if (!$command) {
|
||||
$text .= "\n";
|
||||
$text .= $this->colors->wrap('ARGUMENTS:', Colors::C_BROWN);
|
||||
}
|
||||
$text .= $this->newline;
|
||||
foreach ($this->setup[$command]['args'] as $arg) {
|
||||
$name = '<' . $arg['name'] . '>';
|
||||
|
||||
$text .= $tf->format(
|
||||
array($mv, '30%', '*'),
|
||||
array('', $name, $arg['help']),
|
||||
array('', 'cyan', '')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// head line and intro for following command documentation
|
||||
if (!$command && $hascommands) {
|
||||
$text .= "\n";
|
||||
$text .= $this->colors->wrap('COMMANDS:', Colors::C_BROWN);
|
||||
$text .= "\n";
|
||||
$text .= $tf->format(
|
||||
array($mv, '*'),
|
||||
array('', $commandhelp)
|
||||
);
|
||||
$text .= $this->newline;
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely read the $argv PHP array across different PHP configurations.
|
||||
* Will take care on register_globals and register_argc_argv ini directives
|
||||
*
|
||||
* @throws Exception
|
||||
* @return array the $argv PHP array or PEAR error if not registered
|
||||
*/
|
||||
private function readPHPArgv()
|
||||
{
|
||||
global $argv;
|
||||
if (!is_array($argv)) {
|
||||
if (!@is_array($_SERVER['argv'])) {
|
||||
if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
|
||||
throw new Exception(
|
||||
"Could not read cmd args (register_argc_argv=Off?)",
|
||||
Exception::E_ARG_READ
|
||||
);
|
||||
}
|
||||
return $GLOBALS['HTTP_SERVER_VARS']['argv'];
|
||||
}
|
||||
return $_SERVER['argv'];
|
||||
}
|
||||
return $argv;
|
||||
}
|
||||
}
|
||||
|
16
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/PSR3CLI.php
vendored
Normal file
16
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/PSR3CLI.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\phpcli;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Class PSR3CLI
|
||||
*
|
||||
* This class can be used instead of the CLI class when a class implementing
|
||||
* PSR3 version 2 is needed.
|
||||
*
|
||||
* @see PSR3CLIv3 for a version 3 compatible class
|
||||
*/
|
||||
abstract class PSR3CLI extends CLI implements LoggerInterface {
|
||||
}
|
24
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/PSR3CLIv3.php
vendored
Normal file
24
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/PSR3CLIv3.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\phpcli;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LoggerTrait;
|
||||
|
||||
/**
|
||||
* Class PSR3CLI
|
||||
*
|
||||
* This class can be used instead of the CLI class when a class implementing
|
||||
* PSR3 version 3 is needed.
|
||||
*
|
||||
* @see PSR3CLI for a version 2 compatible class
|
||||
*/
|
||||
abstract class PSR3CLIv3 extends Base implements LoggerInterface
|
||||
{
|
||||
use LoggerTrait;
|
||||
|
||||
public function log($level, string|\Stringable $message, array $context = []): void
|
||||
{
|
||||
$this->logMessage($level, $message, $context);
|
||||
}
|
||||
}
|
325
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/TableFormatter.php
vendored
Normal file
325
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-cli/src/TableFormatter.php
vendored
Normal file
@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\phpcli;
|
||||
|
||||
/**
|
||||
* Class TableFormatter
|
||||
*
|
||||
* Output text in multiple columns
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @license MIT
|
||||
*/
|
||||
class TableFormatter
|
||||
{
|
||||
/** @var string border between columns */
|
||||
protected $border = ' ';
|
||||
|
||||
/** @var int the terminal width */
|
||||
protected $max = 74;
|
||||
|
||||
/** @var Colors for coloring output */
|
||||
protected $colors;
|
||||
|
||||
/**
|
||||
* TableFormatter constructor.
|
||||
*
|
||||
* @param Colors|null $colors
|
||||
*/
|
||||
public function __construct(Colors $colors = null)
|
||||
{
|
||||
// try to get terminal width
|
||||
$width = $this->getTerminalWidth();
|
||||
if ($width) {
|
||||
$this->max = $width - 1;
|
||||
}
|
||||
|
||||
if ($colors) {
|
||||
$this->colors = $colors;
|
||||
} else {
|
||||
$this->colors = new Colors();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The currently set border (defaults to ' ')
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBorder()
|
||||
{
|
||||
return $this->border;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the border. The border is set between each column. Its width is
|
||||
* added to the column widths.
|
||||
*
|
||||
* @param string $border
|
||||
*/
|
||||
public function setBorder($border)
|
||||
{
|
||||
$this->border = $border;
|
||||
}
|
||||
|
||||
/**
|
||||
* Width of the terminal in characters
|
||||
*
|
||||
* initially autodetected
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getMaxWidth()
|
||||
{
|
||||
return $this->max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of the terminal to assume (in characters)
|
||||
*
|
||||
* @param int $max
|
||||
*/
|
||||
public function setMaxWidth($max)
|
||||
{
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to figure out the width of the terminal
|
||||
*
|
||||
* @return int terminal width, 0 if unknown
|
||||
*/
|
||||
protected function getTerminalWidth()
|
||||
{
|
||||
// from environment
|
||||
if (isset($_SERVER['COLUMNS'])) return (int)$_SERVER['COLUMNS'];
|
||||
|
||||
// via tput
|
||||
$process = proc_open('tput cols', array(
|
||||
1 => array('pipe', 'w'),
|
||||
2 => array('pipe', 'w'),
|
||||
), $pipes);
|
||||
$width = (int)stream_get_contents($pipes[1]);
|
||||
proc_close($process);
|
||||
|
||||
return $width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an array with dynamic column width and calculates the correct width
|
||||
*
|
||||
* Column width can be given as fixed char widths, percentages and a single * width can be given
|
||||
* for taking the remaining available space. When mixing percentages and fixed widths, percentages
|
||||
* refer to the remaining space after allocating the fixed width
|
||||
*
|
||||
* @param array $columns
|
||||
* @return int[]
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function calculateColLengths($columns)
|
||||
{
|
||||
$idx = 0;
|
||||
$border = $this->strlen($this->border);
|
||||
$fixed = (count($columns) - 1) * $border; // borders are used already
|
||||
$fluid = -1;
|
||||
|
||||
// first pass for format check and fixed columns
|
||||
foreach ($columns as $idx => $col) {
|
||||
// handle fixed columns
|
||||
if ((string)intval($col) === (string)$col) {
|
||||
$fixed += $col;
|
||||
continue;
|
||||
}
|
||||
// check if other colums are using proper units
|
||||
if (substr($col, -1) == '%') {
|
||||
continue;
|
||||
}
|
||||
if ($col == '*') {
|
||||
// only one fluid
|
||||
if ($fluid < 0) {
|
||||
$fluid = $idx;
|
||||
continue;
|
||||
} else {
|
||||
throw new Exception('Only one fluid column allowed!');
|
||||
}
|
||||
}
|
||||
throw new Exception("unknown column format $col");
|
||||
}
|
||||
|
||||
$alloc = $fixed;
|
||||
$remain = $this->max - $alloc;
|
||||
|
||||
// second pass to handle percentages
|
||||
foreach ($columns as $idx => $col) {
|
||||
if (substr($col, -1) != '%') {
|
||||
continue;
|
||||
}
|
||||
$perc = floatval($col);
|
||||
|
||||
$real = (int)floor(($perc * $remain) / 100);
|
||||
|
||||
$columns[$idx] = $real;
|
||||
$alloc += $real;
|
||||
}
|
||||
|
||||
$remain = $this->max - $alloc;
|
||||
if ($remain < 0) {
|
||||
throw new Exception("Wanted column widths exceed available space");
|
||||
}
|
||||
|
||||
// assign remaining space
|
||||
if ($fluid < 0) {
|
||||
$columns[$idx] += ($remain); // add to last column
|
||||
} else {
|
||||
$columns[$fluid] = $remain;
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays text in multiple word wrapped columns
|
||||
*
|
||||
* @param int[] $columns list of column widths (in characters, percent or '*')
|
||||
* @param string[] $texts list of texts for each column
|
||||
* @param array $colors A list of color names to use for each column. use empty string for default
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function format($columns, $texts, $colors = array())
|
||||
{
|
||||
$columns = $this->calculateColLengths($columns);
|
||||
|
||||
$wrapped = array();
|
||||
$maxlen = 0;
|
||||
|
||||
foreach ($columns as $col => $width) {
|
||||
$wrapped[$col] = explode("\n", $this->wordwrap($texts[$col], $width, "\n", true));
|
||||
$len = count($wrapped[$col]);
|
||||
if ($len > $maxlen) {
|
||||
$maxlen = $len;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$last = count($columns) - 1;
|
||||
$out = '';
|
||||
for ($i = 0; $i < $maxlen; $i++) {
|
||||
foreach ($columns as $col => $width) {
|
||||
if (isset($wrapped[$col][$i])) {
|
||||
$val = $wrapped[$col][$i];
|
||||
} else {
|
||||
$val = '';
|
||||
}
|
||||
$chunk = $this->pad($val, $width);
|
||||
if (isset($colors[$col]) && $colors[$col]) {
|
||||
$chunk = $this->colors->wrap($chunk, $colors[$col]);
|
||||
}
|
||||
$out .= $chunk;
|
||||
|
||||
// border
|
||||
if ($col != $last) {
|
||||
$out .= $this->border;
|
||||
}
|
||||
}
|
||||
$out .= "\n";
|
||||
}
|
||||
return $out;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad the given string to the correct length
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $len
|
||||
* @return string
|
||||
*/
|
||||
protected function pad($string, $len)
|
||||
{
|
||||
$strlen = $this->strlen($string);
|
||||
if ($strlen > $len) return $string;
|
||||
|
||||
$pad = $len - $strlen;
|
||||
return $string . str_pad('', $pad, ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Measures char length in UTF-8 when possible
|
||||
*
|
||||
* @param $string
|
||||
* @return int
|
||||
*/
|
||||
protected function strlen($string)
|
||||
{
|
||||
// don't count color codes
|
||||
$string = preg_replace("/\33\\[\\d+(;\\d+)?m/", '', $string);
|
||||
|
||||
if (function_exists('mb_strlen')) {
|
||||
return mb_strlen($string, 'utf-8');
|
||||
}
|
||||
|
||||
return strlen($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param int $start
|
||||
* @param int|null $length
|
||||
* @return string
|
||||
*/
|
||||
protected function substr($string, $start = 0, $length = null)
|
||||
{
|
||||
if (function_exists('mb_substr')) {
|
||||
return mb_substr($string, $start, $length);
|
||||
} else {
|
||||
// mb_substr() treats $length differently than substr()
|
||||
if ($length) {
|
||||
return substr($string, $start, $length);
|
||||
} else {
|
||||
return substr($string, $start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param int $width
|
||||
* @param string $break
|
||||
* @param bool $cut
|
||||
* @return string
|
||||
* @link http://stackoverflow.com/a/4988494
|
||||
*/
|
||||
protected function wordwrap($str, $width = 75, $break = "\n", $cut = false)
|
||||
{
|
||||
$lines = explode($break, $str);
|
||||
foreach ($lines as &$line) {
|
||||
$line = rtrim($line);
|
||||
if ($this->strlen($line) <= $width) {
|
||||
continue;
|
||||
}
|
||||
$words = explode(' ', $line);
|
||||
$line = '';
|
||||
$actual = '';
|
||||
foreach ($words as $word) {
|
||||
if ($this->strlen($actual . $word) <= $width) {
|
||||
$actual .= $word . ' ';
|
||||
} else {
|
||||
if ($actual != '') {
|
||||
$line .= rtrim($actual) . $break;
|
||||
}
|
||||
$actual = $word;
|
||||
if ($cut) {
|
||||
while ($this->strlen($actual) > $width) {
|
||||
$line .= $this->substr($actual, 0, $width) . $break;
|
||||
$actual = $this->substr($actual, $width);
|
||||
}
|
||||
}
|
||||
$actual .= ' ';
|
||||
}
|
||||
}
|
||||
$line .= trim($actual);
|
||||
}
|
||||
return implode($break, $lines);
|
||||
}
|
||||
}
|
29
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/LICENSE
vendored
Normal file
29
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/LICENSE
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2005, 2006, 2007 Nick Galbreath
|
||||
2006 til today Andreas Gohr and the DokuWiki community
|
||||
|
||||
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.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
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.
|
49
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/README.md
vendored
Normal file
49
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/README.md
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
# PHP JSStrip
|
||||
|
||||
This is a PHP port of Nick Galbreath's python tool [jsstrip.py](https://code.google.com/p/jsstrip/).
|
||||
|
||||
It was originally ported to PHP in 2006 as part of the [DokuWiki](http://www.dokuwiki.org) wiki engine. It has received several improvements over the years and is now available as a standalone library.
|
||||
|
||||
Quoting the original description:
|
||||
|
||||
jsstrip is a open-source library to remove whitespace and comments from a javascript file. You might want to do this to optimize size and performance, or to make a file harder to read. It typically makes 30-40% savings in file size.
|
||||
|
||||
**WARNING**
|
||||
|
||||
jsstrip is not a true javascript parser. It assumes you have properly delimited the 'end of line' using a ';' (semicolon).
|
||||
|
||||
* Yes `print 'foo'; print 'bar';`
|
||||
* No `print 'foo' print 'bar'`
|
||||
|
||||
You'll have to convert your code to use ';' first.
|
||||
|
||||
ALWAYS test the stripped version before deploying to production.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Install via composer
|
||||
|
||||
composer require splitbrain/php-jsstrip
|
||||
|
||||
## Usage
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
$js = file_get_contents('somefile.js'); // gather your JS here somehow
|
||||
|
||||
$minifiedJS = (new \splitbrain\JSStrip\JSStrip())->compress($js);
|
||||
```
|
||||
|
||||
## Skip Minification
|
||||
|
||||
You can skip Minification for parts of your code by surrounding it by special comments:
|
||||
|
||||
```js
|
||||
/* BEGIN NOCOMPRESS */
|
||||
const foo = 'No compression here'; // this comment will also stay
|
||||
/* END NOCOMPRESS */
|
||||
```
|
30
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/composer.json
vendored
Normal file
30
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/composer.json
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "splitbrain/php-jsstrip",
|
||||
"description": "PHP based JavaScript minimizer",
|
||||
"type": "library",
|
||||
"license": "BSD-3-Clause",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"splitbrain\\JSStrip\\tests\\": "tests/",
|
||||
"splitbrain\\JSStrip\\": "src/"
|
||||
}
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andreas Gohr",
|
||||
"email": "andi@splitbrain.org"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/splitbrain",
|
||||
"type": "github"
|
||||
}
|
||||
]
|
||||
}
|
1434
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/composer.lock
generated
vendored
Normal file
1434
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/composer.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/src/Exception.php
vendored
Normal file
7
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/src/Exception.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\JSStrip;
|
||||
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
254
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/src/JSStrip.php
vendored
Normal file
254
snippets/dokuwiki-2023-04-04/vendor/splitbrain/php-jsstrip/src/JSStrip.php
vendored
Normal file
@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
namespace splitbrain\JSStrip;
|
||||
|
||||
/**
|
||||
* Strip comments and whitespaces from given JavaScript Code
|
||||
*
|
||||
* This is a port of Nick Galbreath's python tool jsstrip.py which is
|
||||
* released under BSD license. See link for original code.
|
||||
*
|
||||
* @author Nick Galbreath <nickg@modp.com>
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @link http://code.google.com/p/jsstrip/
|
||||
*/
|
||||
class JSStrip
|
||||
{
|
||||
|
||||
const REGEX_STARTERS = [
|
||||
'(', '=', '<', '>', '?', '[', '{', ',', ';', ':', '!', '&', '|', '+', '-', '%', '~', '^',
|
||||
'return', 'yield', 'else', 'throw', 'await'
|
||||
];
|
||||
const WHITESPACE_CHARS = [" ", "\t", "\n", "\r", "\0", "\x0B"];
|
||||
|
||||
/** items that don't need spaces next to them */
|
||||
const CHARS = "^&|!+\-*\/%=\?:;,{}()<>% \t\n\r'\"`[]~^";
|
||||
|
||||
/**
|
||||
* items which need a space if the sign before and after whitespace is equal.
|
||||
* E.g. '+ ++' may not be compressed to '+++' --> syntax error.
|
||||
*/
|
||||
const OPS = "+-/";
|
||||
|
||||
protected $source;
|
||||
protected $idx = 0;
|
||||
protected $line = 0;
|
||||
|
||||
/**
|
||||
* Compress the given code
|
||||
*
|
||||
* @param string $source The JavaScript code to compress
|
||||
* @return string
|
||||
* @throws Exception if parsing fails
|
||||
*/
|
||||
function compress($source)
|
||||
{
|
||||
$source = ltrim($source); // strip all initial whitespace
|
||||
$source .= "\n";
|
||||
$idx = 0; // char index for input string
|
||||
|
||||
// track these as member variables
|
||||
$this->source = $source;
|
||||
$this->line = 1;
|
||||
$this->idx = &$idx;
|
||||
|
||||
$j = 0; // char forward index for input string
|
||||
$slen = strlen($source); // size of input string
|
||||
$lch = ''; // last char added
|
||||
$result = ''; // we store the final result here
|
||||
|
||||
|
||||
while ($idx < $slen) {
|
||||
// skip all "boring" characters. This is either
|
||||
// reserved word (e.g. "for", "else", "if") or a
|
||||
// variable/object/method (e.g. "foo.color")
|
||||
while ($idx < $slen && (strpos(self::CHARS, $source[$idx]) === false)) {
|
||||
$result .= $source[$idx];
|
||||
$idx = $idx + 1;
|
||||
}
|
||||
|
||||
$ch = $source[$idx];
|
||||
// multiline comments (keeping IE conditionals)
|
||||
if ($ch == '/' && $source[$idx + 1] == '*' && $source[$idx + 2] != '@') {
|
||||
$endC = strpos($source, '*/', $idx + 2);
|
||||
if ($endC === false) $this->fatal('Found invalid /*..*/ comment');
|
||||
|
||||
// check if this is a NOCOMPRESS comment
|
||||
if (substr($source, $idx, $endC + 2 - $idx) == '/* BEGIN NOCOMPRESS */') {
|
||||
// take nested NOCOMPRESS comments into account
|
||||
$depth = 0;
|
||||
$nextNC = $endC;
|
||||
do {
|
||||
$beginNC = strpos($source, '/* BEGIN NOCOMPRESS */', $nextNC + 2);
|
||||
$endNC = strpos($source, '/* END NOCOMPRESS */', $nextNC + 2);
|
||||
|
||||
if ($endNC === false) $this->fatal('Found invalid NOCOMPRESS comment');
|
||||
if ($beginNC !== false && $beginNC < $endNC) {
|
||||
$depth++;
|
||||
$nextNC = $beginNC;
|
||||
} else {
|
||||
$depth--;
|
||||
$nextNC = $endNC;
|
||||
}
|
||||
} while ($depth >= 0);
|
||||
|
||||
// verbatim copy contents, trimming but putting it on its own line
|
||||
$result .= "\n" . trim(substr($source, $idx + 22, $endNC - ($idx + 22))) . "\n"; // BEGIN comment = 22 chars
|
||||
$idx = $endNC + 20; // END comment = 20 chars
|
||||
} else {
|
||||
$idx = $endC + 2;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// singleline
|
||||
if ($ch == '/' && $source[$idx + 1] == '/') {
|
||||
$endC = strpos($source, "\n", $idx + 2);
|
||||
if ($endC === false) $this->fatal('Invalid comment'); // not sure this can happen
|
||||
$idx = $endC;
|
||||
continue;
|
||||
}
|
||||
|
||||
// tricky. might be an RE
|
||||
if ($ch == '/') {
|
||||
// rewind, skip white space
|
||||
$j = 1;
|
||||
while (in_array($source[$idx - $j], self::WHITESPACE_CHARS)) {
|
||||
$j = $j + 1;
|
||||
}
|
||||
if (current(array_filter(
|
||||
self::REGEX_STARTERS,
|
||||
function ($e) use ($source, $idx, $j) {
|
||||
$len = strlen($e);
|
||||
$idx = $idx - $j + 1 - $len;
|
||||
return substr($source, $idx, $len) === $e;
|
||||
}
|
||||
))) {
|
||||
// yes, this is an re
|
||||
// now move forward and find the end of it
|
||||
$j = 1;
|
||||
// we set this flag when inside a character class definition, enclosed by brackets [] where '/' does not terminate the re
|
||||
$ccd = false;
|
||||
while ($ccd || $source[$idx + $j] != '/') {
|
||||
if ($source[$idx + $j] == '\\') $j = $j + 2;
|
||||
else {
|
||||
$j++;
|
||||
// check if we entered/exited a character class definition and set flag accordingly
|
||||
if ($source[$idx + $j - 1] == '[') $ccd = true;
|
||||
else if ($source[$idx + $j - 1] == ']') $ccd = false;
|
||||
}
|
||||
}
|
||||
$result .= substr($source, $idx, $j + 1);
|
||||
$idx = $idx + $j + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// double quote strings
|
||||
if ($ch == '"') {
|
||||
$j = 1;
|
||||
while (($idx + $j < $slen) && $source[$idx + $j] != '"') {
|
||||
if ($source[$idx + $j] == '\\' && ($source[$idx + $j + 1] == '"' || $source[$idx + $j + 1] == '\\')) {
|
||||
$j += 2;
|
||||
} else {
|
||||
$j += 1;
|
||||
}
|
||||
}
|
||||
$string = substr($source, $idx, $j + 1);
|
||||
// remove multiline markers:
|
||||
$string = str_replace("\\\n", '', $string);
|
||||
$result .= $string;
|
||||
$idx = $idx + $j + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// single quote strings
|
||||
if ($ch == "'") {
|
||||
$j = 1;
|
||||
while (($idx + $j < $slen) && $source[$idx + $j] != "'") {
|
||||
if ($source[$idx + $j] == '\\' && ($source[$idx + $j + 1] == "'" || $source[$idx + $j + 1] == '\\')) {
|
||||
$j += 2;
|
||||
} else {
|
||||
$j += 1;
|
||||
}
|
||||
}
|
||||
$string = substr($source, $idx, $j + 1);
|
||||
// remove multiline markers:
|
||||
$string = str_replace("\\\n", '', $string);
|
||||
$result .= $string;
|
||||
$idx = $idx + $j + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// backtick strings
|
||||
if ($ch == "`") {
|
||||
$j = 1;
|
||||
while (($idx + $j < $slen) && $source[$idx + $j] != "`") {
|
||||
if ($source[$idx + $j] == '\\' && ($source[$idx + $j + 1] == "`" || $source[$idx + $j + 1] == '\\')) {
|
||||
$j += 2;
|
||||
} else {
|
||||
$j += 1;
|
||||
}
|
||||
}
|
||||
$string = substr($source, $idx, $j + 1);
|
||||
// remove multiline markers:
|
||||
$string = str_replace("\\\n", '', $string);
|
||||
$result .= $string;
|
||||
$idx = $idx + $j + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// whitespaces
|
||||
if ($ch == ' ' || $ch == "\r" || $ch == "\n" || $ch == "\t") {
|
||||
$lch = substr($result, -1);
|
||||
if ($ch == "\n") $this->line++;
|
||||
|
||||
// Only consider deleting whitespace if the signs before and after
|
||||
// are not equal and are not an operator which may not follow itself.
|
||||
if ($idx + 1 < $slen && ((!$lch || $source[$idx + 1] == ' ')
|
||||
|| $lch != $source[$idx + 1]
|
||||
|| strpos(self::OPS, $source[$idx + 1]) === false)) {
|
||||
// leading spaces
|
||||
if ($idx + 1 < $slen && (strpos(self::CHARS, $source[$idx + 1]) !== false)) {
|
||||
$idx = $idx + 1;
|
||||
continue;
|
||||
}
|
||||
// trailing spaces
|
||||
// if this ch is space AND the last char processed
|
||||
// is special, then skip the space
|
||||
if ($lch && (strpos(self::CHARS, $lch) !== false)) {
|
||||
$idx = $idx + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// else after all of this convert the "whitespace" to
|
||||
// a single space. It will get appended below
|
||||
$ch = ' ';
|
||||
}
|
||||
|
||||
// other chars
|
||||
$result .= $ch;
|
||||
$idx = $idx + 1;
|
||||
}
|
||||
|
||||
return trim($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to throw a fatal error
|
||||
*
|
||||
* Tries to give some context to locate the error
|
||||
*
|
||||
* @param string $msg
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function fatal($msg)
|
||||
{
|
||||
$before = substr($this->source, max(0, $this->idx - 15), $this->idx);
|
||||
$after = substr($this->source, $this->idx, 15);
|
||||
|
||||
$msg = "$msg on line {$this->line}: '{$before}◎{$after}'";
|
||||
throw new Exception($msg);
|
||||
}
|
||||
}
|
4
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/.gitattributes
vendored
Normal file
4
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/.gitattributes
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.xcf filter=lfs diff=lfs merge=lfs -text
|
||||
*.bmp filter=lfs diff=lfs merge=lfs -text
|
3
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/.gitignore
vendored
Normal file
3
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
vendor/
|
||||
artefacts/
|
||||
.phpunit.result.cache
|
7
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/LICENSE
vendored
Normal file
7
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/LICENSE
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
Copyright 2020 Andreas Gohr <andi@splitbrain.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
106
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/README.md
vendored
Normal file
106
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/README.md
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
# Slika - simple image handling for PHP
|
||||
|
||||
This is a library that covers only the bare basics you need when handling images:
|
||||
|
||||
* resizing
|
||||
* cropping
|
||||
* rotation
|
||||
|
||||
It can use either PHP's libGD or a locally installed ImageMagick binary.
|
||||
|
||||
## Installation
|
||||
|
||||
Use composer
|
||||
|
||||
composer require splitbrain/slika
|
||||
|
||||
## Usage
|
||||
|
||||
Simply get an Adapter from the Slika factory, run some operations on it and call `save`.
|
||||
|
||||
Operations can be chained together. Consider the chain to be one command. Do not reuse the adapter returned by `run()`, it is a single use object. All operations can potentially throw a `\splitbrain\slika\Exception`.
|
||||
|
||||
Options (see below) can be passed as a second parameter to the `run` factory.
|
||||
|
||||
```php
|
||||
use \splitbrain\slika\Slika;
|
||||
use \splitbrain\slika\Exception;
|
||||
|
||||
$options = [
|
||||
'quality' => 75
|
||||
];
|
||||
|
||||
try {
|
||||
Slika::run('input.png', $options)
|
||||
->resize(500,500)
|
||||
->rotate(Slika::ROTATE_CCW
|
||||
->save('output.jpg', 'jpg');
|
||||
} catch (Exception $e) {
|
||||
// conversion went wrong, handle it
|
||||
}
|
||||
```
|
||||
|
||||
Please also check the [API Docs](https://splitbrain.github.io/slika/) for details.
|
||||
|
||||
## Operations
|
||||
|
||||
### resize
|
||||
|
||||
All resize operations will keep the original aspect ratio of the image. There will be no distortion.
|
||||
|
||||
Keeping either width or height at zero will auto calculate the value for you.
|
||||
|
||||
```php
|
||||
# fit the image into a bounding box of 500x500 pixels
|
||||
Slika::run('input.jpg')->resize(500,500)->save('output.png', 'png');
|
||||
|
||||
# adjust the image to a maximum width of 500 pixels
|
||||
Slika::run('input.jpg')->resize(500,0)->save('output.png', 'png');
|
||||
|
||||
# adjust the image to a maximum height of 500 pixels
|
||||
Slika::run('input.jpg')->resize(0,500)->save('output.png', 'png');
|
||||
```
|
||||
|
||||
### crop
|
||||
|
||||
Similar to resizing, but this time the image will be cropped to fit the new aspect ratio.
|
||||
|
||||
```php
|
||||
Slika::run('input.jpg')->crop(500,500)->save('output.png', 'png');
|
||||
```
|
||||
|
||||
### rotate
|
||||
|
||||
Rotates the image. The parameter passed is one of the EXIF orientation flags:
|
||||
|
||||

|
||||
|
||||
For your convenience there are three Constants defined:
|
||||
|
||||
|
||||
* `Slika::ROTATE_CCW` counter clockwise rotation
|
||||
* `Slika::ROTATE_CW` clockwise rotation
|
||||
* `Slika::ROTATE_TOPDOWN` full 180 degree rotation
|
||||
|
||||
```php
|
||||
Slika::run('input.jpg')->rotate(Slika::ROTATE_CW)->save('output.png', 'png');
|
||||
```
|
||||
|
||||
### autorotate
|
||||
|
||||
Rotates the image according to the EXIF rotation tag if found.
|
||||
|
||||
```php
|
||||
Slika::run('input.jpg')->autorotate()->save('output.png', 'png');
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
Options can be passed as associatiave array as the second parameter in `Slika::run`.
|
||||
|
||||
The following options are availble currently:
|
||||
|
||||
| Option | Default | Description |
|
||||
|-------------|--------------------|--------------------------------------------|
|
||||
| `imconvert` | `/usr/bin/convert` | The path to ImageMagick's `convert` binary |
|
||||
| `quality` | `92` | The quality when writing JPEG images |
|
24
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/composer.json
vendored
Normal file
24
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/composer.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "splitbrain/slika",
|
||||
"description": "Simple image resizing",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andreas Gohr",
|
||||
"email": "andi@splitbrain.org"
|
||||
}
|
||||
],
|
||||
"suggest": {
|
||||
"ext-gd": "PHP's builtin image manipulation library. Alternatively use an installation of ImageMagick"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"splitbrain\\slika\\tests\\": "tests",
|
||||
"splitbrain\\slika\\": "src"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.0"
|
||||
}
|
||||
}
|
1787
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/composer.lock
generated
vendored
Normal file
1787
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/composer.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
89
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/Adapter.php
vendored
Normal file
89
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/Adapter.php
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace splitbrain\slika;
|
||||
|
||||
/**
|
||||
* Base class for image adapters. Defines what image processing adapters need to provide
|
||||
*/
|
||||
abstract class Adapter
|
||||
{
|
||||
/** @var string path tot he image */
|
||||
protected $imagepath;
|
||||
|
||||
/** @var array Adapter Options */
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* New Slika Adapter
|
||||
*
|
||||
* @param string $imagepath path to the original image
|
||||
* @param array $options set options
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($imagepath, $options = [])
|
||||
{
|
||||
if (!file_exists($imagepath)) {
|
||||
throw new Exception('image file does not exist');
|
||||
}
|
||||
|
||||
if (!is_readable($imagepath)) {
|
||||
throw new Exception('image file is not readable');
|
||||
}
|
||||
|
||||
$this->imagepath = $imagepath;
|
||||
$this->options = array_merge(Slika::DEFAULT_OPTIONS, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rote the image based on the rotation exif tag
|
||||
*
|
||||
* @return Adapter
|
||||
*/
|
||||
abstract public function autorotate();
|
||||
|
||||
/**
|
||||
* Rotate and/or flip the image
|
||||
*
|
||||
* This expects an orientation flag as stored in EXIF data. For typical operations,
|
||||
* Slika::ROTATE_* constants are defined.
|
||||
*
|
||||
* @param int $orientation Exif rotation flags
|
||||
* @return Adapter
|
||||
* @see https://stackoverflow.com/a/53697440 for info on the rotation constants
|
||||
*/
|
||||
abstract public function rotate($orientation);
|
||||
|
||||
/**
|
||||
* Resize to make image fit the given dimension (maintaining the aspect ratio)
|
||||
*
|
||||
* You may omit one of the dimensions to auto calculate it based on the aspect ratio
|
||||
*
|
||||
* @param int|string $width in pixels or %
|
||||
* @param int|string $height in pixels or %
|
||||
* @return Adapter
|
||||
*/
|
||||
abstract public function resize($width, $height);
|
||||
|
||||
|
||||
/**
|
||||
* Resize to the given dimension, cropping the image as needed
|
||||
*
|
||||
* You may omit one of the dimensions to use a square area
|
||||
*
|
||||
* @param int|string $width in pixels or %
|
||||
* @param int|string $height in pixels or %
|
||||
* @return Adapter
|
||||
*/
|
||||
abstract public function crop($width, $height);
|
||||
|
||||
/**
|
||||
* Save the new file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $extension The type of image to save, empty for original
|
||||
* @return void
|
||||
*/
|
||||
abstract public function save($path, $extension = '');
|
||||
|
||||
}
|
12
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/Exception.php
vendored
Normal file
12
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/Exception.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace splitbrain\slika;
|
||||
|
||||
/**
|
||||
* Exception thrown on all errors during image processing
|
||||
*/
|
||||
class Exception extends \Exception
|
||||
{
|
||||
|
||||
}
|
421
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/GdAdapter.php
vendored
Normal file
421
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/GdAdapter.php
vendored
Normal file
@ -0,0 +1,421 @@
|
||||
<?php /** @noinspection PhpComposerExtensionStubsInspection */
|
||||
|
||||
|
||||
namespace splitbrain\slika;
|
||||
|
||||
/**
|
||||
* Image processing adapter for PHP's libGD
|
||||
*/
|
||||
class GdAdapter extends Adapter
|
||||
{
|
||||
/** @var resource libGD image */
|
||||
protected $image;
|
||||
/** @var int width of the current image */
|
||||
protected $width = 0;
|
||||
/** @var int height of the current image */
|
||||
protected $height = 0;
|
||||
/** @var string the extension of the file we're working with */
|
||||
protected $extension;
|
||||
|
||||
|
||||
/** @inheritDoc */
|
||||
public function __construct($imagepath, $options = [])
|
||||
{
|
||||
parent::__construct($imagepath, $options);
|
||||
$this->image = $this->loadImage($imagepath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->image)) {
|
||||
imagedestroy($this->image);
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc
|
||||
* @throws Exception
|
||||
* @link https://gist.github.com/EionRobb/8e0c76178522bc963c75caa6a77d3d37#file-imagecreatefromstring_autorotate-php-L15
|
||||
*/
|
||||
public function autorotate()
|
||||
{
|
||||
if ($this->extension !== 'jpeg') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$orientation = 1;
|
||||
|
||||
if (function_exists('exif_read_data')) {
|
||||
// use PHP's exif capablities
|
||||
$exif = exif_read_data($this->imagepath);
|
||||
if (!empty($exif['Orientation'])) {
|
||||
$orientation = $exif['Orientation'];
|
||||
}
|
||||
} else {
|
||||
// grep the exif info from the raw contents
|
||||
// we read only the first 70k bytes
|
||||
$data = file_get_contents($this->imagepath, false, null, 0, 70000);
|
||||
if (preg_match('@\x12\x01\x03\x00\x01\x00\x00\x00(.)\x00\x00\x00@', $data, $matches)) {
|
||||
// Little endian EXIF
|
||||
$orientation = ord($matches[1]);
|
||||
} else if (preg_match('@\x01\x12\x00\x03\x00\x00\x00\x01\x00(.)\x00\x00@', $data, $matches)) {
|
||||
// Big endian EXIF
|
||||
$orientation = ord($matches[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->rotate($orientation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rotate($orientation)
|
||||
{
|
||||
$orientation = (int)$orientation;
|
||||
if ($orientation < 0 || $orientation > 8) {
|
||||
throw new Exception('Unknown rotation given');
|
||||
}
|
||||
|
||||
if ($orientation <= 1) {
|
||||
// no rotation wanted
|
||||
return $this;
|
||||
}
|
||||
|
||||
// fill color
|
||||
$transparency = imagecolorallocatealpha($this->image, 0, 0, 0, 127);
|
||||
|
||||
// rotate
|
||||
if (in_array($orientation, [3, 4])) {
|
||||
$image = imagerotate($this->image, 180, $transparency, 1);
|
||||
}
|
||||
if (in_array($orientation, [5, 6])) {
|
||||
$image = imagerotate($this->image, -90, $transparency, 1);
|
||||
list($this->width, $this->height) = [$this->height, $this->width];
|
||||
} elseif (in_array($orientation, [7, 8])) {
|
||||
$image = imagerotate($this->image, 90, $transparency, 1);
|
||||
list($this->width, $this->height) = [$this->height, $this->width];
|
||||
}
|
||||
/** @var resource $image is now defined */
|
||||
|
||||
// additionally flip
|
||||
if (in_array($orientation, [2, 5, 7, 4])) {
|
||||
imageflip($image, IMG_FLIP_HORIZONTAL);
|
||||
}
|
||||
|
||||
imagedestroy($this->image);
|
||||
$this->image = $image;
|
||||
|
||||
//keep png alpha channel if possible
|
||||
if ($this->extension == 'png' && function_exists('imagesavealpha')) {
|
||||
imagealphablending($this->image, false);
|
||||
imagesavealpha($this->image, true);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
public function resize($width, $height)
|
||||
{
|
||||
list($width, $height) = $this->boundingBox($width, $height);
|
||||
$this->resizeOperation($width, $height);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
public function crop($width, $height)
|
||||
{
|
||||
list($this->width, $this->height, $offsetX, $offsetY) = $this->cropPosition($width, $height);
|
||||
$this->resizeOperation($width, $height, $offsetX, $offsetY);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
public function save($path, $extension = '')
|
||||
{
|
||||
if ($extension === 'jpg') {
|
||||
$extension = 'jpeg';
|
||||
}
|
||||
if ($extension === '') {
|
||||
$extension = $this->extension;
|
||||
}
|
||||
$saver = 'image' . $extension;
|
||||
if (!function_exists($saver)) {
|
||||
throw new Exception('Can not save image format ' . $extension);
|
||||
}
|
||||
|
||||
if ($extension == 'jpeg') {
|
||||
imagejpeg($this->image, $path, $this->options['quality']);
|
||||
} else {
|
||||
$saver($this->image, $path);
|
||||
}
|
||||
|
||||
imagedestroy($this->image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize libGD on the given image
|
||||
*
|
||||
* @param string $path
|
||||
* @return resource
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function loadImage($path)
|
||||
{
|
||||
// Figure out the file info
|
||||
$info = getimagesize($path);
|
||||
if ($info === false) {
|
||||
throw new Exception('Failed to read image information');
|
||||
}
|
||||
$this->width = $info[0];
|
||||
$this->height = $info[1];
|
||||
|
||||
// what type of image is it?
|
||||
$this->extension = image_type_to_extension($info[2], false);
|
||||
$creator = 'imagecreatefrom' . $this->extension;
|
||||
if (!function_exists($creator)) {
|
||||
throw new Exception('Can not work with image format ' . $this->extension);
|
||||
}
|
||||
|
||||
// create the GD instance
|
||||
$image = @$creator($path);
|
||||
|
||||
if ($image === false) {
|
||||
throw new Exception('Failed to load image wiht libGD');
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new blank image to which we can copy
|
||||
*
|
||||
* Tries to set up alpha/transparency stuff correctly
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @return resource
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function createImage($width, $height)
|
||||
{
|
||||
// create a canvas to copy to, use truecolor if possible (except for gif)
|
||||
$canvas = false;
|
||||
if (function_exists('imagecreatetruecolor') && $this->extension != 'gif') {
|
||||
$canvas = @imagecreatetruecolor($width, $height);
|
||||
}
|
||||
if (!$canvas) {
|
||||
$canvas = @imagecreate($width, $height);
|
||||
}
|
||||
if (!$canvas) {
|
||||
throw new Exception('Failed to create new canvas');
|
||||
}
|
||||
|
||||
//keep png alpha channel if possible
|
||||
if ($this->extension == 'png' && function_exists('imagesavealpha')) {
|
||||
imagealphablending($canvas, false);
|
||||
imagesavealpha($canvas, true);
|
||||
}
|
||||
|
||||
//keep gif transparent color if possible
|
||||
if ($this->extension == 'gif' && function_exists('imagefill') && function_exists('imagecolorallocate')) {
|
||||
if (function_exists('imagecolorsforindex') && function_exists('imagecolortransparent')) {
|
||||
$transcolorindex = @imagecolortransparent($this->image);
|
||||
if ($transcolorindex >= 0) { //transparent color exists
|
||||
$transcolor = @imagecolorsforindex($this->image, $transcolorindex);
|
||||
$transcolorindex = @imagecolorallocate(
|
||||
$canvas,
|
||||
$transcolor['red'],
|
||||
$transcolor['green'],
|
||||
$transcolor['blue']
|
||||
);
|
||||
@imagefill($canvas, 0, 0, $transcolorindex);
|
||||
@imagecolortransparent($canvas, $transcolorindex);
|
||||
} else { //filling with white
|
||||
$whitecolorindex = @imagecolorallocate($canvas, 255, 255, 255);
|
||||
@imagefill($canvas, 0, 0, $whitecolorindex);
|
||||
}
|
||||
} else { //filling with white
|
||||
$whitecolorindex = @imagecolorallocate($canvas, 255, 255, 255);
|
||||
@imagefill($canvas, 0, 0, $whitecolorindex);
|
||||
}
|
||||
}
|
||||
|
||||
return $canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate new size
|
||||
*
|
||||
* If widht and height are given, the new size will be fit within this bounding box.
|
||||
* If only one value is given the other is adjusted to match according to the aspect ratio
|
||||
*
|
||||
* @param int $width width of the bounding box
|
||||
* @param int $height height of the bounding box
|
||||
* @return array (width, height)
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function boundingBox($width, $height)
|
||||
{
|
||||
$width = $this->cleanDimension($width, $this->width);
|
||||
$height = $this->cleanDimension($height, $this->height);
|
||||
|
||||
if ($width == 0 && $height == 0) {
|
||||
throw new Exception('You can not resize to 0x0');
|
||||
}
|
||||
|
||||
if (!$height) {
|
||||
// adjust to match width
|
||||
$height = round(($width * $this->height) / $this->width);
|
||||
} else if (!$width) {
|
||||
// adjust to match height
|
||||
$width = round(($height * $this->width) / $this->height);
|
||||
} else {
|
||||
// fit into bounding box
|
||||
$scale = min($width / $this->width, $height / $this->height);
|
||||
$width = $this->width * $scale;
|
||||
$height = $this->height * $scale;
|
||||
}
|
||||
|
||||
return [$width, $height];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the given Dimension is a proper pixel value
|
||||
*
|
||||
* When a percentage is given, the value is calculated based on the given original dimension
|
||||
*
|
||||
* @param int|string $dim New Dimension
|
||||
* @param int $orig Original dimension
|
||||
* @return int
|
||||
*/
|
||||
protected function cleanDimension($dim, $orig)
|
||||
{
|
||||
if ($dim && substr($dim, -1) == '%') {
|
||||
$dim = round($orig * ((float)$dim / 100));
|
||||
} else {
|
||||
$dim = (int)$dim;
|
||||
}
|
||||
|
||||
return $dim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates crop position
|
||||
*
|
||||
* Given the wanted final size, this calculates which exact area needs to be cut
|
||||
* from the original image to be then resized to the wanted dimensions.
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @return array (cropWidth, cropHeight, offsetX, offsetY)
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function cropPosition($width, $height)
|
||||
{
|
||||
if ($width == 0 && $height == 0) {
|
||||
throw new Exception('You can not crop to 0x0');
|
||||
}
|
||||
|
||||
if (!$height) {
|
||||
$height = $width;
|
||||
}
|
||||
|
||||
if (!$width) {
|
||||
$width = $height;
|
||||
}
|
||||
|
||||
// calculate ratios
|
||||
$oldRatio = $this->width / $this->height;
|
||||
$newRatio = $width / $height;
|
||||
|
||||
// calulate new size
|
||||
if ($newRatio >= 1) {
|
||||
if ($newRatio > $oldRatio) {
|
||||
$cropWidth = $this->width;
|
||||
$cropHeight = (int)($this->width / $newRatio);
|
||||
} else {
|
||||
$cropWidth = (int)($this->height * $newRatio);
|
||||
$cropHeight = $this->height;
|
||||
}
|
||||
} else {
|
||||
if ($newRatio < $oldRatio) {
|
||||
$cropWidth = (int)($this->height * $newRatio);
|
||||
$cropHeight = $this->height;
|
||||
} else {
|
||||
$cropWidth = $this->width;
|
||||
$cropHeight = (int)($this->width / $newRatio);
|
||||
}
|
||||
}
|
||||
|
||||
// calculate crop offset
|
||||
$offsetX = (int)(($this->width - $cropWidth) / 2);
|
||||
$offsetY = (int)(($this->height - $cropHeight) / 2);
|
||||
|
||||
return [$cropWidth, $cropHeight, $offsetX, $offsetY];
|
||||
}
|
||||
|
||||
/**
|
||||
* resize or crop images using PHP's libGD support
|
||||
*
|
||||
* @param int $toWidth desired width
|
||||
* @param int $toHeight desired height
|
||||
* @param int $offsetX offset of crop centre
|
||||
* @param int $offsetY offset of crop centre
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function resizeOperation($toWidth, $toHeight, $offsetX = 0, $offsetY = 0)
|
||||
{
|
||||
$newimg = $this->createImage($toWidth, $toHeight);
|
||||
|
||||
//try resampling first, fall back to resizing
|
||||
if (
|
||||
!function_exists('imagecopyresampled') ||
|
||||
!@imagecopyresampled(
|
||||
$newimg,
|
||||
$this->image,
|
||||
0,
|
||||
0,
|
||||
$offsetX,
|
||||
$offsetY,
|
||||
$toWidth,
|
||||
$toHeight,
|
||||
$this->width,
|
||||
$this->height
|
||||
)
|
||||
) {
|
||||
imagecopyresized(
|
||||
$newimg,
|
||||
$this->image,
|
||||
0,
|
||||
0,
|
||||
$offsetX,
|
||||
$offsetY,
|
||||
$toWidth,
|
||||
$toHeight,
|
||||
$this->width,
|
||||
$this->height
|
||||
);
|
||||
}
|
||||
|
||||
// destroy original GD image ressource and replace with new one
|
||||
imagedestroy($this->image);
|
||||
$this->image = $newimg;
|
||||
$this->width = $toWidth;
|
||||
$this->height = $toHeight;
|
||||
}
|
||||
|
||||
}
|
130
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/ImageMagickAdapter.php
vendored
Normal file
130
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/ImageMagickAdapter.php
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace splitbrain\slika;
|
||||
|
||||
/**
|
||||
* Image Processing Adapter for ImageMagick's command line utility `convert`
|
||||
*/
|
||||
class ImageMagickAdapter extends Adapter
|
||||
{
|
||||
/** @var array the CLI arguments to run imagemagick */
|
||||
protected $args = [];
|
||||
|
||||
/** @inheritDoc */
|
||||
public function __construct($imagepath, $options = [])
|
||||
{
|
||||
parent::__construct($imagepath, $options);
|
||||
|
||||
if (!is_executable($this->options['imconvert'])) {
|
||||
throw new Exception('Can not find or run ' . $this->options['imconvert']);
|
||||
}
|
||||
|
||||
$this->args[] = $this->options['imconvert'];
|
||||
$this->args[] = $imagepath;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public function autorotate()
|
||||
{
|
||||
$this->args[] = '-auto-orient';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public function rotate($orientation)
|
||||
{
|
||||
$orientation = (int)$orientation;
|
||||
if ($orientation < 0 || $orientation > 8) {
|
||||
throw new Exception('Unknown rotation given');
|
||||
}
|
||||
|
||||
// rotate
|
||||
$this->args[] = '-rotate';
|
||||
if (in_array($orientation, [3, 4])) {
|
||||
$this->args[] = '180';
|
||||
} elseif (in_array($orientation, [5, 6])) {
|
||||
$this->args[] = '90';
|
||||
} elseif (in_array($orientation, [7, 8])) {
|
||||
$this->args[] = '270';
|
||||
}
|
||||
|
||||
// additionally flip
|
||||
if (in_array($orientation, [2, 5, 7, 4])) {
|
||||
$this->args[] = '-flop';
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
public function resize($width, $height)
|
||||
{
|
||||
if ($width == 0 && $height == 0) {
|
||||
throw new Exception('You can not resize to 0x0');
|
||||
}
|
||||
if ($width == 0) $width = '';
|
||||
if ($height == 0) $height = '';
|
||||
|
||||
$size = $width . 'x' . $height;
|
||||
|
||||
$this->args[] = '-resize';
|
||||
$this->args[] = $size;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
public function crop($width, $height)
|
||||
{
|
||||
if ($width == 0 && $height == 0) {
|
||||
throw new Exception('You can not crop to 0x0');
|
||||
}
|
||||
|
||||
if ($width == 0) $width = $height;
|
||||
if ($height == 0) $height = $width;
|
||||
|
||||
$size = $width . 'x' . $height;
|
||||
|
||||
$this->args[] = '-resize';
|
||||
$this->args[] = "$size^";
|
||||
$this->args[] = '-gravity';
|
||||
$this->args[] = 'center';
|
||||
$this->args[] = '-crop';
|
||||
$this->args[] = "$size+0+0";
|
||||
$this->args[] = '+repage';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
public function save($path, $extension = '')
|
||||
{
|
||||
if ($extension === 'jpg') {
|
||||
$extension = 'jpeg';
|
||||
}
|
||||
|
||||
$this->args[] = '-quality';
|
||||
$this->args[] = $this->options['quality'];
|
||||
|
||||
if ($extension !== '') $path = $extension . ':' . $path;
|
||||
$this->args[] = $path;
|
||||
|
||||
$args = array_map('escapeshellarg', $this->args);
|
||||
|
||||
$cmd = join(' ', $args);
|
||||
$output = [];
|
||||
$return = 0;
|
||||
exec($cmd, $output, $return);
|
||||
|
||||
if ($return !== 0) {
|
||||
throw new Exception('ImageMagick returned non-zero exit code for ' . $cmd);
|
||||
}
|
||||
}
|
||||
}
|
55
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/Slika.php
vendored
Normal file
55
snippets/dokuwiki-2023-04-04/vendor/splitbrain/slika/src/Slika.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace splitbrain\slika;
|
||||
|
||||
/**
|
||||
* Factory to process an image using an available Adapter
|
||||
*/
|
||||
class Slika
|
||||
{
|
||||
/** rotate an image counter clock wise */
|
||||
const ROTATE_CCW = 8;
|
||||
/** rotate an image clock wise */
|
||||
const ROTATE_CW = 6;
|
||||
/** rotate on it's head */
|
||||
const ROTATE_TOPDOWN = 3;
|
||||
|
||||
/** these can be overwritten using the options array in run() */
|
||||
const DEFAULT_OPTIONS = [
|
||||
'quality' => 92,
|
||||
'imconvert' => '/usr/bin/convert',
|
||||
];
|
||||
|
||||
/**
|
||||
* This is a factory only, thus the constructor is private
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
// there is no constructor.
|
||||
}
|
||||
|
||||
/**
|
||||
* Start processing the image
|
||||
*
|
||||
* @param string $imagePath
|
||||
* @param array $options
|
||||
* @return Adapter
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function run($imagePath, $options = [])
|
||||
{
|
||||
$options = array_merge(self::DEFAULT_OPTIONS, $options);
|
||||
|
||||
if (is_executable($options['imconvert'])) {
|
||||
return new ImageMagickAdapter($imagePath, $options);
|
||||
}
|
||||
|
||||
if (function_exists('gd_info')) {
|
||||
return new GdAdapter($imagePath, $options);
|
||||
}
|
||||
|
||||
throw new Exception('No suitable Adapter found');
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user