first commit
This commit is contained in:
340
libraries/vendor/joomla/filesystem/LICENSE
vendored
Normal file
340
libraries/vendor/joomla/filesystem/LICENSE
vendored
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
13
libraries/vendor/joomla/filesystem/meta/language/en-GB/en-GB.lib_joomla_filesystem_patcher.ini
vendored
Normal file
13
libraries/vendor/joomla/filesystem/meta/language/en-GB/en-GB.lib_joomla_filesystem_patcher.ini
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
; Joomla! Project
|
||||
; Copyright (C) 2005 - 2016 Open Source Matters. All rights reserved.
|
||||
; License GNU General Public License version 2 or later; see LICENSE.txt
|
||||
; Note : All ini files need to be saved as UTF-8 - No BOM
|
||||
|
||||
JLIB_FILESYSTEM_PATCHER_FAILED_VERIFY="Failed source verification of file %s at line %d"
|
||||
JLIB_FILESYSTEM_PATCHER_INVALID_DIFF="Invalid unified diff block"
|
||||
JLIB_FILESYSTEM_PATCHER_INVALID_INPUT="Invalid input"
|
||||
JLIB_FILESYSTEM_PATCHER_UNEXISING_SOURCE="Unexisting source file"
|
||||
JLIB_FILESYSTEM_PATCHER_UNEXPECTED_ADD_LINE="Unexpected add line at line %d'"
|
||||
JLIB_FILESYSTEM_PATCHER_UNEXPECTED_EOF="Unexpected end of file"
|
||||
JLIB_FILESYSTEM_PATCHER_UNEXPECTED_REMOVE_LINE="Unexpected remove line at line %d"
|
||||
|
||||
186
libraries/vendor/joomla/filesystem/src/Buffer.php
vendored
Normal file
186
libraries/vendor/joomla/filesystem/src/Buffer.php
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Filesystem Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Filesystem;
|
||||
|
||||
/**
|
||||
* Generic Buffer stream handler
|
||||
*
|
||||
* This class provides a generic buffer stream. It can be used to store/retrieve/manipulate
|
||||
* string buffers with the standard PHP filesystem I/O methods.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class Buffer
|
||||
{
|
||||
/**
|
||||
* Stream position
|
||||
*
|
||||
* @var integer
|
||||
* @since 1.0
|
||||
*/
|
||||
public $position = 0;
|
||||
|
||||
/**
|
||||
* Buffer name
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* Buffer hash
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0
|
||||
*/
|
||||
public $buffers = [];
|
||||
|
||||
/**
|
||||
* Function to open file or url
|
||||
*
|
||||
* @param string $path The URL that was passed
|
||||
* @param string $mode Mode used to open the file @see fopen
|
||||
* @param integer $options Flags used by the API, may be STREAM_USE_PATH and STREAM_REPORT_ERRORS
|
||||
* @param string $openedPath Full path of the resource. Used with STREAN_USE_PATH option
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.0
|
||||
* @see streamWrapper::stream_open
|
||||
*/
|
||||
public function stream_open($path, $mode, $options, &$openedPath)
|
||||
{
|
||||
$url = parse_url($path);
|
||||
$this->name = $url['host'];
|
||||
$this->buffers[$this->name] = null;
|
||||
$this->position = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read stream
|
||||
*
|
||||
* @param integer $count How many bytes of data from the current position should be returned.
|
||||
*
|
||||
* @return mixed The data from the stream up to the specified number of bytes (all data if
|
||||
* the total number of bytes in the stream is less than $count. Null if
|
||||
* the stream is empty.
|
||||
*
|
||||
* @see streamWrapper::stream_read
|
||||
* @since 1.0
|
||||
*/
|
||||
public function stream_read($count)
|
||||
{
|
||||
$ret = substr($this->buffers[$this->name], $this->position, $count);
|
||||
$this->position += \strlen($ret);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write stream
|
||||
*
|
||||
* @param string $data The data to write to the stream.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @see streamWrapper::stream_write
|
||||
* @since 1.0
|
||||
*/
|
||||
public function stream_write($data)
|
||||
{
|
||||
$left = substr($this->buffers[$this->name], 0, $this->position);
|
||||
$right = substr($this->buffers[$this->name], $this->position + \strlen($data));
|
||||
$this->buffers[$this->name] = $left . $data . $right;
|
||||
$this->position += \strlen($data);
|
||||
|
||||
return \strlen($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the current position of the stream
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @see streamWrapper::stream_tell
|
||||
* @since 1.0
|
||||
*/
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to test for end of file pointer
|
||||
*
|
||||
* @return boolean True if the pointer is at the end of the stream
|
||||
*
|
||||
* @see streamWrapper::stream_eof
|
||||
* @since 1.0
|
||||
*/
|
||||
public function stream_eof()
|
||||
{
|
||||
return $this->position >= \strlen($this->buffers[$this->name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The read write position updates in response to $offset and $whence
|
||||
*
|
||||
* @param integer $offset The offset in bytes
|
||||
* @param integer $whence Position the offset is added to
|
||||
* Options are SEEK_SET, SEEK_CUR, and SEEK_END
|
||||
*
|
||||
* @return boolean True if updated
|
||||
*
|
||||
* @see streamWrapper::stream_seek
|
||||
* @since 1.0
|
||||
*/
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
switch ($whence) {
|
||||
case \SEEK_SET:
|
||||
if ($offset < \strlen($this->buffers[$this->name]) && $offset >= 0) {
|
||||
$this->position = $offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
case \SEEK_CUR:
|
||||
if ($offset >= 0) {
|
||||
$this->position += $offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
case \SEEK_END:
|
||||
if (\strlen($this->buffers[$this->name]) + $offset >= 0) {
|
||||
$this->position = \strlen($this->buffers[$this->name]) + $offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register the stream
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
stream_wrapper_register('buffer', 'Joomla\\Filesystem\\Buffer');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
1635
libraries/vendor/joomla/filesystem/src/Clients/FtpClient.php
vendored
Normal file
1635
libraries/vendor/joomla/filesystem/src/Clients/FtpClient.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
38
libraries/vendor/joomla/filesystem/src/Exception/FilesystemException.php
vendored
Normal file
38
libraries/vendor/joomla/filesystem/src/Exception/FilesystemException.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Filesystem Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Filesystem\Exception;
|
||||
|
||||
use Joomla\Filesystem\Path;
|
||||
|
||||
/**
|
||||
* Exception class for handling errors in the Filesystem package
|
||||
*
|
||||
* @since 1.2.0
|
||||
* @change 2.0.1 If the message contains a full path, the root path (JPATH_ROOT) is removed from it
|
||||
* to avoid any full path disclosure. Before 2.0.1, the path was propagated as provided.
|
||||
*/
|
||||
class FilesystemException extends \RuntimeException
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $message The message
|
||||
* @param integer $code The code
|
||||
* @param \Throwable|null $previous A previous exception
|
||||
*/
|
||||
public function __construct($message = "", $code = 0, \Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(
|
||||
Path::removeRoot($message),
|
||||
$code,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
346
libraries/vendor/joomla/filesystem/src/File.php
vendored
Normal file
346
libraries/vendor/joomla/filesystem/src/File.php
vendored
Normal file
@ -0,0 +1,346 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Filesystem Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Filesystem;
|
||||
|
||||
use Joomla\Filesystem\Exception\FilesystemException;
|
||||
|
||||
/**
|
||||
* A File handling class
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class File
|
||||
{
|
||||
/**
|
||||
* Gets the extension of a file name
|
||||
*
|
||||
* @param string $file The file name
|
||||
*
|
||||
* @return string The file extension
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function getExt($file)
|
||||
{
|
||||
// String manipulation should be faster than pathinfo() on newer PHP versions.
|
||||
$dot = strrpos($file, '.');
|
||||
|
||||
if ($dot === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$ext = substr($file, $dot + 1);
|
||||
|
||||
// Extension cannot contain slashes.
|
||||
if (strpos($ext, '/') !== false || (DIRECTORY_SEPARATOR === '\\' && strpos($ext, '\\') !== false)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips the last extension off of a file name
|
||||
*
|
||||
* @param string $file The file name
|
||||
*
|
||||
* @return string The file name without the extension
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function stripExt($file)
|
||||
{
|
||||
return preg_replace('#\.[^.]*$#', '', $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the file name safe to use
|
||||
*
|
||||
* @param string $file The name of the file [not full path]
|
||||
* @param array $stripChars Array of regex (by default will remove any leading periods)
|
||||
*
|
||||
* @return string The sanitised string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function makeSafe($file, array $stripChars = ['#^\.#'])
|
||||
{
|
||||
// Try transliterating the file name using the native php function
|
||||
if (function_exists('transliterator_transliterate') && function_exists('iconv')) {
|
||||
// Using iconv to ignore characters that can't be transliterated
|
||||
$file = iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", transliterator_transliterate('Any-Latin; Latin-ASCII', $file));
|
||||
}
|
||||
|
||||
$regex = array_merge(['#(\.){2,}#', '#[^A-Za-z0-9\.\_\- ]#'], $stripChars);
|
||||
$file = preg_replace($regex, '', $file);
|
||||
|
||||
// Remove any trailing dots, as those aren't ever valid file names.
|
||||
$file = rtrim($file, '.');
|
||||
|
||||
return trim($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a file
|
||||
*
|
||||
* @param string $src The path to the source file
|
||||
* @param string $dest The path to the destination file
|
||||
* @param string $path An optional base path to prefix to the file names
|
||||
* @param boolean $useStreams True to use streams
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws FilesystemException
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public static function copy($src, $dest, $path = null, $useStreams = false)
|
||||
{
|
||||
// Prepend a base path if it exists
|
||||
if ($path) {
|
||||
$src = Path::clean($path . '/' . $src);
|
||||
$dest = Path::clean($path . '/' . $dest);
|
||||
}
|
||||
|
||||
// Check src path
|
||||
if (!is_readable($src)) {
|
||||
throw new \UnexpectedValueException(
|
||||
sprintf(
|
||||
"%s: Cannot find or read file: %s",
|
||||
__METHOD__,
|
||||
Path::removeRoot($src)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($useStreams) {
|
||||
$stream = Stream::getStream();
|
||||
|
||||
if (!$stream->copy($src, $dest, null, false)) {
|
||||
throw new FilesystemException(sprintf('%1$s(%2$s, %3$s): %4$s', __METHOD__, $src, $dest, $stream->getError()));
|
||||
}
|
||||
|
||||
self::invalidateFileCache($dest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!@ copy($src, $dest)) {
|
||||
throw new FilesystemException(__METHOD__ . ': Copy failed.');
|
||||
}
|
||||
|
||||
self::invalidateFileCache($dest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file or array of files
|
||||
*
|
||||
* @param mixed $file The file name or an array of file names
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
public static function delete($file)
|
||||
{
|
||||
$files = (array) $file;
|
||||
|
||||
foreach ($files as $file) {
|
||||
$file = Path::clean($file);
|
||||
$filename = basename($file);
|
||||
|
||||
if (!Path::canChmod($file)) {
|
||||
throw new FilesystemException(__METHOD__ . ': Failed deleting inaccessible file ' . $filename);
|
||||
}
|
||||
|
||||
// Try making the file writable first. If it's read-only, it can't be deleted
|
||||
// on Windows, even if the parent folder is writable
|
||||
@chmod($file, 0777);
|
||||
|
||||
// In case of restricted permissions we zap it one way or the other
|
||||
// as long as the owner is either the webserver or the ftp
|
||||
if (!@ unlink($file)) {
|
||||
throw new FilesystemException(__METHOD__ . ': Failed deleting ' . $filename);
|
||||
}
|
||||
|
||||
self::invalidateFileCache($file);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a file
|
||||
*
|
||||
* @param string $src The path to the source file
|
||||
* @param string $dest The path to the destination file
|
||||
* @param string $path An optional base path to prefix to the file names
|
||||
* @param boolean $useStreams True to use streams
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
public static function move($src, $dest, $path = '', $useStreams = false)
|
||||
{
|
||||
if ($path) {
|
||||
$src = Path::clean($path . '/' . $src);
|
||||
$dest = Path::clean($path . '/' . $dest);
|
||||
}
|
||||
|
||||
// Check src path
|
||||
if (!is_readable($src)) {
|
||||
return 'Cannot find source file.';
|
||||
}
|
||||
|
||||
if ($useStreams) {
|
||||
$stream = Stream::getStream();
|
||||
|
||||
if (!$stream->move($src, $dest, null, false)) {
|
||||
throw new FilesystemException(__METHOD__ . ': ' . $stream->getError());
|
||||
}
|
||||
|
||||
self::invalidateFileCache($dest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!@ rename($src, $dest)) {
|
||||
throw new FilesystemException(__METHOD__ . ': Rename failed.');
|
||||
}
|
||||
|
||||
self::invalidateFileCache($dest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write contents to a file
|
||||
*
|
||||
* @param string $file The full file path
|
||||
* @param string $buffer The buffer to write
|
||||
* @param boolean $useStreams Use streams
|
||||
* @param boolean $appendToFile Append to the file and not overwrite it.
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function write($file, $buffer, $useStreams = false, $appendToFile = false)
|
||||
{
|
||||
if (\function_exists('set_time_limit'))
|
||||
{
|
||||
set_time_limit(ini_get('max_execution_time'));
|
||||
}
|
||||
|
||||
// If the destination directory doesn't exist we need to create it
|
||||
if (!file_exists(\dirname($file))) {
|
||||
Folder::create(\dirname($file));
|
||||
}
|
||||
|
||||
if ($useStreams) {
|
||||
$stream = Stream::getStream();
|
||||
|
||||
// Beef up the chunk size to a meg
|
||||
$stream->set('chunksize', (1024 * 1024));
|
||||
$stream->writeFile($file, $buffer, $appendToFile);
|
||||
|
||||
self::invalidateFileCache($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$file = Path::clean($file);
|
||||
|
||||
// Set the required flag to only append to the file and not overwrite it
|
||||
if ($appendToFile === true) {
|
||||
$res = \is_int(file_put_contents($file, $buffer, \FILE_APPEND));
|
||||
} else {
|
||||
$res = \is_int(file_put_contents($file, $buffer));
|
||||
}
|
||||
|
||||
self::invalidateFileCache($file);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves an uploaded file to a destination folder
|
||||
*
|
||||
* @param string $src The name of the php (temporary) uploaded file
|
||||
* @param string $dest The path (including filename) to move the uploaded file to
|
||||
* @param boolean $useStreams True to use streams
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
public static function upload($src, $dest, $useStreams = false)
|
||||
{
|
||||
// Ensure that the path is valid and clean
|
||||
$dest = Path::clean($dest);
|
||||
|
||||
// Create the destination directory if it does not exist
|
||||
$baseDir = \dirname($dest);
|
||||
|
||||
if (!is_dir($baseDir)) {
|
||||
Folder::create($baseDir);
|
||||
}
|
||||
|
||||
if ($useStreams) {
|
||||
$stream = Stream::getStream();
|
||||
|
||||
if (!$stream->upload($src, $dest, null, false)) {
|
||||
throw new FilesystemException(sprintf('%1$s(%2$s, %3$s): %4$s', __METHOD__, $src, $dest, $stream->getError()));
|
||||
}
|
||||
|
||||
self::invalidateFileCache($dest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_writable($baseDir) && move_uploaded_file($src, $dest)) {
|
||||
// Short circuit to prevent file permission errors
|
||||
if (Path::setPermissions($dest)) {
|
||||
self::invalidateFileCache($dest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new FilesystemException(__METHOD__ . ': Failed to change file permissions.');
|
||||
}
|
||||
|
||||
throw new FilesystemException(__METHOD__ . ': Failed to move file.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate any opcache for a newly written file immediately, if opcache* functions exist and if this was a PHP file.
|
||||
*
|
||||
* @param string $file The path to the file just written to, to flush from opcache
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function invalidateFileCache($file)
|
||||
{
|
||||
if (function_exists('opcache_invalidate')) {
|
||||
$info = pathinfo($file);
|
||||
|
||||
if (isset($info['extension']) && $info['extension'] === 'php') {
|
||||
// Force invalidation to be absolutely sure the opcache is cleared for this file.
|
||||
opcache_invalidate($file, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
551
libraries/vendor/joomla/filesystem/src/Folder.php
vendored
Normal file
551
libraries/vendor/joomla/filesystem/src/Folder.php
vendored
Normal file
@ -0,0 +1,551 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Filesystem Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Filesystem;
|
||||
|
||||
use Joomla\Filesystem\Exception\FilesystemException;
|
||||
|
||||
/**
|
||||
* A Folder handling class
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract class Folder
|
||||
{
|
||||
/**
|
||||
* Copy a folder.
|
||||
*
|
||||
* @param string $src The path to the source folder.
|
||||
* @param string $dest The path to the destination folder.
|
||||
* @param string $path An optional base path to prefix to the file names.
|
||||
* @param boolean $force Force copy.
|
||||
* @param boolean $useStreams Optionally force folder/file overwrites.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
public static function copy($src, $dest, $path = '', $force = false, $useStreams = false)
|
||||
{
|
||||
if (\function_exists('set_time_limit'))
|
||||
{
|
||||
set_time_limit(ini_get('max_execution_time'));
|
||||
}
|
||||
|
||||
if ($path) {
|
||||
$src = Path::clean($path . '/' . $src);
|
||||
$dest = Path::clean($path . '/' . $dest);
|
||||
}
|
||||
|
||||
// Eliminate trailing directory separators, if any
|
||||
$src = rtrim($src, \DIRECTORY_SEPARATOR);
|
||||
$dest = rtrim($dest, \DIRECTORY_SEPARATOR);
|
||||
|
||||
if (!is_dir(Path::clean($src))) {
|
||||
throw new FilesystemException('Source folder not found', -1);
|
||||
}
|
||||
|
||||
if (is_dir(Path::clean($dest)) && !$force) {
|
||||
throw new FilesystemException('Destination folder not found', -1);
|
||||
}
|
||||
|
||||
// Make sure the destination exists
|
||||
if (!self::create($dest)) {
|
||||
throw new FilesystemException('Cannot create destination folder', -1);
|
||||
}
|
||||
|
||||
if (!($dh = @opendir($src))) {
|
||||
throw new FilesystemException('Cannot open source folder', -1);
|
||||
}
|
||||
|
||||
// Walk through the directory copying files and recursing into folders.
|
||||
while (($file = readdir($dh)) !== false) {
|
||||
$sfid = $src . '/' . $file;
|
||||
$dfid = $dest . '/' . $file;
|
||||
|
||||
switch (filetype($sfid)) {
|
||||
case 'dir':
|
||||
if ($file != '.' && $file != '..') {
|
||||
$ret = self::copy($sfid, $dfid, null, $force, $useStreams);
|
||||
|
||||
if ($ret !== true) {
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'file':
|
||||
if ($useStreams) {
|
||||
Stream::getStream()->copy($sfid, $dfid);
|
||||
} else {
|
||||
if (!@copy($sfid, $dfid)) {
|
||||
throw new FilesystemException('Copy file failed', -1);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a folder -- and all necessary parent folders.
|
||||
*
|
||||
* @param string $path A path to create from the base path.
|
||||
* @param integer $mode Directory permissions to set for folders created. 0755 by default.
|
||||
*
|
||||
* @return boolean True if successful.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
public static function create($path = '', $mode = 0755)
|
||||
{
|
||||
static $nested = 0;
|
||||
|
||||
// Check to make sure the path valid and clean
|
||||
$path = Path::clean($path);
|
||||
|
||||
// Check if parent dir exists
|
||||
$parent = \dirname($path);
|
||||
|
||||
if (!is_dir(Path::clean($parent))) {
|
||||
// Prevent infinite loops!
|
||||
$nested++;
|
||||
|
||||
if (($nested > 20) || ($parent == $path)) {
|
||||
throw new FilesystemException(__METHOD__ . ': Infinite loop detected');
|
||||
}
|
||||
|
||||
try {
|
||||
// Create the parent directory
|
||||
if (self::create($parent, $mode) !== true) {
|
||||
// Folder::create throws an error
|
||||
$nested--;
|
||||
|
||||
return false;
|
||||
}
|
||||
} catch (FilesystemException $exception) {
|
||||
$nested--;
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
// OK, parent directory has been created
|
||||
$nested--;
|
||||
}
|
||||
|
||||
// Check if dir already exists
|
||||
if (is_dir(Path::clean($path))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We need to get and explode the open_basedir paths
|
||||
$obd = ini_get('open_basedir');
|
||||
|
||||
// If open_basedir is set we need to get the open_basedir that the path is in
|
||||
if ($obd != null) {
|
||||
if (\defined('PHP_WINDOWS_VERSION_MAJOR')) {
|
||||
$obdSeparator = ';';
|
||||
} else {
|
||||
$obdSeparator = ':';
|
||||
}
|
||||
|
||||
// Create the array of open_basedir paths
|
||||
$obdArray = explode($obdSeparator, $obd);
|
||||
$inBaseDir = false;
|
||||
|
||||
// Iterate through open_basedir paths looking for a match
|
||||
foreach ($obdArray as $test) {
|
||||
$test = Path::clean($test);
|
||||
|
||||
if (strpos($path, $test) === 0 || strpos($path, realpath($test)) === 0) {
|
||||
$inBaseDir = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($inBaseDir == false) {
|
||||
// Throw a FilesystemException because the path to be created is not in open_basedir
|
||||
throw new FilesystemException(__METHOD__ . ': Path not in open_basedir paths');
|
||||
}
|
||||
}
|
||||
|
||||
// First set umask
|
||||
$origmask = @umask(0);
|
||||
|
||||
// Create the path
|
||||
if (!$ret = @mkdir($path, $mode)) {
|
||||
@umask($origmask);
|
||||
|
||||
throw new FilesystemException(__METHOD__ . ': Could not create directory. Path: ' . $path);
|
||||
}
|
||||
|
||||
// Reset umask
|
||||
@umask($origmask);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a folder.
|
||||
*
|
||||
* @param string $path The path to the folder to delete.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws FilesystemException
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public static function delete($path)
|
||||
{
|
||||
if (\function_exists('set_time_limit'))
|
||||
{
|
||||
set_time_limit(ini_get('max_execution_time'));
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (!$path) {
|
||||
// Bad programmer! Bad Bad programmer!
|
||||
throw new FilesystemException(__METHOD__ . ': You can not delete a base directory.');
|
||||
}
|
||||
|
||||
// Check to make sure the path valid and clean
|
||||
$path = Path::clean($path);
|
||||
|
||||
// Is this really a folder?
|
||||
if (!is_dir($path)) {
|
||||
throw new \UnexpectedValueException(
|
||||
sprintf(
|
||||
'%1$s: Path is not a folder. Path: %2$s',
|
||||
__METHOD__,
|
||||
Path::removeRoot($path)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Remove all the files in folder if they exist; disable all filtering
|
||||
$files = self::files($path, '.', false, true, [], []);
|
||||
|
||||
if (!empty($files)) {
|
||||
if (File::delete($files) !== true) {
|
||||
// File::delete throws an error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove sub-folders of folder; disable all filtering
|
||||
$folders = self::folders($path, '.', false, true, [], []);
|
||||
|
||||
foreach ($folders as $folder) {
|
||||
if (is_link($folder)) {
|
||||
// Don't descend into linked directories, just delete the link.
|
||||
if (File::delete($folder) !== true) {
|
||||
// File::delete throws an error
|
||||
return false;
|
||||
}
|
||||
} elseif (self::delete($folder) !== true) {
|
||||
// Folder::delete throws an error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// In case of restricted permissions we zap it one way or the other as long as the owner is either the webserver or the ftp.
|
||||
if (@rmdir($path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new FilesystemException(sprintf('%1$s: Could not delete folder. Path: %2$s', __METHOD__, $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a folder.
|
||||
*
|
||||
* @param string $src The path to the source folder.
|
||||
* @param string $dest The path to the destination folder.
|
||||
* @param string $path An optional base path to prefix to the file names.
|
||||
* @param boolean $useStreams Optionally use streams.
|
||||
*
|
||||
* @return string|boolean Error message on false or boolean true on success.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function move($src, $dest, $path = '', $useStreams = false)
|
||||
{
|
||||
if ($path) {
|
||||
$src = Path::clean($path . '/' . $src);
|
||||
$dest = Path::clean($path . '/' . $dest);
|
||||
}
|
||||
|
||||
if (!is_dir(Path::clean($src))) {
|
||||
return 'Cannot find source folder';
|
||||
}
|
||||
|
||||
if (is_dir(Path::clean($dest))) {
|
||||
return 'Folder already exists';
|
||||
}
|
||||
|
||||
if ($useStreams) {
|
||||
Stream::getStream()->move($src, $dest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!@rename($src, $dest)) {
|
||||
return 'Rename failed';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to read the files in a folder.
|
||||
*
|
||||
* @param string $path The path of the folder to read.
|
||||
* @param string $filter A filter for file names.
|
||||
* @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth.
|
||||
* @param boolean $full True to return the full path to the file.
|
||||
* @param array $exclude Array with names of files which should not be shown in the result.
|
||||
* @param array $excludeFilter Array of filter to exclude
|
||||
* @param boolean $naturalSort False for asort, true for natsort
|
||||
*
|
||||
* @return array Files in the given folder.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public static function files(
|
||||
$path,
|
||||
$filter = '.',
|
||||
$recurse = false,
|
||||
$full = false,
|
||||
$exclude = ['.svn', 'CVS', '.DS_Store', '__MACOSX'],
|
||||
$excludeFilter = ['^\..*', '.*~'],
|
||||
$naturalSort = false
|
||||
) {
|
||||
// Check to make sure the path valid and clean
|
||||
$path = Path::clean($path);
|
||||
|
||||
// Is the path a folder?
|
||||
if (!is_dir($path)) {
|
||||
throw new \UnexpectedValueException(
|
||||
sprintf(
|
||||
'%1$s: Path is not a folder. Path: %2$s',
|
||||
__METHOD__,
|
||||
Path::removeRoot($path)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Compute the excludefilter string
|
||||
if (\count($excludeFilter)) {
|
||||
$excludeFilterString = '/(' . implode('|', $excludeFilter) . ')/';
|
||||
} else {
|
||||
$excludeFilterString = '';
|
||||
}
|
||||
|
||||
// Get the files
|
||||
$arr = self::_items($path, $filter, $recurse, $full, $exclude, $excludeFilterString, true);
|
||||
|
||||
// Sort the files based on either natural or alpha method
|
||||
if ($naturalSort) {
|
||||
natsort($arr);
|
||||
} else {
|
||||
asort($arr);
|
||||
}
|
||||
|
||||
return array_values($arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to read the folders in a folder.
|
||||
*
|
||||
* @param string $path The path of the folder to read.
|
||||
* @param string $filter A filter for folder names.
|
||||
* @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth.
|
||||
* @param boolean $full True to return the full path to the folders.
|
||||
* @param array $exclude Array with names of folders which should not be shown in the result.
|
||||
* @param array $excludeFilter Array with regular expressions matching folders which should not be shown in the result.
|
||||
*
|
||||
* @return array Folders in the given folder.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public static function folders(
|
||||
$path,
|
||||
$filter = '.',
|
||||
$recurse = false,
|
||||
$full = false,
|
||||
$exclude = ['.svn', 'CVS', '.DS_Store', '__MACOSX'],
|
||||
$excludeFilter = ['^\..*']
|
||||
) {
|
||||
// Check to make sure the path valid and clean
|
||||
$path = Path::clean($path);
|
||||
|
||||
// Is the path a folder?
|
||||
if (!is_dir($path)) {
|
||||
throw new \UnexpectedValueException(
|
||||
sprintf(
|
||||
'%1$s: Path is not a folder. Path: %2$s',
|
||||
__METHOD__,
|
||||
Path::removeRoot($path)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Compute the excludefilter string
|
||||
if (\count($excludeFilter)) {
|
||||
$excludeFilterString = '/(' . implode('|', $excludeFilter) . ')/';
|
||||
} else {
|
||||
$excludeFilterString = '';
|
||||
}
|
||||
|
||||
// Get the folders
|
||||
$arr = self::_items($path, $filter, $recurse, $full, $exclude, $excludeFilterString, false);
|
||||
|
||||
// Sort the folders
|
||||
asort($arr);
|
||||
|
||||
return array_values($arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to read the files/folders in a folder.
|
||||
*
|
||||
* @param string $path The path of the folder to read.
|
||||
* @param string $filter A filter for file names.
|
||||
* @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth.
|
||||
* @param boolean $full True to return the full path to the file.
|
||||
* @param array $exclude Array with names of files which should not be shown in the result.
|
||||
* @param string $excludeFilterString Regexp of files to exclude
|
||||
* @param boolean $findfiles True to read the files, false to read the folders
|
||||
*
|
||||
* @return array Files.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected static function _items($path, $filter, $recurse, $full, $exclude, $excludeFilterString, $findfiles)
|
||||
{
|
||||
if (\function_exists('set_time_limit'))
|
||||
{
|
||||
set_time_limit(ini_get('max_execution_time'));
|
||||
}
|
||||
|
||||
$arr = [];
|
||||
|
||||
// Read the source directory
|
||||
if (!($handle = @opendir($path))) {
|
||||
return $arr;
|
||||
}
|
||||
|
||||
while (($file = readdir($handle)) !== false) {
|
||||
if (
|
||||
$file != '.' && $file != '..' && !\in_array($file, $exclude)
|
||||
&& (empty($excludeFilterString) || !preg_match($excludeFilterString, $file))
|
||||
) {
|
||||
// Compute the fullpath
|
||||
$fullpath = Path::clean($path . '/' . $file);
|
||||
|
||||
// Compute the isDir flag
|
||||
$isDir = is_dir($fullpath);
|
||||
|
||||
if (($isDir xor $findfiles) && preg_match("/$filter/", $file)) {
|
||||
// (fullpath is dir and folders are searched or fullpath is not dir and files are searched) and file matches the filter
|
||||
if ($full) {
|
||||
// Full path is requested
|
||||
$arr[] = $fullpath;
|
||||
} else {
|
||||
// Filename is requested
|
||||
$arr[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isDir && $recurse) {
|
||||
// Search recursively
|
||||
if (\is_int($recurse)) {
|
||||
// Until depth 0 is reached
|
||||
$arr = array_merge($arr, self::_items($fullpath, $filter, $recurse - 1, $full, $exclude, $excludeFilterString, $findfiles));
|
||||
} else {
|
||||
$arr = array_merge($arr, self::_items($fullpath, $filter, $recurse, $full, $exclude, $excludeFilterString, $findfiles));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir($handle);
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists folder in format suitable for tree display.
|
||||
*
|
||||
* @param string $path The path of the folder to read.
|
||||
* @param string $filter A filter for folder names.
|
||||
* @param integer $maxLevel The maximum number of levels to recursively read, defaults to three.
|
||||
* @param integer $level The current level, optional.
|
||||
* @param integer $parent Unique identifier of the parent folder, if any.
|
||||
*
|
||||
* @return array Folders in the given folder.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function listFolderTree($path, $filter, $maxLevel = 3, $level = 0, $parent = 0)
|
||||
{
|
||||
$dirs = [];
|
||||
|
||||
if ($level == 0) {
|
||||
$GLOBALS['_JFolder_folder_tree_index'] = 0;
|
||||
}
|
||||
|
||||
if ($level < $maxLevel) {
|
||||
$folders = self::folders($path, $filter);
|
||||
|
||||
// First path, index foldernames
|
||||
foreach ($folders as $name) {
|
||||
$id = ++$GLOBALS['_JFolder_folder_tree_index'];
|
||||
$fullName = Path::clean($path . '/' . $name);
|
||||
$dirs[] = [
|
||||
'id' => $id,
|
||||
'parent' => $parent,
|
||||
'name' => $name,
|
||||
'fullname' => $fullName,
|
||||
'relname' => str_replace(JPATH_ROOT, '', $fullName),
|
||||
];
|
||||
$dirs2 = self::listFolderTree($fullName, $filter, $maxLevel, $level + 1, $id);
|
||||
$dirs = array_merge($dirs, $dirs2);
|
||||
}
|
||||
}
|
||||
|
||||
return $dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes path name safe to use.
|
||||
*
|
||||
* @param string $path The full path to sanitise.
|
||||
*
|
||||
* @return string The sanitised string.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function makeSafe($path)
|
||||
{
|
||||
$regex = ['#[^A-Za-z0-9_\\\/\(\)\[\]\{\}\#\$\^\+\.\'~`!@&=;,-]#'];
|
||||
|
||||
return preg_replace($regex, '', $path);
|
||||
}
|
||||
}
|
||||
280
libraries/vendor/joomla/filesystem/src/Helper.php
vendored
Normal file
280
libraries/vendor/joomla/filesystem/src/Helper.php
vendored
Normal file
@ -0,0 +1,280 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Filesystem Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Filesystem;
|
||||
|
||||
/**
|
||||
* File system helper
|
||||
*
|
||||
* Holds support functions for the filesystem, particularly the stream
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class Helper
|
||||
{
|
||||
/**
|
||||
* Remote file size function for streams that don't support it
|
||||
*
|
||||
* @param string $url TODO Add text
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @link https://www.php.net/manual/en/function.filesize.php#71098
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function remotefsize($url)
|
||||
{
|
||||
$sch = parse_url($url, \PHP_URL_SCHEME);
|
||||
|
||||
if (!\in_array($sch, ['http', 'https', 'ftp', 'ftps'], true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (\in_array($sch, ['http', 'https'], true)) {
|
||||
$headers = @ get_headers($url, 1);
|
||||
|
||||
if (!$headers || (!\array_key_exists('Content-Length', $headers))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $headers['Content-Length'];
|
||||
}
|
||||
|
||||
if (\in_array($sch, ['ftp', 'ftps'], true)) {
|
||||
$server = parse_url($url, \PHP_URL_HOST);
|
||||
$port = parse_url($url, \PHP_URL_PORT);
|
||||
$path = parse_url($url, \PHP_URL_PATH);
|
||||
$user = parse_url($url, \PHP_URL_USER);
|
||||
$pass = parse_url($url, \PHP_URL_PASS);
|
||||
|
||||
if ((!$server) || (!$path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$port) {
|
||||
$port = 21;
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
$user = 'anonymous';
|
||||
}
|
||||
|
||||
if (!$pass) {
|
||||
$pass = '';
|
||||
}
|
||||
|
||||
$ftpid = null;
|
||||
|
||||
switch ($sch) {
|
||||
case 'ftp':
|
||||
$ftpid = @ftp_connect($server, $port);
|
||||
|
||||
break;
|
||||
|
||||
case 'ftps':
|
||||
$ftpid = @ftp_ssl_connect($server, $port);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$ftpid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$login = @ftp_login($ftpid, $user, $pass);
|
||||
|
||||
if (!$login) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ftpsize = ftp_size($ftpid, $path);
|
||||
ftp_close($ftpid);
|
||||
|
||||
if ($ftpsize == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ftpsize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick FTP chmod
|
||||
*
|
||||
* @param string $url Link identifier
|
||||
* @param integer $mode The new permissions, given as an octal value.
|
||||
*
|
||||
* @return integer|boolean
|
||||
*
|
||||
* @link https://www.php.net/manual/en/function.ftp-chmod.php
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function ftpChmod($url, $mode)
|
||||
{
|
||||
$sch = parse_url($url, \PHP_URL_SCHEME);
|
||||
|
||||
if (($sch != 'ftp') && ($sch != 'ftps')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$server = parse_url($url, \PHP_URL_HOST);
|
||||
$port = parse_url($url, \PHP_URL_PORT);
|
||||
$path = parse_url($url, \PHP_URL_PATH);
|
||||
$user = parse_url($url, \PHP_URL_USER);
|
||||
$pass = parse_url($url, \PHP_URL_PASS);
|
||||
|
||||
if ((!$server) || (!$path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$port) {
|
||||
$port = 21;
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
$user = 'anonymous';
|
||||
}
|
||||
|
||||
if (!$pass) {
|
||||
$pass = '';
|
||||
}
|
||||
|
||||
$ftpid = null;
|
||||
|
||||
switch ($sch) {
|
||||
case 'ftp':
|
||||
$ftpid = @ftp_connect($server, $port);
|
||||
|
||||
break;
|
||||
|
||||
case 'ftps':
|
||||
$ftpid = @ftp_ssl_connect($server, $port);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$ftpid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$login = @ftp_login($ftpid, $user, $pass);
|
||||
|
||||
if (!$login) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$res = @ftp_chmod($ftpid, $mode, $path);
|
||||
ftp_close($ftpid);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modes that require a write operation
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function getWriteModes()
|
||||
{
|
||||
return ['w', 'w+', 'a', 'a+', 'r+', 'x', 'x+'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream and Filter Support Operations
|
||||
*
|
||||
* Returns the supported streams, in addition to direct file access
|
||||
* Also includes Joomla! streams as well as PHP streams
|
||||
*
|
||||
* @return array Streams
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function getSupported()
|
||||
{
|
||||
// Really quite cool what php can do with arrays when you let it...
|
||||
static $streams;
|
||||
|
||||
if (!$streams) {
|
||||
$streams = array_merge(stream_get_wrappers(), self::getJStreams());
|
||||
}
|
||||
|
||||
return $streams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of transports
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function getTransports()
|
||||
{
|
||||
// Is this overkill?
|
||||
return stream_get_transports();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of filters
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function getFilters()
|
||||
{
|
||||
// Note: This will look like the getSupported() function with J! filters.
|
||||
// TODO: add user space filter loading like user space stream loading
|
||||
return stream_get_filters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of J! streams
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function getJStreams()
|
||||
{
|
||||
static $streams = [];
|
||||
|
||||
if (!$streams) {
|
||||
$files = new \DirectoryIterator(__DIR__ . '/Stream');
|
||||
|
||||
/** @var \DirectoryIterator $file */
|
||||
foreach ($files as $file) {
|
||||
// Only load for php files.
|
||||
if (!$file->isFile() || $file->getExtension() != 'php') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$streams[] = $file->getBasename('.php');
|
||||
}
|
||||
}
|
||||
|
||||
return $streams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a stream is a Joomla stream.
|
||||
*
|
||||
* @param string $streamname The name of a stream
|
||||
*
|
||||
* @return boolean True for a Joomla Stream
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function isJoomlaStream($streamname)
|
||||
{
|
||||
return \in_array($streamname, self::getJStreams());
|
||||
}
|
||||
}
|
||||
516
libraries/vendor/joomla/filesystem/src/Patcher.php
vendored
Normal file
516
libraries/vendor/joomla/filesystem/src/Patcher.php
vendored
Normal file
@ -0,0 +1,516 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Filesystem Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Filesystem;
|
||||
|
||||
/**
|
||||
* A Unified Diff Format Patcher class
|
||||
*
|
||||
* @link http://sourceforge.net/projects/phppatcher/ This has been derived from the PhpPatcher version 0.1.1 written by Giuseppe Mazzotta
|
||||
* @since 1.0
|
||||
*/
|
||||
class Patcher
|
||||
{
|
||||
/**
|
||||
* Regular expression for searching source files
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public const SRC_FILE = '/^---\\s+(\\S+)\s+\\d{1,4}-\\d{1,2}-\\d{1,2}\\s+\\d{1,2}:\\d{1,2}:\\d{1,2}(\\.\\d+)?\\s+(\+|-)\\d{4}/A';
|
||||
|
||||
/**
|
||||
* Regular expression for searching destination files
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public const DST_FILE = '/^\\+\\+\\+\\s+(\\S+)\s+\\d{1,4}-\\d{1,2}-\\d{1,2}\\s+\\d{1,2}:\\d{1,2}:\\d{1,2}(\\.\\d+)?\\s+(\+|-)\\d{4}/A';
|
||||
|
||||
/**
|
||||
* Regular expression for searching hunks of differences
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public const HUNK = '/@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@($)/A';
|
||||
|
||||
/**
|
||||
* Regular expression for splitting lines
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public const SPLIT = '/(\r\n)|(\r)|(\n)/';
|
||||
|
||||
/**
|
||||
* Source files
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $sources = [];
|
||||
|
||||
/**
|
||||
* Destination files
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $destinations = [];
|
||||
|
||||
/**
|
||||
* Removal files
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $removals = [];
|
||||
|
||||
/**
|
||||
* Patches
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $patches = [];
|
||||
|
||||
/**
|
||||
* Singleton instance of this class
|
||||
*
|
||||
* @var Patcher
|
||||
* @since 1.0
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* The constructor is protected to force the use of Patcher::getInstance()
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a patcher
|
||||
*
|
||||
* @return Patcher an instance of the patcher
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!isset(static::$instance)) {
|
||||
static::$instance = new static();
|
||||
}
|
||||
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the pacher
|
||||
*
|
||||
* @return Patcher This object for chaining
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->sources = [];
|
||||
$this->destinations = [];
|
||||
$this->removals = [];
|
||||
$this->patches = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the patches
|
||||
*
|
||||
* @return integer The number of files patched
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function apply()
|
||||
{
|
||||
foreach ($this->patches as $patch) {
|
||||
// Separate the input into lines
|
||||
$lines = self::splitLines($patch['udiff']);
|
||||
|
||||
// Loop for each header
|
||||
while (self::findHeader($lines, $src, $dst)) {
|
||||
$done = false;
|
||||
|
||||
if ($patch['strip'] === null) {
|
||||
$src = $patch['root'] . preg_replace('#^([^/]*/)*#', '', $src);
|
||||
$dst = $patch['root'] . preg_replace('#^([^/]*/)*#', '', $dst);
|
||||
} else {
|
||||
$src = $patch['root'] . preg_replace('#^([^/]*/){' . (int) $patch['strip'] . '}#', '', $src);
|
||||
$dst = $patch['root'] . preg_replace('#^([^/]*/){' . (int) $patch['strip'] . '}#', '', $dst);
|
||||
}
|
||||
|
||||
// Loop for each hunk of differences
|
||||
while (self::findHunk($lines, $srcLine, $srcSize, $dstLine, $dstSize)) {
|
||||
$done = true;
|
||||
|
||||
// Apply the hunk of differences
|
||||
$this->applyHunk($lines, $src, $dst, $srcLine, $srcSize, $dstLine, $dstSize);
|
||||
}
|
||||
|
||||
// If no modifications were found, throw an exception
|
||||
if (!$done) {
|
||||
throw new \RuntimeException('Invalid Diff');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the counter
|
||||
$done = 0;
|
||||
|
||||
// Patch each destination file
|
||||
foreach ($this->destinations as $file => $content) {
|
||||
$content = implode("\n", $content);
|
||||
|
||||
if (File::write($file, $content)) {
|
||||
if (isset($this->sources[$file])) {
|
||||
$this->sources[$file] = $content;
|
||||
}
|
||||
|
||||
$done++;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove each removed file
|
||||
foreach ($this->removals as $file) {
|
||||
if (File::delete($file)) {
|
||||
if (isset($this->sources[$file])) {
|
||||
unset($this->sources[$file]);
|
||||
}
|
||||
|
||||
$done++;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the destinations cache
|
||||
$this->destinations = [];
|
||||
|
||||
// Clear the removals
|
||||
$this->removals = [];
|
||||
|
||||
// Clear the patches
|
||||
$this->patches = [];
|
||||
|
||||
return $done;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a unified diff file to the patcher
|
||||
*
|
||||
* @param string $filename Path to the unified diff file
|
||||
* @param string $root The files root path
|
||||
* @param integer $strip The number of '/' to strip
|
||||
*
|
||||
* @return Patcher $this for chaining
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function addFile($filename, $root, $strip = 0)
|
||||
{
|
||||
return $this->add(file_get_contents($filename), $root, $strip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a unified diff string to the patcher
|
||||
*
|
||||
* @param string $udiff Unified diff input string
|
||||
* @param string $root The files root path
|
||||
* @param integer $strip The number of '/' to strip
|
||||
*
|
||||
* @return Patcher $this for chaining
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function add($udiff, $root, $strip = 0)
|
||||
{
|
||||
$this->patches[] = [
|
||||
'udiff' => $udiff,
|
||||
'root' => isset($root) ? rtrim($root, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR : '',
|
||||
'strip' => $strip,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Separate CR or CRLF lines
|
||||
*
|
||||
* @param string $data Input string
|
||||
*
|
||||
* @return array The lines of the input destination file
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected static function splitLines($data)
|
||||
{
|
||||
return preg_split(self::SPLIT, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the diff header
|
||||
*
|
||||
* The internal array pointer of $lines is on the next line after the finding
|
||||
*
|
||||
* @param array $lines The udiff array of lines
|
||||
* @param string $src The source file
|
||||
* @param string $dst The destination file
|
||||
*
|
||||
* @return boolean TRUE in case of success, FALSE in case of failure
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected static function findHeader(&$lines, &$src, &$dst)
|
||||
{
|
||||
// Get the current line
|
||||
$line = current($lines);
|
||||
|
||||
// Search for the header
|
||||
while ($line !== false && !preg_match(self::SRC_FILE, $line, $m)) {
|
||||
$line = next($lines);
|
||||
}
|
||||
|
||||
if ($line === false) {
|
||||
// No header found, return false
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the source file
|
||||
$src = $m[1];
|
||||
|
||||
// Advance to the next line
|
||||
$line = next($lines);
|
||||
|
||||
if ($line === false) {
|
||||
throw new \RuntimeException('Unexpected EOF');
|
||||
}
|
||||
|
||||
// Search the destination file
|
||||
if (!preg_match(self::DST_FILE, $line, $m)) {
|
||||
throw new \RuntimeException('Invalid Diff file');
|
||||
}
|
||||
|
||||
// Set the destination file
|
||||
$dst = $m[1];
|
||||
|
||||
// Advance to the next line
|
||||
if (next($lines) === false) {
|
||||
throw new \RuntimeException('Unexpected EOF');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the next hunk of difference
|
||||
*
|
||||
* The internal array pointer of $lines is on the next line after the finding
|
||||
*
|
||||
* @param array $lines The udiff array of lines
|
||||
* @param string $srcLine The beginning of the patch for the source file
|
||||
* @param string $srcSize The size of the patch for the source file
|
||||
* @param string $dstLine The beginning of the patch for the destination file
|
||||
* @param string $dstSize The size of the patch for the destination file
|
||||
*
|
||||
* @return boolean TRUE in case of success, false in case of failure
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected static function findHunk(&$lines, &$srcLine, &$srcSize, &$dstLine, &$dstSize)
|
||||
{
|
||||
$line = current($lines);
|
||||
|
||||
if (preg_match(self::HUNK, $line, $m)) {
|
||||
$srcLine = (int) $m[1];
|
||||
|
||||
if ($m[3] === '') {
|
||||
$srcSize = 1;
|
||||
} else {
|
||||
$srcSize = (int) $m[3];
|
||||
}
|
||||
|
||||
$dstLine = (int) $m[4];
|
||||
|
||||
if ($m[6] === '') {
|
||||
$dstSize = 1;
|
||||
} else {
|
||||
$dstSize = (int) $m[6];
|
||||
}
|
||||
|
||||
if (next($lines) === false) {
|
||||
throw new \RuntimeException('Unexpected EOF');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the patch
|
||||
*
|
||||
* @param array $lines The udiff array of lines
|
||||
* @param string $src The source file
|
||||
* @param string $dst The destination file
|
||||
* @param string $srcLine The beginning of the patch for the source file
|
||||
* @param string $srcSize The size of the patch for the source file
|
||||
* @param string $dstLine The beginning of the patch for the destination file
|
||||
* @param string $dstSize The size of the patch for the destination file
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function applyHunk(&$lines, $src, $dst, $srcLine, $srcSize, $dstLine, $dstSize)
|
||||
{
|
||||
$srcLine--;
|
||||
$dstLine--;
|
||||
$line = current($lines);
|
||||
|
||||
// Source lines (old file)
|
||||
$source = [];
|
||||
|
||||
// New lines (new file)
|
||||
$destin = [];
|
||||
$srcLeft = $srcSize;
|
||||
$dstLeft = $dstSize;
|
||||
|
||||
do {
|
||||
if (!isset($line[0])) {
|
||||
$source[] = '';
|
||||
$destin[] = '';
|
||||
$srcLeft--;
|
||||
$dstLeft--;
|
||||
} elseif ($line[0] == '-') {
|
||||
if ($srcLeft == 0) {
|
||||
throw new \RuntimeException('Unexpected remove line at line ' . key($lines));
|
||||
}
|
||||
|
||||
$source[] = substr($line, 1);
|
||||
$srcLeft--;
|
||||
} elseif ($line[0] == '+') {
|
||||
if ($dstLeft == 0) {
|
||||
throw new \RuntimeException('Unexpected add line at line ' . key($lines));
|
||||
}
|
||||
|
||||
$destin[] = substr($line, 1);
|
||||
$dstLeft--;
|
||||
} elseif ($line != '\\ No newline at end of file') {
|
||||
$line = substr($line, 1);
|
||||
$source[] = $line;
|
||||
$destin[] = $line;
|
||||
$srcLeft--;
|
||||
$dstLeft--;
|
||||
}
|
||||
|
||||
if ($srcLeft == 0 && $dstLeft == 0) {
|
||||
// Now apply the patch, finally!
|
||||
if ($srcSize > 0) {
|
||||
$srcLines = & $this->getSource($src);
|
||||
|
||||
if (!isset($srcLines)) {
|
||||
throw new \RuntimeException(
|
||||
'Unexisting source file: ' . Path::removeRoot($src)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($dstSize > 0) {
|
||||
if ($srcSize > 0) {
|
||||
$dstLines = & $this->getDestination($dst, $src);
|
||||
$srcBottom = $srcLine + \count($source);
|
||||
|
||||
for ($l = $srcLine; $l < $srcBottom; $l++) {
|
||||
if ($srcLines[$l] != $source[$l - $srcLine]) {
|
||||
throw new \RuntimeException(
|
||||
sprintf(
|
||||
'Failed source verification of file %1$s at line %2$s',
|
||||
Path::removeRoot($src),
|
||||
$l
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
array_splice($dstLines, $dstLine, \count($source), $destin);
|
||||
} else {
|
||||
$this->destinations[$dst] = $destin;
|
||||
}
|
||||
} else {
|
||||
$this->removals[] = $src;
|
||||
}
|
||||
|
||||
next($lines);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$line = next($lines);
|
||||
} while ($line !== false);
|
||||
|
||||
throw new \RuntimeException('Unexpected EOF');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lines of a source file
|
||||
*
|
||||
* @param string $src The path of a file
|
||||
*
|
||||
* @return array The lines of the source file
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function &getSource($src)
|
||||
{
|
||||
if (!isset($this->sources[$src])) {
|
||||
if (is_readable($src)) {
|
||||
$this->sources[$src] = self::splitLines(file_get_contents($src));
|
||||
} else {
|
||||
$this->sources[$src] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->sources[$src];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lines of a destination file
|
||||
*
|
||||
* @param string $dst The path of a destination file
|
||||
* @param string $src The path of a source file
|
||||
*
|
||||
* @return array The lines of the destination file
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function &getDestination($dst, $src)
|
||||
{
|
||||
if (!isset($this->destinations[$dst])) {
|
||||
$this->destinations[$dst] = $this->getSource($src);
|
||||
}
|
||||
|
||||
return $this->destinations[$dst];
|
||||
}
|
||||
}
|
||||
372
libraries/vendor/joomla/filesystem/src/Path.php
vendored
Normal file
372
libraries/vendor/joomla/filesystem/src/Path.php
vendored
Normal file
@ -0,0 +1,372 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Filesystem Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Filesystem;
|
||||
|
||||
use Joomla\Filesystem\Exception\FilesystemException;
|
||||
|
||||
/**
|
||||
* A Path handling class
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class Path
|
||||
{
|
||||
/**
|
||||
* Checks if a path's permissions can be changed.
|
||||
*
|
||||
* @param string $path Path to check.
|
||||
*
|
||||
* @return boolean True if path can have mode changed.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function canChmod($path)
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$perms = @fileperms($path);
|
||||
|
||||
if ($perms !== false) {
|
||||
if (@chmod($path, $perms ^ 0001)) {
|
||||
@chmod($path, $perms);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chmods files and directories recursively to given permissions.
|
||||
*
|
||||
* @param string $path Root path to begin changing mode [without trailing slash].
|
||||
* @param string $filemode Octal representation of the value to change file mode to [null = no change].
|
||||
* @param string $foldermode Octal representation of the value to change folder mode to [null = no change].
|
||||
*
|
||||
* @return boolean True if successful [one fail means the whole operation failed].
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function setPermissions($path, $filemode = '0644', $foldermode = '0755')
|
||||
{
|
||||
// Initialise return value
|
||||
$ret = true;
|
||||
|
||||
if (is_dir($path)) {
|
||||
$dh = @opendir($path);
|
||||
|
||||
if ($dh) {
|
||||
while ($file = readdir($dh)) {
|
||||
if ($file != '.' && $file != '..') {
|
||||
$fullpath = $path . '/' . $file;
|
||||
|
||||
if (is_dir($fullpath)) {
|
||||
if (!static::setPermissions($fullpath, $filemode, $foldermode)) {
|
||||
$ret = false;
|
||||
}
|
||||
} else {
|
||||
if (isset($filemode)) {
|
||||
if (!static::canChmod($fullpath) || !@ chmod($fullpath, octdec($filemode))) {
|
||||
$ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir($dh);
|
||||
}
|
||||
|
||||
if (isset($foldermode)) {
|
||||
if (!static::canChmod($path) || !@ chmod($path, octdec($foldermode))) {
|
||||
$ret = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isset($filemode)) {
|
||||
if (!static::canChmod($path) || !@ chmod($path, octdec($filemode))) {
|
||||
$ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the permissions of the file/folder at a give path.
|
||||
*
|
||||
* @param string $path The path of a file/folder.
|
||||
*
|
||||
* @return string Filesystem permissions.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function getPermissions($path)
|
||||
{
|
||||
$path = self::clean($path);
|
||||
$mode = @ decoct(@ fileperms($path) & 0777);
|
||||
|
||||
if (\strlen($mode) < 3) {
|
||||
return '---------';
|
||||
}
|
||||
|
||||
$parsedMode = '';
|
||||
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
// Read
|
||||
$parsedMode .= ($mode[$i] & 04) ? 'r' : '-';
|
||||
|
||||
// Write
|
||||
$parsedMode .= ($mode[$i] & 02) ? 'w' : '-';
|
||||
|
||||
// Execute
|
||||
$parsedMode .= ($mode[$i] & 01) ? 'x' : '-';
|
||||
}
|
||||
|
||||
return $parsedMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for snooping outside of the file system root.
|
||||
*
|
||||
* @param string $path A file system path to check.
|
||||
* @param string $basePath The base path of the system
|
||||
*
|
||||
* @return string A cleaned version of the path or exit on error.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
public static function check($path, $basePath = '')
|
||||
{
|
||||
if (strpos($path, '..') !== false) {
|
||||
throw new FilesystemException(
|
||||
sprintf(
|
||||
'%s() - Use of relative paths not permitted',
|
||||
__METHOD__
|
||||
),
|
||||
20
|
||||
);
|
||||
}
|
||||
|
||||
$path = static::clean($path);
|
||||
|
||||
// If a base path is defined then check the cleaned path is not outside of root
|
||||
if (($basePath != '') && strpos($path, static::clean($basePath)) !== 0) {
|
||||
throw new FilesystemException(
|
||||
sprintf(
|
||||
'%1$s() - Snooping out of bounds @ %2$s',
|
||||
__METHOD__,
|
||||
$path
|
||||
),
|
||||
20
|
||||
);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to strip additional / or \ in a path name.
|
||||
*
|
||||
* @param string $path The path to clean.
|
||||
* @param string $ds Directory separator (optional).
|
||||
*
|
||||
* @return string The cleaned path.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \UnexpectedValueException If $path is not a string.
|
||||
*/
|
||||
public static function clean($path, $ds = \DIRECTORY_SEPARATOR)
|
||||
{
|
||||
if (!\is_string($path)) {
|
||||
throw new \InvalidArgumentException('You must specify a non-empty path to clean');
|
||||
}
|
||||
|
||||
$stream = explode('://', $path, 2);
|
||||
$scheme = '';
|
||||
$path = $stream[0];
|
||||
|
||||
if (\count($stream) >= 2) {
|
||||
$scheme = $stream[0] . '://';
|
||||
$path = $stream[1];
|
||||
}
|
||||
|
||||
$path = trim($path);
|
||||
|
||||
// Remove double slashes and backslashes and convert all slashes and backslashes to DIRECTORY_SEPARATOR
|
||||
// If dealing with a UNC path don't forget to prepend the path with a backslash.
|
||||
if (($ds == '\\') && ($path[0] == '\\') && ($path[1] == '\\')) {
|
||||
$path = '\\' . preg_replace('#[/\\\\]+#', $ds, $path);
|
||||
} else {
|
||||
$path = preg_replace('#[/\\\\]+#', $ds, $path);
|
||||
}
|
||||
|
||||
return $scheme . $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to determine if script owns the path.
|
||||
*
|
||||
* @param string $path Path to check ownership.
|
||||
*
|
||||
* @return boolean True if the php script owns the path passed.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function isOwner($path)
|
||||
{
|
||||
$tmp = md5(random_bytes(16));
|
||||
$ssp = ini_get('session.save_path');
|
||||
|
||||
// Try to find a writable directory
|
||||
$dir = is_writable('/tmp') ? '/tmp' : false;
|
||||
$dir = !$dir && is_writable('.') ? '.' : $dir;
|
||||
$dir = !$dir && is_writable($ssp) ? $ssp : $dir;
|
||||
|
||||
if ($dir) {
|
||||
$test = $dir . '/' . $tmp;
|
||||
|
||||
// Create the test file
|
||||
$blank = '';
|
||||
File::write($test, $blank, false);
|
||||
|
||||
// Test ownership
|
||||
$return = fileowner($test) === fileowner($path);
|
||||
|
||||
// Delete the test file
|
||||
File::delete($test);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the directory paths for a given file.
|
||||
*
|
||||
* @param mixed $paths A path string or array of path strings to search in
|
||||
* @param string $file The file name to look for.
|
||||
*
|
||||
* @return string|boolean The full path and file name for the target file, or boolean false if the file is not found in any of the paths.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function find($paths, $file)
|
||||
{
|
||||
// Force to array
|
||||
if (!\is_array($paths) && !($paths instanceof \Iterator)) {
|
||||
settype($paths, 'array');
|
||||
}
|
||||
|
||||
// Start looping through the path set
|
||||
foreach ($paths as $path) {
|
||||
// Get the path to the file
|
||||
$fullname = $path . '/' . $file;
|
||||
|
||||
// Is the path based on a stream?
|
||||
if (strpos($path, '://') === false) {
|
||||
// Not a stream, so do a realpath() to avoid directory
|
||||
// traversal attempts on the local file system.
|
||||
|
||||
// Needed for substr() later
|
||||
$path = realpath($path);
|
||||
$fullname = realpath($fullname);
|
||||
}
|
||||
|
||||
/*
|
||||
* The substr() check added to make sure that the realpath()
|
||||
* results in a directory registered so that
|
||||
* non-registered directories are not accessible via directory
|
||||
* traversal attempts.
|
||||
*/
|
||||
if (file_exists($fullname) && substr($fullname, 0, \strlen($path)) == $path) {
|
||||
return $fullname;
|
||||
}
|
||||
}
|
||||
|
||||
// Could not find the file in the set of paths
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves /./, /../ and multiple / in a string and returns the resulting absolute path, inspired by Flysystem
|
||||
* Removes trailing slashes
|
||||
*
|
||||
* @param string $path A path to resolve
|
||||
*
|
||||
* @return string The resolved path
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public static function resolve($path)
|
||||
{
|
||||
$path = static::clean($path);
|
||||
|
||||
// Save start character for absolute path
|
||||
$startCharacter = ($path[0] === DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : '';
|
||||
|
||||
$parts = [];
|
||||
|
||||
foreach (explode(DIRECTORY_SEPARATOR, $path) as $part) {
|
||||
switch ($part) {
|
||||
case '':
|
||||
case '.':
|
||||
break;
|
||||
|
||||
case '..':
|
||||
if (empty($parts)) {
|
||||
throw new FilesystemException('Path is outside of the defined root');
|
||||
}
|
||||
|
||||
array_pop($parts);
|
||||
break;
|
||||
|
||||
default:
|
||||
$parts[] = $part;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $startCharacter . implode(DIRECTORY_SEPARATOR, $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all references to root directory path and the system tmp path from a message
|
||||
*
|
||||
* @param string $message The message to be cleaned
|
||||
* @param string $rootDirectory Optional root directory, defaults to JPATH_ROOT
|
||||
*
|
||||
* @return string
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public static function removeRoot($message, $rootDirectory = null)
|
||||
{
|
||||
if (empty($rootDirectory)) {
|
||||
$rootDirectory = JPATH_ROOT;
|
||||
}
|
||||
|
||||
$makePattern = static function ($dir) {
|
||||
return '~' . str_replace('~', '\\~', preg_replace('~[/\\\\]+~', '.', $dir)) . '~';
|
||||
};
|
||||
|
||||
$replacements = [
|
||||
$makePattern(static::clean($rootDirectory)) => '[ROOT]',
|
||||
$makePattern(sys_get_temp_dir()) => '[TMP]',
|
||||
];
|
||||
|
||||
return preg_replace(array_keys($replacements), array_values($replacements), $message);
|
||||
}
|
||||
}
|
||||
1418
libraries/vendor/joomla/filesystem/src/Stream.php
vendored
Normal file
1418
libraries/vendor/joomla/filesystem/src/Stream.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
290
libraries/vendor/joomla/filesystem/src/Stream/StringWrapper.php
vendored
Normal file
290
libraries/vendor/joomla/filesystem/src/Stream/StringWrapper.php
vendored
Normal file
@ -0,0 +1,290 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Filesystem Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Filesystem\Stream;
|
||||
|
||||
use Joomla\Filesystem\Support\StringController;
|
||||
|
||||
/**
|
||||
* String Stream Wrapper
|
||||
*
|
||||
* This class allows you to use a PHP string in the same way that you would normally use a regular stream wrapper
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
class StringWrapper
|
||||
{
|
||||
/**
|
||||
* The current string
|
||||
*
|
||||
* @var string
|
||||
* @since 1.3.0
|
||||
*/
|
||||
protected $currentString;
|
||||
|
||||
/**
|
||||
* The path
|
||||
*
|
||||
* @var string
|
||||
* @since 1.3.0
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* The mode
|
||||
*
|
||||
* @var string
|
||||
* @since 1.3.0
|
||||
*/
|
||||
protected $mode;
|
||||
|
||||
/**
|
||||
* Enter description here ...
|
||||
*
|
||||
* @var string
|
||||
* @since 1.3.0
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* Enter description here ...
|
||||
*
|
||||
* @var string
|
||||
* @since 1.3.0
|
||||
*/
|
||||
protected $openedPath;
|
||||
|
||||
/**
|
||||
* Current position
|
||||
*
|
||||
* @var integer
|
||||
* @since 1.3.0
|
||||
*/
|
||||
protected $pos;
|
||||
|
||||
/**
|
||||
* Length of the string
|
||||
*
|
||||
* @var string
|
||||
* @since 1.3.0
|
||||
*/
|
||||
protected $len;
|
||||
|
||||
/**
|
||||
* Statistics for a file
|
||||
*
|
||||
* @var array
|
||||
* @since 1.3.0
|
||||
* @link https://www.php.net/manual/en/function.stat.php
|
||||
*/
|
||||
protected $stat;
|
||||
|
||||
/**
|
||||
* Method to open a file or URL.
|
||||
*
|
||||
* @param string $path The stream path.
|
||||
* @param string $mode Not used.
|
||||
* @param integer $options Not used.
|
||||
* @param string $openedPath Not used.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public function stream_open($path, $mode, $options, &$openedPath)
|
||||
{
|
||||
$refPath = StringController::getRef(str_replace('string://', '', $path));
|
||||
|
||||
$this->currentString = &$refPath;
|
||||
|
||||
if ($this->currentString) {
|
||||
$this->len = \strlen($this->currentString);
|
||||
$this->pos = 0;
|
||||
$this->stat = $this->url_stat($path, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to retrieve information from a file resource
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @link https://www.php.net/manual/en/streamwrapper.stream-stat.php
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public function stream_stat()
|
||||
{
|
||||
return $this->stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to retrieve information about a file.
|
||||
*
|
||||
* @param string $path File path or URL to stat
|
||||
* @param integer $flags Additional flags set by the streams API
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @link https://www.php.net/manual/en/streamwrapper.url-stat.php
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public function url_stat($path, $flags = 0)
|
||||
{
|
||||
$now = time();
|
||||
$refPath = StringController::getRef(str_replace('string://', '', $path));
|
||||
$string = &$refPath;
|
||||
$stat = [
|
||||
'dev' => 0,
|
||||
'ino' => 0,
|
||||
'mode' => 0,
|
||||
'nlink' => 1,
|
||||
'uid' => 0,
|
||||
'gid' => 0,
|
||||
'rdev' => 0,
|
||||
'size' => \strlen($string),
|
||||
'atime' => $now,
|
||||
'mtime' => $now,
|
||||
'ctime' => $now,
|
||||
'blksize' => '512',
|
||||
'blocks' => ceil(\strlen($string) / 512),
|
||||
];
|
||||
|
||||
return $stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to read a given number of bytes starting at the current position
|
||||
* and moving to the end of the string defined by the current position plus the
|
||||
* given number.
|
||||
*
|
||||
* @param integer $count Bytes of data from the current position should be returned.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @link https://www.php.net/manual/en/streamwrapper.stream-read.php
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public function stream_read($count)
|
||||
{
|
||||
$result = substr($this->currentString, $this->pos ?? 0, $count);
|
||||
$this->pos += $count;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream write, always returning false.
|
||||
*
|
||||
* @param string $data The data to write.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.3.0
|
||||
* @note Updating the string is not supported.
|
||||
*/
|
||||
public function stream_write($data)
|
||||
{
|
||||
// We don't support updating the string.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the current position
|
||||
*
|
||||
* @return integer The position
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of field check
|
||||
*
|
||||
* @return boolean True if at end of field.
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public function stream_eof()
|
||||
{
|
||||
if ($this->pos >= $this->len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream offset
|
||||
*
|
||||
* @param integer $offset The starting offset.
|
||||
* @param integer $whence SEEK_SET, SEEK_CUR, SEEK_END
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
// $whence: SEEK_SET, SEEK_CUR, SEEK_END
|
||||
if ($offset > $this->len) {
|
||||
// We can't seek beyond our len.
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($whence) {
|
||||
case \SEEK_SET:
|
||||
$this->pos = $offset;
|
||||
|
||||
break;
|
||||
|
||||
case \SEEK_CUR:
|
||||
if (($this->pos + $offset) > $this->len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->pos += $offset;
|
||||
|
||||
break;
|
||||
|
||||
case \SEEK_END:
|
||||
$this->pos = $this->len - $offset;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream flush, always returns true.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.3.0
|
||||
* @note Data storage is not supported
|
||||
*/
|
||||
public function stream_flush()
|
||||
{
|
||||
// We don't store data.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
if (!stream_wrapper_register('string', '\\Joomla\\Filesystem\\Stream\\StringWrapper')) {
|
||||
die('\\Joomla\\Filesystem\\Stream\\StringWrapper Wrapper Registration Failed');
|
||||
}
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
84
libraries/vendor/joomla/filesystem/src/Support/StringController.php
vendored
Normal file
84
libraries/vendor/joomla/filesystem/src/Support/StringController.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Filesystem Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Filesystem\Support;
|
||||
|
||||
/**
|
||||
* String Controller
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class StringController
|
||||
{
|
||||
/**
|
||||
* Internal string references
|
||||
*
|
||||
* @var array
|
||||
* @ssince 1.4.0
|
||||
*/
|
||||
private static $strings = [];
|
||||
|
||||
/**
|
||||
* Defines a variable as an array
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
* @deprecated 2.0 Use `getArray` instead.
|
||||
*/
|
||||
public static function _getArray()
|
||||
{
|
||||
return self::getArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a variable as an array
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public static function getArray()
|
||||
{
|
||||
return self::$strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a reference
|
||||
*
|
||||
* @param string $reference The key
|
||||
* @param string $string The value
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function createRef($reference, &$string)
|
||||
{
|
||||
self::$strings[$reference] = & $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reference
|
||||
*
|
||||
* @param string $reference The key for the reference.
|
||||
*
|
||||
* @return mixed False if not set, reference if it exists
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function getRef($reference)
|
||||
{
|
||||
if (isset(self::$strings[$reference])) {
|
||||
return self::$strings[$reference];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user