first commit
This commit is contained in:
106
libraries/vendor/joomla/utilities/.drone.jsonnet
vendored
Normal file
106
libraries/vendor/joomla/utilities/.drone.jsonnet
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
local volumes = [
|
||||
{
|
||||
name: "composer-cache",
|
||||
path: "/tmp/composer-cache",
|
||||
},
|
||||
];
|
||||
|
||||
local hostvolumes = [
|
||||
{
|
||||
name: "composer-cache",
|
||||
host: {path: "/tmp/composer-cache"}
|
||||
},
|
||||
];
|
||||
|
||||
local composer(phpversion, params) = {
|
||||
name: "composer",
|
||||
image: "joomlaprojects/docker-images:php" + phpversion,
|
||||
volumes: volumes,
|
||||
commands: [
|
||||
"php -v",
|
||||
"composer update " + params,
|
||||
]
|
||||
};
|
||||
|
||||
local phpunit(phpversion) = {
|
||||
name: "PHPUnit",
|
||||
image: "joomlaprojects/docker-images:php" + phpversion,
|
||||
[if phpversion == "8.3" then "failure"]: "ignore",
|
||||
commands: ["vendor/bin/phpunit"]
|
||||
};
|
||||
|
||||
local pipeline(name, phpversion, params) = {
|
||||
kind: "pipeline",
|
||||
name: "PHP " + name,
|
||||
volumes: hostvolumes,
|
||||
steps: [
|
||||
composer(phpversion, params),
|
||||
phpunit(phpversion)
|
||||
],
|
||||
};
|
||||
|
||||
[
|
||||
{
|
||||
kind: "pipeline",
|
||||
name: "Codequality",
|
||||
volumes: hostvolumes,
|
||||
steps: [
|
||||
{
|
||||
name: "composer",
|
||||
image: "joomlaprojects/docker-images:php8.1",
|
||||
volumes: volumes,
|
||||
commands: [
|
||||
"php -v",
|
||||
"composer update"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "phpcs",
|
||||
image: "joomlaprojects/docker-images:php8.1",
|
||||
depends: [ "composer" ],
|
||||
commands: [
|
||||
"vendor/bin/phpcs --standard=ruleset.xml src/"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "phan",
|
||||
image: "joomlaprojects/docker-images:php8.1-ast",
|
||||
depends: [ "composer" ],
|
||||
failure: "ignore",
|
||||
commands: [
|
||||
"vendor/bin/phan"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "phpstan",
|
||||
image: "joomlaprojects/docker-images:php8.1",
|
||||
depends: [ "composer" ],
|
||||
failure: "ignore",
|
||||
commands: [
|
||||
"vendor/bin/phpstan analyse src",
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "phploc",
|
||||
image: "joomlaprojects/docker-images:php8.1",
|
||||
depends: [ "composer" ],
|
||||
failure: "ignore",
|
||||
commands: [
|
||||
"phploc src",
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "phpcpd",
|
||||
image: "joomlaprojects/docker-images:php8.1",
|
||||
depends: [ "composer" ],
|
||||
failure: "ignore",
|
||||
commands: [
|
||||
"phpcpd src",
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
pipeline("8.1 lowest", "8.1", "--prefer-stable --prefer-lowest"),
|
||||
pipeline("8.1", "8.1", "--prefer-stable"),
|
||||
pipeline("8.2", "8.2", "--prefer-stable"),
|
||||
]
|
||||
115
libraries/vendor/joomla/utilities/.drone.yml
vendored
Normal file
115
libraries/vendor/joomla/utilities/.drone.yml
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: Codequality
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- composer update
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- vendor/bin/phpcs --standard=ruleset.xml src/
|
||||
depends:
|
||||
- composer
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: phpcs
|
||||
- commands:
|
||||
- vendor/bin/phan
|
||||
depends:
|
||||
- composer
|
||||
failure: ignore
|
||||
image: joomlaprojects/docker-images:php8.1-ast
|
||||
name: phan
|
||||
- commands:
|
||||
- vendor/bin/phpstan analyse src
|
||||
depends:
|
||||
- composer
|
||||
failure: ignore
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: phpstan
|
||||
- commands:
|
||||
- phploc src
|
||||
depends:
|
||||
- composer
|
||||
failure: ignore
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: phploc
|
||||
- commands:
|
||||
- phpcpd src
|
||||
depends:
|
||||
- composer
|
||||
failure: ignore
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: phpcpd
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
kind: pipeline
|
||||
name: PHP 8.1 lowest
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- composer update --prefer-stable --prefer-lowest
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- vendor/bin/phpunit
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
kind: pipeline
|
||||
name: PHP 8.1
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- vendor/bin/phpunit
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
kind: pipeline
|
||||
name: PHP 8.2
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- vendor/bin/phpunit
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
kind: signature
|
||||
hmac: 78dd0859d7372f750bfddf9d6815094d46108ba147c95e1b247f6cf1c151e67d
|
||||
|
||||
...
|
||||
340
libraries/vendor/joomla/utilities/LICENSE
vendored
Normal file
340
libraries/vendor/joomla/utilities/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.
|
||||
690
libraries/vendor/joomla/utilities/src/ArrayHelper.php
vendored
Normal file
690
libraries/vendor/joomla/utilities/src/ArrayHelper.php
vendored
Normal file
@ -0,0 +1,690 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Utilities 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\Utilities;
|
||||
|
||||
use Joomla\String\StringHelper;
|
||||
|
||||
/**
|
||||
* ArrayHelper is an array utility class for doing all sorts of odds and ends with arrays.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
final class ArrayHelper
|
||||
{
|
||||
/**
|
||||
* Private constructor to prevent instantiation of this class
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to convert array to integer values
|
||||
*
|
||||
* @param array $array The source array to convert
|
||||
* @param int|array $default A default value to assign if $array is not an array
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function toInteger($array, $default = null)
|
||||
{
|
||||
if (\is_array($array)) {
|
||||
return array_map('intval', $array);
|
||||
}
|
||||
|
||||
if ($default === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (\is_array($default)) {
|
||||
return static::toInteger($default, null);
|
||||
}
|
||||
|
||||
return [(int) $default];
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to map an array to a stdClass object.
|
||||
*
|
||||
* @param array $array The array to map.
|
||||
* @param string $class Name of the class to create
|
||||
* @param boolean $recursive Convert also any array inside the main array
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function toObject(array $array, $class = 'stdClass', $recursive = true)
|
||||
{
|
||||
$obj = new $class();
|
||||
|
||||
foreach ($array as $k => $v) {
|
||||
if ($recursive && \is_array($v)) {
|
||||
$obj->$k = static::toObject($v, $class);
|
||||
} else {
|
||||
$obj->$k = $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to map an array to a string.
|
||||
*
|
||||
* @param array $array The array to map.
|
||||
* @param string $innerGlue The glue (optional, defaults to '=') between the key and the value.
|
||||
* @param string $outerGlue The glue (optional, defaults to ' ') between array elements.
|
||||
* @param boolean $keepOuterKey True if final key should be kept.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function toString(array $array, string $innerGlue = '=', string $outerGlue = ' ', $keepOuterKey = false)
|
||||
{
|
||||
$output = [];
|
||||
|
||||
foreach ($array as $key => $item) {
|
||||
if (\is_array($item)) {
|
||||
if ($keepOuterKey) {
|
||||
$output[] = $key;
|
||||
}
|
||||
|
||||
// This is value is an array, go and do it again!
|
||||
$output[] = static::toString($item, $innerGlue, $outerGlue, $keepOuterKey);
|
||||
} else {
|
||||
$output[] = $key . $innerGlue . '"' . $item . '"';
|
||||
}
|
||||
}
|
||||
|
||||
return implode($outerGlue, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to map an object to an array
|
||||
*
|
||||
* @param object $source The source object
|
||||
* @param boolean $recurse True to recurse through multi-level objects
|
||||
* @param string $regex An optional regular expression to match on field names
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function fromObject($source, $recurse = true, $regex = null)
|
||||
{
|
||||
if (\is_object($source) || \is_array($source)) {
|
||||
return self::arrayFromObject($source, $recurse, $regex);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to map an object or array to an array
|
||||
*
|
||||
* @param mixed $item The source object or array
|
||||
* @param boolean $recurse True to recurse through multi-level objects
|
||||
* @param string $regex An optional regular expression to match on field names
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
private static function arrayFromObject($item, $recurse, $regex)
|
||||
{
|
||||
if (\is_object($item)) {
|
||||
$result = [];
|
||||
|
||||
foreach (get_object_vars($item) as $k => $v) {
|
||||
if (!$regex || preg_match($regex, $k)) {
|
||||
if ($recurse) {
|
||||
$result[$k] = self::arrayFromObject($v, $recurse, $regex);
|
||||
} else {
|
||||
$result[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (\is_array($item)) {
|
||||
$result = [];
|
||||
|
||||
foreach ($item as $k => $v) {
|
||||
$result[$k] = self::arrayFromObject($v, $recurse, $regex);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a column to an array of arrays or objects
|
||||
*
|
||||
* @param array $array The source array
|
||||
* @param array $column The array to be used as new column
|
||||
* @param string $colName The index of the new column or name of the new object property
|
||||
* @param string $keyCol The index of the column or name of object property to be used for mapping with the new column
|
||||
*
|
||||
* @return array An array with the new column added to the source array
|
||||
*
|
||||
* @since 1.5.0
|
||||
* @see https://www.php.net/manual/en/language.types.array.php
|
||||
*/
|
||||
public static function addColumn(array $array, array $column, $colName, $keyCol = null)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($array as $i => $item) {
|
||||
$value = null;
|
||||
|
||||
if (!isset($keyCol)) {
|
||||
$value = static::getValue($column, $i);
|
||||
} else {
|
||||
// Convert object to array
|
||||
$subject = \is_object($item) ? static::fromObject($item) : $item;
|
||||
|
||||
if (isset($subject[$keyCol]) && is_scalar($subject[$keyCol])) {
|
||||
$value = static::getValue($column, $subject[$keyCol]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the column
|
||||
if (\is_object($item)) {
|
||||
if (isset($colName)) {
|
||||
$item->$colName = $value;
|
||||
}
|
||||
} else {
|
||||
if (isset($colName)) {
|
||||
$item[$colName] = $value;
|
||||
} else {
|
||||
$item[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$result[$i] = $item;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a column from an array of arrays or objects
|
||||
*
|
||||
* @param array $array The source array
|
||||
* @param string $colName The index of the column or name of object property to be removed
|
||||
*
|
||||
* @return array Column of values from the source array
|
||||
*
|
||||
* @since 1.5.0
|
||||
* @see https://www.php.net/manual/en/language.types.array.php
|
||||
*/
|
||||
public static function dropColumn(array $array, $colName)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($array as $i => $item) {
|
||||
if (\is_object($item) && isset($item->$colName)) {
|
||||
unset($item->$colName);
|
||||
} elseif (\is_array($item) && isset($item[$colName])) {
|
||||
unset($item[$colName]);
|
||||
}
|
||||
|
||||
$result[$i] = $item;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a column from an array of arrays or objects
|
||||
*
|
||||
* @param array $array The source array
|
||||
* @param string $valueCol The index of the column or name of object property to be used as value
|
||||
* It may also be NULL to return complete arrays or objects (this is
|
||||
* useful together with <var>$keyCol</var> to reindex the array).
|
||||
* @param string $keyCol The index of the column or name of object property to be used as key
|
||||
*
|
||||
* @return array Column of values from the source array
|
||||
*
|
||||
* @since 1.0
|
||||
* @see https://www.php.net/manual/en/language.types.array.php
|
||||
* @see https://www.php.net/manual/en/function.array-column.php
|
||||
*/
|
||||
public static function getColumn(array $array, $valueCol, $keyCol = null)
|
||||
{
|
||||
return \array_reduce(
|
||||
$array,
|
||||
function ($result, $item) use ($keyCol, $valueCol) {
|
||||
$array = \is_object($item) ? get_object_vars($item) : $item;
|
||||
|
||||
if ($valueCol === null) {
|
||||
$value = $item;
|
||||
} else {
|
||||
if (!array_key_exists($valueCol, $array)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$value = $array[$valueCol];
|
||||
}
|
||||
|
||||
if ($keyCol !== null && \array_key_exists($keyCol, $array) && \is_scalar($array[$keyCol])) {
|
||||
$result[$array[$keyCol]] = $value;
|
||||
} else {
|
||||
$result[] = $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to return a value from a named array or a specified default
|
||||
*
|
||||
* @param array|\ArrayAccess $array A named array or object that implements ArrayAccess
|
||||
* @param string $name The key to search for (this can be an array index or a dot separated key sequence as in Registry)
|
||||
* @param mixed $default The default value to give if no key found
|
||||
* @param string $type Return type for the variable (INT, FLOAT, STRING, WORD, BOOLEAN, ARRAY)
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function getValue($array, $name, $default = null, string $type = '')
|
||||
{
|
||||
if (!\is_array($array) && !($array instanceof \ArrayAccess)) {
|
||||
throw new \InvalidArgumentException('The object must be an array or an object that implements ArrayAccess');
|
||||
}
|
||||
|
||||
$result = null;
|
||||
|
||||
if (isset($array[$name])) {
|
||||
$result = $array[$name];
|
||||
} elseif (strpos($name, '.')) {
|
||||
list($name, $subset) = explode('.', $name, 2);
|
||||
|
||||
if (isset($array[$name]) && \is_array($array[$name])) {
|
||||
return static::getValue($array[$name], $subset, $default, $type);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the default case
|
||||
if ($result === null) {
|
||||
$result = $default;
|
||||
}
|
||||
|
||||
// Handle the type constraint
|
||||
switch (strtoupper($type)) {
|
||||
case 'INT':
|
||||
case 'INTEGER':
|
||||
// Only use the first integer value
|
||||
@preg_match('/-?[0-9]+/', $result, $matches);
|
||||
$result = @(int) $matches[0];
|
||||
|
||||
break;
|
||||
|
||||
case 'FLOAT':
|
||||
case 'DOUBLE':
|
||||
// Only use the first floating point value
|
||||
@preg_match('/-?[0-9]+(\.[0-9]+)?/', $result, $matches);
|
||||
$result = @(float) $matches[0];
|
||||
|
||||
break;
|
||||
|
||||
case 'BOOL':
|
||||
case 'BOOLEAN':
|
||||
$result = (bool) $result;
|
||||
|
||||
break;
|
||||
|
||||
case 'ARRAY':
|
||||
if (!\is_array($result)) {
|
||||
$result = [$result];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'STRING':
|
||||
$result = (string) $result;
|
||||
|
||||
break;
|
||||
|
||||
case 'WORD':
|
||||
$result = (string) preg_replace('#\W#', '', $result);
|
||||
|
||||
break;
|
||||
|
||||
case 'NONE':
|
||||
default:
|
||||
// No casting necessary
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an associative array of arrays and inverts the array keys to values using the array values as keys.
|
||||
*
|
||||
* Example:
|
||||
* $input = array(
|
||||
* 'New' => array('1000', '1500', '1750'),
|
||||
* 'Used' => array('3000', '4000', '5000', '6000')
|
||||
* );
|
||||
* $output = ArrayHelper::invert($input);
|
||||
*
|
||||
* Output would be equal to:
|
||||
* $output = array(
|
||||
* '1000' => 'New',
|
||||
* '1500' => 'New',
|
||||
* '1750' => 'New',
|
||||
* '3000' => 'Used',
|
||||
* '4000' => 'Used',
|
||||
* '5000' => 'Used',
|
||||
* '6000' => 'Used'
|
||||
* );
|
||||
*
|
||||
* @param array $array The source array.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function invert(array $array)
|
||||
{
|
||||
$return = [];
|
||||
|
||||
foreach ($array as $base => $values) {
|
||||
if (!\is_array($values)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($values as $key) {
|
||||
// If the key isn't scalar then ignore it.
|
||||
if (is_scalar($key)) {
|
||||
$return[$key] = $base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to determine if an array is an associative array.
|
||||
*
|
||||
* @param array $array An array to test.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function isAssociative($array)
|
||||
{
|
||||
if (\is_array($array)) {
|
||||
foreach (array_keys($array) as $k => $v) {
|
||||
if ($k !== $v) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pivots an array to create a reverse lookup of an array of scalars, arrays or objects.
|
||||
*
|
||||
* @param array $source The source array.
|
||||
* @param string $key Where the elements of the source array are objects or arrays, the key to pivot on.
|
||||
*
|
||||
* @return array An array of arrays pivoted either on the value of the keys, or an individual key of an object or array.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function pivot(array $source, $key = null)
|
||||
{
|
||||
$result = [];
|
||||
$counter = [];
|
||||
|
||||
foreach ($source as $index => $value) {
|
||||
// Determine the name of the pivot key, and its value.
|
||||
if (\is_array($value)) {
|
||||
// If the key does not exist, ignore it.
|
||||
if (!isset($value[$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$resultKey = $value[$key];
|
||||
$resultValue = $source[$index];
|
||||
} elseif (\is_object($value)) {
|
||||
// If the key does not exist, ignore it.
|
||||
if (!isset($value->$key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$resultKey = $value->$key;
|
||||
$resultValue = $source[$index];
|
||||
} else {
|
||||
// Just a scalar value.
|
||||
$resultKey = $value;
|
||||
$resultValue = $index;
|
||||
}
|
||||
|
||||
// The counter tracks how many times a key has been used.
|
||||
if (empty($counter[$resultKey])) {
|
||||
// The first time around we just assign the value to the key.
|
||||
$result[$resultKey] = $resultValue;
|
||||
$counter[$resultKey] = 1;
|
||||
} elseif ($counter[$resultKey] == 1) {
|
||||
// If there is a second time, we convert the value into an array.
|
||||
$result[$resultKey] = [
|
||||
$result[$resultKey],
|
||||
$resultValue,
|
||||
];
|
||||
$counter[$resultKey]++;
|
||||
} else {
|
||||
// After the second time, no need to track any more. Just append to the existing array.
|
||||
$result[$resultKey][] = $resultValue;
|
||||
}
|
||||
}
|
||||
|
||||
unset($counter);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to sort an array of objects on a given field
|
||||
*
|
||||
* @param array $a An array of objects
|
||||
* @param mixed $k The key (string) or an array of keys to sort on
|
||||
* @param mixed $direction Direction (integer) or an array of direction to sort in [1 = Ascending] [-1 = Descending]
|
||||
* @param mixed $caseSensitive Boolean or array of booleans to let sort occur case sensitive or insensitive
|
||||
* @param mixed $locale Boolean or array of booleans to let sort occur using the locale language or not
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function sortObjects(array $a, $k, $direction = 1, $caseSensitive = true, $locale = false)
|
||||
{
|
||||
if (!\is_array($locale) || !\is_array($locale[0])) {
|
||||
$locale = [$locale];
|
||||
}
|
||||
|
||||
$sortCase = (array) $caseSensitive;
|
||||
$sortDirection = (array) $direction;
|
||||
$key = (array) $k;
|
||||
$sortLocale = $locale;
|
||||
|
||||
usort(
|
||||
$a,
|
||||
function ($a, $b) use ($sortCase, $sortDirection, $key, $sortLocale) {
|
||||
for ($i = 0, $count = \count($key); $i < $count; $i++) {
|
||||
if (isset($sortDirection[$i])) {
|
||||
$direction = $sortDirection[$i];
|
||||
}
|
||||
|
||||
if (isset($sortCase[$i])) {
|
||||
$caseSensitive = $sortCase[$i];
|
||||
}
|
||||
|
||||
if (isset($sortLocale[$i])) {
|
||||
$locale = $sortLocale[$i];
|
||||
}
|
||||
|
||||
$va = $a->{$key[$i]};
|
||||
$vb = $b->{$key[$i]};
|
||||
|
||||
if ((\is_bool($va) || is_numeric($va)) && (\is_bool($vb) || is_numeric($vb))) {
|
||||
$cmp = $va - $vb;
|
||||
} elseif ($caseSensitive) {
|
||||
$cmp = StringHelper::strcmp($va, $vb, $locale);
|
||||
} else {
|
||||
$cmp = StringHelper::strcasecmp($va, $vb, $locale);
|
||||
}
|
||||
|
||||
if ($cmp > 0) {
|
||||
return $direction;
|
||||
}
|
||||
|
||||
if ($cmp < 0) {
|
||||
return -$direction;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
);
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multidimensional array safe unique test
|
||||
*
|
||||
* @param array $array The array to make unique.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.array-unique.php
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function arrayUnique(array $array)
|
||||
{
|
||||
$array = array_map('serialize', $array);
|
||||
$array = array_unique($array);
|
||||
$array = array_map('unserialize', $array);
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* An improved array_search that allows for partial matching of strings values in associative arrays.
|
||||
*
|
||||
* @param string $needle The text to search for within the array.
|
||||
* @param array $haystack Associative array to search in to find $needle.
|
||||
* @param boolean $caseSensitive True to search case sensitive, false otherwise.
|
||||
*
|
||||
* @return mixed Returns the matching array $key if found, otherwise false.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function arraySearch($needle, array $haystack, $caseSensitive = true)
|
||||
{
|
||||
foreach ($haystack as $key => $value) {
|
||||
$searchFunc = ($caseSensitive) ? 'strpos' : 'stripos';
|
||||
|
||||
if ($searchFunc($value, $needle) === 0) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to recursively convert data to a one dimension array.
|
||||
*
|
||||
* @param array|object $array The array or object to convert.
|
||||
* @param string $separator The key separator.
|
||||
* @param string $prefix Last level key prefix.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public static function flatten($array, $separator = '.', $prefix = '')
|
||||
{
|
||||
if ($array instanceof \Traversable) {
|
||||
$array = iterator_to_array($array);
|
||||
} elseif (\is_object($array)) {
|
||||
$array = get_object_vars($array);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($array as $k => $v) {
|
||||
$key = $prefix ? $prefix . $separator . $k : $k;
|
||||
|
||||
if (\is_object($v) || \is_array($v)) {
|
||||
$result[] = static::flatten($v, $separator, $key);
|
||||
} else {
|
||||
$result[] = [$key => $v];
|
||||
}
|
||||
}
|
||||
|
||||
return array_merge(...$result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge array recursively.
|
||||
*
|
||||
* @param array ...$args Array list to be merged.
|
||||
*
|
||||
* @return array Merged array.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function mergeRecursive(...$args): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($args as $i => $array) {
|
||||
if (!\is_array($array)) {
|
||||
throw new \InvalidArgumentException(sprintf('Argument #%d is not an array.', $i + 2));
|
||||
}
|
||||
|
||||
foreach ($array as $key => &$value) {
|
||||
if (\is_array($value) && isset($result[$key]) && \is_array($result[$key])) {
|
||||
$result[$key] = static::mergeRecursive($result [$key], $value);
|
||||
} else {
|
||||
$result[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
514
libraries/vendor/joomla/utilities/src/IpHelper.php
vendored
Normal file
514
libraries/vendor/joomla/utilities/src/IpHelper.php
vendored
Normal file
@ -0,0 +1,514 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Utilities Package
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @note This file has been modified by the Joomla! Project and no longer reflects the original work of its author.
|
||||
*/
|
||||
|
||||
namespace Joomla\Utilities;
|
||||
|
||||
/**
|
||||
* IpHelper is a utility class for processing IP addresses
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
final class IpHelper
|
||||
{
|
||||
/**
|
||||
* The IP address of the current visitor
|
||||
*
|
||||
* @var string
|
||||
* @since 1.6.0
|
||||
*/
|
||||
private static $ip = null;
|
||||
|
||||
/**
|
||||
* Should I allow IP overrides through X-Forwarded-For or Client-Ip HTTP headers?
|
||||
*
|
||||
* @var boolean
|
||||
* @since 1.6.0
|
||||
* @note The default value is false in version 2.0+
|
||||
*/
|
||||
private static $allowIpOverrides = false;
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation of this class
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current visitor's IP address
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public static function getIp()
|
||||
{
|
||||
if (self::$ip === null) {
|
||||
$ip = static::detectAndCleanIP();
|
||||
|
||||
if (!empty($ip) && ($ip != '0.0.0.0') && \function_exists('inet_pton') && \function_exists('inet_ntop')) {
|
||||
$myIP = @inet_pton($ip);
|
||||
|
||||
if ($myIP !== false) {
|
||||
$ip = inet_ntop($myIP);
|
||||
}
|
||||
}
|
||||
|
||||
static::setIp($ip);
|
||||
}
|
||||
|
||||
return self::$ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the IP address of the current visitor
|
||||
*
|
||||
* @param string $ip The visitor's IP address
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public static function setIp($ip)
|
||||
{
|
||||
self::$ip = $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it an IPv6 IP address?
|
||||
*
|
||||
* @param string $ip An IPv4 or IPv6 address
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public static function isIPv6($ip)
|
||||
{
|
||||
return strpos($ip, ':') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an IP is contained in a list of IPs or IP expressions
|
||||
*
|
||||
* @param string $ip The IPv4/IPv6 address to check
|
||||
* @param array|string $ipTable An IP expression (or a comma-separated or array list of IP expressions) to check against
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public static function IPinList($ip, $ipTable = '')
|
||||
{
|
||||
// No point proceeding with an empty IP list
|
||||
if (empty($ipTable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the IP list is not an array, convert it to an array
|
||||
if (!\is_array($ipTable)) {
|
||||
if (strpos($ipTable, ',') !== false) {
|
||||
$ipTable = explode(',', $ipTable);
|
||||
$ipTable = array_map('trim', $ipTable);
|
||||
} else {
|
||||
$ipTable = trim($ipTable);
|
||||
$ipTable = [$ipTable];
|
||||
}
|
||||
}
|
||||
|
||||
// If no IP address is found, return false
|
||||
if ($ip === '0.0.0.0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If no IP is given, return false
|
||||
if (empty($ip)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (!\function_exists('inet_pton')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the IP's in_adds representation
|
||||
$myIP = @inet_pton($ip);
|
||||
|
||||
// If the IP is in an unrecognisable format, quite
|
||||
if ($myIP === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ipv6 = static::isIPv6($ip);
|
||||
|
||||
foreach ($ipTable as $ipExpression) {
|
||||
$ipExpression = trim($ipExpression);
|
||||
|
||||
// Inclusive IP range, i.e. 123.123.123.123-124.125.126.127
|
||||
if (strstr($ipExpression, '-')) {
|
||||
list($from, $to) = explode('-', $ipExpression, 2);
|
||||
|
||||
if ($ipv6 && (!static::isIPv6($from) || !static::isIPv6($to))) {
|
||||
// Do not apply IPv4 filtering on an IPv6 address
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$ipv6 && (static::isIPv6($from) || static::isIPv6($to))) {
|
||||
// Do not apply IPv6 filtering on an IPv4 address
|
||||
continue;
|
||||
}
|
||||
|
||||
$from = @inet_pton(trim($from));
|
||||
$to = @inet_pton(trim($to));
|
||||
|
||||
// Sanity check
|
||||
if (($from === false) || ($to === false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Swap from/to if they're in the wrong order
|
||||
if ($from > $to) {
|
||||
list($from, $to) = [$to, $from];
|
||||
}
|
||||
|
||||
if (($myIP >= $from) && ($myIP <= $to)) {
|
||||
return true;
|
||||
}
|
||||
} elseif (strstr($ipExpression, '/')) {
|
||||
// Netmask or CIDR provided
|
||||
$binaryip = static::inetToBits($myIP);
|
||||
|
||||
list($net, $maskbits) = explode('/', $ipExpression, 2);
|
||||
|
||||
if ($ipv6 && !static::isIPv6($net)) {
|
||||
// Do not apply IPv4 filtering on an IPv6 address
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$ipv6 && static::isIPv6($net)) {
|
||||
// Do not apply IPv6 filtering on an IPv4 address
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($ipv6 && strstr($maskbits, ':')) {
|
||||
// Perform an IPv6 CIDR check
|
||||
if (static::checkIPv6CIDR($myIP, $ipExpression)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we didn't match it proceed to the next expression
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$ipv6 && strstr($maskbits, '.')) {
|
||||
// Convert IPv4 netmask to CIDR
|
||||
$long = ip2long($maskbits);
|
||||
$base = ip2long('255.255.255.255');
|
||||
$maskbits = 32 - log(($long ^ $base) + 1, 2);
|
||||
}
|
||||
|
||||
// Convert network IP to in_addr representation
|
||||
$net = @inet_pton($net);
|
||||
|
||||
// Sanity check
|
||||
if ($net === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the network's binary representation
|
||||
$expectedNumberOfBits = $ipv6 ? 128 : 24;
|
||||
$binarynet = str_pad(static::inetToBits($net), $expectedNumberOfBits, '0', STR_PAD_RIGHT);
|
||||
|
||||
// Check the corresponding bits of the IP and the network
|
||||
$ipNetBits = substr($binaryip, 0, $maskbits);
|
||||
$netBits = substr($binarynet, 0, $maskbits);
|
||||
|
||||
if ($ipNetBits === $netBits) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// IPv6: Only single IPs are supported
|
||||
if ($ipv6) {
|
||||
$ipExpression = trim($ipExpression);
|
||||
|
||||
if (!static::isIPv6($ipExpression)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ipCheck = @inet_pton($ipExpression);
|
||||
|
||||
if ($ipCheck === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($ipCheck == $myIP) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Standard IPv4 address, i.e. 123.123.123.123 or partial IP address, i.e. 123.[123.][123.][123]
|
||||
$dots = 0;
|
||||
|
||||
if (substr($ipExpression, -1) == '.') {
|
||||
// Partial IP address. Convert to CIDR and re-match
|
||||
foreach (count_chars($ipExpression, 1) as $i => $val) {
|
||||
if ($i == 46) {
|
||||
$dots = $val;
|
||||
}
|
||||
}
|
||||
|
||||
switch ($dots) {
|
||||
case 1:
|
||||
$netmask = '255.0.0.0';
|
||||
$ipExpression .= '0.0.0';
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$netmask = '255.255.0.0';
|
||||
$ipExpression .= '0.0';
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
$netmask = '255.255.255.0';
|
||||
$ipExpression .= '0';
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$dots = 0;
|
||||
}
|
||||
|
||||
if ($dots) {
|
||||
$binaryip = static::inetToBits($myIP);
|
||||
|
||||
// Convert netmask to CIDR
|
||||
$long = ip2long($netmask);
|
||||
$base = ip2long('255.255.255.255');
|
||||
$maskbits = 32 - log(($long ^ $base) + 1, 2);
|
||||
|
||||
$net = @inet_pton($ipExpression);
|
||||
|
||||
// Sanity check
|
||||
if ($net === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the network's binary representation
|
||||
$expectedNumberOfBits = $ipv6 ? 128 : 24;
|
||||
$binarynet = str_pad(static::inetToBits($net), $expectedNumberOfBits, '0', STR_PAD_RIGHT);
|
||||
|
||||
// Check the corresponding bits of the IP and the network
|
||||
$ipNetBits = substr($binaryip, 0, $maskbits);
|
||||
$netBits = substr($binarynet, 0, $maskbits);
|
||||
|
||||
if ($ipNetBits === $netBits) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$dots) {
|
||||
$ip = @inet_pton(trim($ipExpression));
|
||||
|
||||
if ($ip == $myIP) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Works around the REMOTE_ADDR not containing the user's IP
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public static function workaroundIPIssues()
|
||||
{
|
||||
$ip = static::getIp();
|
||||
|
||||
if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] === $ip) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($_SERVER['REMOTE_ADDR'])) {
|
||||
$_SERVER['JOOMLA_REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
|
||||
} elseif (\function_exists('getenv')) {
|
||||
if (getenv('REMOTE_ADDR')) {
|
||||
$_SERVER['JOOMLA_REMOTE_ADDR'] = getenv('REMOTE_ADDR');
|
||||
}
|
||||
}
|
||||
|
||||
$_SERVER['REMOTE_ADDR'] = $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should I allow the remote client's IP to be overridden by an X-Forwarded-For or Client-Ip HTTP header?
|
||||
*
|
||||
* @param boolean $newState True to allow the override
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public static function setAllowIpOverrides($newState)
|
||||
{
|
||||
self::$allowIpOverrides = $newState ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the visitor's IP address.
|
||||
*
|
||||
* Automatically handles reverse proxies reporting the IPs of intermediate devices, like load balancers. Examples:
|
||||
*
|
||||
* - https://www.akeebabackup.com/support/admin-tools/13743-double-ip-adresses-in-security-exception-log-warnings.html
|
||||
* - https://stackoverflow.com/questions/2422395/why-is-request-envremote-addr-returning-two-ips
|
||||
*
|
||||
* The solution used is assuming that the last IP address is the external one.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
protected static function detectAndCleanIP()
|
||||
{
|
||||
$ip = static::detectIP();
|
||||
|
||||
if (strstr($ip, ',') !== false || strstr($ip, ' ') !== false) {
|
||||
$ip = str_replace(' ', ',', $ip);
|
||||
$ip = str_replace(',,', ',', $ip);
|
||||
$ips = explode(',', $ip);
|
||||
$ip = '';
|
||||
|
||||
while (empty($ip) && !empty($ips)) {
|
||||
$ip = array_shift($ips);
|
||||
$ip = trim($ip);
|
||||
}
|
||||
} else {
|
||||
$ip = trim($ip);
|
||||
}
|
||||
|
||||
return $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the visitor's IP address
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
protected static function detectIP()
|
||||
{
|
||||
// Normally the $_SERVER superglobal is set
|
||||
if (isset($_SERVER)) {
|
||||
// Do we have an x-forwarded-for HTTP header (e.g. NginX)?
|
||||
if (self::$allowIpOverrides && isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
return $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
}
|
||||
|
||||
// Do we have a client-ip header (e.g. non-transparent proxy)?
|
||||
if (self::$allowIpOverrides && isset($_SERVER['HTTP_CLIENT_IP'])) {
|
||||
return $_SERVER['HTTP_CLIENT_IP'];
|
||||
}
|
||||
|
||||
// Normal, non-proxied server or server behind a transparent proxy
|
||||
if (isset($_SERVER['REMOTE_ADDR'])) {
|
||||
return $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This part is executed on PHP running as CGI, or on SAPIs which do not set the $_SERVER superglobal
|
||||
* If getenv() is disabled, you're screwed
|
||||
*/
|
||||
if (!\function_exists('getenv')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Do we have an x-forwarded-for HTTP header?
|
||||
if (self::$allowIpOverrides && getenv('HTTP_X_FORWARDED_FOR')) {
|
||||
return getenv('HTTP_X_FORWARDED_FOR');
|
||||
}
|
||||
|
||||
// Do we have a client-ip header?
|
||||
if (self::$allowIpOverrides && getenv('HTTP_CLIENT_IP')) {
|
||||
return getenv('HTTP_CLIENT_IP');
|
||||
}
|
||||
|
||||
// Normal, non-proxied server or server behind a transparent proxy
|
||||
if (getenv('REMOTE_ADDR')) {
|
||||
return getenv('REMOTE_ADDR');
|
||||
}
|
||||
|
||||
// Catch-all case for broken servers, apparently
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts inet_pton output to bits string
|
||||
*
|
||||
* @param string $inet The in_addr representation of an IPv4 or IPv6 address
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
protected static function inetToBits($inet)
|
||||
{
|
||||
if (\strlen($inet) == 4) {
|
||||
$unpacked = unpack('A4', $inet);
|
||||
} else {
|
||||
$unpacked = unpack('A16', $inet);
|
||||
}
|
||||
|
||||
$unpacked = str_split($unpacked[1]);
|
||||
$binaryip = '';
|
||||
|
||||
foreach ($unpacked as $char) {
|
||||
$binaryip .= str_pad(decbin(\ord($char)), 8, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
return $binaryip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an IPv6 address $ip is part of the IPv6 CIDR block $cidrnet
|
||||
*
|
||||
* @param string $ip The IPv6 address to check, e.g. 21DA:00D3:0000:2F3B:02AC:00FF:FE28:9C5A
|
||||
* @param string $cidrnet The IPv6 CIDR block, e.g. 21DA:00D3:0000:2F3B::/64
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
protected static function checkIPv6CIDR($ip, $cidrnet)
|
||||
{
|
||||
$ip = inet_pton($ip);
|
||||
$binaryip = static::inetToBits($ip);
|
||||
|
||||
list($net, $maskbits) = explode('/', $cidrnet);
|
||||
$net = inet_pton($net);
|
||||
$binarynet = static::inetToBits($net);
|
||||
|
||||
$ipNetBits = substr($binaryip, 0, $maskbits);
|
||||
$netBits = substr($binarynet, 0, $maskbits);
|
||||
|
||||
return $ipNetBits === $netBits;
|
||||
}
|
||||
}
|
||||
106
libraries/vendor/joomla/utilities/src/RegEx.php
vendored
Normal file
106
libraries/vendor/joomla/utilities/src/RegEx.php
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* Part of the Joomla Framework Utilities Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Utilities;
|
||||
|
||||
/**
|
||||
* Utility class for building complex Regular Expressions
|
||||
*
|
||||
* @since __DEPLOY_VERSION__
|
||||
*/
|
||||
abstract class RegEx
|
||||
{
|
||||
/**
|
||||
* Match the Regular Expression
|
||||
*
|
||||
* @param string $regex The Regular Expression
|
||||
* @param string $subject The string to check
|
||||
*
|
||||
* @return array Captured values
|
||||
*/
|
||||
public static function match($regex, $subject)
|
||||
{
|
||||
$match = array();
|
||||
|
||||
preg_match($regex, $subject, $match);
|
||||
|
||||
return array_filter(
|
||||
$match,
|
||||
static function ($value, $key) {
|
||||
return !is_numeric($key) && !empty($value);
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a key to an expression.
|
||||
*
|
||||
* @param string $regex The Regular Expression to match
|
||||
* @param string $as The name of the component, used as index
|
||||
*
|
||||
* @return string The modified Regular Expression
|
||||
*/
|
||||
public static function capture($regex, $as = null)
|
||||
{
|
||||
return '(?P<' . $as . '>' . $regex . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a 'zero or one' quantifier to an expression.
|
||||
*
|
||||
* @param string $regex The Regular Expression to match
|
||||
*
|
||||
* @return string The modified Regular Expression
|
||||
*/
|
||||
public static function optional($regex)
|
||||
{
|
||||
return '(?:' . $regex . ')?';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a 'one or more' quantifier to an expression.
|
||||
*
|
||||
* @param string $regex The Regular Expression to match
|
||||
*
|
||||
* @return string The modified Regular Expression
|
||||
*/
|
||||
public static function oneOrMore($regex)
|
||||
{
|
||||
return '(?:' . $regex . ')+';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a 'zero or more' quantifier to an expression.
|
||||
*
|
||||
* @param string $regex The Regular Expression to match
|
||||
*
|
||||
* @return string The modified Regular Expression
|
||||
*/
|
||||
public static function noneOrMore($regex)
|
||||
{
|
||||
return '(?:' . $regex . ')*';
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a list of alternative expressions.
|
||||
*
|
||||
* @param string|array $regexList A list of Regular Expressions to choose from
|
||||
*
|
||||
* @return string The modified Regular Expression
|
||||
*/
|
||||
public static function anyOf($regexList)
|
||||
{
|
||||
if (is_string($regexList))
|
||||
{
|
||||
$regexList = func_get_args();
|
||||
}
|
||||
|
||||
return '(?:' . implode('|', $regexList) . ')';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user