Initial commit

This commit is contained in:
2018-04-02 08:07:38 +02:00
commit 7330c1ed3e
2054 changed files with 405203 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
Contributing
------------
TYPO3 CMS core is a volunteer effort. We encourage you to join the project by submitting changes.
Have a look at our [detailed contribution walkthrough][1].
If you like to contribute code, please use the [main git repository][2], all changes are
processed in our [review system][3]. The [GitHub repository][4] is a synchronized
mirror of the primary git repository and pull requests via GitHub are not supported at the moment.
If you like to contribute to our [documentation][5], use the "Edit me on GitHub" button
in the top right of each manual or reference or just make a pull request in any of the repositories
that can be found in the TYPO3 [documentation team GitHub organisation][6].
[1]: https://docs.typo3.org/typo3cms/ContributionWorkflowGuide/
[2]: https://git.typo3.org/Packages/TYPO3.CMS.git
[3]: https://review.typo3.org/#/q/project:Packages/TYPO3.CMS,n,z
[4]: https://github.com/TYPO3/TYPO3.CMS
[5]: https://docs.typo3.org/typo3cms/
[6]: https://github.com/TYPO3-Documentation

17118
typo3_src-7.6.24/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

305
typo3_src-7.6.24/INSTALL.md Normal file
View File

@@ -0,0 +1,305 @@
INSTALLING TYPO3
================
TYPO3 is an open source PHP based web content management system released
under the GNU GPL. TYPO3 is copyright (c) 1999-2015 by Kasper Skaarhoj.
This document describes:
* System requirements for TYPO3
* Installation routine
* Upgrade routine
Client browser support
----------------------
The TYPO3 backend is accessed through a web browser. TYPO3 CMS 7
supports the following web browsers:
* Internet Explorer 9 and later
* Google Chrome (Windows, MacOS, Linux)
* Firefox (Windows, MacOS, Linux)
* Safari on MacOS
* and other compatible modern browsers
Server system requirements
--------------------------
TYPO3 requires a web server with a PHP environment and a database. The minimum
system requirements for running TYPO3 CMS 7 are:
* Webserver capable of running PHP applications (Apache, Nginx, IIS or other)
* PHP 5.5 up to 7
* MySQL 5.5 up to 5.7 or compatible
* more than 200 MB of disk space
Note: If you use any other webserver than Apache, make sure you add the necessary configuration normally
provided in the various `.htaccess` files inside the TYPO3 core. This configuration is security relevant,
therefore only experienced server administrators should create such configuration.
### MySQL environment
TYPO3 works with MySQL in the above mentioned versions. It will also work on
compatible "drop-in" replacements like MariaDB or Percona.
### MySQL required privileges
The MySQL user needs a least the following privileges on the TYPO3 database:
* SELECT, INSERT, UPDATE, DELETE
* CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES
It is recommended to also grant the following privileges:
* CREATE VIEW, SHOW VIEW
* EXECUTE, CREATE ROUTINE, ALTER ROUTINE
### PHP environment
* memory_limit set to at least 64M
* max_execution_time set to at least 30s (240s recommended)
* register_globals disabled
* AllowOverride in the Apache configuration includes "Indexes" and "FileInfo"
(see FAQ below)
### PHP required extensions
Your PHP needs to support the following extensions. Install will
check if these are available.
* These are usually part of the standard PHP package on most distributions:
* filter
* hash
* openssl
* pcre >= 8.30
* session
* soap
* SPL
* standard
* xml
* zip
* zlib
* These might have to be installed separately:
* gd
* json
* mysqli
### Recommended setup
There are plenty of possible setups for high performance TYPO3 installations
(i.e. using Varnish Cache, Nginx, PHP-FPM, etc). Consider this resource for
more ideas or suggestions: http://wiki.typo3.org/Performance_tuning
This is a basic recommended setup for best performance and increased
functionality:
* Apache with mod_expires and mod_rewrite enabled
* MySQL 5.5 or newer
* GraphicsMagick or ImageMagick v6 or newer installed on the server
* PHP
* version 5.5 or later
* memory_limit set to at least 128M
* max_execution_time set to at least 240s
* max_input_vars set to at least 1500
* always_populate_raw_post_data set to -1 (PHP version >= 5.6, <7.0)
* Additional PHP extensions:
* PHP opcode cache, i.e.: apc, xcache, eaccelerator, Zend Optimizer, wincache (in case of an IIS installation)
* apcu caching (with at least 100 MB of memory available)
* curl
* mbstring
* FreeType 2 (usually included within the PHP distribution)
* bcmath or gmp (needed if you'd like to use the openid system extension)
* fileinfo (mandatory for proper file type detection)
* PHP access to /dev/urandom or /dev/random on Unix-like platforms for
increased security. Make sure to add "/dev/random:/dev/urandom" to
open_basedir settings if you use it. If these paths are unavailable, TYPO3
will attempt to simulate random number generation. This is less secure,
reduces performance and throws out warnings in the TYPO3 system log.
* TYPO3 works with PHP's IPv6 support, which is enabled by default.
If you compile PHP on your own, be aware not to use option "--disable-ipv6",
because this will break the IPv6 support and the according unit tests.
Installation
------------
### Important note for upgrades from TYPO3 CMS versions **below 6.2 LTS**
It is not possible to upgrade any version below 6.2 LTS to 7 directly,
since some upgrade wizards are not available anymore on 7.
It is highly recommended to upgrade to 6.2 LTS first and continue with
a second upgrade to 7.
### If SSH and symlinks are possible
If you have SSH access to your webserver and are able to create symlinks,
this is the recommended way of setting up TYPO3 so that it can easily
be upgraded later through the Install Tool:
* Uncompress the `typo3_src-7.6.x.tar.gz` file one level above the Document
Root of your Web server:
```
/var/www/site/htdocs/ $ cd ..
/var/www/site/ $ tar xzf typo3_src-7.6.x.tar.gz
```
* Important: If you use GIT to fetch the sources, don't forget to run the following commands,
otherwise your installation won't work!
```
cd typo3_src
composer install --no-dev
cd ..
```
* Create the symlinks in your Document Root:
```
cd htdocs
ln -s ../typo3_src-7.6.x typo3_src
ln -s typo3_src/index.php
ln -s typo3_src/typo3
```
* In case you use Apache, copy the .htaccess to your Document Root:
```
cp typo3_src/_.htaccess .htaccess
```
You end up with the follow structure of files:
```
typo3_src-7.6.x/
htdocs/typo3_src -> ../typo3_src-7.6.x/
htdocs/typo3 -> typo3_src/typo3/
htdocs/index.php -> typo3_src/index.php
htdocs/.htaccess
```
This allows you to upgrade TYPO3 later by simply replacing the symlink
with a newer version, or by using the integrated "Core Updater" which can
be found in the Install Tool.
### Windows specifics
On Windows Vista and newer you can create symbolic links using the `mklink` tool:
```
mklink /D C:\<dir>\example.com\typo3_src C:\<dir>\typo3_src-7.6.x
mklink C:\<dir>\example.com\index.php C:\<dir>\typo3_src-7.6.x\index.php
```
Windows users might need to copy `index.php` from the source directory to the
web site root directory in case the Windows version does not support links
for files.
TYPO3 Core upgrades through the Install Tool is not supported under
Windows.
### No SSH and symlinks possible (not recommended)
In case you only have FTP or SFTP access to your hosting environment, you
can still install TYPO3, but you won't easily be able to upgrade your
installation once a new patch-level release is out.
Please note that this is not a recommended setup!
* Uncompress `typo3_src-7.6.x.zip` locally
* Upload all files and subdirectories directly in your Document Root
(where files that are served by your webserver are located).
* In case your provider uses Apache, rename the file `_.htaccess` to `.htaccess`.
You end up with this files in your Document Root:
```
.htaccess
ChangeLog
GPL.txt
index.php
INSTALL.md
LICENSE.txt
NEWS.txt
README.md
typo3/
```
Installation: further steps
---------------------------
Now access the web server using a web browser. You will be redirected to the
Install Tool which will walk you through the steps for setting up TYPO3 for
the first time.
It will check if your environment conforms to the minimum system requirements
and gives you some suggestions on what to change in case there are any
discrepancies.
The Install Tool will create the required directory structure for you
(typo3conf, uploads, fileadmin, typo3temp).
Former versions of TYPO3 required the download of a "Dummy Package"
(or "Blank Package"). This is no longer required since version 6.2!
TYPO3 Security
--------------
To ensure a secure installation, you have to make sure that you keep your
TYPO3 core and the extensions up to date.
* Subscribe to the announcement mailing list. This will inform you about new
releases of the TYPO3 core and security bulletins of core and community
extensions.
http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-announce
* Use the scheduler task "Update Extension List (em)" to update the list of
available extensions regularly. You should check regularly, if new versions
of these extensions are available and apply these updates.
* Please refer to official TYPO3 Security Guide for further information
about security-related topics of TYPO3 CMS and the resources compiled by
the Security Team.
https://docs.typo3.org/typo3cms/SecurityGuide/
https://typo3.org/teams/security/resources/
Installation FAQ
----------------
### 1
Q: Why do I get "500 Server error" when I navigate to my TYPO3 web site
immediately after installation?
A: If you are using Apache web server, check the Apache error log for specifics
on the error. The cause might be some missing module, or some syntax error
in your .htaccess file. The error log is usually located in /var/log/apache2
or /var/log/httpd. Check with your hosting provider if you are in doubt
where the logs are located.
### 2
Q: I went through the setup process and created an admin user. Why can't I log
in now?
A: If you use MySQL 5.x or newer, try setting it to "compatible" mode. Open the
TYPO3 Install Tool under http://example.com/typo3/install/ (where
example.com is the web site domain), navigate to "All configuration".
Find "setDBinit", and add this line to the top of the input field:
```
SET SESSION sql_mode=''
```
### 3
Q: Some modules or extensions make Apache crash on Windows. What is the cause?
A: Fluid uses complex regular expressions which require a lot of stack space
during the first processing. On Windows the default stack size for Apache
is a lot smaller than on unix. You can increase the size to 8MB (default on
unix) by adding to the httpd.conf:
```
<IfModule mpm_winnt_module>
ThreadStackSize 8388608
</IfModule>
```
Restart Apache after this change.

View File

@@ -0,0 +1,345 @@
Some icons used in the TYPO3 project are retrieved from the "Silk" icon set of
Mark James, which can be found at http://famfamfam.com/lab/icons/silk/. This
set is distributed under a Creative Commons Attribution 2.5 License. The
license can be found at http://creativecommons.org/licenses/by/2.5/.
---------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General
Public License instead of this License.

158
typo3_src-7.6.24/README.md Normal file
View File

@@ -0,0 +1,158 @@
TYPO3 CMS
=========
[![Build Status](https://travis-ci.org/TYPO3/TYPO3.CMS.svg?branch=master)](https://travis-ci.org/TYPO3/TYPO3.CMS)
TYPO3 is an open source PHP based web content management system released
under the GNU GPL. TYPO3 is copyright (c) 1999-2017 by Kasper Skaarhoj.
This document provides a basic introduction to TYPO3.
Getting Started
---------------
TYPO3 requires a webserver with PHP and a database (MySQL recommended).
Accessing the backend through a supported browser.
Please see the INSTALL.md in this folder in order to set up a basic TYPO3
installation on your webserver.
What is TYPO3?
--------------
TYPO3 is a free and open source Content Management Framework. It is released
under the GNU General Public License. It can run on several web servers, such
as Apache or IIS, on top of many operating systems, among them Linux, Microsoft
Windows, FreeBSD or MacOS X.
TYPO3 was initially authored by Kasper Skårhøj and is now further developed
by a community of Active Contributors around a small TYPO3 CMS Team.
To get more info about the GPL license, visit
http://www.opensource.org/licenses/gpl-license.php
What is a Content Management Framework?
---------------------------------------
A Content Management Framework is more than just a content management system,
due to the separation of the streamlined core and optional plugins
(extensions). TYPO3 has an open API that allows you to extend the frontend (web
site) and/or backend (administration) functionalities.
The concept of extensions makes TYPO3 capable of being developed and used
in almost any way you can imagine, either by using any of the many extensions
which are available for download, or by writing your own.
TYPO3 System requirements
-----------------------------
TYPO3 is based upon PHP and uses a MySQL database. For more information
regarding these requirements see the [INSTALL.md](INSTALL.md) file in this folder.
Using the Database Abstraction Layer (DBAL) allows one to use TYPO3 with other
Database Management Systems, like PostgreSQL, Oracle and MSSQL.
TYPO3 resources
---------------
Here is an overview of the most important TYPO3 resources to help you get
started:
### Get more information
* https://typo3.org is the main project website. It provides up to
date official news, information about events, access to downloading the
products and extensions.
* https://wiki.typo3.org is a collaborative wiki, providing access to
all kind of information around the TYPO3 ecosphere.
* https://docs.typo3.org/: TYPO3 is one of the most thoroughly
documented OpenSource products around, with manuals covering basic
tutorials, TypoScript, administration, development, core structure, etc.
You should make the time to locate the various documents, and read those
that apply to the work you want to do.
### Chat with us
The TYPO3 team is using a tool called Slack to openly communicate with each
other and with the public. Several teams use Slack as a way to communicate
internally and most channels are a welcome place for you to join and get
yourself involved.
* Register: https://forger.typo3.org/slack/
* Slack: https://typo3.slack.com/
### Exchange information, ask questions, get help
Slack is nice for short discussions, but when asking questions, most
answers are lost in the noise after a few minutes. To let everyone
profit from an answer, we recommend to ask questions on StackOverflow.
If you like, you can then post a link into the corresponding Slack
channel to raise attention. And please, do not forget to tag your
questions correctly with `TYPO3` (and possibly other tags like `Fluid`
or `Extbase`).
* [StackOverflow questions tagged "TYPO3"](https://stackoverflow.com/questions/tagged/typo3)
The community and all TYPO3 teams communicate through newsgroups, which can
also be accessed through mailing lists and forums. Any of these three ways
provide access to the same communication channels:
* Forum (Web): https://forum.typo3.org/
* Mailing Lists (Mail): https://typo3.org/support/mailing-lists/
* Newsgroups (NNTP): news://lists.typo3.org/
Contributing
------------
If you want to contribute to the TYPO3 CMS source code, take a look at our
Contributors Walkthrough and Review System:
* https://wiki.typo3.org/CWT
* https://review.typo3.org/
The [repository at GitHub](https://github.com/TYPO3/TYPO3.CMS) is a
synchronized mirror of the primary TYPO3 CMS core git repository:
* https://git.typo3.org/Packages/TYPO3.CMS.git
If you want to file a bug report, maintain your own extension using our
infrastructure (Git, Issue Tracker, Wiki, etc), take a look at:
* https://forge.typo3.org
Final notes
-----------
TYPO3 is said to be one of the most sophisticated PHP / Internet related
applications available, and the more you play with it, the more you will agree.
Due to the advanced level of the code and functionality, a degree of study,
time and perseverance is required to fully understand it, and get the best from
it. You should keep trying, as we say it's definitely worth it. TYPO3 is the
Enterprise Content Management System "for all".
The GPL license allows for developments that are based upon TYPO3 to also be
freely available under the GPL. Please remember this, because TYPO3 is about
"Inspiring People To Share". If you are making money with TYPO3 you can donate
or become a member of the TYPO3 Association.
By becoming a supporting member, individuals and organisations mainly fund
core development of TYPO3. The decision about what the funds are used for, is
made by all members of the Association and the Expert Advisory Board (EAB).
The decisions will be made transparent to the community and especially the
supporting members. Your funds will also serve for other purposes as laid
out in the bylaws.
* Donate: https://typo3.org/donate
* Become a member of the TYPO3 Association:
https://typo3.org/association/membership/levels/
Copyleft
--------
This document is a part of the TYPO3 project.
Written by Nigel Jackson, Ingmar Schlecht, Ernesto Baschny, Michael Stucki,
Oliver Hader, Ben van 't Ende and others.

366
typo3_src-7.6.24/_.htaccess Normal file
View File

@@ -0,0 +1,366 @@
#####
#
# Example .htaccess file for TYPO3 CMS - for use with Apache Webserver
#
# This file includes settings for the following configuration options:
#
# - Compression
# - Caching
# - MIME types
# - Cross Origin requests
# - Rewriting and Access
# - Miscellaneous
# - PHP optimisation
#
# If you want to use it, you have to copy it to the root folder of your TYPO3 installation (if its
# not there already) and rename it to '.htaccess'. To make .htaccess files work, you might need to
# adjust the 'AllowOverride' directive in your Apache configuration file.
#
# IMPORTANT: You may need to change this file depending on your TYPO3 installation!
# Consider adding this file's content to your webserver's configuration directly for speed improvement
#
# Lots of the options are taken from https://github.com/h5bp/html5-boilerplate/blob/master/dist/.htaccess
#
####
### Begin: Compression ###
# Compressing resource files will save bandwidth and so improve loading speed especially for users
# with slower internet connections. TYPO3 can compress the .js and .css files for you.
# *) Uncomment the following lines and
# *) Set $GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel'] = 9 for the Backend
# *) Set $GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel'] = 9 together with the TypoScript properties
# config.compressJs and config.compressCss for GZIP compression of Frontend JS and CSS files.
#<FilesMatch "\.js\.gzip$">
# AddType "text/javascript" .gzip
#</FilesMatch>
#<FilesMatch "\.css\.gzip$">
# AddType "text/css" .gzip
#</FilesMatch>
#AddEncoding gzip .gzip
<IfModule mod_deflate.c>
# Force compression for mangled `Accept-Encoding` request headers
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
# Compress all output labeled with one of the following media types.
#
# (!) For Apache versions below version 2.3.7 you don't need to
# enable `mod_filter` and can remove the `<IfModule mod_filter.c>`
# and `</IfModule>` lines as `AddOutputFilterByType` is still in
# the core directives.
#
# https://httpd.apache.org/docs/current/mod/mod_filter.html#addoutputfilterbytype
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE application/atom+xml \
application/javascript \
application/json \
application/ld+json \
application/manifest+json \
application/rdf+xml \
application/rss+xml \
application/schema+json \
application/vnd.geo+json \
application/vnd.ms-fontobject \
application/x-font-ttf \
application/x-javascript \
application/x-web-app-manifest+json \
application/xhtml+xml \
application/xml \
font/eot \
font/opentype \
image/bmp \
image/svg+xml \
image/vnd.microsoft.icon \
image/x-icon \
text/cache-manifest \
text/css \
text/html \
text/javascript \
text/plain \
text/vcard \
text/vnd.rim.location.xloc \
text/vtt \
text/x-component \
text/x-cross-domain-policy \
text/xml
</IfModule>
<IfModule mod_mime.c>
AddEncoding gzip svgz
</IfModule>
</IfModule>
### End: Compression ###
### Begin: Browser caching of resource files ###
# This affects Frontend and Backend and increases performance.
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 month"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/ld+json "access plus 0 seconds"
ExpiresByType application/schema+json "access plus 0 seconds"
ExpiresByType application/vnd.geo+json "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType image/vnd.microsoft.icon "access plus 1 week"
ExpiresByType image/x-icon "access plus 1 week"
ExpiresByType text/x-component "access plus 1 month"
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType application/x-javascript "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"
ExpiresByType application/manifest+json "access plus 1 week"
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
ExpiresByType text/cache-manifest "access plus 0 seconds"
ExpiresByType audio/ogg "access plus 1 month"
ExpiresByType image/bmp "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/ogg "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
ExpiresByType application/atom+xml "access plus 1 hour"
ExpiresByType application/rdf+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType font/eot "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType application/font-woff "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType font/woff "access plus 1 month"
ExpiresByType application/font-woff2 "access plus 1 month"
ExpiresByType text/x-cross-domain-policy "access plus 1 week"
</IfModule>
### End: Browser caching of resource files ###
### Begin: MIME types ###
# Proper MIME types for all files
<IfModule mod_mime.c>
# Data interchange
AddType application/atom+xml atom
AddType application/json json map topojson
AddType application/ld+json jsonld
AddType application/rss+xml rss
AddType application/vnd.geo+json geojson
AddType application/xml rdf xml
# JavaScript
AddType application/javascript js
# Manifest files
AddType application/manifest+json webmanifest
AddType application/x-web-app-manifest+json webapp
AddType text/cache-manifest appcache
# Media files
AddType audio/mp4 f4a f4b m4a
AddType audio/ogg oga ogg opus
AddType image/bmp bmp
AddType image/svg+xml svg svgz
AddType image/webp webp
AddType video/mp4 f4v f4p m4v mp4
AddType video/ogg ogv
AddType video/webm webm
AddType video/x-flv flv
AddType image/x-icon cur ico
# Web fonts
AddType application/font-woff woff
AddType application/font-woff2 woff2
AddType application/vnd.ms-fontobject eot
AddType application/x-font-ttf ttc ttf
AddType font/opentype otf
# Other
AddType application/octet-stream safariextz
AddType application/x-bb-appworld bbaw
AddType application/x-chrome-extension crx
AddType application/x-opera-extension oex
AddType application/x-xpinstall xpi
AddType text/vcard vcard vcf
AddType text/vnd.rim.location.xloc xloc
AddType text/vtt vtt
AddType text/x-component htc
</IfModule>
# UTF-8 encoding
AddDefaultCharset utf-8
<IfModule mod_mime.c>
AddCharset utf-8 .atom .css .js .json .manifest .rdf .rss .vtt .webapp .webmanifest .xml
</IfModule>
### End: MIME types ###
### Begin: Cross Origin ###
# Send the CORS header for images when browsers request it.
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
<FilesMatch "\.(bmp|cur|gif|ico|jpe?g|png|svgz?|webp)$">
SetEnvIf Origin ":" IS_CORS
Header set Access-Control-Allow-Origin "*" env=IS_CORS
</FilesMatch>
</IfModule>
</IfModule>
# Allow cross-origin access to web fonts.
<IfModule mod_headers.c>
<FilesMatch "\.(eot|otf|tt[cf]|woff2?)$">
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
</IfModule>
### End: Cross Origin ###
### Begin: Rewriting and Access ###
# You need rewriting, if you use a URL-Rewriting extension (RealURL, CoolUri).
<IfModule mod_rewrite.c>
# Enable URL rewriting
RewriteEngine On
# Store the current location in an environment variable CWD to use
# mod_rewrite in .htaccess files without knowing the RewriteBase
RewriteCond $0#%{REQUEST_URI} ([^#]*)#(.*)\1$
RewriteRule ^.*$ - [E=CWD:%2]
# Rules to set ApplicationContext based on hostname
#RewriteCond %{HTTP_HOST} ^dev\.example\.com$
#RewriteRule .? - [E=TYPO3_CONTEXT:Development]
#RewriteCond %{HTTP_HOST} ^staging\.example\.com$
#RewriteRule .? - [E=TYPO3_CONTEXT:Production/Staging]
#RewriteCond %{HTTP_HOST} ^www\.example\.com$
#RewriteRule .? - [E=TYPO3_CONTEXT:Production]
# Rule for versioned static files, configured through:
# - $GLOBALS['TYPO3_CONF_VARS']['BE']['versionNumberInFilename']
# - $GLOBALS['TYPO3_CONF_VARS']['FE']['versionNumberInFilename']
# IMPORTANT: This rule has to be the very first RewriteCond in order to work!
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$ %{ENV:CWD}$1.$3 [L]
# Access block for folders
RewriteRule _(?:recycler|temp)_/ - [F]
RewriteRule fileadmin/templates/.*\.(?:txt|ts)$ - [F]
RewriteRule ^(?:vendor|typo3_src|typo3temp/logs) - [F]
RewriteRule (?:typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(?:Configuration|Resources/Private|Tests?|Documentation|docs?)/ - [F]
# Block access to all hidden files and directories with the exception of
# the visible content from within the `/.well-known/` hidden directory (RFC 5785).
RewriteCond %{REQUEST_URI} "!(^|/)\.well-known/([^./]+./?)+$" [NC]
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule (?:^|/)\. - [F]
# Stop rewrite processing, if we are in the typo3/ directory or any other known directory
# NOTE: Add your additional local storages here
RewriteRule ^(?:typo3/|fileadmin/|typo3conf/|typo3temp/|uploads/|favicon\.ico) - [L]
# If the file/symlink/directory does not exist => Redirect to index.php.
# For httpd.conf, you need to prefix each '%{REQUEST_FILENAME}' with '%{DOCUMENT_ROOT}'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^.*$ %{ENV:CWD}index.php [QSA,L]
</IfModule>
# Access block for files
<FilesMatch "(?i:^\.|^#.*#|^(?:ChangeLog|ToDo|Readme|License)(?:\.md|\.txt)?|^composer\.(?:json|lock)|^ext_conf_template\.txt|^ext_typoscript_constants\.txt|^ext_typoscript_setup\.txt|flexform[^.]*\.xml|locallang[^.]*\.(?:xml|xlf)|\.(?:bak|co?nf|cfg|ya?ml|ts|dist|fla|in[ci]|log|sh|sql(?:\..*)?|sw[op]|git.*)|.*(?:~|rc))$">
# Apache < 2.3
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
Satisfy All
</IfModule>
# Apache ≥ 2.3
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
# Block access to vcs directories
<IfModule mod_alias.c>
RedirectMatch 404 /\.(?:git|svn|hg)/
</IfModule>
### End: Rewriting and Access ###
### Begin: Miscellaneous ###
# 404 error prevention for non-existing redirected folders
Options -MultiViews
# Make sure that directory listings are disabled.
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
<IfModule mod_headers.c>
# Force IE to render pages in the highest available mode
Header set X-UA-Compatible "IE=edge"
<FilesMatch "\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svgz?|ttf|vcf|webapp|webm|webp|woff2?|xml|xpi)$">
Header unset X-UA-Compatible
</FilesMatch>
# Reducing MIME type security risks
Header set X-Content-Type-Options "nosniff"
</IfModule>
# ETag removal
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
FileETag None
### End: Miscellaneous ###
# Add your own rules here.

View File

@@ -0,0 +1,232 @@
{
"name": "typo3/cms",
"description": "TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.",
"keywords": ["typo3", "cms", "content management system", "extbase"],
"homepage": "https://typo3.org/",
"type": "typo3-cms-core",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "TYPO3 CMS Core Team",
"role": "Developer",
"homepage": "https://forge.typo3.org/projects/typo3cms-core"
},
{
"name": "The TYPO3 Community",
"role": "Contributor",
"homepage": "https://typo3.org/community/"
}
],
"support": {
"general": "https://typo3.org/support/",
"issues": "https://forge.typo3.org",
"irc": "irc://irc.freenode.net/#typo3-cms",
"news": "nntp://lists.typo3.org"
},
"config": {
"optimize-autoloader": true,
"bin-dir": "bin",
"platform": {
"php": "5.5"
}
},
"require": {
"php": ">=5.5.0",
"ext-json": "*",
"ext-pcre": "*",
"ext-session": "*",
"ext-xml": "*",
"psr/log": "~1.0.0",
"pear/http_request2": "~2.3.0",
"swiftmailer/swiftmailer": "~5.4.5",
"symfony/console": "^2.7",
"symfony/finder": "^2.7",
"doctrine/instantiator": "~1.0.4",
"typo3/class-alias-loader": "^1.0",
"typo3/cms-composer-installers": "^1.2.8",
"psr/http-message": "~1.0",
"cogpowered/finediff": "~0.3.1",
"mso/idna-convert": "^0.9.1",
"symfony/debug": "^2.7"
},
"require-dev": {
"phpunit/phpunit": "~4.8.0",
"mikey179/vfsStream": "1.6.0",
"symfony/polyfill-mbstring": "~1.0",
"friendsofphp/php-cs-fixer": "^2.2",
"symfony/stopwatch": "^2.8",
"symfony/process": "^2.8",
"symfony/options-resolver": "^2.8",
"symfony/filesystem": "^2.8",
"symfony/event-dispatcher": "^2.8",
"symfony/yaml": "^2.8"
},
"suggest": {
"ext-gd": "GDlib/Freetype is required for building images with text (GIFBUILDER) and can also be used to scale images",
"ext-fileinfo": "Used for proper file type detection in the file abstraction layer",
"ext-zlib": "TYPO3 uses zlib for amongst others output compression and un/packing t3x extension files",
"ext-openssl": "",
"ext-soap": "",
"ext-zip": "",
"ext-mysqli": ""
},
"extra": {
"typo3/class-alias-loader": {
"always-add-alias-loader": true
},
"branch-alias": {
"dev-TYPO3_7-6": "7.x-dev"
}
},
"replace": {
"typo3/cms-about": "self.version",
"typo3/cms-aboutmodules": "self.version",
"typo3/cms-adodb": "self.version",
"typo3-ter/adodb": "*",
"typo3/cms-backend": "self.version",
"typo3/cms-belog": "self.version",
"typo3/cms-beuser": "self.version",
"typo3/cms-context-help": "self.version",
"typo3/cms-core": "self.version",
"typo3/cms-cshmanual": "self.version",
"typo3/cms-css-styled-content": "self.version",
"typo3/cms-dbal": "self.version",
"typo3-ter/dbal": "*",
"typo3/cms-documentation": "self.version",
"typo3/cms-extbase": "self.version",
"typo3/cms-extensionmanager": "self.version",
"typo3/cms-feedit": "self.version",
"typo3/cms-felogin": "self.version",
"typo3/cms-filelist": "self.version",
"typo3/cms-filemetadata": "self.version",
"typo3/cms-fluid": "self.version",
"typo3/cms-fluid-styled-content": "self.version",
"typo3/cms-form": "self.version",
"typo3/cms-frontend": "self.version",
"typo3/cms-func": "self.version",
"typo3-ter/func": "*",
"typo3/cms-func-wizards": "self.version",
"typo3/cms-impexp": "self.version",
"typo3/cms-indexed-search": "self.version",
"typo3/cms-indexed-search-mysql": "self.version",
"typo3/cms-info": "self.version",
"typo3/cms-info-pagetsconfig": "self.version",
"typo3/cms-install": "self.version",
"typo3/cms-lang": "self.version",
"typo3/cms-linkvalidator": "self.version",
"typo3/cms-lowlevel": "self.version",
"typo3/cms-opendocs": "self.version",
"typo3/cms-recordlist": "self.version",
"typo3/cms-recycler": "self.version",
"typo3/cms-reports": "self.version",
"typo3/cms-rsaauth": "self.version",
"typo3/cms-rtehtmlarea": "self.version",
"typo3-ter/rtehtmlarea": "*",
"typo3/cms-saltedpasswords": "self.version",
"typo3/cms-scheduler": "self.version",
"typo3/cms-setup": "self.version",
"typo3/cms-sv": "self.version",
"typo3/cms-sys-action": "self.version",
"typo3/cms-sys-note": "self.version",
"typo3/cms-t3editor": "self.version",
"typo3/cms-t3skin": "self.version",
"typo3/cms-taskcenter": "self.version",
"typo3/cms-tstemplate": "self.version",
"typo3/cms-version": "self.version",
"typo3/cms-viewpage": "self.version",
"typo3/cms-wizard-crpages": "self.version",
"typo3/cms-wizard-sortpages": "self.version",
"typo3/cms-workspaces": "self.version"
},
"autoload": {
"psr-4": {
"TYPO3\\CMS\\About\\": "typo3/sysext/about/Classes/",
"TYPO3\\CMS\\Aboutmodules\\": "typo3/sysext/aboutmodules/Classes/",
"TYPO3\\CMS\\Backend\\": "typo3/sysext/backend/Classes/",
"TYPO3\\CMS\\Belog\\": "typo3/sysext/belog/Classes/",
"TYPO3\\CMS\\Beuser\\": "typo3/sysext/beuser/Classes/",
"TYPO3\\CMS\\ContextHelp\\": "typo3/sysext/context_help/Classes/",
"TYPO3\\CMS\\Core\\": "typo3/sysext/core/Classes/",
"TYPO3\\CMS\\Cshmanual\\": "typo3/sysext/cshmanual/Classes/",
"TYPO3\\CMS\\CssStyledContent\\": "typo3/sysext/css_styled_content/Classes/",
"TYPO3\\CMS\\Dbal\\": "typo3/sysext/dbal/Classes/",
"TYPO3\\CMS\\Documentation\\": "typo3/sysext/documentation/Classes/",
"TYPO3\\CMS\\Extbase\\": "typo3/sysext/extbase/Classes/",
"TYPO3\\CMS\\Extensionmanager\\": "typo3/sysext/extensionmanager/Classes/",
"TYPO3\\CMS\\Feedit\\": "typo3/sysext/feedit/Classes/",
"TYPO3\\CMS\\Felogin\\": "typo3/sysext/felogin/Classes/",
"TYPO3\\CMS\\Filelist\\": "typo3/sysext/filelist/Classes/",
"TYPO3\\CMS\\Fluid\\": "typo3/sysext/fluid/Classes/",
"TYPO3\\CMS\\FluidStyledContent\\": "typo3/sysext/fluid_styled_content/Classes/",
"TYPO3\\CMS\\Form\\": "typo3/sysext/form/Classes/",
"TYPO3\\CMS\\Frontend\\": "typo3/sysext/frontend/Classes/",
"TYPO3\\CMS\\Func\\": "typo3/sysext/func/Classes/",
"TYPO3\\CMS\\Impexp\\": "typo3/sysext/impexp/Classes/",
"TYPO3\\CMS\\IndexedSearch\\": "typo3/sysext/indexed_search/Classes/",
"TYPO3\\CMS\\IndexedSearchMysql\\": "typo3/sysext/indexed_search_mysql/Classes/",
"TYPO3\\CMS\\Info\\": "typo3/sysext/info/Classes/",
"TYPO3\\CMS\\InfoPagetsconfig\\": "typo3/sysext/info_pagetsconfig/Classes/",
"TYPO3\\CMS\\Install\\": "typo3/sysext/install/Classes/",
"TYPO3\\CMS\\Lang\\": "typo3/sysext/lang/Classes/",
"TYPO3\\CMS\\Linkvalidator\\": "typo3/sysext/linkvalidator/Classes/",
"TYPO3\\CMS\\Lowlevel\\": "typo3/sysext/lowlevel/Classes/",
"TYPO3\\CMS\\Opendocs\\": "typo3/sysext/opendocs/Classes/",
"TYPO3\\CMS\\Recordlist\\": "typo3/sysext/recordlist/Classes/",
"TYPO3\\CMS\\Recycler\\": "typo3/sysext/recycler/Classes/",
"TYPO3\\CMS\\Reports\\": "typo3/sysext/reports/Classes/",
"TYPO3\\CMS\\Rsaauth\\": "typo3/sysext/rsaauth/Classes/",
"TYPO3\\CMS\\Rtehtmlarea\\": "typo3/sysext/rtehtmlarea/Classes/",
"TYPO3\\CMS\\Saltedpasswords\\": "typo3/sysext/saltedpasswords/Classes/",
"TYPO3\\CMS\\Scheduler\\": "typo3/sysext/scheduler/Classes/",
"TYPO3\\CMS\\Setup\\": "typo3/sysext/setup/Classes/",
"TYPO3\\CMS\\Sv\\": "typo3/sysext/sv/Classes/",
"TYPO3\\CMS\\SysAction\\": "typo3/sysext/sys_action/Classes/",
"TYPO3\\CMS\\SysNote\\": "typo3/sysext/sys_note/Classes/",
"TYPO3\\CMS\\T3editor\\": "typo3/sysext/t3editor/Classes/",
"TYPO3\\CMS\\Taskcenter\\": "typo3/sysext/taskcenter/Classes/",
"TYPO3\\CMS\\Tstemplate\\": "typo3/sysext/tstemplate/Classes/",
"TYPO3\\CMS\\Version\\": "typo3/sysext/version/Classes/",
"TYPO3\\CMS\\Viewpage\\": "typo3/sysext/viewpage/Classes/",
"TYPO3\\CMS\\WizardCrpages\\": "typo3/sysext/wizard_crpages/Classes/",
"TYPO3\\CMS\\WizardSortpages\\": "typo3/sysext/wizard_sortpages/Classes/",
"TYPO3\\CMS\\Workspaces\\": "typo3/sysext/workspaces/Classes/"
},
"classmap": [
"typo3/sysext/core/Resources/PHP/",
"typo3/sysext/fluid/Resources/PHP/"
],
"files": [
"typo3/sysext/core/Resources/PHP/GlobalDebugFunctions.php"
]
},
"autoload-dev": {
"psr-4": {
"TYPO3\\CMS\\Backend\\Tests\\": "typo3/sysext/backend/Tests/",
"TYPO3\\CMS\\Belog\\Tests\\": "typo3/sysext/belog/Tests/",
"TYPO3\\CMS\\Beuser\\Tests\\": "typo3/sysext/beuser/Tests/",
"TYPO3\\CMS\\Core\\Tests\\": "typo3/sysext/core/Tests/",
"TYPO3\\CMS\\Dbal\\Tests\\": "typo3/sysext/dbal/Tests/",
"TYPO3\\CMS\\Documentation\\Tests\\": "typo3/sysext/documentation/Tests/",
"TYPO3\\CMS\\Extbase\\Tests\\": "typo3/sysext/extbase/Tests/",
"TYPO3\\CMS\\Extensionmanager\\Tests\\": "typo3/sysext/extensionmanager/Tests/",
"TYPO3\\CMS\\Felogin\\Tests\\": "typo3/sysext/felogin/Tests/",
"TYPO3\\CMS\\Fluid\\Tests\\": "typo3/sysext/fluid/Tests/",
"TYPO3\\CMS\\Form\\Tests\\": "typo3/sysext/form/Tests/",
"TYPO3\\CMS\\Frontend\\Tests\\": "typo3/sysext/frontend/Tests/",
"TYPO3\\CMS\\Impexp\\Tests\\": "typo3/sysext/impexp/Tests/",
"TYPO3\\CMS\\IndexedSearch\\Tests\\": "typo3/sysext/indexed_search/Tests/",
"TYPO3\\CMS\\Install\\Tests\\": "typo3/sysext/install/Tests/",
"TYPO3\\CMS\\Lang\\Tests\\": "typo3/sysext/lang/Tests/",
"TYPO3\\CMS\\Lowlevel\\Tests\\": "typo3/sysext/lowlevel/Tests/",
"TYPO3\\CMS\\Recordlist\\Tests\\": "typo3/sysext/recordlist/Tests/",
"TYPO3\\CMS\\Reports\\Tests\\": "typo3/sysext/reports/Tests/",
"TYPO3\\CMS\\Rsaauth\\Tests\\": "typo3/sysext/rsaauth/Tests/",
"TYPO3\\CMS\\Saltedpasswords\\Tests\\": "typo3/sysext/saltedpasswords/Tests/",
"TYPO3\\CMS\\Scheduler\\Tests\\": "typo3/sysext/scheduler/Tests/",
"TYPO3\\CMS\\Sv\\Tests\\": "typo3/sysext/sv/Tests/",
"TYPO3\\CMS\\Workspaces\\Tests\\": "typo3/sysext/workspaces/Tests/",
"TYPO3\\CMS\\Recycler\\Tests\\": "typo3/sysext/recycler/Tests/"
},
"classmap": ["typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/"]
}
}

2851
typo3_src-7.6.24/composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

14
typo3_src-7.6.24/vendor/autoload.php vendored Normal file
View File

@@ -0,0 +1,14 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
// autoload.php @generated by typo3/class-alias-loader
require_once __DIR__ . '/composer/autoload_alias_loader_real.php';
return ClassAliasLoaderInit21f34c26fff4d7a212f91dfdd964dc90::initializeClassAliasLoader(ComposerAutoloaderInit21f34c26fff4d7a212f91dfdd964dc90::getLoader());

View File

@@ -0,0 +1,120 @@
FineDiff
========
Originally written by Raymond Hill ([https://github.com/gorhill/PHP-FineDiff](https://github.com/gorhill/PHP-FineDiff)) FineDiff has been tweaked to bring it up to date with the modern world. That means documented, nicely formatted, tested code that can be easily extended.
[![Build Status](https://travis-ci.org/cogpowered/FineDiff.png?branch=master)](https://travis-ci.org/cogpowered/FineDiff)
Installation
------------
**Composer**
The preferred way of using FineDiff is through [Composer](http://getcomposer.org).
Add the following to your composer.json file:
```json
{
"require": {
"cogpowered/finediff": "0.3.*"
}
}
```
Upgrading
---------
**0.3.x** introduces a backwards incompatible version, so if you have stored opcodes do not upgrade!
`0.3.x` fixes a double encoding issue that generates a longer opcode than is needed.
Usage
-----
**Render HTML**
Render as HTML the difference between two strings:
```php
$diff = new cogpowered\FineDiff\Diff;
echo $diff->render('string one', 'string two');
```
This would then output:
```html
string <ins>tw</ins>o<del>ne</del>
```
You could change the granularity to `cogpowered\FineDiff\Granularity\Word` so the output is:
```html
string <del>one</del><ins>two</ins>
```
You do this by passing it into the Diff constructor:
```php
$granularity = new cogpowered\FineDiff\Granularity\Word;
$diff = new cogpowered\FineDiff\Diff($granularity);
```
**Grab opcode instructions**
Opcode instructions are what tell FineDiff how to change one string into another.
```php
$diff = new cogpowered\FineDiff\Diff;
echo $diff->getOpcodes('string one', 'string two');
```
This would then output:
```html
c7d3i3:two
```
Render text using the opcodes:
```php
$render = new cogpowered\FineDiff\Render\Text;
echo $render->process('string one', 'c7d3i3:two');
```
Would output:
```html
string two
```
Same with HTML:
```php
$render = new cogpowered\FineDiff\Render\Html;
echo $render->process('string one', 'c7d3i3:two');
```
License
-------
Copyright (c) 2011 Raymond Hill (http://raymondhill.net/blog/?p=441)
Copyright (c) 2013 Rob Crowe (http://cogpowered.com)
Licensed under The MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,27 @@
{
"name": "cogpowered/finediff",
"description": "PHP implementation of a Fine granularity Diff engine",
"homepage": "https://github.com/cogpowered/FineDiff",
"license": "MIT",
"keywords": ["finediff", "diff", "text", "string", "opcode"],
"authors": [
{
"name": "Raymond Hill"
},
{
"name": "Rob Crowe",
"email": "rob@cogpowered.com"
}
],
"type": "library",
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"mockery/mockery": "*",
"phpunit/phpunit": "*"
},
"autoload": {
"psr-0": { "cogpowered\\FineDiff": "src/" }
}
}

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
colors="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="Delimiters">
<directory suffix=".php">tests/Delimiters</directory>
</testsuite>
<testsuite name="Diff">
<directory suffix=".php">tests/Diff</directory>
</testsuite>
<testsuite name="Granularity">
<directory suffix=".php">tests/Granularity</directory>
</testsuite>
<testsuite name="Parser">
<directory suffix=".php">tests/Parser</directory>
</testsuite>
<testsuite name="Render">
<directory suffix=".php">tests/Render</directory>
</testsuite>
<testsuite name="Usage">
<directory suffix=".php">tests/Usage</directory>
</testsuite>
</testsuites>
<filter>
<blacklist>
<directory suffix=".php">PEAR_INSTALL_DIR</directory>
<directory suffix=".php">PHP_LIBDIR</directory>
<directory suffix=".php">vendor</directory>
</blacklist>
</filter>
</phpunit>

View File

@@ -0,0 +1,37 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff;
/**
* Used by classes implementing cogpowered\FineDiff\Granularity\GranularityInterface.
*
* Class is used more like an Enum type; the class can not be instantiated.
*/
abstract class Delimiters
{
const PARAGRAPH = "\n\r";
const SENTENCE = ".\n\r";
const WORD = " \t.\n\r";
const CHARACTER = "";
/**
* Do not allow this class to be instantiated.
*/
private function __construct() {}
}

View File

@@ -0,0 +1,164 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff;
use cogpowered\FineDiff\Granularity\GranularityInterface;
use cogpowered\FineDiff\Render\RendererInterface;
use cogpowered\FineDiff\Parser\ParserInterface;
use cogpowered\FineDiff\Granularity\Character;
use cogpowered\FineDiff\Render\Html;
use cogpowered\FineDiff\Parser\Parser;
/**
* Diff class.
*/
class Diff
{
/**
* @var cogpowered\FineDiff\Granularity\GranularityInterface
*/
protected $granularity;
/**
* @var cogpowered\FineDiff\Render\RendererInterface
*/
protected $renderer;
/**
* @var cogpowered\FineDiff\Parser\ParserInterface
*/
protected $parser;
/**
* Instantiate a new instance of Diff.
*
* @param cogpowered\FineDiff\Granularity\GranularityInterface $granularity Level of diff.
* @param cogpowered\FineDiff\Render\RenderInterface $renderer Diff renderer.
* @param cogpowered\FineDiff\Parser\ParserInterface $parser Parser used to generate opcodes.
*
* @throws cogpowered\FineDiff\Exceptions\GranularityCountException
* @throws cogpowered\FineDiff\Exceptions\OperationException
*/
public function __construct(GranularityInterface $granularity = null, RendererInterface $renderer = null, ParserInterface $parser = null)
{
// Set some sensible defaults
// Set the granularity of the diff
$this->granularity = ($granularity !== null) ? $granularity : new Character;
// Set the renderer to use when calling Diff::render
$this->renderer = ($renderer !== null) ? $renderer : new Html;
// Set the diff parser
$this->parser = ($parser !== null) ? $parser : new Parser($this->granularity);
}
/**
* Returns the granularity object used by the parser.
*
* @return @cogpowered\FineDiff\Granularity\GranularityInterface
*/
public function getGranularity()
{
return $this->parser->getGranularity();
}
/**
* Set the granularity level of the parser.
*
* @param cogpowered\FineDiff\Granularity\GranularityInterface $granularity
* @return void
*/
public function setGranularity(GranularityInterface $granularity)
{
$this->parser->setGranularity($granularity);
}
/**
* Get the render.
*
* @return cogpowered\FineDiff\Render\RendererInterface
*/
public function getRenderer()
{
return $this->renderer;
}
/**
* Set the renderer.
*
* @param cogpowered\FineDiff\Render\RendererInterface $renderer
* @return void
*/
public function setRenderer(RendererInterface $renderer)
{
$this->renderer = $renderer;
}
/**
* Get the parser responsible for generating the diff/opcodes.
*
* @return cogpowered\FineDiff\Parser\ParserInterface
*/
public function getParser()
{
return $this->parser;
}
/**
* Set the parser.
*
* @param cogpowered\FineDiff\Parser\ParserInterface $parser
* @return void
*/
public function setParser(ParserInterface $parser)
{
$this->parser = $parser;
}
/**
* Gets the diff / opcodes between two strings.
*
* Returns the opcode diff which can be used for example, to
* to generate a HTML report of the differences.
*
* @return cogpowered\FineDiff\Parser\Opcodes
*/
public function getOpcodes($from_text, $to_text)
{
return $this->parser->parse($from_text, $to_text);
}
/**
* Render the difference between two strings.
*
* By default will return the difference as HTML.
*
* @param string $from_text
* @param string $to_text
* @return string
*/
public function render($from_text, $to_text)
{
// First we need the opcodes
$opcodes = $this->getOpcodes($from_text, $to_text);
return $this->renderer->process($from_text, $opcodes);
}
}

View File

@@ -0,0 +1,24 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Exceptions;
/**
* A granularity must have at least one thing to match against. Thrown when this isn't the case.
*/
class GranularityCountException extends \Exception {}

View File

@@ -0,0 +1,24 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Exceptions;
/**
* Thrown when trying to set an opcode that doesn't implement cogpowered\FineDiff\Parser\Operations\OperationInterface.
*/
class OperationException extends \Exception {}

View File

@@ -0,0 +1,34 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Granularity;
use cogpowered\FineDiff\Delimiters;
/**
* Character level granularity.
*/
class Character extends Granularity
{
protected $delimiters = array(
Delimiters::PARAGRAPH,
Delimiters::SENTENCE,
Delimiters::WORD,
Delimiters::CHARACTER,
);
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Granularity;
/**
* Granularities should extend this class.
*/
abstract class Granularity implements GranularityInterface, \ArrayAccess, \Countable
{
/**
* @var array Extending granularities should override this.
*/
protected $delimiters = array();
/**
* @inheritdoc
*/
public function offsetExists($offset)
{
return isset($this->delimiters[$offset]);
}
/**
* @inheritdoc
*/
public function offsetGet($offset)
{
return isset($this->delimiters[$offset]) ? $this->delimiters[$offset] : null;
}
/**
* @inheritdoc
*/
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->delimiters[] = $value;
} else {
$this->delimiters[$offset] = $value;
}
}
/**
* @inheritdoc
*/
public function offsetUnset($offset)
{
unset($this->delimiters[$offset]);
}
/**
* Return the number of delimiters this granularity contains.
*
* @return int
*/
public function count()
{
return count($this->delimiters);
}
/**
* @inheritdoc
*/
public function getDelimiters()
{
return $this->delimiters;
}
/**
* @inheritdoc
*/
public function setDelimiters(array $delimiters)
{
$this->delimiters = $delimiters;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Granularity;
interface GranularityInterface
{
public function offsetExists($offset);
public function offsetGet($offset);
public function offsetSet($offset, $value);
public function offsetUnset($offset);
/**
* Get the delimiters that make up the granularity.
*
* @return array
*/
public function getDelimiters();
/**
* Set the delimiters that make up the granularity.
*
* @param array $delimiters
* @return void
*/
public function setDelimiters(array $delimiters);
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Granularity;
use cogpowered\FineDiff\Delimiters;
/**
* Paragraph level granularity.
*/
class Paragraph extends Granularity
{
protected $delimiters = array(
Delimiters::PARAGRAPH,
);
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Granularity;
use cogpowered\FineDiff\Delimiters;
/**
* Sentence level granularity.
*/
class Sentence extends Granularity
{
protected $delimiters = array(
Delimiters::PARAGRAPH,
Delimiters::SENTENCE,
);
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Granularity;
use cogpowered\FineDiff\Delimiters;
/**
* Word level granularity.
*/
class Word extends Granularity
{
protected $delimiters = array(
Delimiters::PARAGRAPH,
Delimiters::SENTENCE,
Delimiters::WORD,
);
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Parser;
use cogpowered\FineDiff\Exceptions\OperationException;
/**
* Holds all the opcodes returned by the parser.
*/
class Opcodes implements OpcodesInterface
{
/**
* @var array Individual opcodes.
*/
protected $opcodes = array();
/**
* @inheritdoc
*/
public function getOpcodes()
{
return $this->opcodes;
}
/**
* @inheritdoc
*/
public function setOpcodes(array $opcodes)
{
$this->opcodes = array();
// Ensure that all elements of the array
// are of the correct type
foreach ($opcodes as $opcode) {
if (!is_a($opcode, 'cogpowered\FineDiff\Parser\Operations\OperationInterface')) {
throw new OperationException('Invalid opcode object');
}
$this->opcodes[] = $opcode->getOpcode();
}
}
/**
* @inheritdoc
*/
public function generate()
{
return implode('', $this->opcodes);
}
/**
* @inheritdoc
*/
public function __toString()
{
return $this->generate();
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Parser;
interface OpcodesInterface
{
/**
* Get the opcodes.
*
* @return array
*/
public function getOpcodes();
/**
* Set the opcodes for this parse.
*
* @param array $opcodes Elements must be an instance of cogpowered\FineDiff\Parser\Operations\OperationInterface.
* @throws cogpowered\FineDiff\Exceptions\OperationException
* @return void
*/
public function setOpcodes(array $opcodes);
/**
* Return the opcodes in a format that can then be rendered.
*
* @return string
*/
public function generate();
/**
* When object is cast to a string returns opcodes as string.
*
* @see Opcodes::generate
* @return string
*/
public function __toString();
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Parser\Operations;
/**
* Generates the opcode for a copy operation.
*/
class Copy implements OperationInterface
{
/**
* Set the initial length.
*
* @param int $len Length of string.
*/
public function __construct($len)
{
$this->len = $len;
}
/**
* @inheritdoc
*/
public function getFromLen()
{
return $this->len;
}
/**
* @inheritdoc
*/
public function getToLen()
{
return $this->len;
}
/**
* @inheritdoc
*/
public function getOpcode()
{
if ($this->len === 1) {
return 'c';
}
return "c{$this->len}";
}
/**
* Increase the length of the string.
*
* @param int $size Amount to increase the string length by.
* @return int New length
*/
public function increase($size)
{
return $this->len += $size;
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Parser\Operations;
/**
* Generates the opcode for a delete operation.
*/
class Delete implements OperationInterface
{
/**
* Set the initial length.
*
* @param int $len Length of string.
*/
public function __construct($len)
{
$this->fromLen = $len;
}
/**
* @inheritdoc
*/
public function getFromLen()
{
return $this->fromLen;
}
/**
* @inheritdoc
*/
public function getToLen()
{
return 0;
}
/**
* @inheritdoc
*/
public function getOpcode()
{
if ($this->fromLen === 1) {
return 'd';
}
return "d{$this->fromLen}";
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Parser\Operations;
/**
* Generates the opcode for a copy operation.
*/
class Insert implements OperationInterface
{
/**
* Sets the text that the operation is working with.
*
* @param string $text
*/
public function __construct($text)
{
$this->text = $text;
}
/**
* @inheritdoc
*/
public function getFromLen()
{
return 0;
}
/**
* @inheritdoc
*/
public function getToLen()
{
return strlen($this->text);
}
/**
* @inheritdoc
*/
public function getText()
{
return $this->text;
}
/**
* @inheritdoc
*/
public function getOpcode()
{
$to_len = strlen($this->text);
if ( $to_len === 1 ) {
return "i:{$this->text}";
}
return "i{$to_len}:{$this->text}";
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Parser\Operations;
interface OperationInterface
{
/**
* @return int
*/
public function getFromLen();
/**
* @return int
*/
public function getToLen();
/**
* @return string Opcode for this operation.
*/
public function getOpcode();
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Parser\Operations;
class Replace implements OperationInterface
{
/**
* @param int $fromLen
* @param string $text
*/
public function __construct($fromLen, $text)
{
$this->fromLen = $fromLen;
$this->text = $text;
}
/**
* @inheritdoc
*/
public function getFromLen()
{
return $this->fromLen;
}
/**
* @inheritdoc
*/
public function getToLen()
{
return strlen($this->text);
}
/**
* Get the text the operation is working with.
*
* @return string
*/
public function getText()
{
return $this->text;
}
/**
* @inheritdoc
*/
public function getOpcode()
{
if ($this->fromLen === 1) {
$del_opcode = 'd';
} else {
$del_opcode = "d{$this->fromLen}";
}
$to_len = strlen($this->text);
if ($to_len === 1) {
return "{$del_opcode}i:{$this->text}";
}
return "{$del_opcode}i{$to_len}:{$this->text}";
}
}

View File

@@ -0,0 +1,477 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Parser;
use cogpowered\FineDiff\Granularity\GranularityInterface;
use cogpowered\FineDiff\Exceptions\GranularityCountException;
use cogpowered\FineDiff\Parser\Operations\Copy;
use cogpowered\FineDiff\Parser\Operations\Delete;
use cogpowered\FineDiff\Parser\Operations\Insert;
use cogpowered\FineDiff\Parser\Operations\Replace;
/**
* Generates a set of instructions to convert one string to another.
*/
class Parser implements ParserInterface
{
/**
* @var cogpowered\FineDiff\GranularityInterface
*/
protected $granularity;
/**
* @var cogpowered\FineDiff\Parser\OpcodesInterface
*/
protected $opcodes;
/**
* @var string Text we are comparing against.
*/
protected $from_text;
/**
* @var int Position of the $from_text we are at.
*/
protected $from_offset = 0;
/**
* @var cogpowered\FineDiff\Operations\OperationInterface
*/
protected $last_edit;
/**
* @var int Current position in the granularity array.
*/
protected $stackpointer = 0;
/**
* @var array Holds the individual opcodes as the diff takes place.
*/
protected $edits = array();
/**
* @inheritdoc
*/
public function __construct(GranularityInterface $granularity)
{
$this->granularity = $granularity;
// Set default opcodes generator
$this->opcodes = new Opcodes;
}
/**
* @inheritdoc
*/
public function getGranularity()
{
return $this->granularity;
}
/**
* @inheritdoc
*/
public function setGranularity(GranularityInterface $granularity)
{
$this->granularity = $granularity;
}
/**
* @inheritdoc
*/
public function getOpcodes()
{
return $this->opcodes;
}
/**
* @inheritdoc
*/
public function setOpcodes(OpcodesInterface $opcodes)
{
$this->opcodes = $opcodes;
}
/**
* @inheritdoc
*/
public function parse($from_text, $to_text)
{
// Ensure the granularity contains some delimiters
if (count($this->granularity) === 0) {
throw new GranularityCountException('Granularity contains no delimiters');
}
// Reset internal parser properties
$this->from_text = $from_text;
$this->from_offset = 0;
$this->last_edit = null;
$this->stackpointer = 0;
$this->edits = array();
// Parse the two string
$this->process($from_text, $to_text);
// Return processed diff
$this->opcodes->setOpcodes($this->edits);
return $this->opcodes;
}
/**
* Actually kicks off the processing. Recursive function.
*
* @param string $from_text
* @param string $to_text
* @return void
*/
protected function process($from_text, $to_text)
{
// Lets get parsing
$delimiters = $this->granularity[$this->stackpointer++];
$has_next_stage = $this->stackpointer < count($this->granularity);
// Actually perform diff
$diff = $this->diff($from_text, $to_text, $delimiters);
$diff = (is_array($diff)) ? $diff : array();
foreach ($diff as $fragment) {
// increase granularity
if ($fragment instanceof Replace && $has_next_stage) {
$this->process(
substr($this->from_text, $this->from_offset, $fragment->getFromLen()),
$fragment->getText()
);
}
// fuse copy ops whenever possible
elseif ($fragment instanceof Copy && $this->last_edit instanceof Copy) {
$this->edits[count($this->edits)-1]->increase($fragment->getFromLen());
$this->from_offset += $fragment->getFromLen();
}
else {
/* $fragment instanceof Copy */
/* $fragment instanceof Delete */
/* $fragment instanceof Insert */
$this->edits[] = $this->last_edit = $fragment;
$this->from_offset += $fragment->getFromLen();
}
}
$this->stackpointer--;
}
/**
* Core parsing function.
*
* @param string $from_text
* @param string $to_text
* @param string $delimiters Delimiter to use for this parse.
* @return array
*/
protected function diff($from_text, $to_text, $delimiters)
{
// Empty delimiter means character-level diffing.
// In such case, use code path optimized for character-level diffing.
if (empty($delimiters)) {
return $this->charDiff($from_text, $to_text);
}
$result = array();
// fragment-level diffing
$from_text_len = strlen($from_text);
$to_text_len = strlen($to_text);
$from_fragments = $this->extractFragments($from_text, $delimiters);
$to_fragments = $this->extractFragments($to_text, $delimiters);
$jobs = array(array(0, $from_text_len, 0, $to_text_len));
$cached_array_keys = array();
while ($job = array_pop($jobs)) {
// get the segments which must be diff'ed
list($from_segment_start, $from_segment_end, $to_segment_start, $to_segment_end) = $job;
// catch easy cases first
$from_segment_length = $from_segment_end - $from_segment_start;
$to_segment_length = $to_segment_end - $to_segment_start;
if (!$from_segment_length || !$to_segment_length ) {
if ( $from_segment_length ) {
$result[$from_segment_start * 4] = new Delete($from_segment_length);
} else if ( $to_segment_length ) {
$result[$from_segment_start * 4 + 1] = new Insert(substr($to_text, $to_segment_start, $to_segment_length));
}
continue;
}
// find longest copy operation for the current segments
$best_copy_length = 0;
$from_base_fragment_index = $from_segment_start;
$cached_array_keys_for_current_segment = array();
while ( $from_base_fragment_index < $from_segment_end ) {
$from_base_fragment = $from_fragments[$from_base_fragment_index];
$from_base_fragment_length = strlen($from_base_fragment);
// performance boost: cache array keys
if (!isset($cached_array_keys_for_current_segment[$from_base_fragment])) {
if ( !isset($cached_array_keys[$from_base_fragment]) ) {
$to_all_fragment_indices = $cached_array_keys[$from_base_fragment] = array_keys($to_fragments, $from_base_fragment, true);
}
else {
$to_all_fragment_indices = $cached_array_keys[$from_base_fragment];
}
// get only indices which falls within current segment
if ($to_segment_start > 0 || $to_segment_end < $to_text_len) {
$to_fragment_indices = array();
foreach ($to_all_fragment_indices as $to_fragment_index) {
if ($to_fragment_index < $to_segment_start) {
continue;
}
if ($to_fragment_index >= $to_segment_end) {
break;
}
$to_fragment_indices[] = $to_fragment_index;
}
$cached_array_keys_for_current_segment[$from_base_fragment] = $to_fragment_indices;
} else {
$to_fragment_indices = $to_all_fragment_indices;
}
} else {
$to_fragment_indices = $cached_array_keys_for_current_segment[$from_base_fragment];
}
// iterate through collected indices
foreach ($to_fragment_indices as $to_base_fragment_index) {
$fragment_index_offset = $from_base_fragment_length;
// iterate until no more match
for (;;) {
$fragment_from_index = $from_base_fragment_index + $fragment_index_offset;
if ($fragment_from_index >= $from_segment_end) {
break;
}
$fragment_to_index = $to_base_fragment_index + $fragment_index_offset;
if ($fragment_to_index >= $to_segment_end) {
break;
}
if ($from_fragments[$fragment_from_index] !== $to_fragments[$fragment_to_index]) {
break;
}
$fragment_length = strlen($from_fragments[$fragment_from_index]);
$fragment_index_offset += $fragment_length;
}
if ($fragment_index_offset > $best_copy_length) {
$best_copy_length = $fragment_index_offset;
$best_from_start = $from_base_fragment_index;
$best_to_start = $to_base_fragment_index;
}
}
$from_base_fragment_index += strlen($from_base_fragment);
// If match is larger than half segment size, no point trying to find better
// TODO: Really?
if ($best_copy_length >= $from_segment_length / 2) {
break;
}
// no point to keep looking if what is left is less than
// current best match
if ( $from_base_fragment_index + $best_copy_length >= $from_segment_end ) {
break;
}
}
if ($best_copy_length) {
$jobs[] = array($from_segment_start, $best_from_start, $to_segment_start, $best_to_start);
$result[$best_from_start * 4 + 2] = new Copy($best_copy_length);
$jobs[] = array($best_from_start + $best_copy_length, $from_segment_end, $best_to_start + $best_copy_length, $to_segment_end);
} else {
$result[$from_segment_start * 4 ] = new Replace($from_segment_length, substr($to_text, $to_segment_start, $to_segment_length));
}
}
ksort($result, SORT_NUMERIC);
return array_values($result);
}
/**
* Same as Parser::diff but tuned for character level granularity.
*
* @param string $from_text
* @param string $to_text
* @return array
*/
protected function charDiff($from_text, $to_text)
{
$result = array();
$jobs = array(array(0, strlen($from_text), 0, strlen($to_text)));
while ($job = array_pop($jobs)) {
// get the segments which must be diff'ed
list($from_segment_start, $from_segment_end, $to_segment_start, $to_segment_end) = $job;
$from_segment_len = $from_segment_end - $from_segment_start;
$to_segment_len = $to_segment_end - $to_segment_start;
// catch easy cases first
if (!$from_segment_len || !$to_segment_len) {
if ($from_segment_len) {
$result[$from_segment_start * 4 + 0] = new Delete($from_segment_len);
} else if ( $to_segment_len ) {
$result[$from_segment_start * 4 + 1] = new Insert(substr($to_text, $to_segment_start, $to_segment_len));
}
continue;
}
if ($from_segment_len >= $to_segment_len) {
$copy_len = $to_segment_len;
while ($copy_len) {
$to_copy_start = $to_segment_start;
$to_copy_start_max = $to_segment_end - $copy_len;
while ($to_copy_start <= $to_copy_start_max) {
$from_copy_start = strpos(substr($from_text, $from_segment_start, $from_segment_len), substr($to_text, $to_copy_start, $copy_len));
if ($from_copy_start !== false) {
$from_copy_start += $from_segment_start;
break 2;
}
$to_copy_start++;
}
$copy_len--;
}
} else {
$copy_len = $from_segment_len;
while ($copy_len) {
$from_copy_start = $from_segment_start;
$from_copy_start_max = $from_segment_end - $copy_len;
while ($from_copy_start <= $from_copy_start_max) {
$to_copy_start = strpos(substr($to_text, $to_segment_start, $to_segment_len), substr($from_text, $from_copy_start, $copy_len));
if ($to_copy_start !== false) {
$to_copy_start += $to_segment_start;
break 2;
}
$from_copy_start++;
}
$copy_len--;
}
}
// match found
if ( $copy_len ) {
$jobs[] = array($from_segment_start, $from_copy_start, $to_segment_start, $to_copy_start);
$result[$from_copy_start * 4 + 2] = new Copy($copy_len);
$jobs[] = array($from_copy_start + $copy_len, $from_segment_end, $to_copy_start + $copy_len, $to_segment_end);
}
// no match, so delete all, insert all
else {
$result[$from_segment_start * 4] = new Replace($from_segment_len, substr($to_text, $to_segment_start, $to_segment_len));
}
}
ksort($result, SORT_NUMERIC);
return array_values($result);
}
/**
* Efficiently fragment the text into an array according to specified delimiters.
*
* No delimiters means fragment into single character. The array indices are the offset of the fragments into
* the input string. A sentinel empty fragment is always added at the end.
* Careful: No check is performed as to the validity of the delimiters.
*
* @param string $text
* @param string $delimiters
* @param array
*/
protected function extractFragments($text, $delimiters)
{
// special case: split into characters
if (empty($delimiters)) {
$chars = str_split($text, 1);
$chars[strlen($text)] = '';
return $chars;
}
$fragments = array();
$start = 0;
$end = 0;
for (;;) {
$end += strcspn($text, $delimiters, $end);
$end += strspn($text, $delimiters, $end);
if ($end === $start) {
break;
}
$fragments[$start] = substr($text, $start, $end - $start);
$start = $end;
}
$fragments[$start] = '';
return $fragments;
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Parser;
use cogpowered\FineDiff\Granularity\GranularityInterface;
interface ParserInterface
{
/**
* Creates an instance.
*
* @param cogpowered\FineDiff\Granularity\GranularityInterface
*/
public function __construct(GranularityInterface $granularity);
/**
* Granularity the parser is working with.
*
* Default is cogpowered\FineDiff\Granularity\Character.
*
* @see cogpowered\FineDiff\Granularity\Character
* @see cogpowered\FineDiff\Granularity\Word
* @see cogpowered\FineDiff\Granularity\Sentence
* @see cogpowered\FineDiff\Granularity\Paragraph
*
* @return cogpowered\FineDiff\Granularity\GranularityInterface
*/
public function getGranularity();
/**
* Set the granularity that the parser is working with.
*
* @see cogpowered\FineDiff\Granularity\Character
* @see cogpowered\FineDiff\Granularity\Word
* @see cogpowered\FineDiff\Granularity\Sentence
* @see cogpowered\FineDiff\Granularity\Paragraph
*
* @param cogpowered\FineDiff\Granularity\GranularityInterface
* @return void
*/
public function setGranularity(GranularityInterface $granularity);
/**
* Get the opcodes object that is used to store all the opcodes.
*
* @return cogpowered\FineDiff\Parser\OpcodesInterface
*/
public function getOpcodes();
/**
* Set the opcodes object used to store all the opcodes for this parse.
*
* @param cogpowered\FineDiff\Parser\OpcodesInterface $opcodes.
* @return void
*/
public function setOpcodes(OpcodesInterface $opcodes);
/**
* Generates the opcodes needed to transform one string to another.
*
* @param string $from_text
* @param string $to_text
* @throws cogpowered\FineDiff\Exceptions\GranularityCountException
* @return cogpowered\FineDiff\Parser\OpcodesInterface
*/
public function parse($from_text, $to_text);
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Render;
use cogpowered\FineDiff\Parser\OpcodeInterface;
class Html extends Renderer
{
public function callback($opcode, $from, $from_offset, $from_len)
{
if ($opcode === 'c') {
$html = htmlentities(substr($from, $from_offset, $from_len));
} else if ($opcode === 'd') {
$deletion = substr($from, $from_offset, $from_len);
if (strcspn($deletion, " \n\r") === 0) {
$deletion = str_replace(array("\n","\r"), array('\n','\r'), $deletion);
}
$html = '<del>'.htmlentities($deletion).'</del>';
} else /* if ( $opcode === 'i' ) */ {
$html = '<ins>'.htmlentities(substr($from, $from_offset, $from_len)).'</ins>';
}
return $html;
}
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Render;
use cogpowered\FineDiff\Parser\OpcodesInterface;
use InvalidArgumentException;
abstract class Renderer implements RendererInterface
{
/**
* Covert text based on the provided opcodes.
*
* @param string $from_text
* @param string|\cogpowered\FineDiff\Parser\OpcodesInterface $opcodes
*
* @return string
*/
public function process($from_text, $opcodes)
{
// Validate opcodes
if (!is_string($opcodes) && !($opcodes instanceof OpcodesInterface)) {
throw new InvalidArgumentException('Invalid opcodes type');
} else {
$opcodes = ($opcodes instanceof OpcodesInterface) ? $opcodes->generate() : $opcodes;
}
// Holds the generated string that is returned
$output = '';
$opcodes_len = strlen($opcodes);
$from_offset = 0;
$opcodes_offset = 0;
while ($opcodes_offset < $opcodes_len) {
$opcode = substr($opcodes, $opcodes_offset, 1);
$opcodes_offset++;
$n = intval(substr($opcodes, $opcodes_offset));
if ($n) {
$opcodes_offset += strlen(strval($n));
} else {
$n = 1;
}
if ($opcode === 'c') {
// copy n characters from source
$data = $this->callback('c', $from_text, $from_offset, $n);
$from_offset += $n;
} else if ($opcode === 'd') {
// delete n characters from source
$data = $this->callback('d', $from_text, $from_offset, $n);
$from_offset += $n;
} else /* if ( $opcode === 'i' ) */ {
// insert n characters from opcodes
$data = $this->callback('i', $opcodes, $opcodes_offset + 1, $n);
$opcodes_offset += 1 + $n;
}
$output .= $data;
}
return $output;
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Render;
interface RendererInterface
{
public function process($from_text, $opcode);
public function callback($opcode, $from, $from_offset, $from_len);
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* FINE granularity DIFF
*
* Computes a set of instructions to convert the content of
* one string into another.
*
* Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
* to date by Cog Powered (https://github.com/cogpowered/FineDiff).
*
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
* @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
* @link https://github.com/cogpowered/FineDiff
* @version 0.0.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace cogpowered\FineDiff\Render;
class Text extends Renderer
{
public function callback($opcode, $from, $from_offset, $from_len)
{
if ($opcode === 'c' || $opcode === 'i') {
return substr($from, $from_offset, $from_len);
}
return '';
}
}

View File

@@ -0,0 +1,445 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath.'\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

View File

@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,25 @@
<?php
// autoload_alias_loader_real.php @generated by typo3/class-alias-loader
class ClassAliasLoaderInit21f34c26fff4d7a212f91dfdd964dc90 {
private static $loader;
public static function initializeClassAliasLoader($composerClassLoader) {
if (null !== self::$loader) {
return self::$loader;
}
self::$loader = $composerClassLoader;
$classAliasMap = require __DIR__ . '/autoload_classaliasmap.php';
$classAliasLoader = new TYPO3\ClassAliasLoader\ClassAliasLoader($composerClassLoader);
$classAliasLoader->setAliasMap($classAliasMap);
$classAliasLoader->setCaseSensitiveClassLoading(true);
$classAliasLoader->register(true);
TYPO3\ClassAliasLoader\ClassAliasMap::setClassAliasLoader($classAliasLoader);
return self::$loader;
}
}

View File

@@ -0,0 +1,9 @@
<?php
return array (
'aliasToClassNameMapping' =>
array (
),
'classNameToAliasMapping' =>
array (
),
);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
'36b1231e1ea912ee05f8f4f652a17ca9' => $baseDir . '/typo3/sysext/core/Resources/PHP/GlobalDebugFunctions.php',
);

View File

@@ -0,0 +1,12 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'cogpowered\\FineDiff' => array($vendorDir . '/cogpowered/finediff/src'),
'PEAR' => array($vendorDir . '/pear/pear_exception'),
'HTTP_Request2' => array($vendorDir . '/pear/http_request2'),
);

View File

@@ -0,0 +1,68 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'TYPO3\\ClassAliasLoader\\' => array($vendorDir . '/typo3/class-alias-loader/src'),
'TYPO3\\CMS\\Workspaces\\' => array($baseDir . '/typo3/sysext/workspaces/Classes'),
'TYPO3\\CMS\\WizardSortpages\\' => array($baseDir . '/typo3/sysext/wizard_sortpages/Classes'),
'TYPO3\\CMS\\WizardCrpages\\' => array($baseDir . '/typo3/sysext/wizard_crpages/Classes'),
'TYPO3\\CMS\\Viewpage\\' => array($baseDir . '/typo3/sysext/viewpage/Classes'),
'TYPO3\\CMS\\Version\\' => array($baseDir . '/typo3/sysext/version/Classes'),
'TYPO3\\CMS\\Tstemplate\\' => array($baseDir . '/typo3/sysext/tstemplate/Classes'),
'TYPO3\\CMS\\Taskcenter\\' => array($baseDir . '/typo3/sysext/taskcenter/Classes'),
'TYPO3\\CMS\\T3editor\\' => array($baseDir . '/typo3/sysext/t3editor/Classes'),
'TYPO3\\CMS\\SysNote\\' => array($baseDir . '/typo3/sysext/sys_note/Classes'),
'TYPO3\\CMS\\SysAction\\' => array($baseDir . '/typo3/sysext/sys_action/Classes'),
'TYPO3\\CMS\\Sv\\' => array($baseDir . '/typo3/sysext/sv/Classes'),
'TYPO3\\CMS\\Setup\\' => array($baseDir . '/typo3/sysext/setup/Classes'),
'TYPO3\\CMS\\Scheduler\\' => array($baseDir . '/typo3/sysext/scheduler/Classes'),
'TYPO3\\CMS\\Saltedpasswords\\' => array($baseDir . '/typo3/sysext/saltedpasswords/Classes'),
'TYPO3\\CMS\\Rtehtmlarea\\' => array($baseDir . '/typo3/sysext/rtehtmlarea/Classes'),
'TYPO3\\CMS\\Rsaauth\\' => array($baseDir . '/typo3/sysext/rsaauth/Classes'),
'TYPO3\\CMS\\Reports\\' => array($baseDir . '/typo3/sysext/reports/Classes'),
'TYPO3\\CMS\\Recycler\\' => array($baseDir . '/typo3/sysext/recycler/Classes'),
'TYPO3\\CMS\\Recordlist\\' => array($baseDir . '/typo3/sysext/recordlist/Classes'),
'TYPO3\\CMS\\Opendocs\\' => array($baseDir . '/typo3/sysext/opendocs/Classes'),
'TYPO3\\CMS\\Lowlevel\\' => array($baseDir . '/typo3/sysext/lowlevel/Classes'),
'TYPO3\\CMS\\Linkvalidator\\' => array($baseDir . '/typo3/sysext/linkvalidator/Classes'),
'TYPO3\\CMS\\Lang\\' => array($baseDir . '/typo3/sysext/lang/Classes'),
'TYPO3\\CMS\\Install\\' => array($baseDir . '/typo3/sysext/install/Classes'),
'TYPO3\\CMS\\Info\\' => array($baseDir . '/typo3/sysext/info/Classes'),
'TYPO3\\CMS\\InfoPagetsconfig\\' => array($baseDir . '/typo3/sysext/info_pagetsconfig/Classes'),
'TYPO3\\CMS\\IndexedSearch\\' => array($baseDir . '/typo3/sysext/indexed_search/Classes'),
'TYPO3\\CMS\\IndexedSearchMysql\\' => array($baseDir . '/typo3/sysext/indexed_search_mysql/Classes'),
'TYPO3\\CMS\\Impexp\\' => array($baseDir . '/typo3/sysext/impexp/Classes'),
'TYPO3\\CMS\\Func\\' => array($baseDir . '/typo3/sysext/func/Classes'),
'TYPO3\\CMS\\Frontend\\' => array($baseDir . '/typo3/sysext/frontend/Classes'),
'TYPO3\\CMS\\Form\\' => array($baseDir . '/typo3/sysext/form/Classes'),
'TYPO3\\CMS\\Fluid\\' => array($baseDir . '/typo3/sysext/fluid/Classes'),
'TYPO3\\CMS\\FluidStyledContent\\' => array($baseDir . '/typo3/sysext/fluid_styled_content/Classes'),
'TYPO3\\CMS\\Filelist\\' => array($baseDir . '/typo3/sysext/filelist/Classes'),
'TYPO3\\CMS\\Felogin\\' => array($baseDir . '/typo3/sysext/felogin/Classes'),
'TYPO3\\CMS\\Feedit\\' => array($baseDir . '/typo3/sysext/feedit/Classes'),
'TYPO3\\CMS\\Extensionmanager\\' => array($baseDir . '/typo3/sysext/extensionmanager/Classes'),
'TYPO3\\CMS\\Extbase\\' => array($baseDir . '/typo3/sysext/extbase/Classes'),
'TYPO3\\CMS\\Documentation\\' => array($baseDir . '/typo3/sysext/documentation/Classes'),
'TYPO3\\CMS\\Dbal\\' => array($baseDir . '/typo3/sysext/dbal/Classes'),
'TYPO3\\CMS\\CssStyledContent\\' => array($baseDir . '/typo3/sysext/css_styled_content/Classes'),
'TYPO3\\CMS\\Cshmanual\\' => array($baseDir . '/typo3/sysext/cshmanual/Classes'),
'TYPO3\\CMS\\Core\\' => array($baseDir . '/typo3/sysext/core/Classes'),
'TYPO3\\CMS\\ContextHelp\\' => array($baseDir . '/typo3/sysext/context_help/Classes'),
'TYPO3\\CMS\\Composer\\' => array($vendorDir . '/typo3/cms-composer-installers/src'),
'TYPO3\\CMS\\Beuser\\' => array($baseDir . '/typo3/sysext/beuser/Classes'),
'TYPO3\\CMS\\Belog\\' => array($baseDir . '/typo3/sysext/belog/Classes'),
'TYPO3\\CMS\\Backend\\' => array($baseDir . '/typo3/sysext/backend/Classes'),
'TYPO3\\CMS\\Aboutmodules\\' => array($baseDir . '/typo3/sysext/aboutmodules/Classes'),
'TYPO3\\CMS\\About\\' => array($baseDir . '/typo3/sysext/about/Classes'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
);

View File

@@ -0,0 +1,74 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit21f34c26fff4d7a212f91dfdd964dc90
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit21f34c26fff4d7a212f91dfdd964dc90', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit21f34c26fff4d7a212f91dfdd964dc90', 'loadClassLoader'));
$includePaths = require __DIR__ . '/include_paths.php';
$includePaths[] = get_include_path();
set_include_path(implode(PATH_SEPARATOR, $includePaths));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit21f34c26fff4d7a212f91dfdd964dc90::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit21f34c26fff4d7a212f91dfdd964dc90::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire21f34c26fff4d7a212f91dfdd964dc90($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequire21f34c26fff4d7a212f91dfdd964dc90($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?php
// include_paths.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
$vendorDir . '/pear/pear_exception',
$vendorDir . '/pear/http_request2',
);

View File

@@ -0,0 +1,866 @@
[
{
"name": "cogpowered/finediff",
"version": "0.3.1",
"version_normalized": "0.3.1.0",
"source": {
"type": "git",
"url": "https://github.com/cogpowered/FineDiff.git",
"reference": "339ddc8c3afb656efed4f2f0a80e5c3d026f8ea8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cogpowered/FineDiff/zipball/339ddc8c3afb656efed4f2f0a80e5c3d026f8ea8",
"reference": "339ddc8c3afb656efed4f2f0a80e5c3d026f8ea8",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"mockery/mockery": "*",
"phpunit/phpunit": "*"
},
"time": "2014-05-19T10:25:02+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"cogpowered\\FineDiff": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rob Crowe",
"email": "rob@cogpowered.com"
},
{
"name": "Raymond Hill"
}
],
"description": "PHP implementation of a Fine granularity Diff engine",
"homepage": "https://github.com/cogpowered/FineDiff",
"keywords": [
"diff",
"finediff",
"opcode",
"string",
"text"
]
},
{
"name": "doctrine/instantiator",
"version": "1.0.5",
"version_normalized": "1.0.5.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
"shasum": ""
},
"require": {
"php": ">=5.3,<8.0-DEV"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"ext-pdo": "*",
"ext-phar": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.0"
},
"time": "2015-06-14T21:17:01+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://github.com/doctrine/instantiator",
"keywords": [
"constructor",
"instantiate"
]
},
{
"name": "mso/idna-convert",
"version": "v0.9.1",
"version_normalized": "0.9.1.0",
"source": {
"type": "git",
"url": "https://github.com/phlylabs/idna-convert.git",
"reference": "0a0a09e460e63739d82c3f0c3f0e5555567a6be3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phlylabs/idna-convert/zipball/0a0a09e460e63739d82c3f0c3f0e5555567a6be3",
"reference": "0a0a09e460e63739d82c3f0c3f0e5555567a6be3",
"shasum": ""
},
"require": {
"ext-pcre": "*",
"php": ">=5.0.0"
},
"time": "2016-01-06T21:05:46+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.9.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"classmap": [
"idna_convert.class.php",
"uctc.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1+"
],
"authors": [
{
"name": "Matthias Sommerfeld",
"email": "mso@phlylabs.de",
"role": "Developer"
}
],
"description": "A library for encoding and decoding internationalized domain names",
"homepage": "http://idnaconv.net/",
"keywords": [
"idn",
"idna",
"php"
]
},
{
"name": "pear/http_request2",
"version": "v2.3.0",
"version_normalized": "2.3.0.0",
"source": {
"type": "git",
"url": "https://github.com/pear/HTTP_Request2.git",
"reference": "3599cf0fe455a4e281da464f6510bfc5c2ce54c4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/HTTP_Request2/zipball/3599cf0fe455a4e281da464f6510bfc5c2ce54c4",
"reference": "3599cf0fe455a4e281da464f6510bfc5c2ce54c4",
"shasum": ""
},
"require": {
"pear/net_url2": "^2.2.0",
"pear/pear_exception": "^1.0.0",
"php": ">=5.2.0"
},
"suggest": {
"ext-fileinfo": "Adds support for looking up mime-types using finfo.",
"ext-zlib": "Allows handling gzip compressed responses.",
"lib-curl": "Allows using cURL as a request backend.",
"lib-openssl": "Allows handling SSL requests when not using cURL."
},
"time": "2016-02-13T20:20:39+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-trunk": "2.2-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-0": {
"HTTP_Request2": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
"./"
],
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Alexey Borzov",
"email": "avb@php.net"
}
],
"description": "Provides an easy way to perform HTTP requests.",
"homepage": "http://pear.php.net/package/HTTP_Request2",
"keywords": [
"PEAR",
"curl",
"http",
"request"
]
},
{
"name": "pear/net_url2",
"version": "v2.2.1",
"version_normalized": "2.2.1.0",
"source": {
"type": "git",
"url": "https://github.com/pear/Net_URL2.git",
"reference": "43a87606daf52efe6685c92131be083143108e37"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/Net_URL2/zipball/43a87606daf52efe6685c92131be083143108e37",
"reference": "43a87606daf52efe6685c92131be083143108e37",
"shasum": ""
},
"require": {
"php": ">=5.1.4"
},
"require-dev": {
"phpunit/phpunit": ">=3.3.0"
},
"time": "2016-04-18T22:24:01+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"classmap": [
"Net/URL2.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "David Coallier",
"email": "davidc@php.net"
},
{
"name": "Tom Klingenberg",
"email": "tkli@php.net"
},
{
"name": "Christian Schmidt",
"email": "chmidt@php.net"
}
],
"description": "Class for parsing and handling URL. Provides parsing of URLs into their constituent parts (scheme, host, path etc.), URL generation, and resolving of relative URLs.",
"homepage": "https://github.com/pear/Net_URL2",
"keywords": [
"PEAR",
"net",
"networking",
"rfc3986",
"uri",
"url"
]
},
{
"name": "pear/pear_exception",
"version": "v1.0.0",
"version_normalized": "1.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/pear/PEAR_Exception.git",
"reference": "8c18719fdae000b690e3912be401c76e406dd13b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/8c18719fdae000b690e3912be401c76e406dd13b",
"reference": "8c18719fdae000b690e3912be401c76e406dd13b",
"shasum": ""
},
"require": {
"php": ">=4.4.0"
},
"require-dev": {
"phpunit/phpunit": "*"
},
"time": "2015-02-10T20:07:52+00:00",
"type": "class",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-0": {
"PEAR": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
"."
],
"license": [
"BSD-2-Clause"
],
"authors": [
{
"name": "Helgi Thormar",
"email": "dufuz@php.net"
},
{
"name": "Greg Beaver",
"email": "cellog@php.net"
}
],
"description": "The PEAR Exception base class.",
"homepage": "https://github.com/pear/PEAR_Exception",
"keywords": [
"exception"
]
},
{
"name": "psr/http-message",
"version": "1.0.1",
"version_normalized": "1.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2016-08-06T14:39:51+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
]
},
{
"name": "psr/log",
"version": "1.0.2",
"version_normalized": "1.0.2.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2016-10-10T12:19:37+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
]
},
{
"name": "swiftmailer/swiftmailer",
"version": "v5.4.5",
"version_normalized": "5.4.5.0",
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "cd142238a339459b10da3d8234220963f392540c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/cd142238a339459b10da3d8234220963f392540c",
"reference": "cd142238a339459b10da3d8234220963f392540c",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"mockery/mockery": "~0.9.1",
"symfony/phpunit-bridge": "~3.2"
},
"time": "2016-12-29T10:02:40+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.4-dev"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"lib/swift_required.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Chris Corbyn"
},
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Swiftmailer, free feature-rich PHP mailer",
"homepage": "http://swiftmailer.org",
"keywords": [
"email",
"mail",
"mailer"
]
},
{
"name": "symfony/console",
"version": "v2.8.31",
"version_normalized": "2.8.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "7cad097cf081c0ab3d0322cc38d34ee80484d86f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/7cad097cf081c0ab3d0322cc38d34ee80484d86f",
"reference": "7cad097cf081c0ab3d0322cc38d34ee80484d86f",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"symfony/debug": "^2.7.2|~3.0.0",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/event-dispatcher": "~2.1|~3.0.0",
"symfony/process": "~2.1|~3.0.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/process": ""
},
"time": "2017-11-16T15:20:19+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com"
},
{
"name": "symfony/debug",
"version": "v2.8.31",
"version_normalized": "2.8.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "a0a29e9867debabdace779a20a9385c623a23bbd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/a0a29e9867debabdace779a20a9385c623a23bbd",
"reference": "a0a29e9867debabdace779a20a9385c623a23bbd",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"psr/log": "~1.0"
},
"conflict": {
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
},
"require-dev": {
"symfony/class-loader": "~2.2|~3.0.0",
"symfony/http-kernel": "~2.3.24|~2.5.9|^2.6.2|~3.0.0"
},
"time": "2017-10-24T13:48:52+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Component\\Debug\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com"
},
{
"name": "symfony/finder",
"version": "v2.8.31",
"version_normalized": "2.8.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "efeceae6a05a9b2fcb3391333f1d4a828ff44ab8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/efeceae6a05a9b2fcb3391333f1d4a828ff44ab8",
"reference": "efeceae6a05a9b2fcb3391333f1d4a828ff44ab8",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"time": "2017-11-05T15:25:56+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Component\\Finder\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.3.0",
"version_normalized": "1.3.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "e79d363049d1c2128f133a2667e4f4190904f7f4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4",
"reference": "e79d363049d1c2128f133a2667e4f4190904f7f4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2016-11-14T01:06:16+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
]
},
{
"name": "typo3/class-alias-loader",
"version": "1.0.0",
"version_normalized": "1.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/TYPO3/class-alias-loader.git",
"reference": "a9dd295c81ed0b51455644be420ab9210cad688f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/TYPO3/class-alias-loader/zipball/a9dd295c81ed0b51455644be420ab9210cad688f",
"reference": "a9dd295c81ed0b51455644be420ab9210cad688f",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0",
"php": ">=5.3.7"
},
"replace": {
"helhum/class-alias-loader": "*"
},
"require-dev": {
"composer/composer": "dev-master",
"mikey179/vfsstream": "1.4.*@dev",
"phpunit/phpunit": "~4.7.0"
},
"time": "2015-10-06T10:25:44+00:00",
"type": "composer-plugin",
"extra": {
"class": "TYPO3\\ClassAliasLoader\\Plugin",
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"TYPO3\\ClassAliasLoader\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Helmut Hummel",
"email": "info@helhum.io"
}
],
"description": "Amends the composer class loader to support class aliases to provide backwards compatibility for packages",
"homepage": "http://github.com/TYPO3/class-alias-loader",
"keywords": [
"alias",
"autoloader",
"classloader",
"composer"
]
},
{
"name": "typo3/cms-composer-installers",
"version": "1.3.2",
"version_normalized": "1.3.2.0",
"source": {
"type": "git",
"url": "https://github.com/TYPO3/CmsComposerInstallers.git",
"reference": "98fec6f650016c437b29e56487dd349ed062af93"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/TYPO3/CmsComposerInstallers/zipball/98fec6f650016c437b29e56487dd349ed062af93",
"reference": "98fec6f650016c437b29e56487dd349ed062af93",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0.0",
"php": ">=5.5 <7.3"
},
"conflict": {
"composer/installers": "<1.0.24 || >1.0.24"
},
"replace": {
"lw/typo3cms-installers": "*",
"netresearch/composer-installers": "*"
},
"require-dev": {
"composer/composer": "1.*"
},
"time": "2017-12-04T15:30:33+00:00",
"type": "composer-plugin",
"extra": {
"class": "TYPO3\\CMS\\Composer\\Installer\\Plugin",
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"TYPO3\\CMS\\Composer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0+"
],
"authors": [
{
"name": "Christian Opitz",
"email": "christian.opitz@netresearch.de"
},
{
"name": "Lars Peipmann",
"email": "lars@peipmann.de"
},
{
"name": "Helmut Hummel",
"email": "info@helhum.io"
}
],
"description": "TYPO3 CMS Installers",
"homepage": "https://github.com/TYPO3/CmsComposerInstallers",
"keywords": [
"cms",
"core",
"extension",
"installer",
"typo3"
]
}
]

View File

@@ -0,0 +1,46 @@
before_commands:
- "composer install --prefer-source"
tools:
external_code_coverage:
timeout: 600
php_code_coverage:
enabled: true
test_command: ./vendor/bin/phpunit
php_code_sniffer:
enabled: true
config:
standard: PSR2
filter:
paths: ["src/*", "tests/*"]
php_cpd:
enabled: true
excluded_dirs: ["build/*", "tests", "vendor"]
php_cs_fixer:
enabled: true
config:
level: all
filter:
paths: ["src/*", "tests/*"]
php_loc:
enabled: true
excluded_dirs: ["build", "tests", "vendor"]
php_mess_detector:
enabled: true
config:
ruleset: phpmd.xml.dist
design_rules: { eval_expression: false }
filter:
paths: ["src/*"]
php_pdepend:
enabled: true
excluded_dirs: ["build", "tests", "vendor"]
php_analyzer:
enabled: true
filter:
paths: ["src/*", "tests/*"]
php_hhvm:
enabled: true
filter:
paths: ["src/*", "tests/*"]
sensiolabs_security_checker: true

View File

@@ -0,0 +1,14 @@
#!/bin/sh
set -x
if [ "$TRAVIS_PHP_VERSION" = 'hhvm' ] || [ "$TRAVIS_PHP_VERSION" = 'hhvm-nightly' ] ; then
curl -sS https://getcomposer.org/installer > composer-installer.php
hhvm composer-installer.php
hhvm -v ResourceLimit.SocketDefaultTimeout=30 -v Http.SlowQueryThreshold=30000 composer.phar update --prefer-source
elif [ "$TRAVIS_PHP_VERSION" = '5.3.3' ] ; then
composer self-update
composer update --prefer-source --no-dev
composer dump-autoload
else
composer self-update
composer update --prefer-source
fi

View File

@@ -0,0 +1,35 @@
# Contributing
* Coding standard for the project is [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
* The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php)
* Any contribution must provide tests for additional introduced conditions
* Any un-confirmed issue needs a failing test case before being accepted
* Pull requests must be sent from a new hotfix/feature branch, not from `master`.
## Installation
To install the project and run the tests, you need to clone it first:
```sh
$ git clone git://github.com/doctrine/instantiator.git
```
You will then need to run a composer installation:
```sh
$ cd Instantiator
$ curl -s https://getcomposer.org/installer | php
$ php composer.phar update
```
## Testing
The PHPUnit version to be used is the one installed as a dev- dependency via composer:
```sh
$ ./vendor/bin/phpunit
```
Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement
won't be merged.

View File

@@ -0,0 +1,19 @@
Copyright (c) 2014 Doctrine Project
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,40 @@
# Instantiator
This library provides a way of avoiding usage of constructors when instantiating PHP classes.
[![Build Status](https://travis-ci.org/doctrine/instantiator.svg?branch=master)](https://travis-ci.org/doctrine/instantiator)
[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master)
[![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator)
[![HHVM Status](http://hhvm.h4cc.de/badge/doctrine/instantiator.png)](http://hhvm.h4cc.de/package/doctrine/instantiator)
[![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator)
[![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator)
## Installation
The suggested installation method is via [composer](https://getcomposer.org/):
```sh
php composer.phar require "doctrine/instantiator:~1.0.3"
```
## Usage
The instantiator is able to create new instances of any class without using the constructor or any API of the class
itself:
```php
$instantiator = new \Doctrine\Instantiator\Instantiator();
$instance = $instantiator->instantiate('My\\ClassName\\Here');
```
## Contributing
Please read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out!
## Credits
This library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which
has been donated to the doctrine organization, and which is now deprecated in favour of this package.

View File

@@ -0,0 +1,45 @@
{
"name": "doctrine/instantiator",
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"type": "library",
"license": "MIT",
"homepage": "https://github.com/doctrine/instantiator",
"keywords": [
"instantiate",
"constructor"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/"
}
],
"require": {
"php": ">=5.3,<8.0-DEV"
},
"require-dev": {
"ext-phar": "*",
"ext-pdo": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.0",
"athletic/athletic": "~0.1.8"
},
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"autoload-dev": {
"psr-0": {
"DoctrineTest\\InstantiatorPerformance\\": "tests",
"DoctrineTest\\InstantiatorTest\\": "tests",
"DoctrineTest\\InstantiatorTestAsset\\": "tests"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
}
}

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" ?>
<ruleset
name="Instantiator rules"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
>
<rule ref="rulesets/cleancode.xml">
<!-- static access is used for caching purposes -->
<exclude name="StaticAccess"/>
</rule>
<rule ref="rulesets/codesize.xml"/>
<rule ref="rulesets/controversial.xml"/>
<rule ref="rulesets/design.xml"/>
<rule ref="rulesets/naming.xml"/>
<rule ref="rulesets/unusedcode.xml"/>
<rule
name="NPathComplexity"
message="The {0} {1}() has an NPath complexity of {2}. The configured NPath complexity threshold is {3}."
class="PHP_PMD_Rule_Design_NpathComplexity"
>
<properties>
<property name="minimum" description="The npath reporting threshold" value="10"/>
</properties>
</rule>
</ruleset>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<phpunit
bootstrap="./vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
verbose="true"
stopOnFailure="false"
processIsolation="false"
backupGlobals="false"
syntaxCheck="true"
>
<testsuite name="Doctrine\Instantiator tests">
<directory>./tests/DoctrineTest/InstantiatorTest</directory>
</testsuite>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./src</directory>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,29 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator\Exception;
/**
* Base exception marker interface for the instantiator component
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
interface ExceptionInterface
{
}

View File

@@ -0,0 +1,62 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator\Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
use ReflectionClass;
/**
* Exception for invalid arguments provided to the instantiator
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface
{
/**
* @param string $className
*
* @return self
*/
public static function fromNonExistingClass($className)
{
if (interface_exists($className)) {
return new self(sprintf('The provided type "%s" is an interface, and can not be instantiated', $className));
}
if (PHP_VERSION_ID >= 50400 && trait_exists($className)) {
return new self(sprintf('The provided type "%s" is a trait, and can not be instantiated', $className));
}
return new self(sprintf('The provided class "%s" does not exist', $className));
}
/**
* @param ReflectionClass $reflectionClass
*
* @return self
*/
public static function fromAbstractClass(ReflectionClass $reflectionClass)
{
return new self(sprintf(
'The provided class "%s" is abstract, and can not be instantiated',
$reflectionClass->getName()
));
}
}

View File

@@ -0,0 +1,79 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator\Exception;
use Exception;
use ReflectionClass;
use UnexpectedValueException as BaseUnexpectedValueException;
/**
* Exception for given parameters causing invalid/unexpected state on instantiation
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface
{
/**
* @param ReflectionClass $reflectionClass
* @param Exception $exception
*
* @return self
*/
public static function fromSerializationTriggeredException(ReflectionClass $reflectionClass, Exception $exception)
{
return new self(
sprintf(
'An exception was raised while trying to instantiate an instance of "%s" via un-serialization',
$reflectionClass->getName()
),
0,
$exception
);
}
/**
* @param ReflectionClass $reflectionClass
* @param string $errorString
* @param int $errorCode
* @param string $errorFile
* @param int $errorLine
*
* @return UnexpectedValueException
*/
public static function fromUncleanUnSerialization(
ReflectionClass $reflectionClass,
$errorString,
$errorCode,
$errorFile,
$errorLine
) {
return new self(
sprintf(
'Could not produce an instance of "%s" via un-serialization, since an error was triggered '
. 'in file "%s" at line "%d"',
$reflectionClass->getName(),
$errorFile,
$errorLine
),
0,
new Exception($errorString, $errorCode)
);
}
}

View File

@@ -0,0 +1,273 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator;
use Closure;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use Exception;
use ReflectionClass;
/**
* {@inheritDoc}
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
final class Instantiator implements InstantiatorInterface
{
/**
* Markers used internally by PHP to define whether {@see \unserialize} should invoke
* the method {@see \Serializable::unserialize()} when dealing with classes implementing
* the {@see \Serializable} interface.
*/
const SERIALIZATION_FORMAT_USE_UNSERIALIZER = 'C';
const SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O';
/**
* @var \Closure[] of {@see \Closure} instances used to instantiate specific classes
*/
private static $cachedInstantiators = array();
/**
* @var object[] of objects that can directly be cloned
*/
private static $cachedCloneables = array();
/**
* {@inheritDoc}
*/
public function instantiate($className)
{
if (isset(self::$cachedCloneables[$className])) {
return clone self::$cachedCloneables[$className];
}
if (isset(self::$cachedInstantiators[$className])) {
$factory = self::$cachedInstantiators[$className];
return $factory();
}
return $this->buildAndCacheFromFactory($className);
}
/**
* Builds the requested object and caches it in static properties for performance
*
* @param string $className
*
* @return object
*/
private function buildAndCacheFromFactory($className)
{
$factory = self::$cachedInstantiators[$className] = $this->buildFactory($className);
$instance = $factory();
if ($this->isSafeToClone(new ReflectionClass($instance))) {
self::$cachedCloneables[$className] = clone $instance;
}
return $instance;
}
/**
* Builds a {@see \Closure} capable of instantiating the given $className without
* invoking its constructor.
*
* @param string $className
*
* @return Closure
*/
private function buildFactory($className)
{
$reflectionClass = $this->getReflectionClass($className);
if ($this->isInstantiableViaReflection($reflectionClass)) {
return function () use ($reflectionClass) {
return $reflectionClass->newInstanceWithoutConstructor();
};
}
$serializedString = sprintf(
'%s:%d:"%s":0:{}',
$this->getSerializationFormat($reflectionClass),
strlen($className),
$className
);
$this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString);
return function () use ($serializedString) {
return unserialize($serializedString);
};
}
/**
* @param string $className
*
* @return ReflectionClass
*
* @throws InvalidArgumentException
*/
private function getReflectionClass($className)
{
if (! class_exists($className)) {
throw InvalidArgumentException::fromNonExistingClass($className);
}
$reflection = new ReflectionClass($className);
if ($reflection->isAbstract()) {
throw InvalidArgumentException::fromAbstractClass($reflection);
}
return $reflection;
}
/**
* @param ReflectionClass $reflectionClass
* @param string $serializedString
*
* @throws UnexpectedValueException
*
* @return void
*/
private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, $serializedString)
{
set_error_handler(function ($code, $message, $file, $line) use ($reflectionClass, & $error) {
$error = UnexpectedValueException::fromUncleanUnSerialization(
$reflectionClass,
$message,
$code,
$file,
$line
);
});
$this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
restore_error_handler();
if ($error) {
throw $error;
}
}
/**
* @param ReflectionClass $reflectionClass
* @param string $serializedString
*
* @throws UnexpectedValueException
*
* @return void
*/
private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, $serializedString)
{
try {
unserialize($serializedString);
} catch (Exception $exception) {
restore_error_handler();
throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception);
}
}
/**
* @param ReflectionClass $reflectionClass
*
* @return bool
*/
private function isInstantiableViaReflection(ReflectionClass $reflectionClass)
{
if (\PHP_VERSION_ID >= 50600) {
return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal());
}
return \PHP_VERSION_ID >= 50400 && ! $this->hasInternalAncestors($reflectionClass);
}
/**
* Verifies whether the given class is to be considered internal
*
* @param ReflectionClass $reflectionClass
*
* @return bool
*/
private function hasInternalAncestors(ReflectionClass $reflectionClass)
{
do {
if ($reflectionClass->isInternal()) {
return true;
}
} while ($reflectionClass = $reflectionClass->getParentClass());
return false;
}
/**
* Verifies if the given PHP version implements the `Serializable` interface serialization
* with an incompatible serialization format. If that's the case, use serialization marker
* "C" instead of "O".
*
* @link http://news.php.net/php.internals/74654
*
* @param ReflectionClass $reflectionClass
*
* @return string the serialization format marker, either self::SERIALIZATION_FORMAT_USE_UNSERIALIZER
* or self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER
*/
private function getSerializationFormat(ReflectionClass $reflectionClass)
{
if ($this->isPhpVersionWithBrokenSerializationFormat()
&& $reflectionClass->implementsInterface('Serializable')
) {
return self::SERIALIZATION_FORMAT_USE_UNSERIALIZER;
}
return self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER;
}
/**
* Checks whether the current PHP runtime uses an incompatible serialization format
*
* @return bool
*/
private function isPhpVersionWithBrokenSerializationFormat()
{
return PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513;
}
/**
* Checks if a class is cloneable
*
* @param ReflectionClass $reflection
*
* @return bool
*/
private function isSafeToClone(ReflectionClass $reflection)
{
if (method_exists($reflection, 'isCloneable') && ! $reflection->isCloneable()) {
return false;
}
// not cloneable if it implements `__clone`, as we want to avoid calling it
return ! $reflection->hasMethod('__clone');
}
}

View File

@@ -0,0 +1,37 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator;
/**
* Instantiator provides utility methods to build objects without invoking their constructors
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
interface InstantiatorInterface
{
/**
* @param string $className
*
* @return object
*
* @throws \Doctrine\Instantiator\Exception\ExceptionInterface
*/
public function instantiate($className);
}

View File

@@ -0,0 +1,17 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

View File

@@ -0,0 +1,505 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
(This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.)
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
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 and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, 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 library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete 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 distribute a copy of this License along with the
Library.
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 Library or any portion
of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
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 Library, 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 Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you 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.
If distribution of 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 satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be 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.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library 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.
9. 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 Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
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 with
this License.
11. 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 Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library 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 Library.
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.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library 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.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser 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 Library
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 Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
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
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "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
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. 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 LIBRARY 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
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. 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.
{description}
Copyright (C) {year} {fullname}
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random
Hacker.
{signature of Ty Coon}, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@@ -0,0 +1,210 @@
# IDNA Convert (idna_convert.class.php)
<http://idnaconv.phlymail.de>
<phlymail@phlylabs.de>
(c) 2004-2015 phlyLabs, Berlin
## Introduction
The class idna_convert allows to convert internationalized domain names (see RFC 3490, 3491, 3492 and 3454 for details) as they can be used with various registries worldwide to be translated between their original (localized) form and their encoded form as it will be used in the DNS (Domain Name System).
The class provides two public methods, encode() and decode(), which do exactly what you would expect them to do. You are allowed to use complete domain names, simple strings and complete email addresses as well. That means, that you might use any of the following notations:
- www.nörgler.com
- xn--nrgler-wxa
- xn--brse-5qa.xn--knrz-1ra.info
Errors, incorrectly encoded or invalid strings will lead to either a FALSE response (when in strict mode) or to only partially converted strings.
You can query the occurred error by calling the method get_last_error().
Unicode strings are expected to be either UTF-8 strings, UCS-4 strings or UCS-4 arrays. The default format is UTF-8. For setting different encodings, you can call the method setParams() - please see the inline documentation for details.
ACE strings (the Punycode form) are always 7bit ASCII strings.
**ATTENTION:** As of version 0.6.0 this class is written in the OOP style of PHP5. Since PHP4 is no longer actively maintained, you should switch to PHP5 as fast as possible. We expect to see no compatibility issues with the upcoming PHP6, too.
**ATTENTION:** BC break! As of version 0.6.4 the class per default allows the German ligature ß to be encoded as the DeNIC, the registry for .DE allows domains containing ß.
In older builds "ß" was mapped to "ss". Should you still need this behaviour, see example 5 below.
**ATTENTION:** As of version 0.8.0 the class fully supports IDNA 2008. Thus the aforementioned parameter is deprecated and replaced by a parameter to switch between the standards. See the updated example 5 below.
## Files
- **idna_convert.class.php** - The actual class
- **example.php** - An example web page for converting
- **transcode_wrapper.php** - Convert various encodings, see below
- **uctc.php** - phlyLabs' Unicode Transcoder, see below
- **ReadMe.md** - This file
- **LICENCE** - The LGPL licence file
The class is contained in idna_convert.class.php.
## Installation
### Via Composer
```php
{
"require" : {
"mso/idna-convert" : "0.9.*"
}
}
```
### Official ZIP Package
Go to <http://idnaconv.phlymail.de/> and follow the download link. Once downloaded and uncompressed, just copy the file `idna_convert.class.php` into your application and start using it.
## Examples
### Example 1.
Say we wish to encode the domain name nörgler.com:
```php
<?php
// Include the class
require_once('idna_convert.class.php');
// Instantiate it
$IDN = new idna_convert();
// The input string, if input is not UTF-8 or UCS-4, it must be converted before
$input = utf8_encode('nörgler.com');
// Encode it to its punycode presentation
$output = $IDN->encode($input);
// Output, what we got now
echo $output; // This will read: xn--nrgler-wxa.com
```
### Example 2.
We received an email from a punycoded domain and are willing to learn, how the domain name reads originally
```php
<?php
// Include the class
require_once('idna_convert.class.php');
// Instantiate it
$IDN = new idna_convert();
// The input string
$input = 'andre@xn--brse-5qa.xn--knrz-1ra.info';
// Encode it to its punycode presentation
$output = $IDN->decode($input);
// Output, what we got now, if output should be in a format different to UTF-8
// or UCS-4, you will have to convert it before outputting it
echo utf8_decode($output); // This will read: andre@börse.knörz.info
```
### Example 3.
The input is read from a UCS-4 coded file and encoded line by line. By appending the optional second parameter we tell enode() about the input format to be used
```php
<?php
// Include the class
require_once('idna_convert.class.php');
// Instantiate it
$IDN = new dinca_convert();
// Iterate through the input file line by line
foreach (file('ucs4-domains.txt') as $line) {
echo $IDN->encode(trim($line), 'ucs4_string');
echo "\n";
}
```
### Example 4.
We wish to convert a whole URI into the IDNA form, but leave the path or query string component of it alone. Just using encode() would lead to mangled paths or query strings. Here the public method encode_uri() comes into play:
```php
<?php
// Include the class
require_once('idna_convert.class.php');
// Instantiate it
$IDN = new idna_convert();
// The input string, a whole URI in UTF-8 (!)
$input = 'http://nörgler:secret@nörgler.com/my_päth_is_not_ÄSCII/');
// Encode it to its punycode presentation
$output = $IDN->encode_uri($input);
// Output, what we got now
echo $output; // http://nörgler:secret@xn--nrgler-wxa.com/my_päth_is_not_ÄSCII/
```
### Example 5.
To support IDNA 2008, the class needs to be invoked with an additional parameter. This can also be achieved on an instance.
```php
<?php
// Include the class
require_once('idna_convert.class.php');
// Instantiate it
$IDN = new idna_convert(array('idn_version' => 2008));
// Sth. containing the German letter ß
$input = 'meine-straße.de');
// Encode it to its punycode presentation
$output = $IDN->encode_uri($input);
// Output, what we got now
echo $output; // xn--meine-strae-46a.de
// Switch back to old IDNA 2003, the original standard
$IDN->set_parameter('idn_version', 2003);
// Sth. containing the German letter ß
$input = 'meine-straße.de');
// Encode it to its punycode presentation
$output = $IDN->encode_uri($input);
// Output, what we got now
echo $output; // meine-strasse.de
```
## Transcode wrapper
In case you have strings in different encoding than ISO-8859-1 and UTF-8 you might need to translate these strings to UTF-8 before feeding the IDNA converter with it.
PHP's built in functions `utf8_encode()` and `utf8_decode()` can only deal with ISO-8859-1.
Use the file transcode_wrapper.php for the conversion. It requires either iconv, libiconv or mbstring installed together with one of the relevant PHP extensions. The functions you will find useful are
`encode_utf8()` as a replacement for `utf8_encode()` and
`decode_utf8()` as a replacement for `utf8_decode()`.
Example usage:
```php
<?php
require_once('idna_convert.class.php');
require_once('transcode_wrapper.php');
$mystring = '<something in e.g. ISO-8859-15';
$mystring = encode_utf8($mystring, 'ISO-8859-15');
echo $IDN->encode($mystring);
```
## UCTC - Unicode Transcoder
Another class you might find useful when dealing with one or more of the Unicode encoding flavours. The class is static, it requires PHP5. It can transcode into each other:
- UCS-4 string / array
- UTF-8
- UTF-7
- UTF-7 IMAP (modified UTF-7)
All encodings expect / return a string in the given format, with one major exception: UCS-4 array is just an array, where each value represents one code-point in the string, i.e. every value is a 32bit integer value.
Example usage:
```php
<?php
require_once('uctc.php');
$mystring = 'nörgler.com';
echo uctc::convert($mystring, 'utf8', 'utf7imap');
```
## Contact us
In case of errors, bugs, questions, wishes, please don't hesitate to contact us under the email address below.
The team of phlyLabs
http://phlylabs.de
mailto:phlymail@phlylabs.de

View File

@@ -0,0 +1,29 @@
{
"name": "mso/idna-convert",
"description": "A library for encoding and decoding internationalized domain names",
"license": "LGPL-2.1+",
"keywords": ["PHP","IDN","IDNA"],
"homepage": "http://idnaconv.net/",
"authors": [
{
"name": "Matthias Sommerfeld",
"email": "mso@phlylabs.de",
"role": "Developer"
}
],
"autoload": {
"classmap": [
"idna_convert.class.php",
"uctc.php"
]
},
"require": {
"ext-pcre": "*",
"php": ">=5.0.0"
},
"extra": {
"branch-alias": {
"dev-master": "0.9.x-dev"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,137 @@
<?php
/**
* transcode wrapper functions
* @package IDNA Convert
* @subpackage charset transcoding
* @author Matthias Sommerfeld, <mso@phlylabs.de>
* @version 0.1.0
*/
/**
* Convert a string from any of various encodings to UTF-8
*
* @param string String to encode
*[@param string Encoding; Default: ISO-8859-1]
*[@param bool Safe Mode: if set to TRUE, the original string is retunred on errors]
* @return string The encoded string or false on failure
* @since 0.0.1
*/
function encode_utf8($string = '', $encoding = 'iso-8859-1', $safe_mode = false)
{
$safe = ($safe_mode) ? $string : false;
if (strtoupper($encoding) == 'UTF-8' || strtoupper($encoding) == 'UTF8') {
return $string;
} elseif (strtoupper($encoding) == 'ISO-8859-1') {
return utf8_encode($string);
} elseif (strtoupper($encoding) == 'WINDOWS-1252') {
return utf8_encode(map_w1252_iso8859_1($string));
} elseif (strtoupper($encoding) == 'UNICODE-1-1-UTF-7') {
$encoding = 'utf-7';
}
if (function_exists('mb_convert_encoding')) {
$conv = @mb_convert_encoding($string, 'UTF-8', strtoupper($encoding));
if ($conv) return $conv;
}
if (function_exists('iconv')) {
$conv = @iconv(strtoupper($encoding), 'UTF-8', $string);
if ($conv) return $conv;
}
if (function_exists('libiconv')) {
$conv = @libiconv(strtoupper($encoding), 'UTF-8', $string);
if ($conv) return $conv;
}
return $safe;
}
/**
* Convert a string from UTF-8 to any of various encodings
*
* @param string String to decode
*[@param string Encoding; Default: ISO-8859-1]
*[@param bool Safe Mode: if set to TRUE, the original string is retunred on errors]
* @return string The decoded string or false on failure
* @since 0.0.1
*/
function decode_utf8($string = '', $encoding = 'iso-8859-1', $safe_mode = false)
{
$safe = ($safe_mode) ? $string : false;
if (!$encoding) $encoding = 'ISO-8859-1';
if (strtoupper($encoding) == 'UTF-8' || strtoupper($encoding) == 'UTF8') {
return $string;
} elseif (strtoupper($encoding) == 'ISO-8859-1') {
return utf8_decode($string);
} elseif (strtoupper($encoding) == 'WINDOWS-1252') {
return map_iso8859_1_w1252(utf8_decode($string));
} elseif (strtoupper($encoding) == 'UNICODE-1-1-UTF-7') {
$encoding = 'utf-7';
}
if (function_exists('mb_convert_encoding')) {
$conv = @mb_convert_encoding($string, strtoupper($encoding), 'UTF-8');
if ($conv) return $conv;
}
if (function_exists('iconv')) {
$conv = @iconv('UTF-8', strtoupper($encoding), $string);
if ($conv) return $conv;
}
if (function_exists('libiconv')) {
$conv = @libiconv('UTF-8', strtoupper($encoding), $string);
if ($conv) return $conv;
}
return $safe;
}
/**
* Special treatment for our guys in Redmond
* Windows-1252 is basically ISO-8859-1 -- with some exceptions, which get accounted for here
* @param string Your input in Win1252
* @param string The resulting ISO-8859-1 string
* @since 3.0.8
*/
function map_w1252_iso8859_1($string = '')
{
if ($string == '') return '';
$return = '';
for ($i = 0; $i < strlen($string); ++$i) {
$c = ord($string{$i});
switch ($c) {
case 129: $return .= chr(252); break;
case 132: $return .= chr(228); break;
case 142: $return .= chr(196); break;
case 148: $return .= chr(246); break;
case 153: $return .= chr(214); break;
case 154: $return .= chr(220); break;
case 225: $return .= chr(223); break;
default: $return .= chr($c); break;
}
}
return $return;
}
/**
* Special treatment for our guys in Redmond
* Windows-1252 is basically ISO-8859-1 -- with some exceptions, which get accounted for here
* @param string Your input in ISO-8859-1
* @param string The resulting Win1252 string
* @since 3.0.8
*/
function map_iso8859_1_w1252($string = '')
{
if ($string == '') return '';
$return = '';
for ($i = 0; $i < strlen($string); ++$i) {
$c = ord($string{$i});
switch ($c) {
case 196: $return .= chr(142); break;
case 214: $return .= chr(153); break;
case 220: $return .= chr(154); break;
case 223: $return .= chr(225); break;
case 228: $return .= chr(132); break;
case 246: $return .= chr(148); break;
case 252: $return .= chr(129); break;
default: $return .= chr($c); break;
}
}
return $return;
}
?>

View File

@@ -0,0 +1,300 @@
<?php
/**
* UCTC - The Unicode Transcoder
*
* Converts between various flavours of Unicode representations like UCS-4 or UTF-8
* Supported schemes:
* - UCS-4 Little Endian / Big Endian / Array (partially)
* - UTF-16 Little Endian / Big Endian (not yet)
* - UTF-8
* - UTF-7
* - UTF-7 IMAP (modified UTF-7)
*
* @package phlyMail Nahariya 4.0+ Default branch
* @author Matthias Sommerfeld <mso@phlyLabs.de>
* @copyright 2003-2009 phlyLabs Berlin, http://phlylabs.de
* @version 0.0.6 2009-05-10
*/
class uctc {
private static $mechs = array('ucs4', /*'ucs4le', 'ucs4be', */'ucs4array', /*'utf16', 'utf16le', 'utf16be', */'utf8', 'utf7', 'utf7imap');
private static $allow_overlong = false;
private static $safe_mode;
private static $safe_char;
/**
* The actual conversion routine
*
* @param mixed $data The data to convert, usually a string, array when converting from UCS-4 array
* @param string $from Original encoding of the data
* @param string $to Target encoding of the data
* @param bool $safe_mode SafeMode tries to correct invalid codepoints
* @return mixed False on failure, String or array on success, depending on target encoding
* @access public
* @since 0.0.1
*/
public static function convert($data, $from, $to, $safe_mode = false, $safe_char = 0xFFFC)
{
self::$safe_mode = ($safe_mode) ? true : false;
self::$safe_char = ($safe_char) ? $safe_char : 0xFFFC;
if (self::$safe_mode) self::$allow_overlong = true;
if (!in_array($from, self::$mechs)) throw new Exception('Invalid input format specified');
if (!in_array($to, self::$mechs)) throw new Exception('Invalid output format specified');
if ($from != 'ucs4array') eval('$data = self::'.$from.'_ucs4array($data);');
if ($to != 'ucs4array') eval('$data = self::ucs4array_'.$to.'($data);');
return $data;
}
/**
* This converts an UTF-8 encoded string to its UCS-4 representation
*
* @param string $input The UTF-8 string to convert
* @return array Array of 32bit values representing each codepoint
* @access private
*/
private static function utf8_ucs4array($input)
{
$output = array();
$out_len = 0;
$inp_len = strlen($input);
$mode = 'next';
$test = 'none';
for ($k = 0; $k < $inp_len; ++$k) {
$v = ord($input{$k}); // Extract byte from input string
if ($v < 128) { // We found an ASCII char - put into stirng as is
$output[$out_len] = $v;
++$out_len;
if ('add' == $mode) {
if (self::$safe_mode) {
$output[$out_len-2] = self::$safe_char;
$mode = 'next';
} else {
throw new Exception('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
}
}
continue;
}
if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char
$start_byte = $v;
$mode = 'add';
$test = 'range';
if ($v >> 5 == 6) { // &110xxxxx 10xxxxx
$next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left
$v = ($v - 192) << 6;
} elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx
$next_byte = 1;
$v = ($v - 224) << 12;
} elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
$next_byte = 2;
$v = ($v - 240) << 18;
} elseif (self::$safe_mode) {
$mode = 'next';
$output[$out_len] = self::$safe_char;
++$out_len;
continue;
} else {
throw new Exception('This might be UTF-8, but I don\'t understand it at byte '.$k);
}
if ($inp_len-$k-$next_byte < 2) {
$output[$out_len] = self::$safe_char;
$mode = 'no';
continue;
}
if ('add' == $mode) {
$output[$out_len] = (int) $v;
++$out_len;
continue;
}
}
if ('add' == $mode) {
if (!self::$allow_overlong && $test == 'range') {
$test = 'none';
if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) {
throw new Exception('Bogus UTF-8 character detected (out of legal range) at byte '.$k);
}
}
if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx
$v = ($v-128) << ($next_byte*6);
$output[($out_len-1)] += $v;
--$next_byte;
} else {
if (self::$safe_mode) {
$output[$out_len-1] = ord(self::$safe_char);
$k--;
$mode = 'next';
continue;
} else {
throw new Exception('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
}
}
if ($next_byte < 0) {
$mode = 'next';
}
}
} // for
return $output;
}
/**
* Convert UCS-4 string into UTF-8 string
* See utf8_ucs4array() for details
* @access private
*/
private static function ucs4array_utf8($input)
{
$output = '';
foreach ($input as $v) {
if ($v < 128) { // 7bit are transferred literally
$output .= chr($v);
} elseif ($v < (1 << 11)) { // 2 bytes
$output .= chr(192+($v >> 6)).chr(128+($v & 63));
} elseif ($v < (1 << 16)) { // 3 bytes
$output .= chr(224+($v >> 12)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63));
} elseif ($v < (1 << 21)) { // 4 bytes
$output .= chr(240+($v >> 18)).chr(128+(($v >> 12) & 63)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63));
} elseif (self::$safe_mode) {
$output .= self::$safe_char;
} else {
throw new Exception('Conversion from UCS-4 to UTF-8 failed: malformed input at byte '.$k);
}
}
return $output;
}
private static function utf7imap_ucs4array($input)
{
return self::utf7_ucs4array(str_replace(',', '/', $input), '&');
}
private static function utf7_ucs4array($input, $sc = '+')
{
$output = array();
$out_len = 0;
$inp_len = strlen($input);
$mode = 'd';
$b64 = '';
for ($k = 0; $k < $inp_len; ++$k) {
$c = $input{$k};
if (0 == ord($c)) continue; // Ignore zero bytes
if ('b' == $mode) {
// Sequence got terminated
if (!preg_match('![A-Za-z0-9/'.preg_quote($sc, '!').']!', $c)) {
if ('-' == $c) {
if ($b64 == '') {
$output[$out_len] = ord($sc);
$out_len++;
$mode = 'd';
continue;
}
}
$tmp = base64_decode($b64);
$tmp = substr($tmp, -1 * (strlen($tmp) % 2));
for ($i = 0; $i < strlen($tmp); $i++) {
if ($i % 2) {
$output[$out_len] += ord($tmp{$i});
$out_len++;
} else {
$output[$out_len] = ord($tmp{$i}) << 8;
}
}
$mode = 'd';
$b64 = '';
continue;
} else {
$b64 .= $c;
}
}
if ('d' == $mode) {
if ($sc == $c) {
$mode = 'b';
continue;
}
$output[$out_len] = ord($c);
$out_len++;
}
}
return $output;
}
private static function ucs4array_utf7imap($input)
{
return str_replace('/', ',', self::ucs4array_utf7($input, '&'));
}
private static function ucs4array_utf7($input, $sc = '+')
{
$output = '';
$mode = 'd';
$b64 = '';
while (true) {
$v = (!empty($input)) ? array_shift($input) : false;
$is_direct = (false !== $v) ? (0x20 <= $v && $v <= 0x7e && $v != ord($sc)) : true;
if ($mode == 'b') {
if ($is_direct) {
if ($b64 == chr(0).$sc) {
$output .= $sc.'-';
$b64 = '';
} elseif ($b64) {
$output .= $sc.str_replace('=', '', base64_encode($b64)).'-';
$b64 = '';
}
$mode = 'd';
} elseif (false !== $v) {
$b64 .= chr(($v >> 8) & 255). chr($v & 255);
}
}
if ($mode == 'd' && false !== $v) {
if ($is_direct) {
$output .= chr($v);
} else {
$b64 = chr(($v >> 8) & 255). chr($v & 255);
$mode = 'b';
}
}
if (false === $v && $b64 == '') break;
}
return $output;
}
/**
* Convert UCS-4 array into UCS-4 string (Little Endian at the moment)
* @access private
*/
private static function ucs4array_ucs4($input)
{
$output = '';
foreach ($input as $v) {
$output .= chr(($v >> 24) & 255).chr(($v >> 16) & 255).chr(($v >> 8) & 255).chr($v & 255);
}
return $output;
}
/**
* Convert UCS-4 string (LE in the moment) into UCS-4 garray
* @access private
*/
private static function ucs4_ucs4array($input)
{
$output = array();
$inp_len = strlen($input);
// Input length must be dividable by 4
if ($inp_len % 4) {
throw new Exception('Input UCS4 string is broken');
}
// Empty input - return empty output
if (!$inp_len) return $output;
for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) {
if (!($i % 4)) { // Increment output position every 4 input bytes
$out_len++;
$output[$out_len] = 0;
}
$output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) );
}
return $output;
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,137 @@
<?php
/**
* Base class for HTTP_Request2 adapters
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/**
* Class representing a HTTP response
*/
require_once 'HTTP/Request2/Response.php';
/**
* Base class for HTTP_Request2 adapters
*
* HTTP_Request2 class itself only defines methods for aggregating the request
* data, all actual work of sending the request to the remote server and
* receiving its response is performed by adapters.
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
abstract class HTTP_Request2_Adapter
{
/**
* A list of methods that MUST NOT have a request body, per RFC 2616
* @var array
*/
protected static $bodyDisallowed = array('TRACE');
/**
* Methods having defined semantics for request body
*
* Content-Length header (indicating that the body follows, section 4.3 of
* RFC 2616) will be sent for these methods even if no body was added
*
* @var array
* @link http://pear.php.net/bugs/bug.php?id=12900
* @link http://pear.php.net/bugs/bug.php?id=14740
*/
protected static $bodyRequired = array('POST', 'PUT');
/**
* Request being sent
* @var HTTP_Request2
*/
protected $request;
/**
* Request body
* @var string|resource|HTTP_Request2_MultipartBody
* @see HTTP_Request2::getBody()
*/
protected $requestBody;
/**
* Length of the request body
* @var integer
*/
protected $contentLength;
/**
* Sends request to the remote server and returns its response
*
* @param HTTP_Request2 $request HTTP request message
*
* @return HTTP_Request2_Response
* @throws HTTP_Request2_Exception
*/
abstract public function sendRequest(HTTP_Request2 $request);
/**
* Calculates length of the request body, adds proper headers
*
* @param array &$headers associative array of request headers, this method
* will add proper 'Content-Length' and 'Content-Type'
* headers to this array (or remove them if not needed)
*/
protected function calculateRequestLength(&$headers)
{
$this->requestBody = $this->request->getBody();
if (is_string($this->requestBody)) {
$this->contentLength = strlen($this->requestBody);
} elseif (is_resource($this->requestBody)) {
$stat = fstat($this->requestBody);
$this->contentLength = $stat['size'];
rewind($this->requestBody);
} else {
$this->contentLength = $this->requestBody->getLength();
$headers['content-type'] = 'multipart/form-data; boundary=' .
$this->requestBody->getBoundary();
$this->requestBody->rewind();
}
if (in_array($this->request->getMethod(), self::$bodyDisallowed)
|| 0 == $this->contentLength
) {
// No body: send a Content-Length header nonetheless (request #12900),
// but do that only for methods that require a body (bug #14740)
if (in_array($this->request->getMethod(), self::$bodyRequired)) {
$headers['content-length'] = 0;
} else {
unset($headers['content-length']);
// if the method doesn't require a body and doesn't have a
// body, don't send a Content-Type header. (request #16799)
unset($headers['content-type']);
}
} else {
if (empty($headers['content-type'])) {
$headers['content-type'] = 'application/x-www-form-urlencoded';
}
// Content-Length should not be sent for chunked Transfer-Encoding (bug #20125)
if (!isset($headers['transfer-encoding'])) {
$headers['content-length'] = $this->contentLength;
}
}
}
}
?>

View File

@@ -0,0 +1,577 @@
<?php
/**
* Adapter for HTTP_Request2 wrapping around cURL extension
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/**
* Base class for HTTP_Request2 adapters
*/
require_once 'HTTP/Request2/Adapter.php';
/**
* Adapter for HTTP_Request2 wrapping around cURL extension
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
{
/**
* Mapping of header names to cURL options
* @var array
*/
protected static $headerMap = array(
'accept-encoding' => CURLOPT_ENCODING,
'cookie' => CURLOPT_COOKIE,
'referer' => CURLOPT_REFERER,
'user-agent' => CURLOPT_USERAGENT
);
/**
* Mapping of SSL context options to cURL options
* @var array
*/
protected static $sslContextMap = array(
'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER,
'ssl_cafile' => CURLOPT_CAINFO,
'ssl_capath' => CURLOPT_CAPATH,
'ssl_local_cert' => CURLOPT_SSLCERT,
'ssl_passphrase' => CURLOPT_SSLCERTPASSWD
);
/**
* Mapping of CURLE_* constants to Exception subclasses and error codes
* @var array
*/
protected static $errorMap = array(
CURLE_UNSUPPORTED_PROTOCOL => array('HTTP_Request2_MessageException',
HTTP_Request2_Exception::NON_HTTP_REDIRECT),
CURLE_COULDNT_RESOLVE_PROXY => array('HTTP_Request2_ConnectionException'),
CURLE_COULDNT_RESOLVE_HOST => array('HTTP_Request2_ConnectionException'),
CURLE_COULDNT_CONNECT => array('HTTP_Request2_ConnectionException'),
// error returned from write callback
CURLE_WRITE_ERROR => array('HTTP_Request2_MessageException',
HTTP_Request2_Exception::NON_HTTP_REDIRECT),
CURLE_OPERATION_TIMEOUTED => array('HTTP_Request2_MessageException',
HTTP_Request2_Exception::TIMEOUT),
CURLE_HTTP_RANGE_ERROR => array('HTTP_Request2_MessageException'),
CURLE_SSL_CONNECT_ERROR => array('HTTP_Request2_ConnectionException'),
CURLE_LIBRARY_NOT_FOUND => array('HTTP_Request2_LogicException',
HTTP_Request2_Exception::MISCONFIGURATION),
CURLE_FUNCTION_NOT_FOUND => array('HTTP_Request2_LogicException',
HTTP_Request2_Exception::MISCONFIGURATION),
CURLE_ABORTED_BY_CALLBACK => array('HTTP_Request2_MessageException',
HTTP_Request2_Exception::NON_HTTP_REDIRECT),
CURLE_TOO_MANY_REDIRECTS => array('HTTP_Request2_MessageException',
HTTP_Request2_Exception::TOO_MANY_REDIRECTS),
CURLE_SSL_PEER_CERTIFICATE => array('HTTP_Request2_ConnectionException'),
CURLE_GOT_NOTHING => array('HTTP_Request2_MessageException'),
CURLE_SSL_ENGINE_NOTFOUND => array('HTTP_Request2_LogicException',
HTTP_Request2_Exception::MISCONFIGURATION),
CURLE_SSL_ENGINE_SETFAILED => array('HTTP_Request2_LogicException',
HTTP_Request2_Exception::MISCONFIGURATION),
CURLE_SEND_ERROR => array('HTTP_Request2_MessageException'),
CURLE_RECV_ERROR => array('HTTP_Request2_MessageException'),
CURLE_SSL_CERTPROBLEM => array('HTTP_Request2_LogicException',
HTTP_Request2_Exception::INVALID_ARGUMENT),
CURLE_SSL_CIPHER => array('HTTP_Request2_ConnectionException'),
CURLE_SSL_CACERT => array('HTTP_Request2_ConnectionException'),
CURLE_BAD_CONTENT_ENCODING => array('HTTP_Request2_MessageException'),
);
/**
* Response being received
* @var HTTP_Request2_Response
*/
protected $response;
/**
* Whether 'sentHeaders' event was sent to observers
* @var boolean
*/
protected $eventSentHeaders = false;
/**
* Whether 'receivedHeaders' event was sent to observers
* @var boolean
*/
protected $eventReceivedHeaders = false;
/**
* Whether 'sentBoody' event was sent to observers
* @var boolean
*/
protected $eventSentBody = false;
/**
* Position within request body
* @var integer
* @see callbackReadBody()
*/
protected $position = 0;
/**
* Information about last transfer, as returned by curl_getinfo()
* @var array
*/
protected $lastInfo;
/**
* Creates a subclass of HTTP_Request2_Exception from curl error data
*
* @param resource $ch curl handle
*
* @return HTTP_Request2_Exception
*/
protected static function wrapCurlError($ch)
{
$nativeCode = curl_errno($ch);
$message = 'Curl error: ' . curl_error($ch);
if (!isset(self::$errorMap[$nativeCode])) {
return new HTTP_Request2_Exception($message, 0, $nativeCode);
} else {
$class = self::$errorMap[$nativeCode][0];
$code = empty(self::$errorMap[$nativeCode][1])
? 0 : self::$errorMap[$nativeCode][1];
return new $class($message, $code, $nativeCode);
}
}
/**
* Sends request to the remote server and returns its response
*
* @param HTTP_Request2 $request HTTP request message
*
* @return HTTP_Request2_Response
* @throws HTTP_Request2_Exception
*/
public function sendRequest(HTTP_Request2 $request)
{
if (!extension_loaded('curl')) {
throw new HTTP_Request2_LogicException(
'cURL extension not available', HTTP_Request2_Exception::MISCONFIGURATION
);
}
$this->request = $request;
$this->response = null;
$this->position = 0;
$this->eventSentHeaders = false;
$this->eventReceivedHeaders = false;
$this->eventSentBody = false;
try {
if (false === curl_exec($ch = $this->createCurlHandle())) {
$e = self::wrapCurlError($ch);
}
} catch (Exception $e) {
}
if (isset($ch)) {
$this->lastInfo = curl_getinfo($ch);
if (CURLE_OK !== curl_errno($ch)) {
$this->request->setLastEvent('warning', curl_error($ch));
}
curl_close($ch);
}
$response = $this->response;
unset($this->request, $this->requestBody, $this->response);
if (!empty($e)) {
throw $e;
}
if ($jar = $request->getCookieJar()) {
$jar->addCookiesFromResponse($response);
}
if (0 < $this->lastInfo['size_download']) {
$request->setLastEvent('receivedBody', $response);
}
return $response;
}
/**
* Returns information about last transfer
*
* @return array associative array as returned by curl_getinfo()
*/
public function getInfo()
{
return $this->lastInfo;
}
/**
* Creates a new cURL handle and populates it with data from the request
*
* @return resource a cURL handle, as created by curl_init()
* @throws HTTP_Request2_LogicException
* @throws HTTP_Request2_NotImplementedException
*/
protected function createCurlHandle()
{
$ch = curl_init();
curl_setopt_array($ch, array(
// setup write callbacks
CURLOPT_HEADERFUNCTION => array($this, 'callbackWriteHeader'),
CURLOPT_WRITEFUNCTION => array($this, 'callbackWriteBody'),
// buffer size
CURLOPT_BUFFERSIZE => $this->request->getConfig('buffer_size'),
// connection timeout
CURLOPT_CONNECTTIMEOUT => $this->request->getConfig('connect_timeout'),
// save full outgoing headers, in case someone is interested
CURLINFO_HEADER_OUT => true,
// request url
CURLOPT_URL => $this->request->getUrl()->getUrl()
));
// set up redirects
if (!$this->request->getConfig('follow_redirects')) {
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
} else {
if (!@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)) {
throw new HTTP_Request2_LogicException(
'Redirect support in curl is unavailable due to open_basedir or safe_mode setting',
HTTP_Request2_Exception::MISCONFIGURATION
);
}
curl_setopt($ch, CURLOPT_MAXREDIRS, $this->request->getConfig('max_redirects'));
// limit redirects to http(s), works in 5.2.10+
if (defined('CURLOPT_REDIR_PROTOCOLS')) {
curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
}
// works in 5.3.2+, http://bugs.php.net/bug.php?id=49571
if ($this->request->getConfig('strict_redirects') && defined('CURLOPT_POSTREDIR')) {
curl_setopt($ch, CURLOPT_POSTREDIR, 3);
}
}
// set local IP via CURLOPT_INTERFACE (request #19515)
if ($ip = $this->request->getConfig('local_ip')) {
curl_setopt($ch, CURLOPT_INTERFACE, $ip);
}
// request timeout
if ($timeout = $this->request->getConfig('timeout')) {
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
}
// set HTTP version
switch ($this->request->getConfig('protocol_version')) {
case '1.0':
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
break;
case '1.1':
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
}
// set request method
switch ($this->request->getMethod()) {
case HTTP_Request2::METHOD_GET:
curl_setopt($ch, CURLOPT_HTTPGET, true);
break;
case HTTP_Request2::METHOD_POST:
curl_setopt($ch, CURLOPT_POST, true);
break;
case HTTP_Request2::METHOD_HEAD:
curl_setopt($ch, CURLOPT_NOBODY, true);
break;
case HTTP_Request2::METHOD_PUT:
curl_setopt($ch, CURLOPT_UPLOAD, true);
break;
default:
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod());
}
// set proxy, if needed
if ($host = $this->request->getConfig('proxy_host')) {
if (!($port = $this->request->getConfig('proxy_port'))) {
throw new HTTP_Request2_LogicException(
'Proxy port not provided', HTTP_Request2_Exception::MISSING_VALUE
);
}
curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port);
if ($user = $this->request->getConfig('proxy_user')) {
curl_setopt(
$ch, CURLOPT_PROXYUSERPWD,
$user . ':' . $this->request->getConfig('proxy_password')
);
switch ($this->request->getConfig('proxy_auth_scheme')) {
case HTTP_Request2::AUTH_BASIC:
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
break;
case HTTP_Request2::AUTH_DIGEST:
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
}
}
if ($type = $this->request->getConfig('proxy_type')) {
switch ($type) {
case 'http':
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
break;
case 'socks5':
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
break;
default:
throw new HTTP_Request2_NotImplementedException(
"Proxy type '{$type}' is not supported"
);
}
}
}
// set authentication data
if ($auth = $this->request->getAuth()) {
curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']);
switch ($auth['scheme']) {
case HTTP_Request2::AUTH_BASIC:
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
break;
case HTTP_Request2::AUTH_DIGEST:
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
}
}
// set SSL options
foreach ($this->request->getConfig() as $name => $value) {
if ('ssl_verify_host' == $name && null !== $value) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0);
} elseif (isset(self::$sslContextMap[$name]) && null !== $value) {
curl_setopt($ch, self::$sslContextMap[$name], $value);
}
}
$headers = $this->request->getHeaders();
// make cURL automagically send proper header
if (!isset($headers['accept-encoding'])) {
$headers['accept-encoding'] = '';
}
if (($jar = $this->request->getCookieJar())
&& ($cookies = $jar->getMatching($this->request->getUrl(), true))
) {
$headers['cookie'] = (empty($headers['cookie'])? '': $headers['cookie'] . '; ') . $cookies;
}
// set headers having special cURL keys
foreach (self::$headerMap as $name => $option) {
if (isset($headers[$name])) {
curl_setopt($ch, $option, $headers[$name]);
unset($headers[$name]);
}
}
$this->calculateRequestLength($headers);
if (isset($headers['content-length']) || isset($headers['transfer-encoding'])) {
$this->workaroundPhpBug47204($ch, $headers);
}
// set headers not having special keys
$headersFmt = array();
foreach ($headers as $name => $value) {
$canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
$headersFmt[] = $canonicalName . ': ' . $value;
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt);
return $ch;
}
/**
* Workaround for PHP bug #47204 that prevents rewinding request body
*
* The workaround consists of reading the entire request body into memory
* and setting it as CURLOPT_POSTFIELDS, so it isn't recommended for large
* file uploads, use Socket adapter instead.
*
* @param resource $ch cURL handle
* @param array &$headers Request headers
*/
protected function workaroundPhpBug47204($ch, &$headers)
{
// no redirects, no digest auth -> probably no rewind needed
// also apply workaround only for POSTs, othrerwise we get
// https://pear.php.net/bugs/bug.php?id=20440 for PUTs
if (!$this->request->getConfig('follow_redirects')
&& (!($auth = $this->request->getAuth())
|| HTTP_Request2::AUTH_DIGEST != $auth['scheme'])
|| HTTP_Request2::METHOD_POST !== $this->request->getMethod()
) {
curl_setopt($ch, CURLOPT_READFUNCTION, array($this, 'callbackReadBody'));
} else {
// rewind may be needed, read the whole body into memory
if ($this->requestBody instanceof HTTP_Request2_MultipartBody) {
$this->requestBody = $this->requestBody->__toString();
} elseif (is_resource($this->requestBody)) {
$fp = $this->requestBody;
$this->requestBody = '';
while (!feof($fp)) {
$this->requestBody .= fread($fp, 16384);
}
}
// curl hangs up if content-length is present
unset($headers['content-length']);
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody);
}
}
/**
* Callback function called by cURL for reading the request body
*
* @param resource $ch cURL handle
* @param resource $fd file descriptor (not used)
* @param integer $length maximum length of data to return
*
* @return string part of the request body, up to $length bytes
*/
protected function callbackReadBody($ch, $fd, $length)
{
if (!$this->eventSentHeaders) {
$this->request->setLastEvent(
'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
);
$this->eventSentHeaders = true;
}
if (in_array($this->request->getMethod(), self::$bodyDisallowed)
|| 0 == $this->contentLength || $this->position >= $this->contentLength
) {
return '';
}
if (is_string($this->requestBody)) {
$string = substr($this->requestBody, $this->position, $length);
} elseif (is_resource($this->requestBody)) {
$string = fread($this->requestBody, $length);
} else {
$string = $this->requestBody->read($length);
}
$this->request->setLastEvent('sentBodyPart', strlen($string));
$this->position += strlen($string);
return $string;
}
/**
* Callback function called by cURL for saving the response headers
*
* @param resource $ch cURL handle
* @param string $string response header (with trailing CRLF)
*
* @return integer number of bytes saved
* @see HTTP_Request2_Response::parseHeaderLine()
*/
protected function callbackWriteHeader($ch, $string)
{
if (!$this->eventSentHeaders
// we may receive a second set of headers if doing e.g. digest auth
// but don't bother with 100-Continue responses (bug #15785)
|| $this->eventReceivedHeaders && $this->response->getStatus() >= 200
) {
$this->request->setLastEvent(
'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
);
}
if (!$this->eventSentBody) {
$upload = curl_getinfo($ch, CURLINFO_SIZE_UPLOAD);
// if body wasn't read by the callback, send event with total body size
if ($upload > $this->position) {
$this->request->setLastEvent(
'sentBodyPart', $upload - $this->position
);
}
if ($upload > 0) {
$this->request->setLastEvent('sentBody', $upload);
}
}
$this->eventSentHeaders = true;
$this->eventSentBody = true;
if ($this->eventReceivedHeaders || empty($this->response)) {
$this->eventReceivedHeaders = false;
$this->response = new HTTP_Request2_Response(
$string, false, curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)
);
} else {
$this->response->parseHeaderLine($string);
if ('' == trim($string)) {
// don't bother with 100-Continue responses (bug #15785)
if (200 <= $this->response->getStatus()) {
$this->request->setLastEvent('receivedHeaders', $this->response);
}
if ($this->request->getConfig('follow_redirects') && $this->response->isRedirect()) {
$redirectUrl = new Net_URL2($this->response->getHeader('location'));
// for versions lower than 5.2.10, check the redirection URL protocol
if (!defined('CURLOPT_REDIR_PROTOCOLS') && $redirectUrl->isAbsolute()
&& !in_array($redirectUrl->getScheme(), array('http', 'https'))
) {
return -1;
}
if ($jar = $this->request->getCookieJar()) {
$jar->addCookiesFromResponse($this->response);
if (!$redirectUrl->isAbsolute()) {
$redirectUrl = $this->request->getUrl()->resolve($redirectUrl);
}
if ($cookies = $jar->getMatching($redirectUrl, true)) {
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
}
}
}
$this->eventReceivedHeaders = true;
$this->eventSentBody = false;
}
}
return strlen($string);
}
/**
* Callback function called by cURL for saving the response body
*
* @param resource $ch cURL handle (not used)
* @param string $string part of the response body
*
* @return integer number of bytes saved
* @throws HTTP_Request2_MessageException
* @see HTTP_Request2_Response::appendBody()
*/
protected function callbackWriteBody($ch, $string)
{
// cURL calls WRITEFUNCTION callback without calling HEADERFUNCTION if
// response doesn't start with proper HTTP status line (see bug #15716)
if (empty($this->response)) {
throw new HTTP_Request2_MessageException(
"Malformed response: {$string}",
HTTP_Request2_Exception::MALFORMED_RESPONSE
);
}
if ($this->request->getConfig('store_body')) {
$this->response->appendBody($string);
}
$this->request->setLastEvent('receivedBodyPart', $string);
return strlen($string);
}
}
?>

View File

@@ -0,0 +1,166 @@
<?php
/**
* Mock adapter intended for testing
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/**
* Base class for HTTP_Request2 adapters
*/
require_once 'HTTP/Request2/Adapter.php';
/**
* Mock adapter intended for testing
*
* Can be used to test applications depending on HTTP_Request2 package without
* actually performing any HTTP requests. This adapter will return responses
* previously added via addResponse()
* <code>
* $mock = new HTTP_Request2_Adapter_Mock();
* $mock->addResponse("HTTP/1.1 ... ");
*
* $request = new HTTP_Request2();
* $request->setAdapter($mock);
*
* // This will return the response set above
* $response = $req->send();
* </code>
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter
{
/**
* A queue of responses to be returned by sendRequest()
* @var array
*/
protected $responses = array();
/**
* Returns the next response from the queue built by addResponse()
*
* Only responses without explicit URLs or with URLs equal to request URL
* will be considered. If matching response is not found or the queue is
* empty then default empty response with status 400 will be returned,
* if an Exception object was added to the queue it will be thrown.
*
* @param HTTP_Request2 $request HTTP request message
*
* @return HTTP_Request2_Response
* @throws Exception
*/
public function sendRequest(HTTP_Request2 $request)
{
$requestUrl = (string)$request->getUrl();
$response = null;
foreach ($this->responses as $k => $v) {
if (!$v[1] || $requestUrl == $v[1]) {
$response = $v[0];
array_splice($this->responses, $k, 1);
break;
}
}
if (!$response) {
return self::createResponseFromString("HTTP/1.1 400 Bad Request\r\n\r\n");
} elseif ($response instanceof HTTP_Request2_Response) {
return $response;
} else {
// rethrow the exception
$class = get_class($response);
$message = $response->getMessage();
$code = $response->getCode();
throw new $class($message, $code);
}
}
/**
* Adds response to the queue
*
* @param mixed $response either a string, a pointer to an open file,
* an instance of HTTP_Request2_Response or Exception
* @param string $url A request URL this response should be valid for
* (see {@link http://pear.php.net/bugs/bug.php?id=19276})
*
* @throws HTTP_Request2_Exception
*/
public function addResponse($response, $url = null)
{
if (is_string($response)) {
$response = self::createResponseFromString($response);
} elseif (is_resource($response)) {
$response = self::createResponseFromFile($response);
} elseif (!$response instanceof HTTP_Request2_Response &&
!$response instanceof Exception
) {
throw new HTTP_Request2_Exception('Parameter is not a valid response');
}
$this->responses[] = array($response, $url);
}
/**
* Creates a new HTTP_Request2_Response object from a string
*
* @param string $str string containing HTTP response message
*
* @return HTTP_Request2_Response
* @throws HTTP_Request2_Exception
*/
public static function createResponseFromString($str)
{
$parts = preg_split('!(\r?\n){2}!m', $str, 2);
$headerLines = explode("\n", $parts[0]);
$response = new HTTP_Request2_Response(array_shift($headerLines));
foreach ($headerLines as $headerLine) {
$response->parseHeaderLine($headerLine);
}
$response->parseHeaderLine('');
if (isset($parts[1])) {
$response->appendBody($parts[1]);
}
return $response;
}
/**
* Creates a new HTTP_Request2_Response object from a file
*
* @param resource $fp file pointer returned by fopen()
*
* @return HTTP_Request2_Response
* @throws HTTP_Request2_Exception
*/
public static function createResponseFromFile($fp)
{
$response = new HTTP_Request2_Response(fgets($fp));
do {
$headerLine = fgets($fp);
$response->parseHeaderLine($headerLine);
} while ('' != trim($headerLine));
while (!feof($fp)) {
$response->appendBody(fread($fp, 8192));
}
return $response;
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,547 @@
<?php
/**
* Stores cookies and passes them between HTTP requests
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/** Class representing a HTTP request message */
require_once 'HTTP/Request2.php';
/**
* Stores cookies and passes them between HTTP requests
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
class HTTP_Request2_CookieJar implements Serializable
{
/**
* Array of stored cookies
*
* The array is indexed by domain, path and cookie name
* .example.com
* /
* some_cookie => cookie data
* /subdir
* other_cookie => cookie data
* .example.org
* ...
*
* @var array
*/
protected $cookies = array();
/**
* Whether session cookies should be serialized when serializing the jar
* @var bool
*/
protected $serializeSession = false;
/**
* Whether Public Suffix List should be used for domain matching
* @var bool
*/
protected $useList = true;
/**
* Whether an attempt to store an invalid cookie should be ignored, rather than cause an Exception
* @var bool
*/
protected $ignoreInvalid = false;
/**
* Array with Public Suffix List data
* @var array
* @link http://publicsuffix.org/
*/
protected static $psl = array();
/**
* Class constructor, sets various options
*
* @param bool $serializeSessionCookies Controls serializing session cookies,
* see {@link serializeSessionCookies()}
* @param bool $usePublicSuffixList Controls using Public Suffix List,
* see {@link usePublicSuffixList()}
* @param bool $ignoreInvalidCookies Whether invalid cookies should be ignored,
* see {@link ignoreInvalidCookies()}
*/
public function __construct(
$serializeSessionCookies = false, $usePublicSuffixList = true,
$ignoreInvalidCookies = false
) {
$this->serializeSessionCookies($serializeSessionCookies);
$this->usePublicSuffixList($usePublicSuffixList);
$this->ignoreInvalidCookies($ignoreInvalidCookies);
}
/**
* Returns current time formatted in ISO-8601 at UTC timezone
*
* @return string
*/
protected function now()
{
$dt = new DateTime();
$dt->setTimezone(new DateTimeZone('UTC'));
return $dt->format(DateTime::ISO8601);
}
/**
* Checks cookie array for correctness, possibly updating its 'domain', 'path' and 'expires' fields
*
* The checks are as follows:
* - cookie array should contain 'name' and 'value' fields;
* - name and value should not contain disallowed symbols;
* - 'expires' should be either empty parseable by DateTime;
* - 'domain' and 'path' should be either not empty or an URL where
* cookie was set should be provided.
* - if $setter is provided, then document at that URL should be allowed
* to set a cookie for that 'domain'. If $setter is not provided,
* then no domain checks will be made.
*
* 'expires' field will be converted to ISO8601 format from COOKIE format,
* 'domain' and 'path' will be set from setter URL if empty.
*
* @param array $cookie cookie data, as returned by
* {@link HTTP_Request2_Response::getCookies()}
* @param Net_URL2 $setter URL of the document that sent Set-Cookie header
*
* @return array Updated cookie array
* @throws HTTP_Request2_LogicException
* @throws HTTP_Request2_MessageException
*/
protected function checkAndUpdateFields(array $cookie, Net_URL2 $setter = null)
{
if ($missing = array_diff(array('name', 'value'), array_keys($cookie))) {
throw new HTTP_Request2_LogicException(
"Cookie array should contain 'name' and 'value' fields",
HTTP_Request2_Exception::MISSING_VALUE
);
}
if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['name'])) {
throw new HTTP_Request2_LogicException(
"Invalid cookie name: '{$cookie['name']}'",
HTTP_Request2_Exception::INVALID_ARGUMENT
);
}
if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['value'])) {
throw new HTTP_Request2_LogicException(
"Invalid cookie value: '{$cookie['value']}'",
HTTP_Request2_Exception::INVALID_ARGUMENT
);
}
$cookie += array('domain' => '', 'path' => '', 'expires' => null, 'secure' => false);
// Need ISO-8601 date @ UTC timezone
if (!empty($cookie['expires'])
&& !preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+0000$/', $cookie['expires'])
) {
try {
$dt = new DateTime($cookie['expires']);
$dt->setTimezone(new DateTimeZone('UTC'));
$cookie['expires'] = $dt->format(DateTime::ISO8601);
} catch (Exception $e) {
throw new HTTP_Request2_LogicException($e->getMessage());
}
}
if (empty($cookie['domain']) || empty($cookie['path'])) {
if (!$setter) {
throw new HTTP_Request2_LogicException(
'Cookie misses domain and/or path component, cookie setter URL needed',
HTTP_Request2_Exception::MISSING_VALUE
);
}
if (empty($cookie['domain'])) {
if ($host = $setter->getHost()) {
$cookie['domain'] = $host;
} else {
throw new HTTP_Request2_LogicException(
'Setter URL does not contain host part, can\'t set cookie domain',
HTTP_Request2_Exception::MISSING_VALUE
);
}
}
if (empty($cookie['path'])) {
$path = $setter->getPath();
$cookie['path'] = empty($path)? '/': substr($path, 0, strrpos($path, '/') + 1);
}
}
if ($setter && !$this->domainMatch($setter->getHost(), $cookie['domain'])) {
throw new HTTP_Request2_MessageException(
"Domain " . $setter->getHost() . " cannot set cookies for "
. $cookie['domain']
);
}
return $cookie;
}
/**
* Stores a cookie in the jar
*
* @param array $cookie cookie data, as returned by
* {@link HTTP_Request2_Response::getCookies()}
* @param Net_URL2 $setter URL of the document that sent Set-Cookie header
*
* @return bool whether the cookie was successfully stored
* @throws HTTP_Request2_Exception
*/
public function store(array $cookie, Net_URL2 $setter = null)
{
try {
$cookie = $this->checkAndUpdateFields($cookie, $setter);
} catch (HTTP_Request2_Exception $e) {
if ($this->ignoreInvalid) {
return false;
} else {
throw $e;
}
}
if (strlen($cookie['value'])
&& (is_null($cookie['expires']) || $cookie['expires'] > $this->now())
) {
if (!isset($this->cookies[$cookie['domain']])) {
$this->cookies[$cookie['domain']] = array();
}
if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) {
$this->cookies[$cookie['domain']][$cookie['path']] = array();
}
$this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie;
} elseif (isset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']])) {
unset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']]);
}
return true;
}
/**
* Adds cookies set in HTTP response to the jar
*
* @param HTTP_Request2_Response $response HTTP response message
* @param Net_URL2 $setter original request URL, needed for
* setting default domain/path. If not given,
* effective URL from response will be used.
*
* @return bool whether all cookies were successfully stored
* @throws HTTP_Request2_LogicException
*/
public function addCookiesFromResponse(HTTP_Request2_Response $response, Net_URL2 $setter = null)
{
if (null === $setter) {
if (!($effectiveUrl = $response->getEffectiveUrl())) {
throw new HTTP_Request2_LogicException(
'Response URL required for adding cookies from response',
HTTP_Request2_Exception::MISSING_VALUE
);
}
$setter = new Net_URL2($effectiveUrl);
}
$success = true;
foreach ($response->getCookies() as $cookie) {
$success = $this->store($cookie, $setter) && $success;
}
return $success;
}
/**
* Returns all cookies matching a given request URL
*
* The following checks are made:
* - cookie domain should match request host
* - cookie path should be a prefix for request path
* - 'secure' cookies will only be sent for HTTPS requests
*
* @param Net_URL2 $url Request url
* @param bool $asString Whether to return cookies as string for "Cookie: " header
*
* @return array|string Matching cookies
*/
public function getMatching(Net_URL2 $url, $asString = false)
{
$host = $url->getHost();
$path = $url->getPath();
$secure = 0 == strcasecmp($url->getScheme(), 'https');
$matched = $ret = array();
foreach (array_keys($this->cookies) as $domain) {
if ($this->domainMatch($host, $domain)) {
foreach (array_keys($this->cookies[$domain]) as $cPath) {
if (0 === strpos($path, $cPath)) {
foreach ($this->cookies[$domain][$cPath] as $name => $cookie) {
if (!$cookie['secure'] || $secure) {
$matched[$name][strlen($cookie['path'])] = $cookie;
}
}
}
}
}
}
foreach ($matched as $cookies) {
krsort($cookies);
$ret = array_merge($ret, $cookies);
}
if (!$asString) {
return $ret;
} else {
$str = '';
foreach ($ret as $c) {
$str .= (empty($str)? '': '; ') . $c['name'] . '=' . $c['value'];
}
return $str;
}
}
/**
* Returns all cookies stored in a jar
*
* @return array
*/
public function getAll()
{
$cookies = array();
foreach (array_keys($this->cookies) as $domain) {
foreach (array_keys($this->cookies[$domain]) as $path) {
foreach ($this->cookies[$domain][$path] as $name => $cookie) {
$cookies[] = $cookie;
}
}
}
return $cookies;
}
/**
* Sets whether session cookies should be serialized when serializing the jar
*
* @param boolean $serialize serialize?
*/
public function serializeSessionCookies($serialize)
{
$this->serializeSession = (bool)$serialize;
}
/**
* Sets whether invalid cookies should be silently ignored or cause an Exception
*
* @param boolean $ignore ignore?
* @link http://pear.php.net/bugs/bug.php?id=19937
* @link http://pear.php.net/bugs/bug.php?id=20401
*/
public function ignoreInvalidCookies($ignore)
{
$this->ignoreInvalid = (bool)$ignore;
}
/**
* Sets whether Public Suffix List should be used for restricting cookie-setting
*
* Without PSL {@link domainMatch()} will only prevent setting cookies for
* top-level domains like '.com' or '.org'. However, it will not prevent
* setting a cookie for '.co.uk' even though only third-level registrations
* are possible in .uk domain.
*
* With the List it is possible to find the highest level at which a domain
* may be registered for a particular top-level domain and consequently
* prevent cookies set for '.co.uk' or '.msk.ru'. The same list is used by
* Firefox, Chrome and Opera browsers to restrict cookie setting.
*
* Note that PSL is licensed differently to HTTP_Request2 package (refer to
* the license information in public-suffix-list.php), so you can disable
* its use if this is an issue for you.
*
* @param boolean $useList use the list?
*
* @link http://publicsuffix.org/learn/
*/
public function usePublicSuffixList($useList)
{
$this->useList = (bool)$useList;
}
/**
* Returns string representation of object
*
* @return string
*
* @see Serializable::serialize()
*/
public function serialize()
{
$cookies = $this->getAll();
if (!$this->serializeSession) {
for ($i = count($cookies) - 1; $i >= 0; $i--) {
if (empty($cookies[$i]['expires'])) {
unset($cookies[$i]);
}
}
}
return serialize(array(
'cookies' => $cookies,
'serializeSession' => $this->serializeSession,
'useList' => $this->useList,
'ignoreInvalid' => $this->ignoreInvalid
));
}
/**
* Constructs the object from serialized string
*
* @param string $serialized string representation
*
* @see Serializable::unserialize()
*/
public function unserialize($serialized)
{
$data = unserialize($serialized);
$now = $this->now();
$this->serializeSessionCookies($data['serializeSession']);
$this->usePublicSuffixList($data['useList']);
if (array_key_exists('ignoreInvalid', $data)) {
$this->ignoreInvalidCookies($data['ignoreInvalid']);
}
foreach ($data['cookies'] as $cookie) {
if (!empty($cookie['expires']) && $cookie['expires'] <= $now) {
continue;
}
if (!isset($this->cookies[$cookie['domain']])) {
$this->cookies[$cookie['domain']] = array();
}
if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) {
$this->cookies[$cookie['domain']][$cookie['path']] = array();
}
$this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie;
}
}
/**
* Checks whether a cookie domain matches a request host.
*
* The method is used by {@link store()} to check for whether a document
* at given URL can set a cookie with a given domain attribute and by
* {@link getMatching()} to find cookies matching the request URL.
*
* @param string $requestHost request host
* @param string $cookieDomain cookie domain
*
* @return bool match success
*/
public function domainMatch($requestHost, $cookieDomain)
{
if ($requestHost == $cookieDomain) {
return true;
}
// IP address, we require exact match
if (preg_match('/^(?:\d{1,3}\.){3}\d{1,3}$/', $requestHost)) {
return false;
}
if ('.' != $cookieDomain[0]) {
$cookieDomain = '.' . $cookieDomain;
}
// prevents setting cookies for '.com' and similar domains
if (!$this->useList && substr_count($cookieDomain, '.') < 2
|| $this->useList && !self::getRegisteredDomain($cookieDomain)
) {
return false;
}
return substr('.' . $requestHost, -strlen($cookieDomain)) == $cookieDomain;
}
/**
* Removes subdomains to get the registered domain (the first after top-level)
*
* The method will check Public Suffix List to find out where top-level
* domain ends and registered domain starts. It will remove domain parts
* to the left of registered one.
*
* @param string $domain domain name
*
* @return string|bool registered domain, will return false if $domain is
* either invalid or a TLD itself
*/
public static function getRegisteredDomain($domain)
{
$domainParts = explode('.', ltrim($domain, '.'));
// load the list if needed
if (empty(self::$psl)) {
$path = '@data_dir@' . DIRECTORY_SEPARATOR . 'HTTP_Request2';
if (0 === strpos($path, '@' . 'data_dir@')) {
$path = realpath(
dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'
. DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data'
);
}
self::$psl = include_once $path . DIRECTORY_SEPARATOR . 'public-suffix-list.php';
}
if (!($result = self::checkDomainsList($domainParts, self::$psl))) {
// known TLD, invalid domain name
return false;
}
// unknown TLD
if (!strpos($result, '.')) {
// fallback to checking that domain "has at least two dots"
if (2 > ($count = count($domainParts))) {
return false;
}
return $domainParts[$count - 2] . '.' . $domainParts[$count - 1];
}
return $result;
}
/**
* Recursive helper method for {@link getRegisteredDomain()}
*
* @param array $domainParts remaining domain parts
* @param mixed $listNode node in {@link HTTP_Request2_CookieJar::$psl} to check
*
* @return string|null concatenated domain parts, null in case of error
*/
protected static function checkDomainsList(array $domainParts, $listNode)
{
$sub = array_pop($domainParts);
$result = null;
if (!is_array($listNode) || is_null($sub)
|| array_key_exists('!' . $sub, $listNode)
) {
return $sub;
} elseif (array_key_exists($sub, $listNode)) {
$result = self::checkDomainsList($domainParts, $listNode[$sub]);
} elseif (array_key_exists('*', $listNode)) {
$result = self::checkDomainsList($domainParts, $listNode['*']);
} else {
return $sub;
}
return (strlen($result) > 0) ? ($result . '.' . $sub) : null;
}
}
?>

View File

@@ -0,0 +1,160 @@
<?php
/**
* Exception classes for HTTP_Request2 package
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/**
* Base class for exceptions in PEAR
*/
require_once 'PEAR/Exception.php';
/**
* Base exception class for HTTP_Request2 package
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=132
*/
class HTTP_Request2_Exception extends PEAR_Exception
{
/** An invalid argument was passed to a method */
const INVALID_ARGUMENT = 1;
/** Some required value was not available */
const MISSING_VALUE = 2;
/** Request cannot be processed due to errors in PHP configuration */
const MISCONFIGURATION = 3;
/** Error reading the local file */
const READ_ERROR = 4;
/** Server returned a response that does not conform to HTTP protocol */
const MALFORMED_RESPONSE = 10;
/** Failure decoding Content-Encoding or Transfer-Encoding of response */
const DECODE_ERROR = 20;
/** Operation timed out */
const TIMEOUT = 30;
/** Number of redirects exceeded 'max_redirects' configuration parameter */
const TOO_MANY_REDIRECTS = 40;
/** Redirect to a protocol other than http(s):// */
const NON_HTTP_REDIRECT = 50;
/**
* Native error code
* @var int
*/
private $_nativeCode;
/**
* Constructor, can set package error code and native error code
*
* @param string $message exception message
* @param int $code package error code, one of class constants
* @param int $nativeCode error code from underlying PHP extension
*/
public function __construct($message = null, $code = null, $nativeCode = null)
{
parent::__construct($message, $code);
$this->_nativeCode = $nativeCode;
}
/**
* Returns error code produced by underlying PHP extension
*
* For Socket Adapter this may contain error number returned by
* stream_socket_client(), for Curl Adapter this will contain error number
* returned by curl_errno()
*
* @return integer
*/
public function getNativeCode()
{
return $this->_nativeCode;
}
}
/**
* Exception thrown in case of missing features
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
class HTTP_Request2_NotImplementedException extends HTTP_Request2_Exception
{
}
/**
* Exception that represents error in the program logic
*
* This exception usually implies a programmer's error, like passing invalid
* data to methods or trying to use PHP extensions that weren't installed or
* enabled. Usually exceptions of this kind will be thrown before request even
* starts.
*
* The exception will usually contain a package error code.
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
class HTTP_Request2_LogicException extends HTTP_Request2_Exception
{
}
/**
* Exception thrown when connection to a web or proxy server fails
*
* The exception will not contain a package error code, but will contain
* native error code, as returned by stream_socket_client() or curl_errno().
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
class HTTP_Request2_ConnectionException extends HTTP_Request2_Exception
{
}
/**
* Exception thrown when sending or receiving HTTP message fails
*
* The exception may contain both package error code and native error code.
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
class HTTP_Request2_MessageException extends HTTP_Request2_Exception
{
}
?>

View File

@@ -0,0 +1,268 @@
<?php
/**
* Helper class for building multipart/form-data request body
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/** Exception class for HTTP_Request2 package */
require_once 'HTTP/Request2/Exception.php';
/**
* Class for building multipart/form-data request body
*
* The class helps to reduce memory consumption by streaming large file uploads
* from disk, it also allows monitoring of upload progress (see request #7630)
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
* @link http://tools.ietf.org/html/rfc1867
*/
class HTTP_Request2_MultipartBody
{
/**
* MIME boundary
* @var string
*/
private $_boundary;
/**
* Form parameters added via {@link HTTP_Request2::addPostParameter()}
* @var array
*/
private $_params = array();
/**
* File uploads added via {@link HTTP_Request2::addUpload()}
* @var array
*/
private $_uploads = array();
/**
* Header for parts with parameters
* @var string
*/
private $_headerParam = "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n";
/**
* Header for parts with uploads
* @var string
*/
private $_headerUpload = "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n";
/**
* Current position in parameter and upload arrays
*
* First number is index of "current" part, second number is position within
* "current" part
*
* @var array
*/
private $_pos = array(0, 0);
/**
* Constructor. Sets the arrays with POST data.
*
* @param array $params values of form fields set via
* {@link HTTP_Request2::addPostParameter()}
* @param array $uploads file uploads set via
* {@link HTTP_Request2::addUpload()}
* @param bool $useBrackets whether to append brackets to array variable names
*/
public function __construct(array $params, array $uploads, $useBrackets = true)
{
$this->_params = self::_flattenArray('', $params, $useBrackets);
foreach ($uploads as $fieldName => $f) {
if (!is_array($f['fp'])) {
$this->_uploads[] = $f + array('name' => $fieldName);
} else {
for ($i = 0; $i < count($f['fp']); $i++) {
$upload = array(
'name' => ($useBrackets? $fieldName . '[' . $i . ']': $fieldName)
);
foreach (array('fp', 'filename', 'size', 'type') as $key) {
$upload[$key] = $f[$key][$i];
}
$this->_uploads[] = $upload;
}
}
}
}
/**
* Returns the length of the body to use in Content-Length header
*
* @return integer
*/
public function getLength()
{
$boundaryLength = strlen($this->getBoundary());
$headerParamLength = strlen($this->_headerParam) - 4 + $boundaryLength;
$headerUploadLength = strlen($this->_headerUpload) - 8 + $boundaryLength;
$length = $boundaryLength + 6;
foreach ($this->_params as $p) {
$length += $headerParamLength + strlen($p[0]) + strlen($p[1]) + 2;
}
foreach ($this->_uploads as $u) {
$length += $headerUploadLength + strlen($u['name']) + strlen($u['type']) +
strlen($u['filename']) + $u['size'] + 2;
}
return $length;
}
/**
* Returns the boundary to use in Content-Type header
*
* @return string
*/
public function getBoundary()
{
if (empty($this->_boundary)) {
$this->_boundary = '--' . md5('PEAR-HTTP_Request2-' . microtime());
}
return $this->_boundary;
}
/**
* Returns next chunk of request body
*
* @param integer $length Number of bytes to read
*
* @return string Up to $length bytes of data, empty string if at end
* @throws HTTP_Request2_LogicException
*/
public function read($length)
{
$ret = '';
$boundary = $this->getBoundary();
$paramCount = count($this->_params);
$uploadCount = count($this->_uploads);
while ($length > 0 && $this->_pos[0] <= $paramCount + $uploadCount) {
$oldLength = $length;
if ($this->_pos[0] < $paramCount) {
$param = sprintf(
$this->_headerParam, $boundary, $this->_params[$this->_pos[0]][0]
) . $this->_params[$this->_pos[0]][1] . "\r\n";
$ret .= substr($param, $this->_pos[1], $length);
$length -= min(strlen($param) - $this->_pos[1], $length);
} elseif ($this->_pos[0] < $paramCount + $uploadCount) {
$pos = $this->_pos[0] - $paramCount;
$header = sprintf(
$this->_headerUpload, $boundary, $this->_uploads[$pos]['name'],
$this->_uploads[$pos]['filename'], $this->_uploads[$pos]['type']
);
if ($this->_pos[1] < strlen($header)) {
$ret .= substr($header, $this->_pos[1], $length);
$length -= min(strlen($header) - $this->_pos[1], $length);
}
$filePos = max(0, $this->_pos[1] - strlen($header));
if ($filePos < $this->_uploads[$pos]['size']) {
while ($length > 0 && !feof($this->_uploads[$pos]['fp'])) {
if (false === ($chunk = fread($this->_uploads[$pos]['fp'], $length))) {
throw new HTTP_Request2_LogicException(
'Failed reading file upload', HTTP_Request2_Exception::READ_ERROR
);
}
$ret .= $chunk;
$length -= strlen($chunk);
}
}
if ($length > 0) {
$start = $this->_pos[1] + ($oldLength - $length) -
strlen($header) - $this->_uploads[$pos]['size'];
$ret .= substr("\r\n", $start, $length);
$length -= min(2 - $start, $length);
}
} else {
$closing = '--' . $boundary . "--\r\n";
$ret .= substr($closing, $this->_pos[1], $length);
$length -= min(strlen($closing) - $this->_pos[1], $length);
}
if ($length > 0) {
$this->_pos = array($this->_pos[0] + 1, 0);
} else {
$this->_pos[1] += $oldLength;
}
}
return $ret;
}
/**
* Sets the current position to the start of the body
*
* This allows reusing the same body in another request
*/
public function rewind()
{
$this->_pos = array(0, 0);
foreach ($this->_uploads as $u) {
rewind($u['fp']);
}
}
/**
* Returns the body as string
*
* Note that it reads all file uploads into memory so it is a good idea not
* to use this method with large file uploads and rely on read() instead.
*
* @return string
*/
public function __toString()
{
$this->rewind();
return $this->read($this->getLength());
}
/**
* Helper function to change the (probably multidimensional) associative array
* into the simple one.
*
* @param string $name name for item
* @param mixed $values item's values
* @param bool $useBrackets whether to append [] to array variables' names
*
* @return array array with the following items: array('item name', 'item value');
*/
private static function _flattenArray($name, $values, $useBrackets)
{
if (!is_array($values)) {
return array(array($name, $values));
} else {
$ret = array();
foreach ($values as $k => $v) {
if (empty($name)) {
$newName = $k;
} elseif ($useBrackets) {
$newName = $name . '[' . $k . ']';
} else {
$newName = $name;
}
$ret = array_merge($ret, self::_flattenArray($newName, $v, $useBrackets));
}
return $ret;
}
}
}
?>

View File

@@ -0,0 +1,192 @@
<?php
/**
* An observer useful for debugging / testing.
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author David Jean Louis <izi@php.net>
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/**
* Exception class for HTTP_Request2 package
*/
require_once 'HTTP/Request2/Exception.php';
/**
* A debug observer useful for debugging / testing.
*
* This observer logs to a log target data corresponding to the various request
* and response events, it logs by default to php://output but can be configured
* to log to a file or via the PEAR Log package.
*
* A simple example:
* <code>
* require_once 'HTTP/Request2.php';
* require_once 'HTTP/Request2/Observer/Log.php';
*
* $request = new HTTP_Request2('http://www.example.com');
* $observer = new HTTP_Request2_Observer_Log();
* $request->attach($observer);
* $request->send();
* </code>
*
* A more complex example with PEAR Log:
* <code>
* require_once 'HTTP/Request2.php';
* require_once 'HTTP/Request2/Observer/Log.php';
* require_once 'Log.php';
*
* $request = new HTTP_Request2('http://www.example.com');
* // we want to log with PEAR log
* $observer = new HTTP_Request2_Observer_Log(Log::factory('console'));
*
* // we only want to log received headers
* $observer->events = array('receivedHeaders');
*
* $request->attach($observer);
* $request->send();
* </code>
*
* @category HTTP
* @package HTTP_Request2
* @author David Jean Louis <izi@php.net>
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
class HTTP_Request2_Observer_Log implements SplObserver
{
// properties {{{
/**
* The log target, it can be a a resource or a PEAR Log instance.
*
* @var resource|Log $target
*/
protected $target = null;
/**
* The events to log.
*
* @var array $events
*/
public $events = array(
'connect',
'sentHeaders',
'sentBody',
'receivedHeaders',
'receivedBody',
'disconnect',
);
// }}}
// __construct() {{{
/**
* Constructor.
*
* @param mixed $target Can be a file path (default: php://output), a resource,
* or an instance of the PEAR Log class.
* @param array $events Array of events to listen to (default: all events)
*
* @return void
*/
public function __construct($target = 'php://output', array $events = array())
{
if (!empty($events)) {
$this->events = $events;
}
if (is_resource($target) || $target instanceof Log) {
$this->target = $target;
} elseif (false === ($this->target = @fopen($target, 'ab'))) {
throw new HTTP_Request2_Exception("Unable to open '{$target}'");
}
}
// }}}
// update() {{{
/**
* Called when the request notifies us of an event.
*
* @param HTTP_Request2 $subject The HTTP_Request2 instance
*
* @return void
*/
public function update(SplSubject $subject)
{
$event = $subject->getLastEvent();
if (!in_array($event['name'], $this->events)) {
return;
}
switch ($event['name']) {
case 'connect':
$this->log('* Connected to ' . $event['data']);
break;
case 'sentHeaders':
$headers = explode("\r\n", $event['data']);
array_pop($headers);
foreach ($headers as $header) {
$this->log('> ' . $header);
}
break;
case 'sentBody':
$this->log('> ' . $event['data'] . ' byte(s) sent');
break;
case 'receivedHeaders':
$this->log(sprintf(
'< HTTP/%s %s %s', $event['data']->getVersion(),
$event['data']->getStatus(), $event['data']->getReasonPhrase()
));
$headers = $event['data']->getHeader();
foreach ($headers as $key => $val) {
$this->log('< ' . $key . ': ' . $val);
}
$this->log('< ');
break;
case 'receivedBody':
$this->log($event['data']->getBody());
break;
case 'disconnect':
$this->log('* Disconnected');
break;
}
}
// }}}
// log() {{{
/**
* Logs the given message to the configured target.
*
* @param string $message Message to display
*
* @return void
*/
protected function log($message)
{
if ($this->target instanceof Log) {
$this->target->debug($message);
} elseif (is_resource($this->target)) {
fwrite($this->target, $message . "\r\n");
}
}
// }}}
}
?>

View File

@@ -0,0 +1,265 @@
<?php
/**
* An observer that saves response body to stream, possibly uncompressing it
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Delian Krustev <krustev@krustev.net>
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
require_once 'HTTP/Request2/Response.php';
/**
* An observer that saves response body to stream, possibly uncompressing it
*
* This Observer is written in compliment to pear's HTTP_Request2 in order to
* avoid reading the whole response body in memory. Instead it writes the body
* to a stream. If the body is transferred with content-encoding set to
* "deflate" or "gzip" it is decoded on the fly.
*
* The constructor accepts an already opened (for write) stream (file_descriptor).
* If the response is deflate/gzip encoded a "zlib.inflate" filter is applied
* to the stream. When the body has been read from the request and written to
* the stream ("receivedBody" event) the filter is removed from the stream.
*
* The "zlib.inflate" filter works fine with pure "deflate" encoding. It does
* not understand the "deflate+zlib" and "gzip" headers though, so they have to
* be removed prior to being passed to the stream. This is done in the "update"
* method.
*
* It is also possible to limit the size of written extracted bytes by passing
* "max_bytes" to the constructor. This is important because e.g. 1GB of
* zeroes take about a MB when compressed.
*
* Exceptions are being thrown if data could not be written to the stream or
* the written bytes have already exceeded the requested maximum. If the "gzip"
* header is malformed or could not be parsed an exception will be thrown too.
*
* Example usage follows:
*
* <code>
* require_once 'HTTP/Request2.php';
* require_once 'HTTP/Request2/Observer/UncompressingDownload.php';
*
* #$inPath = 'http://carsten.codimi.de/gzip.yaws/daniels.html';
* #$inPath = 'http://carsten.codimi.de/gzip.yaws/daniels.html?deflate=on';
* $inPath = 'http://carsten.codimi.de/gzip.yaws/daniels.html?deflate=on&zlib=on';
* #$outPath = "/dev/null";
* $outPath = "delme";
*
* $stream = fopen($outPath, 'wb');
* if (!$stream) {
* throw new Exception('fopen failed');
* }
*
* $request = new HTTP_Request2(
* $inPath,
* HTTP_Request2::METHOD_GET,
* array(
* 'store_body' => false,
* 'connect_timeout' => 5,
* 'timeout' => 10,
* 'ssl_verify_peer' => true,
* 'ssl_verify_host' => true,
* 'ssl_cafile' => null,
* 'ssl_capath' => '/etc/ssl/certs',
* 'max_redirects' => 10,
* 'follow_redirects' => true,
* 'strict_redirects' => false
* )
* );
*
* $observer = new HTTP_Request2_Observer_UncompressingDownload($stream, 9999999);
* $request->attach($observer);
*
* $response = $request->send();
*
* fclose($stream);
* echo "OK\n";
* </code>
*
* @category HTTP
* @package HTTP_Request2
* @author Delian Krustev <krustev@krustev.net>
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
*/
class HTTP_Request2_Observer_UncompressingDownload implements SplObserver
{
/**
* The stream to write response body to
* @var resource
*/
private $_stream;
/**
* zlib.inflate filter possibly added to stream
* @var resource
*/
private $_streamFilter;
/**
* The value of response's Content-Encoding header
* @var string
*/
private $_encoding;
/**
* Whether the observer is still waiting for gzip/deflate header
* @var bool
*/
private $_processingHeader = true;
/**
* Starting position in the stream observer writes to
* @var int
*/
private $_startPosition = 0;
/**
* Maximum bytes to write
* @var int|null
*/
private $_maxDownloadSize;
/**
* Whether response being received is a redirect
* @var bool
*/
private $_redirect = false;
/**
* Accumulated body chunks that may contain (gzip) header
* @var string
*/
private $_possibleHeader = '';
/**
* Class constructor
*
* Note that there might be problems with max_bytes and files bigger
* than 2 GB on 32bit platforms
*
* @param resource $stream a stream (or file descriptor) opened for writing.
* @param int $maxDownloadSize maximum bytes to write
*/
public function __construct($stream, $maxDownloadSize = null)
{
$this->_stream = $stream;
if ($maxDownloadSize) {
$this->_maxDownloadSize = $maxDownloadSize;
$this->_startPosition = ftell($this->_stream);
}
}
/**
* Called when the request notifies us of an event.
*
* @param SplSubject $request The HTTP_Request2 instance
*
* @return void
* @throws HTTP_Request2_MessageException
*/
public function update(SplSubject $request)
{
/* @var $request HTTP_Request2 */
$event = $request->getLastEvent();
$encoded = false;
/* @var $event['data'] HTTP_Request2_Response */
switch ($event['name']) {
case 'receivedHeaders':
$this->_processingHeader = true;
$this->_redirect = $event['data']->isRedirect();
$this->_encoding = strtolower($event['data']->getHeader('content-encoding'));
$this->_possibleHeader = '';
break;
case 'receivedEncodedBodyPart':
if (!$this->_streamFilter
&& ($this->_encoding === 'deflate' || $this->_encoding === 'gzip')
) {
$this->_streamFilter = stream_filter_append(
$this->_stream, 'zlib.inflate', STREAM_FILTER_WRITE
);
}
$encoded = true;
// fall-through is intentional
case 'receivedBodyPart':
if ($this->_redirect) {
break;
}
if (!$encoded || !$this->_processingHeader) {
$bytes = fwrite($this->_stream, $event['data']);
} else {
$offset = 0;
$this->_possibleHeader .= $event['data'];
if ('deflate' === $this->_encoding) {
if (2 > strlen($this->_possibleHeader)) {
break;
}
$header = unpack('n', substr($this->_possibleHeader, 0, 2));
if (0 == $header[1] % 31) {
$offset = 2;
}
} elseif ('gzip' === $this->_encoding) {
if (10 > strlen($this->_possibleHeader)) {
break;
}
try {
$offset = HTTP_Request2_Response::parseGzipHeader($this->_possibleHeader, false);
} catch (HTTP_Request2_MessageException $e) {
// need more data?
if (false !== strpos($e->getMessage(), 'data too short')) {
break;
}
throw $e;
}
}
$this->_processingHeader = false;
$bytes = fwrite($this->_stream, substr($this->_possibleHeader, $offset));
}
if (false === $bytes) {
throw new HTTP_Request2_MessageException('fwrite failed.');
}
if ($this->_maxDownloadSize
&& ftell($this->_stream) - $this->_startPosition > $this->_maxDownloadSize
) {
throw new HTTP_Request2_MessageException(sprintf(
'Body length limit (%d bytes) reached',
$this->_maxDownloadSize
));
}
break;
case 'receivedBody':
if ($this->_streamFilter) {
stream_filter_remove($this->_streamFilter);
$this->_streamFilter = null;
}
break;
}
}
}

View File

@@ -0,0 +1,680 @@
<?php
/**
* Class representing a HTTP response
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/**
* Exception class for HTTP_Request2 package
*/
require_once 'HTTP/Request2/Exception.php';
/**
* Class representing a HTTP response
*
* The class is designed to be used in "streaming" scenario, building the
* response as it is being received:
* <code>
* $statusLine = read_status_line();
* $response = new HTTP_Request2_Response($statusLine);
* do {
* $headerLine = read_header_line();
* $response->parseHeaderLine($headerLine);
* } while ($headerLine != '');
*
* while ($chunk = read_body()) {
* $response->appendBody($chunk);
* }
*
* var_dump($response->getHeader(), $response->getCookies(), $response->getBody());
* </code>
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
* @link http://tools.ietf.org/html/rfc2616#section-6
*/
class HTTP_Request2_Response
{
/**
* HTTP protocol version (e.g. 1.0, 1.1)
* @var string
*/
protected $version;
/**
* Status code
* @var integer
* @link http://tools.ietf.org/html/rfc2616#section-6.1.1
*/
protected $code;
/**
* Reason phrase
* @var string
* @link http://tools.ietf.org/html/rfc2616#section-6.1.1
*/
protected $reasonPhrase;
/**
* Effective URL (may be different from original request URL in case of redirects)
* @var string
*/
protected $effectiveUrl;
/**
* Associative array of response headers
* @var array
*/
protected $headers = array();
/**
* Cookies set in the response
* @var array
*/
protected $cookies = array();
/**
* Name of last header processed by parseHederLine()
*
* Used to handle the headers that span multiple lines
*
* @var string
*/
protected $lastHeader = null;
/**
* Response body
* @var string
*/
protected $body = '';
/**
* Whether the body is still encoded by Content-Encoding
*
* cURL provides the decoded body to the callback; if we are reading from
* socket the body is still gzipped / deflated
*
* @var bool
*/
protected $bodyEncoded;
/**
* Associative array of HTTP status code / reason phrase.
*
* @var array
* @link http://tools.ietf.org/html/rfc2616#section-10
*/
protected static $phrases = array(
// 1xx: Informational - Request received, continuing process
100 => 'Continue',
101 => 'Switching Protocols',
// 2xx: Success - The action was successfully received, understood and
// accepted
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
// 3xx: Redirection - Further action must be taken in order to complete
// the request
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found', // 1.1
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
// 4xx: Client Error - The request contains bad syntax or cannot be
// fulfilled
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
// 5xx: Server Error - The server failed to fulfill an apparently
// valid request
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
509 => 'Bandwidth Limit Exceeded',
);
/**
* Returns the default reason phrase for the given code or all reason phrases
*
* @param int $code Response code
*
* @return string|array|null Default reason phrase for $code if $code is given
* (null if no phrase is available), array of all
* reason phrases if $code is null
* @link http://pear.php.net/bugs/18716
*/
public static function getDefaultReasonPhrase($code = null)
{
if (null === $code) {
return self::$phrases;
} else {
return isset(self::$phrases[$code]) ? self::$phrases[$code] : null;
}
}
/**
* Constructor, parses the response status line
*
* @param string $statusLine Response status line (e.g. "HTTP/1.1 200 OK")
* @param bool $bodyEncoded Whether body is still encoded by Content-Encoding
* @param string $effectiveUrl Effective URL of the response
*
* @throws HTTP_Request2_MessageException if status line is invalid according to spec
*/
public function __construct($statusLine, $bodyEncoded = true, $effectiveUrl = null)
{
if (!preg_match('!^HTTP/(\d\.\d) (\d{3})(?: (.+))?!', $statusLine, $m)) {
throw new HTTP_Request2_MessageException(
"Malformed response: {$statusLine}",
HTTP_Request2_Exception::MALFORMED_RESPONSE
);
}
$this->version = $m[1];
$this->code = intval($m[2]);
$this->reasonPhrase = !empty($m[3]) ? trim($m[3]) : self::getDefaultReasonPhrase($this->code);
$this->bodyEncoded = (bool)$bodyEncoded;
$this->effectiveUrl = (string)$effectiveUrl;
}
/**
* Parses the line from HTTP response filling $headers array
*
* The method should be called after reading the line from socket or receiving
* it into cURL callback. Passing an empty string here indicates the end of
* response headers and triggers additional processing, so be sure to pass an
* empty string in the end.
*
* @param string $headerLine Line from HTTP response
*/
public function parseHeaderLine($headerLine)
{
$headerLine = trim($headerLine, "\r\n");
if ('' == $headerLine) {
// empty string signals the end of headers, process the received ones
if (!empty($this->headers['set-cookie'])) {
$cookies = is_array($this->headers['set-cookie'])?
$this->headers['set-cookie']:
array($this->headers['set-cookie']);
foreach ($cookies as $cookieString) {
$this->parseCookie($cookieString);
}
unset($this->headers['set-cookie']);
}
foreach (array_keys($this->headers) as $k) {
if (is_array($this->headers[$k])) {
$this->headers[$k] = implode(', ', $this->headers[$k]);
}
}
} elseif (preg_match('!^([^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+):(.+)$!', $headerLine, $m)) {
// string of the form header-name: header value
$name = strtolower($m[1]);
$value = trim($m[2]);
if (empty($this->headers[$name])) {
$this->headers[$name] = $value;
} else {
if (!is_array($this->headers[$name])) {
$this->headers[$name] = array($this->headers[$name]);
}
$this->headers[$name][] = $value;
}
$this->lastHeader = $name;
} elseif (preg_match('!^\s+(.+)$!', $headerLine, $m) && $this->lastHeader) {
// continuation of a previous header
if (!is_array($this->headers[$this->lastHeader])) {
$this->headers[$this->lastHeader] .= ' ' . trim($m[1]);
} else {
$key = count($this->headers[$this->lastHeader]) - 1;
$this->headers[$this->lastHeader][$key] .= ' ' . trim($m[1]);
}
}
}
/**
* Parses a Set-Cookie header to fill $cookies array
*
* @param string $cookieString value of Set-Cookie header
*
* @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html
*/
protected function parseCookie($cookieString)
{
$cookie = array(
'expires' => null,
'domain' => null,
'path' => null,
'secure' => false
);
if (!strpos($cookieString, ';')) {
// Only a name=value pair
$pos = strpos($cookieString, '=');
$cookie['name'] = trim(substr($cookieString, 0, $pos));
$cookie['value'] = trim(substr($cookieString, $pos + 1));
} else {
// Some optional parameters are supplied
$elements = explode(';', $cookieString);
$pos = strpos($elements[0], '=');
$cookie['name'] = trim(substr($elements[0], 0, $pos));
$cookie['value'] = trim(substr($elements[0], $pos + 1));
for ($i = 1; $i < count($elements); $i++) {
if (false === strpos($elements[$i], '=')) {
$elName = trim($elements[$i]);
$elValue = null;
} else {
list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i]));
}
$elName = strtolower($elName);
if ('secure' == $elName) {
$cookie['secure'] = true;
} elseif ('expires' == $elName) {
$cookie['expires'] = str_replace('"', '', $elValue);
} elseif ('path' == $elName || 'domain' == $elName) {
$cookie[$elName] = urldecode($elValue);
} else {
$cookie[$elName] = $elValue;
}
}
}
$this->cookies[] = $cookie;
}
/**
* Appends a string to the response body
*
* @param string $bodyChunk part of response body
*/
public function appendBody($bodyChunk)
{
$this->body .= $bodyChunk;
}
/**
* Returns the effective URL of the response
*
* This may be different from the request URL if redirects were followed.
*
* @return string
* @link http://pear.php.net/bugs/bug.php?id=18412
*/
public function getEffectiveUrl()
{
return $this->effectiveUrl;
}
/**
* Returns the status code
*
* @return integer
*/
public function getStatus()
{
return $this->code;
}
/**
* Returns the reason phrase
*
* @return string
*/
public function getReasonPhrase()
{
return $this->reasonPhrase;
}
/**
* Whether response is a redirect that can be automatically handled by HTTP_Request2
*
* @return bool
*/
public function isRedirect()
{
return in_array($this->code, array(300, 301, 302, 303, 307))
&& isset($this->headers['location']);
}
/**
* Returns either the named header or all response headers
*
* @param string $headerName Name of header to return
*
* @return string|array Value of $headerName header (null if header is
* not present), array of all response headers if
* $headerName is null
*/
public function getHeader($headerName = null)
{
if (null === $headerName) {
return $this->headers;
} else {
$headerName = strtolower($headerName);
return isset($this->headers[$headerName])? $this->headers[$headerName]: null;
}
}
/**
* Returns cookies set in response
*
* @return array
*/
public function getCookies()
{
return $this->cookies;
}
/**
* Returns the body of the response
*
* @return string
* @throws HTTP_Request2_Exception if body cannot be decoded
*/
public function getBody()
{
if (0 == strlen($this->body) || !$this->bodyEncoded
|| !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate'))
) {
return $this->body;
} else {
if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
$oldEncoding = mb_internal_encoding();
mb_internal_encoding('8bit');
}
try {
switch (strtolower($this->getHeader('content-encoding'))) {
case 'gzip':
$decoded = self::decodeGzip($this->body);
break;
case 'deflate':
$decoded = self::decodeDeflate($this->body);
}
} catch (Exception $e) {
}
if (!empty($oldEncoding)) {
mb_internal_encoding($oldEncoding);
}
if (!empty($e)) {
throw $e;
}
return $decoded;
}
}
/**
* Get the HTTP version of the response
*
* @return string
*/
public function getVersion()
{
return $this->version;
}
/**
* Checks whether data starts with GZIP format identification bytes from RFC 1952
*
* @param string $data gzip-encoded (presumably) data
*
* @return bool
*/
public static function hasGzipIdentification($data)
{
return 0 === strcmp(substr($data, 0, 2), "\x1f\x8b");
}
/**
* Tries to parse GZIP format header in the given string
*
* If the header conforms to RFC 1952, its length is returned. If any
* sanity check fails, HTTP_Request2_MessageException is thrown.
*
* Note: This function might be usable outside of HTTP_Request2 so it might
* be good idea to be moved to some common package. (Delian Krustev)
*
* @param string $data Either the complete response body or
* the leading part of it
* @param boolean $dataComplete Whether $data contains complete response body
*
* @return int gzip header length in bytes
* @throws HTTP_Request2_MessageException
* @link http://tools.ietf.org/html/rfc1952
*/
public static function parseGzipHeader($data, $dataComplete = false)
{
// if data is complete, trailing 8 bytes should be present for size and crc32
$length = strlen($data) - ($dataComplete ? 8 : 0);
if ($length < 10 || !self::hasGzipIdentification($data)) {
throw new HTTP_Request2_MessageException(
'The data does not seem to contain a valid gzip header',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$method = ord(substr($data, 2, 1));
if (8 != $method) {
throw new HTTP_Request2_MessageException(
'Error parsing gzip header: unknown compression method',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$flags = ord(substr($data, 3, 1));
if ($flags & 224) {
throw new HTTP_Request2_MessageException(
'Error parsing gzip header: reserved bits are set',
HTTP_Request2_Exception::DECODE_ERROR
);
}
// header is 10 bytes minimum. may be longer, though.
$headerLength = 10;
// extra fields, need to skip 'em
if ($flags & 4) {
if ($length - $headerLength - 2 < 0) {
throw new HTTP_Request2_MessageException(
'Error parsing gzip header: data too short',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$extraLength = unpack('v', substr($data, 10, 2));
if ($length - $headerLength - 2 - $extraLength[1] < 0) {
throw new HTTP_Request2_MessageException(
'Error parsing gzip header: data too short',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$headerLength += $extraLength[1] + 2;
}
// file name, need to skip that
if ($flags & 8) {
if ($length - $headerLength - 1 < 0) {
throw new HTTP_Request2_MessageException(
'Error parsing gzip header: data too short',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$filenameLength = strpos(substr($data, $headerLength), chr(0));
if (false === $filenameLength
|| $length - $headerLength - $filenameLength - 1 < 0
) {
throw new HTTP_Request2_MessageException(
'Error parsing gzip header: data too short',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$headerLength += $filenameLength + 1;
}
// comment, need to skip that also
if ($flags & 16) {
if ($length - $headerLength - 1 < 0) {
throw new HTTP_Request2_MessageException(
'Error parsing gzip header: data too short',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$commentLength = strpos(substr($data, $headerLength), chr(0));
if (false === $commentLength
|| $length - $headerLength - $commentLength - 1 < 0
) {
throw new HTTP_Request2_MessageException(
'Error parsing gzip header: data too short',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$headerLength += $commentLength + 1;
}
// have a CRC for header. let's check
if ($flags & 2) {
if ($length - $headerLength - 2 < 0) {
throw new HTTP_Request2_MessageException(
'Error parsing gzip header: data too short',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$crcReal = 0xffff & crc32(substr($data, 0, $headerLength));
$crcStored = unpack('v', substr($data, $headerLength, 2));
if ($crcReal != $crcStored[1]) {
throw new HTTP_Request2_MessageException(
'Header CRC check failed',
HTTP_Request2_Exception::DECODE_ERROR
);
}
$headerLength += 2;
}
return $headerLength;
}
/**
* Decodes the message-body encoded by gzip
*
* The real decoding work is done by gzinflate() built-in function, this
* method only parses the header and checks data for compliance with
* RFC 1952
*
* @param string $data gzip-encoded data
*
* @return string decoded data
* @throws HTTP_Request2_LogicException
* @throws HTTP_Request2_MessageException
* @link http://tools.ietf.org/html/rfc1952
*/
public static function decodeGzip($data)
{
// If it doesn't look like gzip-encoded data, don't bother
if (!self::hasGzipIdentification($data)) {
return $data;
}
if (!function_exists('gzinflate')) {
throw new HTTP_Request2_LogicException(
'Unable to decode body: gzip extension not available',
HTTP_Request2_Exception::MISCONFIGURATION
);
}
// unpacked data CRC and size at the end of encoded data
$tmp = unpack('V2', substr($data, -8));
$dataCrc = $tmp[1];
$dataSize = $tmp[2];
$headerLength = self::parseGzipHeader($data, true);
// don't pass $dataSize to gzinflate, see bugs #13135, #14370
$unpacked = gzinflate(substr($data, $headerLength, -8));
if (false === $unpacked) {
throw new HTTP_Request2_MessageException(
'gzinflate() call failed',
HTTP_Request2_Exception::DECODE_ERROR
);
} elseif ($dataSize != strlen($unpacked)) {
throw new HTTP_Request2_MessageException(
'Data size check failed',
HTTP_Request2_Exception::DECODE_ERROR
);
} elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) {
throw new HTTP_Request2_MessageException(
'Data CRC check failed',
HTTP_Request2_Exception::DECODE_ERROR
);
}
return $unpacked;
}
/**
* Decodes the message-body encoded by deflate
*
* @param string $data deflate-encoded data
*
* @return string decoded data
* @throws HTTP_Request2_LogicException
*/
public static function decodeDeflate($data)
{
if (!function_exists('gzuncompress')) {
throw new HTTP_Request2_LogicException(
'Unable to decode body: gzip extension not available',
HTTP_Request2_Exception::MISCONFIGURATION
);
}
// RFC 2616 defines 'deflate' encoding as zlib format from RFC 1950,
// while many applications send raw deflate stream from RFC 1951.
// We should check for presence of zlib header and use gzuncompress() or
// gzinflate() as needed. See bug #15305
$header = unpack('n', substr($data, 0, 2));
return (0 == $header[1] % 31)? gzuncompress($data): gzinflate($data);
}
}
?>

View File

@@ -0,0 +1,135 @@
<?php
/**
* SOCKS5 proxy connection class
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/** Socket wrapper class used by Socket Adapter */
require_once 'HTTP/Request2/SocketWrapper.php';
/**
* SOCKS5 proxy connection class (used by Socket Adapter)
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
* @link http://pear.php.net/bugs/bug.php?id=19332
* @link http://tools.ietf.org/html/rfc1928
*/
class HTTP_Request2_SOCKS5 extends HTTP_Request2_SocketWrapper
{
/**
* Constructor, tries to connect and authenticate to a SOCKS5 proxy
*
* @param string $address Proxy address, e.g. 'tcp://localhost:1080'
* @param int $timeout Connection timeout (seconds)
* @param array $contextOptions Stream context options
* @param string $username Proxy user name
* @param string $password Proxy password
*
* @throws HTTP_Request2_LogicException
* @throws HTTP_Request2_ConnectionException
* @throws HTTP_Request2_MessageException
*/
public function __construct(
$address, $timeout = 10, array $contextOptions = array(),
$username = null, $password = null
) {
parent::__construct($address, $timeout, $contextOptions);
if (strlen($username)) {
$request = pack('C4', 5, 2, 0, 2);
} else {
$request = pack('C3', 5, 1, 0);
}
$this->write($request);
$response = unpack('Cversion/Cmethod', $this->read(3));
if (5 != $response['version']) {
throw new HTTP_Request2_MessageException(
'Invalid version received from SOCKS5 proxy: ' . $response['version'],
HTTP_Request2_Exception::MALFORMED_RESPONSE
);
}
switch ($response['method']) {
case 2:
$this->performAuthentication($username, $password);
case 0:
break;
default:
throw new HTTP_Request2_ConnectionException(
"Connection rejected by proxy due to unsupported auth method"
);
}
}
/**
* Performs username/password authentication for SOCKS5
*
* @param string $username Proxy user name
* @param string $password Proxy password
*
* @throws HTTP_Request2_ConnectionException
* @throws HTTP_Request2_MessageException
* @link http://tools.ietf.org/html/rfc1929
*/
protected function performAuthentication($username, $password)
{
$request = pack('C2', 1, strlen($username)) . $username
. pack('C', strlen($password)) . $password;
$this->write($request);
$response = unpack('Cvn/Cstatus', $this->read(3));
if (1 != $response['vn'] || 0 != $response['status']) {
throw new HTTP_Request2_ConnectionException(
'Connection rejected by proxy due to invalid username and/or password'
);
}
}
/**
* Connects to a remote host via proxy
*
* @param string $remoteHost Remote host
* @param int $remotePort Remote port
*
* @throws HTTP_Request2_ConnectionException
* @throws HTTP_Request2_MessageException
*/
public function connect($remoteHost, $remotePort)
{
$request = pack('C5', 0x05, 0x01, 0x00, 0x03, strlen($remoteHost))
. $remoteHost . pack('n', $remotePort);
$this->write($request);
$response = unpack('Cversion/Creply/Creserved', $this->read(1024));
if (5 != $response['version'] || 0 != $response['reserved']) {
throw new HTTP_Request2_MessageException(
'Invalid response received from SOCKS5 proxy',
HTTP_Request2_Exception::MALFORMED_RESPONSE
);
} elseif (0 != $response['reply']) {
throw new HTTP_Request2_ConnectionException(
"Unable to connect to {$remoteHost}:{$remotePort} through SOCKS5 proxy",
0, $response['reply']
);
}
}
}
?>

View File

@@ -0,0 +1,320 @@
<?php
/**
* Socket wrapper class used by Socket Adapter
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to BSD 3-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @copyright 2008-2016 Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @link http://pear.php.net/package/HTTP_Request2
*/
/** Exception classes for HTTP_Request2 package */
require_once 'HTTP/Request2/Exception.php';
/**
* Socket wrapper class used by Socket Adapter
*
* Needed to properly handle connection errors, global timeout support and
* similar things. Loosely based on Net_Socket used by older HTTP_Request.
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
* @version Release: @package_version@
* @link http://pear.php.net/package/HTTP_Request2
* @link http://pear.php.net/bugs/bug.php?id=19332
* @link http://tools.ietf.org/html/rfc1928
*/
class HTTP_Request2_SocketWrapper
{
/**
* PHP warning messages raised during stream_socket_client() call
* @var array
*/
protected $connectionWarnings = array();
/**
* Connected socket
* @var resource
*/
protected $socket;
/**
* Sum of start time and global timeout, exception will be thrown if request continues past this time
* @var integer
*/
protected $deadline;
/**
* Global timeout value, mostly for exception messages
* @var integer
*/
protected $timeout;
/**
* Class constructor, tries to establish connection
*
* @param string $address Address for stream_socket_client() call,
* e.g. 'tcp://localhost:80'
* @param int $timeout Connection timeout (seconds)
* @param array $contextOptions Context options
*
* @throws HTTP_Request2_LogicException
* @throws HTTP_Request2_ConnectionException
*/
public function __construct($address, $timeout, array $contextOptions = array())
{
if (!empty($contextOptions)
&& !isset($contextOptions['socket']) && !isset($contextOptions['ssl'])
) {
// Backwards compatibility with 2.1.0 and 2.1.1 releases
$contextOptions = array('ssl' => $contextOptions);
}
if (isset($contextOptions['ssl'])) {
$contextOptions['ssl'] += array(
// Using "Intermediate compatibility" cipher bundle from
// https://wiki.mozilla.org/Security/Server_Side_TLS
'ciphers' => 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:'
. 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:'
. 'DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:'
. 'ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:'
. 'ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:'
. 'ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:'
. 'ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:'
. 'DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:'
. 'DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:'
. 'ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:'
. 'AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:'
. 'AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:'
. '!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'
);
if (version_compare(phpversion(), '5.4.13', '>=')) {
$contextOptions['ssl']['disable_compression'] = true;
if (version_compare(phpversion(), '5.6', '>=')) {
$contextOptions['ssl']['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
| STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
}
}
}
$context = stream_context_create();
foreach ($contextOptions as $wrapper => $options) {
foreach ($options as $name => $value) {
if (!stream_context_set_option($context, $wrapper, $name, $value)) {
throw new HTTP_Request2_LogicException(
"Error setting '{$wrapper}' wrapper context option '{$name}'"
);
}
}
}
set_error_handler(array($this, 'connectionWarningsHandler'));
$this->socket = stream_socket_client(
$address, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context
);
restore_error_handler();
// if we fail to bind to a specified local address (see request #19515),
// connection still succeeds, albeit with a warning. Throw an Exception
// with the warning text in this case as that connection is unlikely
// to be what user wants and as Curl throws an error in similar case.
if ($this->connectionWarnings) {
if ($this->socket) {
fclose($this->socket);
}
$error = $errstr ? $errstr : implode("\n", $this->connectionWarnings);
throw new HTTP_Request2_ConnectionException(
"Unable to connect to {$address}. Error: {$error}", 0, $errno
);
}
}
/**
* Destructor, disconnects socket
*/
public function __destruct()
{
fclose($this->socket);
}
/**
* Wrapper around fread(), handles global request timeout
*
* @param int $length Reads up to this number of bytes
*
* @return string Data read from socket
* @throws HTTP_Request2_MessageException In case of timeout
*/
public function read($length)
{
if ($this->deadline) {
stream_set_timeout($this->socket, max($this->deadline - time(), 1));
}
$data = fread($this->socket, $length);
$this->checkTimeout();
return $data;
}
/**
* Reads until either the end of the socket or a newline, whichever comes first
*
* Strips the trailing newline from the returned data, handles global
* request timeout. Method idea borrowed from Net_Socket PEAR package.
*
* @param int $bufferSize buffer size to use for reading
* @param int $localTimeout timeout value to use just for this call
* (used when waiting for "100 Continue" response)
*
* @return string Available data up to the newline (not including newline)
* @throws HTTP_Request2_MessageException In case of timeout
*/
public function readLine($bufferSize, $localTimeout = null)
{
$line = '';
while (!feof($this->socket)) {
if (null !== $localTimeout) {
stream_set_timeout($this->socket, $localTimeout);
} elseif ($this->deadline) {
stream_set_timeout($this->socket, max($this->deadline - time(), 1));
}
$line .= @fgets($this->socket, $bufferSize);
if (null === $localTimeout) {
$this->checkTimeout();
} else {
$info = stream_get_meta_data($this->socket);
// reset socket timeout if we don't have request timeout specified,
// prevents further calls failing with a bogus Exception
if (!$this->deadline) {
$default = (int)@ini_get('default_socket_timeout');
stream_set_timeout($this->socket, $default > 0 ? $default : PHP_INT_MAX);
}
if ($info['timed_out']) {
throw new HTTP_Request2_MessageException(
"readLine() call timed out", HTTP_Request2_Exception::TIMEOUT
);
}
}
if (substr($line, -1) == "\n") {
return rtrim($line, "\r\n");
}
}
return $line;
}
/**
* Wrapper around fwrite(), handles global request timeout
*
* @param string $data String to be written
*
* @return int
* @throws HTTP_Request2_MessageException
*/
public function write($data)
{
if ($this->deadline) {
stream_set_timeout($this->socket, max($this->deadline - time(), 1));
}
$written = fwrite($this->socket, $data);
$this->checkTimeout();
// http://www.php.net/manual/en/function.fwrite.php#96951
if ($written < strlen($data)) {
throw new HTTP_Request2_MessageException('Error writing request');
}
return $written;
}
/**
* Tests for end-of-file on a socket
*
* @return bool
*/
public function eof()
{
return feof($this->socket);
}
/**
* Sets request deadline
*
* @param int $deadline Exception will be thrown if request continues
* past this time
* @param int $timeout Original request timeout value, to use in
* Exception message
*/
public function setDeadline($deadline, $timeout)
{
$this->deadline = $deadline;
$this->timeout = $timeout;
}
/**
* Turns on encryption on a socket
*
* @throws HTTP_Request2_ConnectionException
*/
public function enableCrypto()
{
if (version_compare(phpversion(), '5.6', '<')) {
$cryptoMethod = STREAM_CRYPTO_METHOD_TLS_CLIENT;
} else {
$cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
| STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
}
if (!stream_socket_enable_crypto($this->socket, true, $cryptoMethod)) {
throw new HTTP_Request2_ConnectionException(
'Failed to enable secure connection when connecting through proxy'
);
}
}
/**
* Throws an Exception if stream timed out
*
* @throws HTTP_Request2_MessageException
*/
protected function checkTimeout()
{
$info = stream_get_meta_data($this->socket);
if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {
$reason = $this->deadline
? "after {$this->timeout} second(s)"
: 'due to default_socket_timeout php.ini setting';
throw new HTTP_Request2_MessageException(
"Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT
);
}
}
/**
* Error handler to use during stream_socket_client() call
*
* One stream_socket_client() call may produce *multiple* PHP warnings
* (especially OpenSSL-related), we keep them in an array to later use for
* the message of HTTP_Request2_ConnectionException
*
* @param int $errno error level
* @param string $errstr error message
*
* @return bool
*/
protected function connectionWarningsHandler($errno, $errstr)
{
if ($errno & E_WARNING) {
array_unshift($this->connectionWarnings, $errstr);
}
return true;
}
}
?>

View File

@@ -0,0 +1,82 @@
# HTTP_Request2
[![Build Status](https://travis-ci.org/pear/HTTP_Request2.svg?branch=trunk)](https://travis-ci.org/pear/HTTP_Request2)
Provides an easy way to perform HTTP requests, uses pluggable adapters
* Socket: pure PHP implementation of HTTP protocol (does *not* use http stream wrapper), based on older [PEAR HTTP_Request] package
* Curl: wrapper around PHP's cURL extension
* Mock: used for testing packages depending on HTTP_Request2, returns predefined responses without network interaction
Both Socket and Curl adapters support POST requests with data and file uploads, basic and digest
authentication, cookies, managing cookies across requests, HTTP and SOCKS5 proxies, gzip and
deflate encodings, redirects, monitoring the request progress with Observers...
This package is [PEAR HTTP_Request2] and has been migrated from [PEAR SVN]
Please report all issues via the [PEAR bug tracker].
Pull requests are welcome.
[PEAR HTTP_Request]: http://pear.php.net/package/HTTP_Request/
[PEAR HTTP_Request2]: http://pear.php.net/package/HTTP_Request2/
[PEAR SVN]: https://svn.php.net/repository/pear/packages/HTTP_Request2
[PEAR bug tracker]: http://pear.php.net/bugs/search.php?cmd=display&package_name[]=HTTP_Request2
## Basic usage
```PHP
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2('http://pear.php.net/', HTTP_Request2::METHOD_GET);
try {
$response = $request->send();
if (200 == $response->getStatus()) {
echo $response->getBody();
} else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
} catch (HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
```
## Documentation
...is available on PEAR website
* Numerous [configuration options](http://pear.php.net/manual/en/package.http.http-request2.config.php)
* How to populate [the request object](http://pear.php.net/manual/en/package.http.http-request2.request.php)
* Description of [available adapters](http://pear.php.net/manual/en/package.http.http-request2.adapters.php)
* Processing of [HTTP response](http://pear.php.net/manual/en/package.http.http-request2.response.php)
* Monitoring the progress of request with [observers](http://pear.php.net/manual/en/package.http.http-request2.observers.php)
* Possible [exceptions](http://pear.php.net/manual/en/package.http.http-request2.exceptions.php)
[Generated API documentation](http://pear.php.net/package/HTTP_Request2/docs/latest/) for the current release is also there.
## Testing, Packaging and Installing (Pear)
To test, run either
$ phpunit tests/
or
$ pear run-tests -r
You may need to set up the NetworkConfig.php file if you want to perform tests that interact with a web server.
Its template is NetworkConfig.php.dist file, consult it for the details.
To build, simply
$ pear package
To install from scratch
$ pear install package.xml
To upgrade
$ pear upgrade -f package.xml

View File

@@ -0,0 +1,42 @@
{
"name" : "pear/http_request2",
"description" : "Provides an easy way to perform HTTP requests.",
"type" : "library",
"keywords" : [ "http", "request", "pear", "curl" ],
"homepage" : "http://pear.php.net/package/HTTP_Request2",
"license" : "BSD-3-Clause",
"authors" : [
{
"name" : "Alexey Borzov",
"email" : "avb@php.net"
}
],
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=HTTP_Request2",
"source": "https://github.com/pear/HTTP_Request2"
},
"require" : {
"php" : ">=5.2.0",
"pear/net_url2" : "^2.2.0",
"pear/pear_exception" : "^1.0.0"
},
"suggest" : {
"ext-fileinfo" : "Adds support for looking up mime-types using finfo.",
"ext-zlib" : "Allows handling gzip compressed responses.",
"lib-curl" : "Allows using cURL as a request backend.",
"lib-openssl" : "Allows handling SSL requests when not using cURL."
},
"autoload": {
"psr-0": {
"HTTP_Request2" : ""
}
},
"include-path": [
"./"
],
"extra": {
"branch-alias": {
"dev-trunk": "2.2-dev"
}
}
}

View File

@@ -0,0 +1,103 @@
<?php
/**
* Helper file for downloading Public Suffix List and converting it to PHP array
*
* You can run this script to update PSL to the current version instead of
* waiting for a new release of HTTP_Request2.
*
* NB: peer validation is DISABLED when downloading. If you want to enable it,
* change ssl_verify_peer to true and provide CA file (see below)
*/
/** URL to download Public Suffix List from */
define('LIST_URL', 'https://publicsuffix.org/list/public_suffix_list.dat');
/** Name of PHP file to write */
define('OUTPUT_FILE', dirname(__FILE__) . '/public-suffix-list.php');
require_once 'HTTP/Request2.php';
function buildSubdomain(&$node, $tldParts)
{
$part = trim(array_pop($tldParts));
if (!array_key_exists($part, $node)) {
$node[$part] = array();
}
if (0 < count($tldParts)) {
buildSubdomain($node[$part], $tldParts);
}
}
function writeNode($fp, $valueTree, $key = null, $indent = 0)
{
if (is_null($key)) {
fwrite($fp, "return ");
} else {
fwrite($fp, str_repeat(' ', $indent) . "'$key' => ");
}
if (0 == ($count = count($valueTree))) {
fwrite($fp, 'true');
} else {
fwrite($fp, "array(\n");
for ($keys = array_keys($valueTree), $i = 0; $i < $count; $i++) {
writeNode($fp, $valueTree[$keys[$i]], $keys[$i], $indent + 1);
if ($i + 1 != $count) {
fwrite($fp, ",\n");
} else {
fwrite($fp, "\n");
}
}
fwrite($fp, str_repeat(' ', $indent) . ")");
}
}
try {
$request = new HTTP_Request2(LIST_URL, HTTP_Request2::METHOD_GET, array(
// Provide path to your CA file and change 'ssl_verify_peer' to true to enable peer validation
// 'ssl_cafile' => '... path to your Certificate Authority file ...',
'ssl_verify_peer' => false
));
$response = $request->send();
if (200 != $response->getStatus()) {
throw new Exception("List download URL returned status: " .
$response->getStatus() . ' ' . $response->getReasonPhrase());
}
$list = $response->getBody();
if (false === strpos($list, '// ===BEGIN ICANN DOMAINS===')) {
throw new Exception("List download URL does not contain expected phrase");
}
if (!($fp = @fopen(OUTPUT_FILE, 'wt'))) {
throw new Exception("Unable to open " . OUTPUT_FILE);
}
} catch (Exception $e) {
die($e->getMessage());
}
$tldTree = array();
$license = true;
fwrite($fp, "<?php\n");
foreach (array_filter(array_map('trim', explode("\n", $list))) as $line) {
if ('//' != substr($line, 0, 2)) {
buildSubdomain($tldTree, explode('.', $line));
} elseif ($license) {
if (0 === strpos($line, "// ===BEGIN ICANN DOMAINS===")) {
fwrite($fp, "\n");
$license = false;
} else {
fwrite($fp, $line . "\n");
}
}
}
writeNode($fp, $tldTree);
fwrite($fp, ";\n?>");
fclose($fp);
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,698 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<package version="2.0"
xmlns="http://pear.php.net/dtd/package-2.0"
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
<name>HTTP_Request2</name>
<channel>pear.php.net</channel>
<extends>HTTP_Request</extends>
<summary>Provides an easy way to perform HTTP requests.</summary>
<description>
PHP5 rewrite of HTTP_Request package (with parts of HTTP_Client). Provides
cleaner API and pluggable Adapters:
* Socket adapter, based on old HTTP_Request code,
* Curl adapter, wraps around PHP's cURL extension,
* Mock adapter, to use for testing packages dependent on HTTP_Request2.
Supports POST requests with data and file uploads, basic and digest
authentication, cookies, managing cookies across requests, proxies, gzip and
deflate encodings, redirects, monitoring the request progress with Observers...
</description>
<lead>
<name>Alexey Borzov</name>
<user>avb</user>
<email>avb@php.net</email>
<active>yes</active>
</lead>
<date>2016-02-13</date>
<version>
<release>2.3.0</release>
<api>2.3.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/BSD-3-Clause">BSD 3-Clause License</license>
<notes>
New features:
* New observer that can do on-the-fly decoding of compressed responses,
see HTTP_Request2_Observer_UncompressingDownload.
Thanks to Delian Krustev for initial implementation.
* CookieJar can now silently ignore invalid cookies with $jar-&gt;ignoreInvalidCookies(true);
instead of throwing an exception. See requests #19937 and #20401
* Adapters now dispatch a new 'warning' event, e.g. in case of incomplete response
body or broken 'chunked' encoding. Exception was thrown previously by Socket adapter
in the latter case, see bug #20228
* Improved security of HTTPS requests in Socket adapter
- Use 'tls://' instead of 'ssl://' in connection string to prevent fallback to
known insecure versions, use only TLS when enabling crypto via proxy (see bug #20462)
- On PHP 5.6+ require using only TLS 1.1 and TLS 1.2
- Do not use insecure ciphers
* Improved test suite, network-backed tests now run on Travis CI
Changes and fixes:
* Curl adapter failed to send PUT request body with 'follow_redirects' on (bug #20440)
* Curl adapter supplied invalid cookie domain to CookieJar after redirect (bug #20561)
* Curl adapter now properly dispatches events while sending the request
* mime_content_type() returning false was handled incorrectly when guessing content-type
* Use 'peer_name' and 'verify_peer_name' SSL context options on PHP 5.6+
instead of deprecated 'CN_match'
* Public Suffix List updated to current version, its download location changed
Note to Composer users: next package version will probably get rid of 'include-path'
setting in composer.json favour of using autoloader.
</notes>
<contents>
<dir name="/">
<dir name="HTTP">
<dir name="Request2">
<dir name="Adapter">
<file role="php" name="Curl.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file role="php" name="Mock.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file role="php" name="Socket.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir>
<file role="php" name="Adapter.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file role="php" name="CookieJar.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
<tasks:replace from="@data_dir@" to="data_dir" type="pear-config" />
</file>
<file role="php" name="Exception.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file role="php" name="MultipartBody.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file role="php" name="SocketWrapper.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file role="php" name="SOCKS5.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<dir name="Observer">
<file role="php" name="Log.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file role="php" name="UncompressingDownload.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir>
<file role="php" name="Response.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir>
<file role="php" name="Request2.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir>
<dir name="tests">
<dir name="_files">
<file role="test" name="bug_15305" />
<file role="test" name="bug_18169" />
<file role="test" name="empty.gif" />
<file role="test" name="plaintext.txt" />
<file role="test" name="response_cookies" />
<file role="test" name="response_deflate" />
<file role="test" name="response_gzip" />
<file role="test" name="response_gzip_broken" />
<file role="test" name="response_headers" />
</dir>
<dir name="_network">
<file role="test" name="basicauth.php" />
<file role="test" name="bug19934.php" />
<file role="test" name="bug20228.php" />
<file role="test" name="cookies.php" />
<file role="test" name="digestauth.php" />
<file role="test" name="download.php" />
<file role="test" name="getparameters.php" />
<file role="test" name="incompletebody.php" />
<file role="test" name="postparameters.php" />
<file role="test" name="rawpostdata.php" />
<file role="test" name="redirects.php" />
<file role="test" name="setcookie.php" />
<file role="test" name="timeout.php" />
<file role="test" name="uploads.php" />
</dir>
<dir name="Request2">
<dir name="Adapter">
<file role="test" name="AllTests.php" />
<file role="test" name="CommonNetworkTest.php" />
<file role="test" name="CurlTest.php" />
<file role="test" name="MockTest.php" />
<file role="test" name="SkippedTests.php" />
<file role="test" name="SocketProxyTest.php" />
<file role="test" name="SocketTest.php" />
</dir>
<file role="test" name="AllTests.php" />
<file role="test" name="CookieJarTest.php" />
<file role="test" name="MultipartBodyTest.php" />
<file role="test" name="ResponseTest.php" />
</dir>
<file role="test" name="AllTests.php" />
<file role="test" name="NetworkConfig.php.dist" />
<file role="test" name="ObserverTest.php" />
<file role="test" name="Request2Test.php" />
<file role="test" name="TestHelper.php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir>
<dir name="docs">
<file role="doc" name="LICENSE" />
<file role="doc" name="examples/upload-rapidshare.php" />
</dir>
<dir name="data">
<file role="data" name="generate-list.php" />
<file role="data" name="public-suffix-list.php" />
</dir>
</dir>
</contents>
<dependencies>
<required>
<php>
<min>5.2.0</min>
</php>
<pearinstaller>
<min>1.9.2</min>
</pearinstaller>
<package>
<name>Net_URL2</name>
<channel>pear.php.net</channel>
<min>2.2.0</min>
</package>
<package>
<name>PEAR</name>
<channel>pear.php.net</channel>
<min>1.9.2</min>
</package>
</required>
<optional>
<extension>
<name>curl</name>
</extension>
<extension>
<name>fileinfo</name>
</extension>
<extension>
<name>zlib</name>
</extension>
<extension>
<name>openssl</name>
</extension>
</optional>
</dependencies>
<phprelease>
<filelist>
<install as="LICENSE" name="docs/LICENSE" />
<install as="examples/upload-rapidshare.php" name="docs/examples/upload-rapidshare.php" />
<install as="generate-list.php" name="data/generate-list.php" />
<install as="public-suffix-list.php" name="data/public-suffix-list.php" />
<install as="AllTests.php" name="tests/AllTests.php" />
<install as="NetworkConfig.php.dist" name="tests/NetworkConfig.php.dist" />
<install as="ObserverTest.php" name="tests/ObserverTest.php" />
<install as="Request2Test.php" name="tests/Request2Test.php" />
<install as="TestHelper.php" name="tests/TestHelper.php" />
<install as="_files/bug_15305" name="tests/_files/bug_15305" />
<install as="_files/bug_18169" name="tests/_files/bug_18169" />
<install as="_files/empty.gif" name="tests/_files/empty.gif" />
<install as="_files/plaintext.txt" name="tests/_files/plaintext.txt" />
<install as="_files/response_cookies" name="tests/_files/response_cookies" />
<install as="_files/response_deflate" name="tests/_files/response_deflate" />
<install as="_files/response_gzip" name="tests/_files/response_gzip" />
<install as="_files/response_gzip_broken" name="tests/_files/response_gzip_broken" />
<install as="_files/response_headers" name="tests/_files/response_headers" />
<install as="_network/basicauth.php" name="tests/_network/basicauth.php" />
<install as="_network/bug19934.php" name="tests/_network/bug19934.php" />
<install as="_network/bug20228.php" name="tests/_network/bug20228.php" />
<install as="_network/cookies.php" name="tests/_network/cookies.php" />
<install as="_network/digestauth.php" name="tests/_network/digestauth.php" />
<install as="_network/download.php" name="tests/_network/download.php" />
<install as="_network/getparameters.php" name="tests/_network/getparameters.php" />
<install as="_network/incompletebody.php" name="tests/_network/incompletebody.php" />
<install as="_network/postparameters.php" name="tests/_network/postparameters.php" />
<install as="_network/rawpostdata.php" name="tests/_network/rawpostdata.php" />
<install as="_network/redirects.php" name="tests/_network/redirects.php" />
<install as="_network/setcookie.php" name="tests/_network/setcookie.php" />
<install as="_network/timeout.php" name="tests/_network/timeout.php" />
<install as="_network/uploads.php" name="tests/_network/uploads.php" />
<install as="Request2/AllTests.php" name="tests/Request2/AllTests.php" />
<install as="Request2/CookieJarTest.php" name="tests/Request2/CookieJarTest.php" />
<install as="Request2/MultipartBodyTest.php" name="tests/Request2/MultipartBodyTest.php" />
<install as="Request2/ResponseTest.php" name="tests/Request2/ResponseTest.php" />
<install as="Request2/Adapter/AllTests.php" name="tests/Request2/Adapter/AllTests.php" />
<install as="Request2/Adapter/CommonNetworkTest.php" name="tests/Request2/Adapter/CommonNetworkTest.php" />
<install as="Request2/Adapter/CurlTest.php" name="tests/Request2/Adapter/CurlTest.php" />
<install as="Request2/Adapter/MockTest.php" name="tests/Request2/Adapter/MockTest.php" />
<install as="Request2/Adapter/SkippedTests.php" name="tests/Request2/Adapter/SkippedTests.php" />
<install as="Request2/Adapter/SocketProxyTest.php" name="tests/Request2/Adapter/SocketProxyTest.php" />
<install as="Request2/Adapter/SocketTest.php" name="tests/Request2/Adapter/SocketTest.php" />
</filelist>
</phprelease>
<changelog>
<release>
<date>2014-01-16</date>
<version>
<release>2.2.1</release>
<api>2.2.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/BSD-3-Clause">BSD 3-Clause License</license>
<notes>
* Fixed a bogus timeout Exception in Socket adapter after waiting for
&quot;100 Continue&quot; response: the same one-second timeout was used
for further socket operations if explicit 'timeout' parameter was not set.
Thanks to Andrea Brancatelli (abrancatelli at schema31 dot it) for the report.
* Bundled a separate LICENSE file (request #20175). Updated phrasing and links
to mention 3-Clause BSD license the package actually uses.
</notes>
</release>
<release>
<date>2014-01-12</date>
<version>
<release>2.2.0</release>
<api>2.2.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
New features
* Socket adapter will send &quot;Expect: 100-continue&quot; header and wait for
&quot;100 Continue&quot; response by default before sending large request body
(request #19233). This can be disabled by setting an empty &quot;Expect&quot;
header, the same way as done with Curl adapter (see bug #15937)
* It is possible to specify a local IP address to bind to using 'local_ip'
configuration parameter (request #19515)
Other changes and fixes
* An infinite loop was possible when using a stream wrapper instead of
a regular file with MultipartBody (bug #19934)
* Socket adapter will properly send chunked request body if
&quot;Transfer-Encoding: chunked&quot; header is set for the request (bug #20125)
* Updated Public Suffix List to the latest version and updated its download script
* Unit tests fixes
</notes>
</release>
<release>
<date>2012-04-08</date>
<version>
<release>2.1.1</release>
<api>2.1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
Fixes for SOCKS5 proxies support in Socket adapter
</notes>
</release>
<release>
<date>2012-04-07</date>
<version>
<release>2.1.0</release>
<api>2.1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
New features:
* Mock adapter can return responses based on request URL (request #19276)
* Support for SOCKS5 proxies, added 'proxy_type' configuration parameter
(request #19332)
* Proxy configuration may be given as an URL, e.g.
$request-&gt;setConfig('proxy', 'socks5://localhost:1080');
Other changes and fixes:
* Coding standards fixes (request #14990)
* Unit tests now run from SVN checkout and under PHPUnit 3.6.x
* Explicit dependency on PEAR (until PEAR_Exception is a separate package)
* Get rid of track_errors, use a more robust solution (bug #19337)
* Additional class_exists() check in setAdapter() (request #19344)
* Public suffix list updated to current version
</notes>
</release>
<release>
<date>2011-10-20</date>
<version>
<release>2.0.0</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
2.0.0RC2 repackaged as stable and depending on stable Net_URL2. No code changes.
</notes>
</release>
<release>
<date>2011-10-01</date>
<version>
<release>2.0.0RC2</release>
<api>2.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
* Added an accessor method for HTTP_Request2_Response::$phrases (request #18716)
* HTTP_Request2::send() throws an exception if URL is not provided
rather than dies with a fatal error (bug #18755)
* Public Suffix List updated to current version
</notes>
</release>
<release>
<date>2011-05-06</date>
<version>
<release>2.0.0RC1</release>
<api>2.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
SSL options for Curl Adapter are always set, this prevents errors when
redirecting from HTTP to HTTPS (bug #18443)
</notes>
</release>
<release>
<version>
<release>2.0.0beta3</release>
<api>2.0.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2011-04-03</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
* Added getEffectiveUrl() method to Response object, it returns the URL
response was received from, possibly after redirects (request #18412)
* Curl Adapter didn't send body for PUT requests sometimes (bug #18421)
</notes>
</release>
<release>
<version>
<release>2.0.0beta2</release>
<api>2.0.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2011-03-25</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
* Unit tests can now be run under recent PHPUnit versions (3.5+)
* Public Suffix List updated to current version
* PHP warning produced by stream_socket_client() in Socket adapter is now
added to Exception message (bug #18331)
</notes>
</release>
<release>
<version>
<release>2.0.0beta1</release>
<api>2.0.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2011-02-27</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
Additions and changes:
* Implemented cookie jar that allows to store and pass cookies across HTTP
requests (see request #18225)
* Added several specialized subclasses of HTTP_Request2_Exception, they are
now thrown instead of the parent. Also added error codes and possibility
to get native error code (as returned by stream_socket_client() and
curl_errno()) (request #16762)
* An additional 'sentBody' event is now sent to Observers (request #16828)
* setBody() and addUpload() can now accept file pointers (request #16863)
Bugfixes:
* Incorrect check in Socket Adapter prevented Keep-alive from working in
some cases (bug #17031)
</notes>
</release>
<release>
<version>
<release>0.6.0</release>
<api>0.6.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2011-02-14</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
Additions and changes:
* Added test suite that interacts with a webserver. Please refer to
tests/NetworkConfig.php.dist for instructions.
* Packaging changes: docs/ and tests/ contents are installed without
redundant subdirectories.
* Added a $replace parameter to HTTP_Request2::setHeader() that controls
whether new header value will overwrite previous one or be appended
to it (request #17507)
Bugfixes:
* Fixed a typo in Curl Adapter that prevented 'strict_redirects' from working
* Curl Adapter will throw an exception if CURLOPT_FOLLOWLOCATION can not be
enabled due to PHP setup (bug #17450)
* Allow parameters in manually set Content-Type headers (bug #17460)
* Properly reset redirect limit if multiple requests are performed with the
same instance of Socket Adapter (bug #17826)
* Response::getBody() no longer tries to decode empty strings (bug #18169)
</notes>
</release>
<release>
<version>
<release>0.5.2</release>
<api>0.5.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2010-04-21</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
* magic_quotes_runtime PHP setting could be incorrectly enabled after
performing the request (bug #16440)
* Unit tests fixes (bugs #17079, #17106, #17326)
* Observer_Log now appends to the log file rather than rewrites it (thanks to
troelskn at gmail dot com for reporting)
</notes>
</release>
<release>
<version>
<release>0.5.1</release>
<api>0.5.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2009-11-21</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
* Content-Type request header is no longer removed for POST and PUT requests
with empty request body (request #16799).
* CURLOPT_NOBODY option is now set when doing HEAD requests with Curl adapter.
</notes>
</release>
<release>
<version>
<release>0.5.0</release>
<api>0.5.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2009-11-18</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
* Redirect support added, new configuration parameters 'follow_redirects',
'max_redirects' and 'strict_redirects' available
* Implemented workaround for PHP bug #47204, Curl Adapter can now handle
Digest authentication and redirects when doing POST requests, unfortunately
this requires loading the entire request body into memory.
* Config parameter 'use_brackets' is propagated to created instances of Net_URL2
* Prevent memory leaks due to circular references (request #16646)
* Fixed a misleading error message when timing out due to default_socket_timeout
* HTTP_Request2::setBody() can now accept an instance of HTTP_Request2_MultipartBody
without trying to convert it to string
* Calling HTTP_Request2::setBody() now clears post parameters and uploads
</notes>
</release>
<release>
<version>
<release>0.4.1</release>
<api>0.4.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2009-09-14</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
* Decoding of gzipped responses failed if mbstring.func_overload was enabled
(bug #16555)
* Changed boundary generation in multipart bodies to work correctly with
rapidshare.com, added first usage example: file uploading to rapidshare.com
* Added forgotten optional dependency on OpenSSL PHP extension
</notes>
</release>
<release>
<version>
<release>0.4.0</release>
<api>0.4.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2009-05-03</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
* Added 'store_body' config parameter, if set to false it will prevent storing
the response body in Response object (request #15881)
* HTTP_Request2::setHeader() method now works as documented, setHeader('name')
will remove the 'name' header, while setHeader('name', '') will set 'name'
header to empty value (bug #15937)
* Custom 'Host' header will not be overwritten by generated one (bug #16146)
* When trying to reuse the connected socket in Socket adapter, make sure that
it is still connected (bug #16149)
</notes>
</release>
<release>
<version>
<release>0.3.0</release>
<api>0.3.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2009-01-28</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
API changes:
* Removed HTTP_Request2::getConfigValue() method
Feature additions:
* Added digest authentication (RFC 2617) support to Socket adapter. Thanks
to Tom Snyder (tomsn at inetoffice dot com) who sent me a prototype
implementation for HTTP_Request a couple of years ago.
* Added HTTPS proxy support to Socket adapter, this works through CONNECT
request described in RFC 2817.
* Mock adapter can now throw an Exception instead of returning a response
if Exception object is added via its addResponse() method (request #15629)
Other changes and fixes:
* Support RFC 3986 by not encoding '~' in POST body (request #15368)
* Prevent an error with particular versions of PHP and Curl (bug #15617)
* Regular expressions used in HTTP_Request2 are now class constants
(request #15630)
* Curl adapter now throws an exception in case of malformed (non-HTTP)
response rather than dies with a fatal error (bug #15716)
* Curl handle wasn't closed in Curl adapter in case of error (bug #15721)
* Curl adapter sent an extra 'sentHeaders' event and returned bogus
response status when server returned 100-Continue response (bug #15785)
</notes>
</release>
<release>
<version>
<release>0.2.0</release>
<api>0.2.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2009-01-07</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
API changes:
* HTTP_Request2::getConfigValue() is deprecated and will be removed in next
release. Use HTTP_Request2::getConfig().
* Changed HTTP_Request2::setConfig() to accept a pair of parameter name and
parameter value in addition to array('parameter name' =&gt; 'value')
* Added HTTP_Request2::getConfig() method that can return a single
configuration parameter or the whole configuration array
Other additions and changes:
* Added a debug Observer that can log request progress to a file or an
instance of PEAR::Log (thanks to David Jean Louis, request #15424)
* Added a new 'timeout' parameter that limits total number of seconds
a request can take (see requests #5735 and #8964)
* Added various SSL protocol options: 'ssl_verify_peer', 'ssl_verify_host',
'ssl_cafile', 'ssl_capath', 'ssl_local_cert', 'ssl_passphrase'. Note that
'ssl_verify_host' option behaves differently in Socket and Curl Adapters:
http://bugs.php.net/bug.php?id=47030
Fixes:
* Fixed 'data error' when processing response encoded by 'deflate'
encoding (bug #15305)
* Curl Adapter now passes full request headers in 'sentHeaders' event
</notes>
</release>
<release>
<version>
<release>0.1.0</release>
<api>0.1.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2008-11-17</date>
<license uri="http://opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
Initial release. The features supported are mostly the same as those of
HTTP_Request, with the following additional feature requests implemented:
* cURL extension support (request #5463)
* It is now possible to monitor the file upload progress with Observers
(request #7630)
* Added 'sentHeaders' notification providing the request headers to the
Observers (request #7633)
* Added support for 'deflate' encoding (request #11246)
</notes>
</release>
</changelog>
</package>

View File

@@ -0,0 +1,38 @@
filter:
excluded_paths:
- 'docs/*'
tools:
php_code_coverage:
enabled: true
test_command: phpunit
php_cpd:
excluded_dirs:
- tests
filter:
excluded_paths: []
php_pdepend:
excluded_dirs:
- tests
php_hhvm:
filter:
excluded_paths: []
php_mess_detector:
filter:
excluded_paths: []
php_analyzer:
enabled: true
filter:
excluded_paths: ['docs/*']
php_code_sniffer:
enabled: true
filter:
excluded_paths: ['docs/*']
config:
tab_width: 4
encoding: utf8
ruleset: ~
standard: PEAR
php_loc:
excluded_dirs:
- tests
- docs

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
[![Net_URL2 on Packagist](https://poser.pugx.org/pear/net_url2/v/stable.png)][pear/net_url2]
[![Build Status](https://travis-ci.org/pear/Net_URL2.png)][Travis CI]
[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/pear/Net_URL2/badges/quality-score.png?s=23b0d3f0ed58ee865317c500ee2cbe94517438ec)](https://scrutinizer-ci.com/g/pear/Net_URL2/)
[![Code Coverage](https://scrutinizer-ci.com/g/pear/Net_URL2/badges/coverage.png?s=44d3682d7cdef471570d80dd8a7290a1e23fdfee)](https://scrutinizer-ci.com/g/pear/Net_URL2/)
# Net_URL2
Class for parsing and handling URL. Provides parsing of URLs into their constituent parts (scheme, host, path etc.),
URL generation, and resolving of relative URLs.
This package is [Pear Net_URL2] and has been migrated from [Pear SVN]
Please report all new issues via the [PEAR bug tracker].
On Packagist as [pear/net_url2].
[Pear Net_URL2]: https://pear.php.net/package/Net_URL2
[Pear SVN]: https://svn.php.net/repository/pear/packages/Net_URL2
[PEAR bug tracker]: https://pear.php.net/bugs/search.php?cmd=display&package_name%5B%5D=Net_URL2
[pear/net_url2]: https://packagist.org/packages/pear/net_url2
[Travis CI]: https://travis-ci.org/pear/Net_URL2
## Testing, Packaging and Installing (Pear)
To test, run either
$ phpunit tests/
or
$ pear run-tests -r
To build, simply
$ pear package
To install from scratch
$ pear install package.xml
To upgrade
$ pear upgrade -f package.xml

View File

@@ -0,0 +1,47 @@
{
"name": "pear/net_url2",
"description": "Class for parsing and handling URL. Provides parsing of URLs into their constituent parts (scheme, host, path etc.), URL generation, and resolving of relative URLs.",
"type": "library",
"keywords": [
"pear",
"net",
"url",
"uri",
"networking",
"rfc3986"
],
"homepage": "https://github.com/pear/Net_URL2",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Tom Klingenberg",
"email": "tkli@php.net"
},
{
"name": "David Coallier",
"email": "davidc@php.net"
},
{
"name": "Christian Schmidt",
"email": "chmidt@php.net"
}
],
"support": {
"issues": "https://pear.php.net/bugs/search.php?cmd=display&package_name[]=Net_URL2",
"source": "https://github.com/pear/Net_URL2"
},
"require": {
"php": ">=5.1.4"
},
"autoload": {
"classmap": ["Net/URL2.php"]
},
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev"
}
},
"require-dev": {
"phpunit/phpunit": ">=3.3.0"
}
}

View File

@@ -0,0 +1,494 @@
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.5.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd">
<name>Net_URL2</name>
<channel>pear.php.net</channel>
<extends>Net_URL</extends>
<summary>Class for parsing and handling URL.</summary>
<description>
Provides parsing of URLs into their constituent parts (scheme, host, path etc.), URL generation, and resolving of
relative URLs.
</description>
<lead>
<name>Tom Klingenberg</name>
<user>tkli</user>
<email>tkli@php.net</email>
<active>yes</active>
</lead>
<lead>
<name>David Coallier</name>
<user>davidc</user>
<email>davidc@php.net</email>
<active>no</active>
</lead>
<lead>
<name>Christian Schmidt</name>
<user>schmidt</user>
<email>schmidt@php.net</email>
<active>no</active>
</lead>
<date>2016-04-19</date>
<time>00:00:00</time>
<version>
<release>2.2.1</release>
<api>2.1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fix: Correct earlier regex delimiter
* Fix: Travis missing hhvm-nightly
* Fix: Travis PHP 5.2
* Fix: Correct case of method call name
</notes>
<contents>
<dir name="/">
<dir name="docs">
<file baseinstalldir="Net" name="example.php" role="doc" />
<file baseinstalldir="Net" name="6470.php" role="doc" />
<file baseinstalldir="Net" name="BSD-3-CLAUSE-Heyes" role="doc" />
</dir>
<!-- //docs -->
<dir name="tests">
<file name="AllTests.php" role="test" />
<dir name="Net">
<file name="URL2Test.php" role="test">
<tasks:replace type="package-info" to="version" from="@package_version@" />
</file>
</dir>
</dir>
<dir name="Net">
<file name="URL2.php" role="php">
<tasks:replace type="package-info" to="version" from="@package_version@" />
</file>
</dir>
</dir>
<!-- / -->
</contents>
<dependencies>
<required>
<php>
<min>5.1.4</min>
</php>
<pearinstaller>
<min>1.4.0b1</min>
</pearinstaller>
</required>
</dependencies>
<phprelease />
<changelog>
<release>
<date>2016-04-19</date>
<time>00:00:00</time>
<version>
<release>2.2.1</release>
<api>2.1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fix: Correct earlier regex delimiter
* Fix: Travis missing hhvm-nightly
* Fix: Travis PHP 5.2
* Fix: Correct case of method call name
</notes>
</release>
<release>
<date>2015-04-18</date>
<time>19:00:00</time>
<version>
<release>2.2.0</release>
<api>2.1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Changed composer autoloader to classmap, fixes include path pollution
</notes>
</release>
<release>
<date>2014-12-27</date>
<time>14:00:00</time>
<version>
<release>2.1.1</release>
<api>2.1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fixed #20473: Normalize query and fragment broken
</notes>
</release>
<release>
<date>2014-10-21</date>
<time>18:09:00</time>
<version>
<release>2.1.0</release>
<api>2.1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* New: OPTION_DROP_SEQUENCE
</notes>
</release>
<release>
<date>2014-10-21</date>
<time>18:06:00</time>
<version>
<release>2.0.12</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Removed: OPTION_DROP_SEQUENCE
</notes>
</release>
<release>
<date>2014-10-18</date>
<time>08:39:00</time>
<version>
<release>2.0.11</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* New: OPTION_DROP_SEQUENCE
</notes>
</release>
<release>
<date>2014-10-09</date>
<time>22:12:00</time>
<version>
<release>2.0.10</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Imp: composer for pear
* Fix: Documentation problem
</notes>
</release>
<release>
<date>2014-10-08</date>
<time>15:52:00</time>
<version>
<release>2.0.9</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fixed #20418: Incorrect normalization of URI with missing authority
* Upd: Test for RFC 3986 Section 1.1.2 Examples
* Upd: Travis CI - PHP 5.6 added
</notes>
</release>
<release>
<date>2014-10-07</date>
<time>23:25:00</time>
<version>
<release>2.0.8</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fixed #20420: Inconsistent setAuthority and getAuthority
* Fixed #20423: URI with IPv6 or IPvFuture not parsed
* Imp: Test for RFC 3986 Section 1.1.2 Examples
</notes>
</release>
<release>
<date>2014-09-07</date>
<time>08:34:00</time>
<version>
<release>2.0.7</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fixed #20385: Incorrect normalization of userinfo
* Fixed #20399: Setting userinfo to FALSE not transparent
</notes>
</release>
<release>
<date>2014-07-21</date>
<time>00:03:00</time>
<version>
<release>2.0.6</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fixed #20304: file:// URI gets crippled
</notes>
</release>
<release>
<date>2014-01-01</date>
<time>21:59:00</time>
<version>
<release>2.0.5</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fixed #17036: Brackets broken for query variables
* Fixed diverse coding style violations and misc. minor issues
* Increased code coverage
</notes>
</release>
<release>
<date>2013-12-31</date>
<time>01:59:00</time>
<version>
<release>2.0.4</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fixed #20161: URLs with "0" as host fail to normalize with empty path
* A flaw in NetURL2::removeDotSegments() introduced in 2.0.1 has been fixed
* New: NetURL2::removeDotSegments() emits a warning on loop limit reach
* Url-segment maximum count raised from 100 to 256 (loop limit)
</notes>
</release>
<release>
<date>2013-12-30</date>
<time>01:32:00</time>
<version>
<release>2.0.3</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fixed #20156: setAuthority() flaw with "0" as host
* Fixed #20157: normalize() flaw with "0" as path
* Fixed #20158: Fragment-only references are not resolved to non-absolute base URI
* Fixed #20159: Authority not terminated by slash
* Fixed diverse coding style violations and misc. minor issues
* Increased code coverage
* Added support for Scrutinizer CI
</notes>
</release>
<release>
<date>2013-12-27</date>
<time>19:16:00</time>
<version>
<release>2.0.2</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://spdx.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
* Fixed #19684: Redirects containing spaces do not work
* Fixed diverse coding style violations and misc. minor issues
* Improved source package distribution
* Added support for Travis CI
</notes>
</release>
<release>
<date>2013-12-24</date>
<time>18:12:00</time>
<version>
<release>2.0.1</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license>BSD-3-Clause</license>
<notes>
* Fixed Bug #20013: getNormalizedURL() adds leading "@" chars in the Authority
* Fixed Bug #20016: Wrong data in 6d4f4dd "Package.xml preparation."
* Fixed Bug #19176: resolve() does not merge the path if the base path is empty
* Fixed Bug #19315: removeDotSegments("0") not working
</notes>
</release>
<release>
<date>2011-10-20</date>
<time>10:43:00</time>
<version>
<release>2.0.0</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license>BSD-3-Clause</license>
<notes>
* Fixed the version of the release. Follow the convention for Package2.
* Fixed Bug #18917: URL2.php moved to ./Net/Net (davidc)
</notes>
</release>
<release>
<version>
<release>1.0.0</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2011-10-20</date>
<license>BSD-3-Clause</license>
<notes>
* Fixed Bug #17036: Problem with parsed query string
* Fixed Bug #17087: setOption() function is gone
* Fixed #17166: Fluent Interface
* Fixed #17167: Refactor __construct
* Fixed Bug #18267: setQueryVariables() fails to encode array values
* Fixed Bug #14399: Fixed multiple bugs in Net_URL2 (Missing setOption value, unused properties, etc.)
</notes>
</release>
<release>
<version>
<release>0.3.1</release>
<api>0.3.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2011-02-22</date>
<license>BSD-3-Clause</license>
<notes>
* BC break: Removed setOption() to avoid undefined behaviour (bug #16674)
* Fixed Bug #16854: Invalid package.xml making it impossible to install with Pyrus
* Fixed Bug #16651: Port may be an empty string
* Fixed Bug #16653: Don't make OPTION_SEPARATOR_(IN|OUT)PUT default to arg_separator.(in|out)put
</notes>
</release>
<release>
<version>
<release>0.3.0</release>
<api>0.3.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2009-09-05</date>
<license>BSD-3-Clause</license>
<notes>
* Fixed #14399 (Errors in URL parsing (items #1 and #3))
* Fixed #14735 (Encode query string values)
* Fixed #15546 (Add adding __toString())
* Fixed #15367 (Use RFC 3986-compliant version of rawurlencode() in PHP &lt; 5.2)
* Fixed #14289 (Add __get() and __set())
</notes>
</release>
<release>
<version>
<release>0.2.0</release>
<api>0.2.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2008-06-18</date>
<license>BSD-3-Clause</license>
<notes>
* Major rewrite to comply with RFC3986 (bug #11574).
* Much better support for resolving relative URLs.
* WARNING: Method and property names has changed to reflect the terminology used in the RFC - THIS RELEASE IS
NOT BACKWARDS COMPATIBLE WITH VERSION 0.1.0.
</notes>
</release>
<release>
<version>
<release>0.1.0</release>
<api>0.1.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2007-05-08</date>
<license>BSD-3-Clause</license>
<notes>Convert to PHP5 only. PHP4 users should continue with version 1.0.15</notes>
</release>
</changelog>
</package>

View File

@@ -0,0 +1,17 @@
<phpunit bootstrap="Net/URL2.php"
colors="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
stopOnFailure="true">
<testsuites>
<testsuite name="Tests">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<file>Net/URL2.php</file>
</whitelist>
</filter>
</phpunit>

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.4" version="2.0"
xmlns="http://pear.php.net/dtd/package-2.0"
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"
>
<name>PEAR_Exception</name>
<channel>pear.php.net</channel>
<summary>The PEAR Exception base class</summary>
<description>PEAR_Exception PHP5 error handling mechanism</description>
<lead>
<name>Christian Weiske</name>
<user>cweiske</user>
<email>cweiske@php.net</email>
<active>yes</active>
</lead>
<lead>
<name>Helgi Thormar</name>
<user>dufuz</user>
<email>dufuz@php.net</email>
<active>no</active>
</lead>
<developer>
<name>Greg Beaver</name>
<user>cellog</user>
<email>cellog@php.net</email>
<active>no</active>
</developer>
<date>2015-02-10</date>
<time>21:02:23</time>
<version>
<release>1.0.0</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
<notes>
This package was split out from the PEAR package.
If you use PEAR_Exception in your package and use nothing from the PEAR package
then it's better to depend on just PEAR_Exception.
</notes>
<contents>
<dir name="/">
<file name="/PEAR/Exception.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<dir name="tests">
<dir name="PEAR">
<file name="ExceptionTest.php" role="test"/>
</dir>
</dir>
</dir>
</contents>
<dependencies>
<required>
<php>
<min>5.4.0</min>
</php>
<pearinstaller>
<min>1.9.5</min>
</pearinstaller>
</required>
</dependencies>
<phprelease />
<changelog>
<release>
<version>
<release>1.0.0</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2015-02-10</date>
<license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
<notes>Release stable version</notes>
</release>
<release>
<version>
<release>1.0.0beta2</release>
<api>1.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<date>2014-02-21</date>
<license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
<notes>Bump up PEAR dependency.</notes>
</release>
<release>
<version>
<release>1.0.0beta1</release>
<api>1.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<date>2012-05-10</date>
<license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
<notes>
This packge was split out from the PEAR package. If you use PEAR_Exception in your package
and use nothing from the PEAR package then it&apos;s better to depend on just PEAR_Exception.
</notes>
</release>
</changelog>
</package>

View File

@@ -0,0 +1,36 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 1.0.1 - 2016-08-06
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Updated all `@return self` annotation references in interfaces to use
`@return static`, which more closelly follows the semantics of the
specification.
- Updated the `MessageInterface::getHeaders()` return annotation to use the
value `string[][]`, indicating the format is a nested array of strings.
- Updated the `@link` annotation for `RequestInterface::withRequestTarget()`
to point to the correct section of RFC 7230.
- Updated the `ServerRequestInterface::withUploadedFiles()` parameter annotation
to add the parameter name (`$uploadedFiles`).
- Updated a `@throws` annotation for the `UploadedFileInterface::moveTo()`
method to correctly reference the method parameter (it was referencing an
incorrect parameter name previously).
## 1.0.0 - 2016-05-18
Initial stable release; reflects accepted PSR-7 specification.

View File

@@ -0,0 +1,19 @@
Copyright (c) 2014 PHP Framework Interoperability Group
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,13 @@
PSR Http Message
================
This repository holds all interfaces/classes/traits related to
[PSR-7](http://www.php-fig.org/psr/psr-7/).
Note that this is not a HTTP message implementation of its own. It is merely an
interface that describes a HTTP message. See the specification for more details.
Usage
-----
We'll certainly need some stuff in here.

View File

@@ -0,0 +1,26 @@
{
"name": "psr/http-message",
"description": "Common interface for HTTP messages",
"keywords": ["psr", "psr-7", "http", "http-message", "request", "response"],
"homepage": "https://github.com/php-fig/http-message",
"license": "MIT",
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"require": {
"php": ">=5.3.0"
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
}
}

View File

@@ -0,0 +1,187 @@
<?php
namespace Psr\Http\Message;
/**
* HTTP messages consist of requests from a client to a server and responses
* from a server to a client. This interface defines the methods common to
* each.
*
* Messages are considered immutable; all methods that might change state MUST
* be implemented such that they retain the internal state of the current
* message and return an instance that contains the changed state.
*
* @link http://www.ietf.org/rfc/rfc7230.txt
* @link http://www.ietf.org/rfc/rfc7231.txt
*/
interface MessageInterface
{
/**
* Retrieves the HTTP protocol version as a string.
*
* The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
*
* @return string HTTP protocol version.
*/
public function getProtocolVersion();
/**
* Return an instance with the specified HTTP protocol version.
*
* The version string MUST contain only the HTTP version number (e.g.,
* "1.1", "1.0").
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* new protocol version.
*
* @param string $version HTTP protocol version
* @return static
*/
public function withProtocolVersion($version);
/**
* Retrieves all message header values.
*
* The keys represent the header name as it will be sent over the wire, and
* each value is an array of strings associated with the header.
*
* // Represent the headers as a string
* foreach ($message->getHeaders() as $name => $values) {
* echo $name . ": " . implode(", ", $values);
* }
*
* // Emit headers iteratively:
* foreach ($message->getHeaders() as $name => $values) {
* foreach ($values as $value) {
* header(sprintf('%s: %s', $name, $value), false);
* }
* }
*
* While header names are not case-sensitive, getHeaders() will preserve the
* exact case in which headers were originally specified.
*
* @return string[][] Returns an associative array of the message's headers. Each
* key MUST be a header name, and each value MUST be an array of strings
* for that header.
*/
public function getHeaders();
/**
* Checks if a header exists by the given case-insensitive name.
*
* @param string $name Case-insensitive header field name.
* @return bool Returns true if any header names match the given header
* name using a case-insensitive string comparison. Returns false if
* no matching header name is found in the message.
*/
public function hasHeader($name);
/**
* Retrieves a message header value by the given case-insensitive name.
*
* This method returns an array of all the header values of the given
* case-insensitive header name.
*
* If the header does not appear in the message, this method MUST return an
* empty array.
*
* @param string $name Case-insensitive header field name.
* @return string[] An array of string values as provided for the given
* header. If the header does not appear in the message, this method MUST
* return an empty array.
*/
public function getHeader($name);
/**
* Retrieves a comma-separated string of the values for a single header.
*
* This method returns all of the header values of the given
* case-insensitive header name as a string concatenated together using
* a comma.
*
* NOTE: Not all header values may be appropriately represented using
* comma concatenation. For such headers, use getHeader() instead
* and supply your own delimiter when concatenating.
*
* If the header does not appear in the message, this method MUST return
* an empty string.
*
* @param string $name Case-insensitive header field name.
* @return string A string of values as provided for the given header
* concatenated together using a comma. If the header does not appear in
* the message, this method MUST return an empty string.
*/
public function getHeaderLine($name);
/**
* Return an instance with the provided value replacing the specified header.
*
* While header names are case-insensitive, the casing of the header will
* be preserved by this function, and returned from getHeaders().
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* new and/or updated header and value.
*
* @param string $name Case-insensitive header field name.
* @param string|string[] $value Header value(s).
* @return static
* @throws \InvalidArgumentException for invalid header names or values.
*/
public function withHeader($name, $value);
/**
* Return an instance with the specified header appended with the given value.
*
* Existing values for the specified header will be maintained. The new
* value(s) will be appended to the existing list. If the header did not
* exist previously, it will be added.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* new header and/or value.
*
* @param string $name Case-insensitive header field name to add.
* @param string|string[] $value Header value(s).
* @return static
* @throws \InvalidArgumentException for invalid header names or values.
*/
public function withAddedHeader($name, $value);
/**
* Return an instance without the specified header.
*
* Header resolution MUST be done without case-sensitivity.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that removes
* the named header.
*
* @param string $name Case-insensitive header field name to remove.
* @return static
*/
public function withoutHeader($name);
/**
* Gets the body of the message.
*
* @return StreamInterface Returns the body as a stream.
*/
public function getBody();
/**
* Return an instance with the specified message body.
*
* The body MUST be a StreamInterface object.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return a new instance that has the
* new body stream.
*
* @param StreamInterface $body Body.
* @return static
* @throws \InvalidArgumentException When the body is not valid.
*/
public function withBody(StreamInterface $body);
}

Some files were not shown because too many files have changed in this diff Show More